Merge pull request #2 from yandex/master

Sync with master
This commit is contained in:
chenxing-xc 2018-05-21 10:39:05 +08:00 committed by GitHub
commit e8c8014d4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5844 changed files with 35595 additions and 1927572 deletions

View File

@ -1,24 +1,21 @@
---
BasedOnStyle: WebKit
Language: Cpp
BasedOnStyle: WebKit
Language: Cpp
AlignAfterOpenBracket: false
BreakBeforeBraces: Custom
BraceWrapping: {
AfterClass: 'true'
AfterControlStatement: 'true'
AfterEnum : 'true'
AfterFunction : 'true'
AfterNamespace : 'true'
AfterStruct : 'true'
AfterUnion : 'true'
BeforeCatch : 'true'
BeforeElse : 'true'
IndentBraces : 'false'
}
BraceWrapping:
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterStruct: true
AfterUnion: true
BeforeCatch: true
BeforeElse: true
IndentBraces: false
BreakConstructorInitializersBeforeComma: false
Cpp11BracedListStyle: true
ColumnLimit: 140
ColumnLimit: 140
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ExperimentalAutoDetectBinPacking: true
UseTab: Never
@ -28,36 +25,35 @@ Standard: Cpp11
PointerAlignment: Middle
MaxEmptyLinesToKeep: 2
KeepEmptyLinesAtTheStartOfBlocks: false
#AllowShortFunctionsOnASingleLine: Inline
AllowShortFunctionsOnASingleLine: Empty
AlwaysBreakTemplateDeclarations: true
IndentCaseLabels: true
#SpaceAfterTemplateKeyword: true
SpaceAfterTemplateKeyword: true
SortIncludes: true
IncludeCategories:
- Regex: '^<[a-z_]+>'
Priority: 1
- Regex: '^<[a-z_]+.h>'
Priority: 2
- Regex: '^["<](common|ext|mysqlxx|daemon|zkutil)/'
Priority: 90
- Regex: '^["<](DB)/'
Priority: 100
- Regex: '^["<](Poco)/'
Priority: 50
- Regex: '^"'
Priority: 110
- Regex: '/'
Priority: 30
- Regex: '.*'
Priority: 40
- Regex: '^<[a-z_]+>'
Priority: 1
- Regex: '^<[a-z_]+.h>'
Priority: 2
- Regex: '^["<](common|ext|mysqlxx|daemon|zkutil)/'
Priority: 90
- Regex: '^["<](DB)/'
Priority: 100
- Regex: '^["<](Poco)/'
Priority: 50
- Regex: '^"'
Priority: 110
- Regex: '/'
Priority: 30
- Regex: '.*'
Priority: 40
ReflowComments: false
AlignEscapedNewlinesLeft: true
# Not changed:
AccessModifierOffset: -4
AlignConsecutiveAssignments: false
AlignOperands: false
AlignOperands: false
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
@ -70,16 +66,15 @@ BinPackArguments: false
BinPackParameters: false
BreakBeforeBinaryOperators: All
BreakBeforeTernaryOperators: true
CommentPragmas: '^ IWYU pragma:'
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
DerivePointerAlignment: false
DisableFormat: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IndentWidth: 4
DisableFormat: false
IndentWidth: 4
IndentWrappedFunctionNames: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MacroBlockEnd: ''
NamespaceIndentation: Inner
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: true
@ -99,5 +94,3 @@ SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
...

1
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1 @@
I hereby agree to the terms of the CLA available at: https://yandex.ru/legal/cla/?lang=en

3
.gitignore vendored
View File

@ -9,7 +9,7 @@
# auto generated files
*.logrt
build
/build
/docs/en_single_page/
/docs/ru_single_page/
/docs/venv/
@ -43,6 +43,7 @@ cmake-build-*
# Python cache
*.pyc
__pycache__
*.pytest_cache
# ignore generated files
*-metrika-yandex

12
.gitmodules vendored
View File

@ -1,6 +1,3 @@
[submodule "contrib/zookeeper"]
path = contrib/zookeeper
url = https://github.com/ClickHouse-Extras/zookeeper.git
[submodule "contrib/poco"]
path = contrib/poco
url = https://github.com/ClickHouse-Extras/poco
@ -31,3 +28,12 @@
[submodule "contrib/re2"]
path = contrib/re2
url = https://github.com/google/re2.git
[submodule "contrib/ssl"]
path = contrib/ssl
url = https://github.com/ClickHouse-Extras/ssl.git
[submodule "contrib/boost"]
path = contrib/boost
url = https://github.com/ClickHouse-Extras/boost.git
[submodule "contrib/llvm"]
path = contrib/llvm
url = https://github.com/ClickHouse-Extras/llvm

View File

@ -11,9 +11,10 @@ matrix:
#
# addons:
# apt:
# update: true
# sources:
# - ubuntu-toolchain-r-test
# packages: [ g++-7, libicu-dev, libreadline-dev, libmysqlclient-dev, unixodbc-dev, libltdl-dev, libssl-dev, libboost-dev, zlib1g-dev, libdouble-conversion-dev, libzookeeper-mt-dev, libsparsehash-dev, librdkafka-dev, libcapnp-dev, libsparsehash-dev, libgoogle-perftools-dev, bash, expect, python, python-lxml, python-termcolor, curl, perl, sudo ]
# packages: [ g++-7, libicu-dev, libreadline-dev, libmysqlclient-dev, unixodbc-dev, libltdl-dev, libssl-dev, libboost-dev, zlib1g-dev, libdouble-conversion-dev, libsparsehash-dev, librdkafka-dev, libcapnp-dev, libsparsehash-dev, libgoogle-perftools-dev, bash, expect, python, python-lxml, python-termcolor, curl, perl, sudo, openssl ]
#
# env:
# - MATRIX_EVAL="export CC=gcc-7 && export CXX=g++-7"
@ -33,10 +34,11 @@ matrix:
addons:
apt:
update: true
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-5.0
packages: [ g++-7, clang-5.0, libicu-dev, libreadline-dev, libmysqlclient-dev, unixodbc-dev, libltdl-dev, libssl-dev, libboost-dev, zlib1g-dev, libdouble-conversion-dev, libzookeeper-mt-dev, libsparsehash-dev, librdkafka-dev, libcapnp-dev, libsparsehash-dev, libgoogle-perftools-dev, bash, expect, python, python-lxml, python-termcolor, curl, perl, sudo ]
packages: [ g++-7, clang-5.0, lld-5.0, libicu-dev, libreadline-dev, libmysqlclient-dev, unixodbc-dev, libltdl-dev, libssl-dev, libboost-dev, zlib1g-dev, libdouble-conversion-dev, libsparsehash-dev, librdkafka-dev, libcapnp-dev, libsparsehash-dev, libgoogle-perftools-dev, bash, expect, python, python-lxml, python-termcolor, curl, perl, sudo, openssl]
env:
- MATRIX_EVAL="export CC=clang-5.0 && export CXX=clang++-5.0"
@ -77,6 +79,7 @@ matrix:
addons:
apt:
update: true
packages: [ pbuilder, fakeroot, debhelper ]
script:
@ -94,6 +97,7 @@ matrix:
#
# addons:
# apt:
# update: true
# packages: [ pbuilder, fakeroot, debhelper ]
#
# env:
@ -115,10 +119,11 @@ matrix:
#
# addons:
# apt:
# update: true
# packages: [ pbuilder, fakeroot, debhelper ]
#
# env:
# - MATRIX_EVAL="export DEB_CC=clang-6.0 && export DEB_CXX=clang++-6.0 && export DIST=bionic && export EXTRAPACKAGES=clang-6.0"
# - MATRIX_EVAL="export DEB_CC=clang-6.0 && export DEB_CXX=clang++-6.0 && export DIST=bionic && export EXTRAPACKAGES='clang-6.0 lld-6.0'"
#
# script:
# - utils/travis/pbuilder.sh
@ -137,7 +142,7 @@ matrix:
# - brew link --overwrite gcc || true
#
# env:
# - MATRIX_EVAL="export CC=gcc-7 && export CXX=g++-7"
# - MATRIX_EVAL="export CC=gcc-8 && export CXX=g++-8"
#
# script:
# - env CMAKE_FLAGS="-DUSE_INTERNAL_BOOST_LIBRARY=1" utils/travis/normal.sh

View File

@ -1,3 +1,192 @@
# ClickHouse release 1.1.54381, 2018-05-14
## Bug fixes:
* Fixed a nodes leak in ZooKeeper when ClickHouse loses connection to ZooKeeper server.
# ClickHouse release 1.1.54380, 2018-04-21
## New features:
* Added table function `file(path, format, structure)`. An example reading bytes from `/dev/urandom`: `ln -s /dev/urandom /var/lib/clickhouse/user_files/random` `clickhouse-client -q "SELECT * FROM file('random', 'RowBinary', 'd UInt8') LIMIT 10"`.
## Improvements:
* Subqueries could be wrapped by `()` braces (to enhance queries readability). For example, `(SELECT 1) UNION ALL (SELECT 1)`.
* Simple `SELECT` queries from table `system.processes` are not counted in `max_concurrent_queries` limit.
## Bug fixes:
* Fixed incorrect behaviour of `IN` operator when select from `MATERIALIZED VIEW`.
* Fixed incorrect filtering by partition index in expressions like `WHERE partition_key_column IN (...)`
* Fixed inability to execute `OPTIMIZE` query on non-leader replica if the table was `REANAME`d.
* Fixed authorization error when execute `OPTIMIZE` or `ALTER` queries on a non-leader replica.
* Fixed freezing of `KILL QUERY` queries.
* Fixed an error in ZooKeeper client library which led to watches loses, freezing of distributed DDL queue and slowing replication queue if non-empty `chroot` prefix is used in ZooKeeper configuration.
## Backward incompatible changes:
* Removed support of expressions like `(a, b) IN (SELECT (a, b))` (instead of them you can use their equivalent `(a, b) IN (SELECT a, b)`). In previous releases, these expressions led to undetermined data filtering or caused errors.
# ClickHouse release 1.1.54378, 2018-04-16
## New features:
* Logging level can be changed without restarting the server.
* Added the `SHOW CREATE DATABASE` query.
* The `query_id` can be passed to `clickhouse-client` (elBroom).
* New setting: `max_network_bandwidth_for_all_users`.
* Added support for `ALTER TABLE ... PARTITION ... ` for `MATERIALIZED VIEW`.
* Added information about the size of data parts in uncompressed form in the system table.
* Server-to-server encryption support for distributed tables (`<secure>1</secure>` in the replica config in `<remote_servers>`).
* Configuration of the table level for the `ReplicatedMergeTree` family in order to minimize the amount of data stored in zookeeper: `use_minimalistic_checksums_in_zookeeper = 1`
* Configuration of the `clickhouse-client` prompt. By default, server names are now output to the prompt. The server's display name can be changed; it's also sent in the `X-ClickHouse-Display-Name` HTTP header (Kirill Shvakov).
* Multiple comma-separated `topics` can be specified for the `Kafka` engine (Tobias Adamson).
* When a query is stopped by `KILL QUERY` or `replace_running_query`, the client receives the `Query was cancelled` exception instead of an incomplete response.
## Improvements:
* `ALTER TABLE ... DROP/DETACH PARTITION` queries are run at the front of the replication queue.
* `SELECT ... FINAL` and `OPTIMIZE ... FINAL` can be used even when the table has a single data part.
* A `query_log` table is recreated on the fly if it was deleted manually (Kirill Shvakov).
* The `lengthUTF8` function runs faster (zhang2014).
* Improved performance of synchronous inserts in `Distributed` tables (`insert_distributed_sync = 1`) when there is a very large number of shards.
* The server accepts the `send_timeout` and `receive_timeout` settings from the client and applies them when connecting to the client (they are applied in reverse order: the server socket's `send_timeout` is set to the `receive_timeout` value received from the client, and vice versa).
* More robust crash recovery for asynchronous insertion into `Distributed` tables.
* The return type of the `countEqual` function changed from `UInt32` to `UInt64` (谢磊).
## Bug fixes:
* Fixed an error with `IN` when the left side of the expression is `Nullable`.
* Correct results are now returned when using tuples with `IN` when some of the tuple components are in the table index.
* The `max_execution_time` limit now works correctly with distributed queries.
* Fixed errors when calculating the size of composite columns in the `system.columns` table.
* Fixed an error when creating a temporary table `CREATE TEMPORARY TABLE IF NOT EXISTS`.
* Fixed errors in `StorageKafka` (#2075)
* Fixed server crashes from invalid arguments of certain aggregate functions.
* Fixed the error that prevented the `DETACH DATABASE` query from stopping background tasks for `ReplicatedMergeTree` tables.
* `Too many parts` state is less likely to happen when inserting into aggregated materialized views (#2084).
* Corrected recursive handling of substitutions in the config if a substitution must be followed by another substitution on the same level.
* Corrected the syntax in the metadata file when creating a `VIEW` that uses a query with `UNION ALL`.
* `SummingMergeTree` now works correctly for summation of nested data structures with a composite key.
* Fixed the possibility of a race condition when choosing the leader for `ReplicatedMergeTree` tables.
## Build changes:
* The build supports `ninja` instead of `make` and uses it by default for building releases.
* Renamed packages: `clickhouse-server-base` is now `clickhouse-common-static`; `clickhouse-server-common` is now `clickhouse-server`; `clickhouse-common-dbg` is now `clickhouse-common-static-dbg`. To install, use `clickhouse-server clickhouse-client`. Packages with the old names will still load in the repositories for backward compatibility.
## Backward-incompatible changes:
* Removed the special interpretation of an IN expression if an array is specified on the left side. Previously, the expression `arr IN (set)` was interpreted as "at least one `arr` element belongs to the `set`". To get the same behavior in the new version, write `arrayExists(x -> x IN (set), arr)`.
* Disabled the incorrect use of the socket option `SO_REUSEPORT`, which was incorrectly enabled by default in the Poco library. Note that on Linux there is no longer any reason to simultaneously specify the addresses `::` and `0.0.0.0` for listen use just `::`, which allows listening to the connection both over IPv4 and IPv6 (with the default kernel config settings). You can also revert to the behavior from previous versions by specifying `<listen_reuse_port>1</listen_reuse_port>` in the config.
# ClickHouse release 1.1.54370, 2018-03-16
## New features:
* Added the `system.macros` table and auto updating of macros when the config file is changed.
* Added the `SYSTEM RELOAD CONFIG` query.
* Added the `maxIntersections(left_col, right_col)` aggregate function, which returns the maximum number of simultaneously intersecting intervals `[left; right]`. The `maxIntersectionsPosition(left, right)` function returns the beginning of the "maximum" interval. ([Michael Furmur](https://github.com/yandex/ClickHouse/pull/2012)).
## Improvements:
* When inserting data in a `Replicated` table, fewer requests are made to `ZooKeeper` (and most of the user-level errors have disappeared from the `ZooKeeper` log).
* Added the ability to create aliases for sets. Example: `WITH (1, 2, 3) AS set SELECT number IN set FROM system.numbers LIMIT 10`.
## Bug fixes:
* Fixed the `Illegal PREWHERE` error when reading from `Merge` tables over `Distributed` tables.
* Added fixes that allow you to run `clickhouse-server` in IPv4-only Docker containers.
* Fixed a race condition when reading from system `system.parts_columns` tables.
* Removed double buffering during a synchronous insert to a `Distributed` table, which could have caused the connection to timeout.
* Fixed a bug that caused excessively long waits for an unavailable replica before beginning a `SELECT` query.
* Fixed incorrect dates in the `system.parts` table.
* Fixed a bug that made it impossible to insert data in a `Replicated` table if `chroot` was non-empty in the configuration of the `ZooKeeper` cluster.
* Fixed the vertical merging algorithm for an empty `ORDER BY` table.
* Restored the ability to use dictionaries in queries to remote tables, even if these dictionaries are not present on the requestor server. This functionality was lost in release 1.1.54362.
* Restored the behavior for queries like `SELECT * FROM remote('server2', default.table) WHERE col IN (SELECT col2 FROM default.table)` when the right side argument of the `IN` should use a remote `default.table` instead of a local one. This behavior was broken in version 1.1.54358.
* Removed extraneous error-level logging of `Not found column ... in block`.
# ClickHouse release 1.1.54356, 2018-03-06
## New features:
* Aggregation without `GROUP BY` for an empty set (such as `SELECT count(*) FROM table WHERE 0`) now returns a result with one row with null values for aggregate functions, in compliance with the SQL standard. To restore the old behavior (return an empty result), set `empty_result_for_aggregation_by_empty_set` to 1.
* Added type conversion for `UNION ALL`. Different alias names are allowed in `SELECT` positions in `UNION ALL`, in compliance with the SQL standard.
* Arbitrary expressions are supported in `LIMIT BY` sections. Previously, it was only possible to use columns resulting from `SELECT`.
* An index of `MergeTree` tables is used when `IN` is applied to a tuple of expressions from the columns of the primary key. Example: `WHERE (UserID, EventDate) IN ((123, '2000-01-01'), ...)` (Anastasiya Tsarkova).
* Added the `clickhouse-copier` tool for copying between clusters and resharding data (beta).
* Added consistent hashing functions: `yandexConsistentHash`, `jumpConsistentHash`, `sumburConsistentHash`. They can be used as a sharding key in order to reduce the amount of network traffic during subsequent reshardings.
* Added functions: `arrayAny`, `arrayAll`, `hasAny`, `hasAll`, `arrayIntersect`, `arrayResize`.
* Added the `arrayCumSum` function (Javi Santana).
* Added the `parseDateTimeBestEffort`, `parseDateTimeBestEffortOrZero`, and `parseDateTimeBestEffortOrNull`functions to read the DateTime from a string containing text in a wide variety of possible formats.
* It is now possible to change the logging settings without restarting the server.
* Added the `cluster` table function. Example: `cluster(cluster_name, db, table)`. The `remote` table function can accept the cluster name as the first argument, if it is specified as an identifier.
* Added the `create_table_query` and `engine_full` virtual columns to the `system.tables`table . The `metadata_modification_time` column is virtual.
* Added the `data_path` and `metadata_path` columns to `system.tables` and` system.databases` tables, and added the `path` column to the `system.parts` and `system.parts_columns` tables.
* Added additional information about merges in the `system.part_log` table.
* An arbitrary partitioning key can be used for the `system.query_log` table (Kirill Shvakov).
* The `SHOW TABLES` query now also shows temporary tables. Added temporary tables and the `is_temporary` column to `system.tables` (zhang2014).
* Added the `DROP TEMPORARY TABLE` query (zhang2014).
* Support for `SHOW CREATE TABLE` for temporary tables (zhang2014).
* Added the `system_profile` configuration parameter for the settings used by internal processes.
* Support for loading `object_id` as an attribute in `MongoDB` dictionaries (Pavel Litvinenko).
* Reading `null` as the default value when loading data for an external dictionary with the `MongoDB` source (Pavel Litvinenko).
* Reading `DateTime` values in the `Values` format from a Unix timestamp without single quotes.
* Failover is supported in `remote` table functions for cases when some of the replicas are missing the requested table.
* Configuration settings can be overridden in the command line when you run `clickhouse-server`. Example: `clickhouse-server -- --logger.level=information`.
* Implemented the `empty` function from a `FixedString` argument: the function returns 1 if the string consists entirely of null bytes (zhang2014).
* Added the `listen_try`configuration parameter for listening to at least one of the listen addresses without quitting, if some of the addresses can't be listened to (useful for systems with disabled support for IPv4 or IPv6).
* Added the `VersionedCollapsingMergeTree` table engine.
* Support for rows and arbitrary numeric types for the `library` dictionary source.
* `MergeTree` tables can be used without a primary key (you need to specify `ORDER BY tuple()`).
* A `Nullable` type can be `CAST` to a non-`Nullable` type if the argument is not `NULL`.
* `RENAME TABLE` can be performed for `VIEW`.
* Added the `odbc_default_field_size` option, which allows you to extend the maximum size of the value loaded from an ODBC source (by default, it is 1024).
## Improvements:
* Limits and quotas on the result are no longer applied to intermediate data for `INSERT SELECT` queries or for `SELECT` subqueries.
* Fewer false triggers of `force_restore_data` when checking the status of `Replicated` tables when the server starts.
* Added the `allow_distributed_ddl` option.
* Nondeterministic functions are not allowed in expressions for `MergeTree` table keys.
* Files with substitutions from `config.d` directories are loaded in alphabetical order.
* Improved performance of the `arrayElement` function in the case of a constant multidimensional array with an empty array as one of the elements. Example: `[[1], []][x]`.
* The server starts faster now when using configuration files with very large substitutions (for instance, very large lists of IP networks).
* When running a query, table valued functions run once. Previously, `remote` and `mysql` table valued functions performed the same query twice to retrieve the table structure from a remote server.
* The `MkDocs` documentation generator is used.
* When you try to delete a table column that `DEFAULT`/`MATERIALIZED` expressions of other columns depend on, an exception is thrown (zhang2014).
* Added the ability to parse an empty line in text formats as the number 0 for `Float` data types. This feature was previously available but was lost in release 1.1.54342.
* `Enum` values can be used in `min`, `max`, `sum` and some other functions. In these cases, it uses the corresponding numeric values. This feature was previously available but was lost in the release 1.1.54337.
* Added `max_expanded_ast_elements` to restrict the size of the AST after recursively expanding aliases.
## Bug fixes:
* Fixed cases when unnecessary columns were removed from subqueries in error, or not removed from subqueries containing `UNION ALL`.
* Fixed a bug in merges for `ReplacingMergeTree` tables.
* Fixed synchronous insertions in `Distributed` tables (`insert_distributed_sync = 1`).
* Fixed segfault for certain uses of `FULL` and `RIGHT JOIN` with duplicate columns in subqueries.
* Fixed the order of the `source` and `last_exception` columns in the `system.dictionaries` table.
* Fixed a bug when the `DROP DATABASE` query did not delete the file with metadata.
* Fixed the `DROP DATABASE` query for `Dictionary` databases.
* Fixed the low precision of `uniqHLL12` and `uniqCombined` functions for cardinalities greater than 100 million items (Alex Bocharov).
* Fixed the calculation of implicit default values when necessary to simultaneously calculate default explicit expressions in `INSERT` queries (zhang2014).
* Fixed a rare case when a query to a `MergeTree` table couldn't finish (chenxing-xc).
* Fixed a crash that occurred when running a `CHECK` query for `Distributed` tables if all shards are local (chenxing.xc).
* Fixed a slight performance regression with functions that use regular expressions.
* Fixed a performance regression when creating multidimensional arrays from complex expressions.
* Fixed a bug that could cause an extra `FORMAT` section to appear in an `.sql` file with metadata.
* Fixed a bug that caused the `max_table_size_to_drop` limit to apply when trying to delete a `MATERIALIZED VIEW` looking at an explicitly specified table.
* Fixed incompatibility with old clients (old clients were sometimes sent data with the `DateTime('timezone')` type, which they do not understand).
* Fixed a bug when reading `Nested` column elements of structures that were added using `ALTER` but that are empty for the old partitions, when the conditions for these columns moved to `PREWHERE`.
* Fixed a bug when filtering tables by virtual `_table` columns in queries to `Merge` tables.
* Fixed a bug when using `ALIAS` columns in `Distributed` tables.
* Fixed a bug that made dynamic compilation impossible for queries with aggregate functions from the `quantile` family.
* Fixed a race condition in the query execution pipeline that occurred in very rare cases when using `Merge` tables with a large number of tables, and when using `GLOBAL` subqueries.
* Fixed a crash when passing arrays of different sizes to an `arrayReduce` function when using aggregate functions from multiple arguments.
* Prohibited the use of queries with `UNION ALL` in a `MATERIALIZED VIEW`.
## Backward incompatible changes:
* Removed the `distributed_ddl_allow_replicated_alter` option. This behavior is enabled by default.
* Removed the `UnsortedMergeTree` engine.
# ClickHouse release 1.1.54343, 2018-02-05
* Added macros support for defining cluster names in distributed DDL queries and constructors of Distributed tables: `CREATE TABLE distr ON CLUSTER '{cluster}' (...) ENGINE = Distributed('{cluster}', 'db', 'table')`.
@ -6,7 +195,7 @@
# ClickHouse release 1.1.54342, 2018-01-22
This release contains bug fixes for the previous release 1.1.54342:
This release contains bug fixes for the previous release 1.1.54337:
* Fixed a regression in 1.1.54337: if the default user has readonly access, then the server refuses to start up with the message `Cannot create database in readonly mode`.
* Fixed a regression in 1.1.54337: on systems with `systemd`, logs are always written to syslog regardless of the configuration; the watchdog script still uses `init.d`.
* Fixed a regression in 1.1.54337: wrong default configuration in the Docker image.

View File

@ -1,3 +1,201 @@
# ClickHouse release 1.1.54381, 2018-05-14
## Исправление ошибок:
* Исправлена ошибка, приводящая к "утеканию" метаданных в ZooKeeper при потере соединения с сервером ZooKeeper.
# ClickHouse release 1.1.54380, 2018-04-21
## Новые возможности:
* Добавлена табличная функция `file(path, format, structure)`. Пример, читающий байты из `/dev/urandom`: `ln -s /dev/urandom /var/lib/clickhouse/user_files/random` `clickhouse-client -q "SELECT * FROM file('random', 'RowBinary', 'd UInt8') LIMIT 10"`.
## Улучшения:
* Добавлена возможность оборачивать подзапросы скобками `()` для повышения читаемости запросов. Например: `(SELECT 1) UNION ALL (SELECT 1)`.
* Простые запросы `SELECT` из таблицы `system.processes` не учитываются в ограничении `max_concurrent_queries`.
## Исправление ошибок:
* Исправлена неправильная работа оператора `IN` в `MATERIALIZED VIEW`.
* Исправлена неправильная работа индекса по ключу партиционирования в выражениях типа `partition_key_column IN (...)`.
* Исправлена невозможность выполнить `OPTIMIZE` запрос на лидирующей реплике после выполнения `RENAME` таблицы.
* Исправлены ошибки авторизации возникающие при выполнении запросов `OPTIMIZE` и `ALTER` на нелидирующей реплике.
* Исправлены зависания запросов `KILL QUERY`.
* Исправлена ошибка в клиентской библиотеке ZooKeeper, которая при использовании непустого префикса `chroot` в конфигурации приводила к потере watch'ей, остановке очереди distributed DDL запросов и замедлению репликации.
## Обратно несовместимые изменения:
* Убрана поддержка выражений типа `(a, b) IN (SELECT (a, b))` (можно использовать эквивалентные выражение `(a, b) IN (SELECT a, b)`). Раньше такие запросы могли приводить к недетерминированной фильтрации в `WHERE`.
# ClickHouse release 1.1.54378, 2018-04-16
## Новые возможности:
* Возможность изменения уровня логгирования без перезагрузки сервера.
* Добавлен запрос `SHOW CREATE DATABASE`.
* Возможность передать `query_id` в `clickhouse-client` (elBroom).
* Добавлена настройка `max_network_bandwidth_for_all_users`.
* Добавлена поддержка `ALTER TABLE ... PARTITION ... ` для `MATERIALIZED VIEW`.
* Добавлена информация о размере кусков данных в несжатом виде в системные таблицы.
* Поддержка межсерверного шифрования для distributed таблиц (`<secure>1</secure>` в конфигурации реплики в `<remote_servers>`).
* Добавлена настройка уровня таблицы семейства `ReplicatedMergeTree` для уменьшения объема данных, хранимых в zookeeper: `use_minimalistic_checksums_in_zookeeper = 1`
* Возможность настройки приглашения `clickhouse-client`. По-умолчанию добавлен вывод имени сервера в приглашение. Возможность изменить отображаемое имя сервера. Отправка его в HTTP заголовке `X-ClickHouse-Display-Name` (Kirill Shvakov).
* Возможность указания нескольких `topics` через запятую для движка `Kafka` (Tobias Adamson)
* При остановке запроса по причине `KILL QUERY` или `replace_running_query`, клиент получает исключение `Query was cancelled` вместо неполного результата.
## Улучшения:
* Запросы вида `ALTER TABLE ... DROP/DETACH PARTITION` выполняются впереди очереди репликации.
* Возможность использовать `SELECT ... FINAL` и `OPTIMIZE ... FINAL` даже в случае, если данные в таблице представлены одним куском.
* Пересоздание таблицы `query_log` налету в случае если было произведено её удаление вручную (Kirill Shvakov).
* Ускорение функции `lengthUTF8` (zhang2014).
* Улучшена производительность синхронной вставки в `Distributed` таблицы (`insert_distributed_sync = 1`) в случае очень большого количества шардов.
* Сервер принимает настройки `send_timeout` и `receive_timeout` от клиента и применяет их на своей стороне для соединения с клиентом (в переставленном порядке: `send_timeout` у сокета на стороне сервера выставляется в значение `receive_timeout` принятое от клиента, и наоборот).
* Более надёжное восстановление после сбоев при асинхронной вставке в `Distributed` таблицы.
* Возвращаемый тип функции `countEqual` изменён с `UInt32` на `UInt64` (谢磊)
## Исправление ошибок:
* Исправлена ошибка c `IN` где левая часть выражения `Nullable`.
* Исправлен неправильный результат при использовании кортежей с `IN` в случае, если часть компоненнтов кортежа есть в индексе таблицы.
* Исправлена работа ограничения `max_execution_time` с распределенными запросами.
* Исправлены ошибки при вычислении размеров составных столбцов в таблице `system.columns`.
* Исправлена ошибка при создании временной таблицы `CREATE TEMPORARY TABLE IF NOT EXISTS`
* Исправлены ошибки в `StorageKafka` (#2075)
* Исправлены падения сервера от некорректных аргументов некоторых аггрегатных функций.
* Исправлена ошибка, из-за которой запрос `DETACH DATABASE` мог не приводить к остановке фоновых задач таблицы типа `ReplicatedMergeTree`.
* Исправлена проблема с появлением `Too many parts` в агрегирующих материализованных представлениях (#2084).
* Исправлена рекурсивная обработка подстановок в конфиге, если после одной подстановки, требуется другая подстановка на том же уровне.
* Исправлена ошибка с неправильным синтаксисом в файле с метаданными при создании `VIEW`, использующих запрос с `UNION ALL`.
* Исправлена работа `SummingMergeTree` в случае суммирования вложенных структур данных с составным ключом.
* Исправлена возможность возникновения race condition при выборе лидера таблиц `ReplicatedMergeTree`.
## Изменения сборки:
* Поддержка `ninja` вместо `make` при сборке. `ninja` используется по-умолчанию при сборке релизов.
* Переименованы пакеты `clickhouse-server-base` в `clickhouse-common-static`; `clickhouse-server-common` в `clickhouse-server`; `clickhouse-common-dbg` в `clickhouse-common-static-dbg`. Для установки используйте `clickhouse-server clickhouse-client`. Для совместимости, пакеты со старыми именами продолжают загружаться в репозиторий.
## Обратно несовместимые изменения:
* Удалена специальная интерпретация выражения IN, если слева указан массив. Ранее выражение вида `arr IN (set)` воспринималось как "хотя бы один элемент `arr` принадлежит множеству `set`". Для получения такого же поведения в новой версии, напишите `arrayExists(x -> x IN (set), arr)`.
* Отключено ошибочное использование опции сокета `SO_REUSEPORT` (которая по ошибке включена по-умолчанию в библиотеке Poco). Стоит обратить внимание, что на Linux системах теперь не имеет смысла указывать одновременно адреса `::` и `0.0.0.0` для listen - следует использовать лишь адрес `::`, который (с настройками ядра по-умолчанию) позволяет слушать соединения как по IPv4 так и по IPv6. Также вы можете вернуть поведение старых версий, указав в конфиге `<listen_reuse_port>1</listen_reuse_port>`.
# ClickHouse release 1.1.54370, 2018-03-16
## Новые возможности:
* Добавлена системная таблица `system.macros` и автоматическое обновление макросов при изменении конфигурационного файла.
* Добавлен запрос `SYSTEM RELOAD CONFIG`.
* Добавлена агрегатная функция `maxIntersections(left_col, right_col)`, возвращающая максимальное количество одновременно пересекающихся интервалов `[left; right]`. Функция `maxIntersectionsPosition(left, right)` возвращает начало такого "максимального" интервала. ([Michael Furmur](https://github.com/yandex/ClickHouse/pull/2012)).
## Улучшения:
* При вставке данных в `Replicated`-таблицу делается меньше обращений к `ZooKeeper` (также из лога `ZooKeeper` исчезло большинство user-level ошибок).
* Добавлена возможность создавать алиасы для множеств. Пример: `WITH (1, 2, 3) AS set SELECT number IN set FROM system.numbers LIMIT 10`.
## Исправление ошибок:
* Исправлена ошибка `Illegal PREWHERE` при чтении из Merge-таблицы над `Distributed`-таблицами.
* Добавлены исправления, позволяющие запускать clickhouse-server в IPv4-only docker-контейнерах.
* Исправлен race condition при чтении из системной таблицы `system.parts_columns`
* Убрана двойная буферизация при синхронной вставке в `Distributed`-таблицу, которая могла приводить к timeout-ам соединений.
* Исправлена ошибка, вызывающая чрезмерно долгое ожидание недоступной реплики перед началом выполнения `SELECT`.
* Исправлено некорректное отображение дат в таблице `system.parts`.
* Исправлена ошибка, приводящая к невозможности вставить данные в `Replicated`-таблицу, если в конфигурации кластера `ZooKeeper` задан непустой `chroot`.
* Исправлен алгоритм вертикального мержа при пустом ключе `ORDER BY` таблицы.
* Возвращена возможность использовать словари в запросах к удаленным таблицам, даже если этих словарей нет на сервере-инициаторе. Данная функциональность была потеряна в версии 1.1.54362.
* Восстановлено поведение, при котором в запросах типа `SELECT * FROM remote('server2', default.table) WHERE col IN (SELECT col2 FROM default.table)` в правой части `IN` должна использоваться удаленная таблица `default.table`, а не локальная. данное поведение было нарушено в версии 1.1.54358.
* Устранено ненужное Error-level логирование `Not found column ... in block`.
# Релиз ClickHouse 1.1.54362, 2018-03-11
## Новые возможности:
* Агрегация без `GROUP BY` по пустому множеству (как например, `SELECT count(*) FROM table WHERE 0`) теперь возвращает результат из одной строки с нулевыми значениями агрегатных функций, в соответствии со стандартом SQL. Вы можете вернуть старое поведение (возвращать пустой результат), выставив настройку `empty_result_for_aggregation_by_empty_set` в значение 1.
* Добавлено приведение типов при `UNION ALL`. Допустимо использование столбцов с разными алиасами в соответствующих позициях `SELECT` в `UNION ALL`, что соответствует стандарту SQL.
* Поддержка произвольных выражений в секции `LIMIT BY`. Ранее было возможно лишь использование столбцов - результата `SELECT`.
* Использование индекса таблиц семейства `MergeTree` при наличии условия `IN` на кортеж от выражений от столбцов первичного ключа. Пример `WHERE (UserID, EventDate) IN ((123, '2000-01-01'), ...)` (Anastasiya Tsarkova).
* Добавлен инструмент `clickhouse-copier` для межкластерного копирования и перешардирования данных (бета).
* Добавлены функции консистентного хэширования `yandexConsistentHash`, `jumpConsistentHash`, `sumburConsistentHash`. Их можно использовать в качестве ключа шардирования для того, чтобы уменьшить объём сетевого трафика при последующих перешардированиях.
* Добавлены функции `arrayAny`, `arrayAll`, `hasAny`, `hasAll`, `arrayIntersect`, `arrayResize`.
* Добавлена функция `arrayCumSum` (Javi Santana).
* Добавлена функция `parseDateTimeBestEffort`, `parseDateTimeBestEffortOrZero`, `parseDateTimeBestEffortOrNull`, позволяющая прочитать DateTime из строки, содержащей текст в широком множестве возможных форматов.
* Возможность частичной перезагрузки данных внешних словарей при их обновлении (загрузка лишь записей со значением заданного поля большим, чем при предыдущей загрузке) (Arsen Hakobyan).
* Добавлена табличная функция `cluster`. Пример: `cluster(cluster_name, db, table)`. Табличная функция `remote` может принимать имя кластера в качестве первого аргумента, если оно указано в виде идентификатора.
* Возможность использования табличных функций `remote`, `cluster` в `INSERT` запросах.
* Добавлены виртуальные столбцы `create_table_query`, `engine_full` в таблице `system.tables`. Столбец `metadata_modification_time` сделан виртуальным.
* Добавлены столбцы `data_path`, `metadata_path` в таблицы `system.tables` и` system.databases`, а также столбец `path` в таблицы `system.parts` и `system.parts_columns`.
* Добавлена дополнительная информация о слияниях в таблице `system.part_log`.
* Возможность использования произвольного ключа партиционирования для таблицы `system.query_log` (Kirill Shvakov).
* Запрос `SHOW TABLES` теперь показывает также и временные таблицы. Добавлены временные таблицы и столбец `is_temporary` в таблице `system.tables` (zhang2014).
* Добавлен запрос `DROP TEMPORARY TABLE`, `EXISTS TEMPORARY TABLE` (zhang2014).
* Поддержка `SHOW CREATE TABLE` для временных таблиц (zhang2014).
* Добавлен конфигурационный параметр `system_profile` для настроек, используемых внутренними процессами.
* Поддержка загрузки `object_id` в качестве атрибута в словарях с источником `MongoDB` (Павел Литвиненко).
* Возможность читать `null` как значение по-умолчанию при загрузке данных для внешнего словаря с источником `MongoDB` (Павел Литвиненко).
* Возможность чтения значения типа `DateTime` в формате `Values` из unix timestamp без одинарных кавычек.
* Поддержан failover в табличной функции `remote` для случая, когда на части реплик отсутствует запрошенная таблица.
* Возможность переопределять параметры конфигурации в параметрах командной строки при запуске `clickhouse-server`, пример: `clickhouse-server -- --logger.level=information`.
* Реализована функция `empty` от аргумента типа `FixedString`: функция возвращает 1, если строка состоит полностью из нулевых байт (zhang2014).
* Добавлен конфигурационный параметр `listen_try`, позволяющий слушать хотя бы один из listen адресов и не завершать работу, если некоторые адреса не удаётся слушать (полезно для систем с выключенной поддержкой IPv4 или IPv6).
* Добавлен движок таблиц `VersionedCollapsingMergeTree`.
* Поддержка строк и произвольных числовых типов для источника словарей `library`.
* Возможность использования таблиц семейства `MergeTree` без первичного ключа (для этого необходимо указать `ORDER BY tuple()`).
* Добавлена возможность выполнить преобразование (`CAST`) `Nullable` типа в не `Nullable` тип, если аргумент не является `NULL`.
* Возможность выполнения `RENAME TABLE` для `VIEW`.
* Добавлена функция `throwIf`.
* Добавлена настройка `odbc_default_field_size`, позволяющая расширить максимальный размер значения, загружаемого из ODBC источника (по-умолчанию - 1024).
* В таблицу `system.processes` и в `SHOW PROCESSLIST` добавлены столбцы `is_cancelled` и `peak_memory_usage`.
## Улучшения:
* Ограничения на результат и квоты на результат теперь не применяются к промежуточным данным для запросов `INSERT SELECT` и для подзапросов в `SELECT`.
* Уменьшено количество ложных срабатываний при проверке состояния `Replicated` таблиц при запуске сервера, приводивших к необходимости выставления флага `force_restore_data`.
* Добавлена настройка `allow_distributed_ddl`.
* Запрещено использование недетерминированных функций в выражениях для ключей таблиц семейства `MergeTree`.
* Файлы с подстановками из `config.d` директорий загружаются в алфавитном порядке.
* Увеличена производительность функции `arrayElement` в случае константного многомерного массива с пустым массивом в качестве одного из элементов. Пример: `[[1], []][x]`.
* Увеличена скорость запуска сервера при использовании конфигурационных файлов с очень большими подстановками (например, очень большими списками IP-сетей).
* При выполнении запроса, табличные функции выполняются один раз. Ранее табличные функции `remote`, `mysql` дважды делали одинаковый запрос на получение структуры таблицы с удалённого сервера.
* Используется генератор документации `MkDocs`.
* При попытке удалить столбец таблицы, от которого зависят `DEFAULT`/`MATERIALIZED` выражения других столбцов, кидается исключение (zhang2014).
* Добавлена возможность парсинга пустой строки в текстовых форматах как числа 0 для `Float` типов данных. Эта возможность присутствовала раньше, но была потеряна в релизе 1.1.54342.
* Значения типа `Enum` можно использовать в функциях `min`, `max`, `sum` и некоторых других - в этих случаях используются соответствующие числовые значения. Эта возможность присутствовала ранее, но была потеряна в релизе 1.1.54337.
* Добавлено ограничение `max_expanded_ast_elements` действующее на размер AST после рекурсивного раскрытия алиасов.
## Исправление ошибок:
* Исправлены случаи ошибочного удаления ненужных столбцов из подзапросов, а также отсутствие удаления ненужных столбцов из подзапросов, содержащих `UNION ALL`.
* Исправлена ошибка в слияниях для таблиц типа `ReplacingMergeTree`.
* Исправлена работа синхронного режима вставки в `Distributed` таблицы (`insert_distributed_sync = 1`).
* Исправлены segfault при некоторых случаях использования `FULL` и `RIGHT JOIN` с дублирующимися столбцами в подзапросах.
* Исправлены segfault, которые могут возникать при использовании функциональности `replace_running_query` и `KILL QUERY`.
* Исправлен порядок столбцов `source` и `last_exception` в таблице `system.dictionaries`.
* Исправлена ошибка - запрос `DROP DATABASE` не удалял файл с метаданными.
* Исправлен запрос `DROP DATABASE` для базы данных типа `Dictionary`.
* Исправлена неоправданно низкая точность работы функций `uniqHLL12` и `uniqCombined` для кардинальностей больше 100 млн. элементов (Alex Bocharov).
* Исправлено вычисление неявных значений по-умолчанию при необходимости одновременного вычисления явных выражений по-умолчанию в запросах `INSERT` (zhang2014).
* Исправлен редкий случай, в котором запрос к таблице типа `MergeTree` мог не завершаться (chenxing-xc).
* Исправлено падение при выполнении запроса `CHECK` для `Distributed` таблиц, если все шарды локальные (chenxing.xc).
* Исправлена незначительная регрессия производительности при работе функций, использующих регулярные выражения.
* Исправлена регрессия производительности при создании многомерных массивов от сложных выражений.
* Исправлена ошибка, из-за которой в `.sql` файл с метаданными может записываться лишняя секция `FORMAT`.
* Исправлена ошибка, приводящая к тому, что ограничение `max_table_size_to_drop` действует при попытке удаления `MATERIALIZED VIEW`, смотрящего на явно указанную таблицу.
* Исправлена несовместимость со старыми клиентами (на старые клиенты могли отправляться данные с типом `DateTime('timezone')`, который они не понимают).
* Исправлена ошибка при чтении столбцов-элементов `Nested` структур, которые были добавлены с помощью `ALTER`, но являются пустыми для старых партиций, когда условия на такие столбцы переносятся в `PREWHERE`.
* Исправлена ошибка при фильтрации таблиц по условию на виртуальных столбец `_table` в запросах к таблицам типа `Merge`.
* Исправлена ошибка при использовании `ALIAS` столбцов в `Distributed` таблицах.
* Исправлена ошибка, приводящая к невозможности динамической компиляции запросов с агрегатными функциями из семейства `quantile`.
* Исправлен race condition в конвейере выполнения запроса, который мог проявляться в очень редких случаях при использовании `Merge` таблиц над большим количеством таблиц, а также при использовании `GLOBAL` подзапросов.
* Исправлено падение при передаче массивов разных размеров в функцию `arrayReduce` при использовании агрегатных функций от нескольких аргументов.
* Запрещено использование запросов с `UNION ALL` в `MATERIALIZED VIEW`.
* Исправлена ошибка, которая может возникать при инициализации системной таблицы `part_log` при старте сервера (по-умолчанию `part_log` выключен).
## Обратно несовместимые изменения:
* Удалена настройка `distributed_ddl_allow_replicated_alter`. Соответствующее поведение включено по-умолчанию.
* Удалена настройка `strict_insert_defaults`. Если вы использовали эту функциональность, напишите на `clickhouse-feedback@yandex-team.com`.
* Удалён движок таблиц `UnsortedMergeTree`.
# Релиз ClickHouse 1.1.54343, 2018-02-05
* Добавлена возможность использовать макросы при задании имени кластера в распределенных DLL запросах и создании Distributed-таблиц: `CREATE TABLE distr ON CLUSTER '{cluster}' (...) ENGINE = Distributed('{cluster}', 'db', 'table')`.
@ -6,7 +204,7 @@
# Релиз ClickHouse 1.1.54342, 2018-01-22
Релиз содержит исправление к предыдущему релизу 1.1.54318:
Релиз содержит исправление к предыдущему релизу 1.1.54337:
* Исправлена регрессия в версии 1.1.54337: если пользователь по-умолчанию имеет readonly доступ, то сервер отказывался стартовать с сообщением `Cannot create database in readonly mode`.
* Исправлена регрессия в версии 1.1.54337: на системах под управлением systemd, логи по ошибке всегда записываются в syslog; watchdog скрипт по ошибке использует init.d.
* Исправлена регрессия в версии 1.1.54337: неправильная конфигурация по-умоланию в Docker образе.

View File

@ -17,7 +17,6 @@ else ()
message (WARNING "You are using an unsupported compiler! Compilation has only been tested with Clang 5+ and GCC 7+.")
endif ()
# Write compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
@ -35,32 +34,16 @@ message (STATUS "CMAKE_BUILD_TYPE: " ${CMAKE_BUILD_TYPE} )
# TSan is not supported due to false positive errors in libstdc++ and necessity to rebuild libstdc++ with TSan
set (CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Debug;Release;MinSizeRel;ASan;UBSan" CACHE STRING "" FORCE)
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*)")
set (ARCH_AARCH64 1)
endif ()
if (ARCH_AARCH64 OR CMAKE_SYSTEM_PROCESSOR MATCHES "arm")
set (ARCH_ARM 1)
endif ()
if (CMAKE_LIBRARY_ARCHITECTURE MATCHES "i386")
set (ARCH_I386 1)
endif ()
if ( ( ARCH_ARM AND NOT ARCH_AARCH64 ) OR ARCH_I386)
set (ARCH_32 1)
message (WARNING "Support for 32bit platforms is highly experimental")
endif ()
if (CMAKE_SYSTEM MATCHES "Linux")
set (ARCH_LINUX 1)
endif ()
if (CMAKE_SYSTEM MATCHES "FreeBSD")
set (ARCH_FREEBSD 1)
include (cmake/arch.cmake)
if (NOT MSVC)
set (COMMON_WARNING_FLAGS "${COMMON_WARNING_FLAGS} -Wall") # -Werror is also added inside directories with our own code.
endif ()
if (ARCH_FREEBSD)
set (PLATFORM_EXTRA_CXX_FLAG "-DCLOCK_MONOTONIC_COARSE=CLOCK_MONOTONIC_FAST")
if (COMPILER_GCC OR COMPILER_CLANG)
set (CXX_WARNING_FLAGS "${CXX_WARNING_FLAGS} -Wnon-virtual-dtor")
endif ()
set (COMMON_WARNING_FLAGS "${COMMON_WARNING_FLAGS} -Wall") # -Werror is also added inside directories with our own code.
set (CXX_WARNING_FLAGS "${CXX_WARNING_FLAGS} -Wnon-virtual-dtor")
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# clang: warning: argument unused during compilation: '-stdlib=libc++'
# clang: warning: argument unused during compilation: '-specs=/usr/share/dpkg/no-pie-compile.specs' [-Wunused-command-line-argument]
@ -72,7 +55,7 @@ if (ARCH_LINUX)
endif ()
option (TEST_COVERAGE "Enables flags for test coverage" OFF)
option (ENABLE_TESTS "Enables tests" ON)
option (ENABLE_TESTS "Enables tests" ${NOT_MSVC})
option (USE_STATIC_LIBRARIES "Set to FALSE to use shared libraries" ON)
option (MAKE_STATIC_LIBRARIES "Set to FALSE to make shared libraries" ${USE_STATIC_LIBRARIES})
@ -111,8 +94,10 @@ endif ()
set (COMPILER_FLAGS "${COMPILER_FLAGS} ${CXX11_ABI_FLAGS}")
find_program (LLD_PATH NAMES lld)
find_program (GOLD_PATH NAMES gold)
string(REGEX MATCH "-?[0-9]+(.[0-9]+)?$" COMPILER_POSTFIX ${CMAKE_CXX_COMPILER})
find_program (LLD_PATH NAMES "lld${COMPILER_POSTFIX}" "lld")
find_program (GOLD_PATH NAMES "gold")
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND LLD_PATH AND NOT LINKER_NAME)
set (LINKER_NAME "lld")
@ -121,8 +106,8 @@ elseif (GOLD_PATH)
endif ()
if (LINKER_NAME)
message(STATUS "Using linker: ${LINKER_NAME}")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=${LINKER_NAME}")
message(STATUS "Using linker: ${LINKER_NAME} (selected from: LLD_PATH=${LLD_PATH}; GOLD_PATH=${GOLD_PATH}; COMPILER_POSTFIX=${COMPILER_POSTFIX})")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=${LINKER_NAME}")
endif ()
option (PIPE "-pipe compiler option [less /tmp usage, more ram usage]" ON)
@ -176,6 +161,8 @@ if (ARCH_LINUX AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GLIBC_COMPATIBILITY_LINK_FLAGS} ${CXX11_ABI_FLAGS}")
option (USE_LIBCXX "Use libc++ and libc++abi instead of libstdc++ (only make sense on Linux with Clang)" ${HAVE_LIBCXX})
set (LIBCXX_PATH "" CACHE STRING "Use custom path for libc++. It should be used for MSan.")
if (USE_LIBCXX)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") # Ok for clang6, for older can cause 'not used option' warning
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_LIBCPP_DEBUG=0") # More checks in debug build.
@ -184,6 +171,11 @@ if (ARCH_LINUX AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
else ()
link_libraries (-stdlib=libc++ c++ c++abi)
endif ()
if (LIBCXX_PATH)
# include_directories (BEFORE SYSTEM "${LIBCXX_PATH}/include" "${LIBCXX_PATH}/include/c++/v1")
link_directories ("${LIBCXX_PATH}/lib")
endif ()
endif ()
endif ()
@ -196,29 +188,7 @@ if (NOT MAKE_STATIC_LIBRARIES)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif ()
set (SAN_FLAGS "${SAN_FLAGS} -g -fno-omit-frame-pointer")
if (SAN_DEBUG)
set (SAN_FLAGS "${SAN_FLAGS} -O0")
else ()
set (SAN_FLAGS "${SAN_FLAGS} -O3")
endif ()
set (CMAKE_CXX_FLAGS_ASAN "${CMAKE_CXX_FLAGS_ASAN} ${SAN_FLAGS} -fsanitize=address")
set (CMAKE_C_FLAGS_ASAN "${CMAKE_C_FLAGS_ASAN} ${SAN_FLAGS} -fsanitize=address")
set (CMAKE_CXX_FLAGS_UBSAN "${CMAKE_CXX_FLAGS_UBSAN} ${SAN_FLAGS} -fsanitize=undefined")
set (CMAKE_C_FLAGS_UBSAN "${CMAKE_C_FLAGS_UBSAN} ${SAN_FLAGS} -fsanitize=undefined")
set (CMAKE_CXX_FLAGS_MSAN "${CMAKE_CXX_FLAGS_MSAN} ${SAN_FLAGS} -fsanitize=memory")
set (CMAKE_C_FLAGS_MSAN "${CMAKE_C_FLAGS_MSAN} ${SAN_FLAGS} -fsanitize=memory")
set (CMAKE_CXX_FLAGS_TSAN "${CMAKE_CXX_FLAGS_TSAN} ${SAN_FLAGS} -fsanitize=thread")
set (CMAKE_C_FLAGS_TSAN "${CMAKE_C_FLAGS_TSAN} ${SAN_FLAGS} -fsanitize=thread")
# clang use static linking by default
if (MAKE_STATIC_LIBRARIES AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set (CMAKE_EXE_LINKER_FLAGS_ASAN "${CMAKE_EXE_LINKER_FLAGS_ASAN} -static-libasan")
set (CMAKE_EXE_LINKER_FLAGS_UBSAN "${CMAKE_EXE_LINKER_FLAGS_UBSAN} -static-libubsan")
set (CMAKE_EXE_LINKER_FLAGS_MSAN "${CMAKE_EXE_LINKER_FLAGS_MSAN} -static-libmsan")
set (CMAKE_EXE_LINKER_FLAGS_TSAN "${CMAKE_EXE_LINKER_FLAGS_TSAN} -static-libtsan")
endif ()
include (cmake/sanitize.cmake)
# Using "include-what-you-use" tool.
option (USE_INCLUDE_WHAT_YOU_USE "Use 'include-what-you-use' tool" OFF)
@ -264,7 +234,7 @@ message (STATUS "Building for: ${CMAKE_SYSTEM} ${CMAKE_SYSTEM_PROCESSOR} ${CMAKE
include(GNUInstallDirs)
include (cmake/find_openssl.cmake)
include (cmake/find_ssl.cmake)
if (NOT OPENSSL_FOUND)
message (FATAL_ERROR "Need openssl for build. debian tip: sudo apt install libssl-dev")
endif ()
@ -276,18 +246,19 @@ include (cmake/find_boost.cmake)
include (cmake/find_zlib.cmake)
include (cmake/find_zstd.cmake)
include (cmake/find_ltdl.cmake) # for odbc
include (cmake/find_termcap.cmake)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/poco/cmake/FindODBC.cmake)
include (${CMAKE_CURRENT_SOURCE_DIR}/contrib/poco/cmake/FindODBC.cmake) # for poco
else ()
include (cmake/find_odbc.cmake)
endif ()
message (STATUS "Using odbc: ${ODBC_INCLUDE_DIRECTORIES} : ${ODBC_LIBRARIES}")
include (cmake/find_poco.cmake)
include (cmake/find_lz4.cmake)
include (cmake/find_sparsehash.cmake)
include (cmake/find_rt.cmake)
include (cmake/find_execinfo.cmake)
include (cmake/find_readline_edit.cmake)
include (cmake/find_zookeeper.cmake)
include (cmake/find_re2.cmake)
include (cmake/find_rdkafka.cmake)
include (cmake/find_capnp.cmake)
@ -307,13 +278,7 @@ include (libs/libcommon/cmake/find_cctz.cmake)
include (libs/libmysqlxx/cmake/find_mysqlclient.cmake)
include (libs/libdaemon/cmake/find_unwind.cmake)
set (FULL_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_UC}}")
set (FULL_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UC}}")
set (FULL_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UC}}")
message (STATUS "C_FLAGS = ${FULL_C_FLAGS}")
message (STATUS "CXX_FLAGS = ${FULL_CXX_FLAGS}")
message (STATUS "LINKER_FLAGS = ${FULL_EXE_LINKER_FLAGS}")
include (cmake/print_flags.cmake)
# Directory for Yandex specific files
set (CLICKHOUSE_PRIVATE_DIR ${ClickHouse_SOURCE_DIR}/private/)

View File

@ -30,3 +30,5 @@ Replace the bracketed text as follows:
* [link] is the link at the current version of the CLA (you may add here a link https://yandex.ru/legal/cla/?lang=en (in English) or a link https://yandex.ru/legal/cla/?lang=ru (in Russian).
It is enough to provide us such notification at once.
If you don't agree with the CLA, you still can open a pull request to provide your contributions.

View File

@ -1,5 +1,6 @@
# ClickHouse
ClickHouse is an open-source column-oriented database management system that allows generating analytical data reports in real time.
[Read more...](https://clickhouse.yandex/)
Learn more about ClickHouse at [https://clickhouse.yandex/](https://clickhouse.yandex/)
[![Build Status](https://travis-ci.org/yandex/ClickHouse.svg?branch=master)](https://travis-ci.org/yandex/ClickHouse)

142
ci/README.md Normal file
View File

@ -0,0 +1,142 @@
## Build and test ClickHouse on various plaforms
Quick and dirty scripts.
Usage example:
```
./run-with-docker.sh ubuntu:bionic jobs/quick-build/run.sh
```
Another example, check build on ARM 64:
```
./prepare-docker-image-ubuntu.sh
./run-with-docker.sh multiarch/ubuntu-core:arm64-bionic jobs/quick-build/run.sh
```
Another example, check build on FreeBSD:
```
./prepare-vagrant-image-freebsd.sh
./run-with-vagrant.sh freebsd jobs/quick-build/run.sh
```
Look at `default_config` and `jobs/quick-build/run.sh`
Various possible options. We are not going to automate testing all of them.
#### CPU architectures:
- x86_64;
- AArch64.
x86_64 is the main CPU architecture. We also have minimal support for AArch64.
#### Operating systems:
- Linux;
- FreeBSD.
We also target Mac OS X, but it's more difficult to test.
Linux is the main. FreeBSD is also supported as production OS.
Mac OS is intended only for development and have minimal support: client should work, server should just start.
#### Linux distributions:
For build:
- Ubuntu Bionic;
- Ubuntu Trusty.
For run:
- Ubuntu Hardy;
- CentOS 5
We should support almost any Linux to run ClickHouse. That's why we test also on old distributions.
#### How to obtain sources:
- use sources from local working copy;
- clone sources from github;
- download source tarball.
#### Compilers:
- gcc-7;
- gcc-8;
- clang-6;
- clang-svn.
#### Compiler installation:
- from OS packages;
- build from sources.
#### C++ standard library implementation:
- libc++;
- libstdc++ with C++11 ABI;
- libstdc++ with old ABI.
When building with clang, libc++ is used. When building with gcc, we choose libstdc++ with C++11 ABI.
#### Linkers:
- ldd;
- gold;
When building with clang on x86_64, ldd is used. Otherwise we use gold.
#### Build types:
- RelWithDebInfo;
- Debug;
- ASan;
- TSan.
#### Build types, extra:
- -g0 for quick build;
- enable test coverage;
- debug tcmalloc.
#### What to build:
- only `clickhouse` target;
- all targets;
- debian packages;
We also have intent to build RPM and simple tgz packages.
#### Where to get third-party libraries:
- from contrib directory (submodules);
- from OS packages.
The only production option is to use libraries from contrib directory.
Using libraries from OS packages is discouraged, but we also support this option.
#### Linkage types:
- static;
- shared;
Static linking is the only option for production usage.
We also have support for shared linking, but it is indended only for developers.
#### Make tools:
- make;
- ninja.
#### Installation options:
- run built `clickhouse` binary directly;
- install from packages.
#### How to obtain packages:
- build them;
- download from repository.
#### Sanity checks:
- check that clickhouse binary has no dependencies on unexpected shared libraries;
- check that source code have no style violations.
#### Tests:
- Functional tests;
- Integration tests;
- Unit tests;
- Simple sh/reference tests;
- Performance tests (note that they require predictable computing power);
- Tests for external dictionaries (should be moved to integration tests);
- Jepsen like tests for quorum inserts (not yet available in opensource).
#### Tests extra:
- Run functional tests with Valgrind.
#### Static analyzers:
- CppCheck;
- clang-tidy;
- Coverity.

38
ci/build-clang-from-sources.sh Executable file
View File

@ -0,0 +1,38 @@
#!/usr/bin/env bash
set -e -x
source default-config
# TODO Non debian systems
./install-os-packages.sh svn
./install-os-packages.sh cmake
mkdir "${WORKSPACE}/llvm"
svn co "http://llvm.org/svn/llvm-project/llvm/${CLANG_SOURCES_BRANCH}" "${WORKSPACE}/llvm/llvm"
svn co "http://llvm.org/svn/llvm-project/cfe/${CLANG_SOURCES_BRANCH}" "${WORKSPACE}/llvm/llvm/tools/clang"
svn co "http://llvm.org/svn/llvm-project/lld/${CLANG_SOURCES_BRANCH}" "${WORKSPACE}/llvm/llvm/tools/lld"
svn co "http://llvm.org/svn/llvm-project/polly/${CLANG_SOURCES_BRANCH}" "${WORKSPACE}/llvm/llvm/tools/polly"
svn co "http://llvm.org/svn/llvm-project/clang-tools-extra/${CLANG_SOURCES_BRANCH}" "${WORKSPACE}/llvm/llvm/tools/clang/tools/extra"
svn co "http://llvm.org/svn/llvm-project/compiler-rt/${CLANG_SOURCES_BRANCH}" "${WORKSPACE}/llvm/llvm/projects/compiler-rt"
svn co "http://llvm.org/svn/llvm-project/libcxx/${CLANG_SOURCES_BRANCH}" "${WORKSPACE}/llvm/llvm/projects/libcxx"
svn co "http://llvm.org/svn/llvm-project/libcxxabi/${CLANG_SOURCES_BRANCH}" "${WORKSPACE}/llvm/llvm/projects/libcxxabi"
mkdir "${WORKSPACE}/llvm/build"
cd "${WORKSPACE}/llvm/build"
# NOTE You must build LLVM with the same ABI as ClickHouse.
# For example, if you compile ClickHouse with libc++, you must add
# -DLLVM_ENABLE_LIBCXX=1
# to the line below.
cmake -DCMAKE_BUILD_TYPE:STRING=Release ../llvm
make -j $THREADS
$SUDO make install
hash clang
cd ../../..
export CC=clang
export CXX=clang++

8
ci/build-debian-packages.sh Executable file
View File

@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -e -x
source default-config
[[ -d "${WORKSPACE}/sources" ]] || die "Run get-sources.sh first"
./sources/release

47
ci/build-gcc-from-sources.sh Executable file
View File

@ -0,0 +1,47 @@
#!/usr/bin/env bash
set -e -x
source default-config
./install-os-packages.sh curl
if [[ "${GCC_SOURCES_VERSION}" == "latest" ]]; then
GCC_SOURCES_VERSION=$(curl -sSL https://ftpmirror.gnu.org/gcc/ | grep -oE 'gcc-[0-9]+(\.[0-9]+)+' | sort -Vr | head -n1)
fi
GCC_VERSION_SHORT=$(echo "$GCC_SOURCES_VERSION" | grep -oE '[0-9]' | head -n1)
echo "Will download ${GCC_SOURCES_VERSION} (short version: $GCC_VERSION_SHORT)."
THREADS=$(grep -c ^processor /proc/cpuinfo)
mkdir "${WORKSPACE}/gcc"
pushd "${WORKSPACE}/gcc"
wget https://ftpmirror.gnu.org/gcc/${GCC_SOURCES_VERSION}/${GCC_SOURCES_VERSION}.tar.xz
tar xf ${GCC_SOURCES_VERSION}.tar.xz
pushd ${GCC_SOURCES_VERSION}
./contrib/download_prerequisites
popd
mkdir gcc-build
pushd gcc-build
../${GCC_SOURCES_VERSION}/configure --enable-languages=c,c++ --disable-multilib
make -j $THREADS
$SUDO make install
popd
popd
$SUDO ln -sf /usr/local/bin/gcc /usr/local/bin/gcc-${GCC_GCC_SOURCES_VERSION_SHORT}
$SUDO ln -sf /usr/local/bin/g++ /usr/local/bin/g++-${GCC_GCC_SOURCES_VERSION_SHORT}
$SUDO ln -sf /usr/local/bin/gcc /usr/local/bin/cc
$SUDO ln -sf /usr/local/bin/g++ /usr/local/bin/c++
echo '/usr/local/lib64' | $SUDO tee /etc/ld.so.conf.d/10_local-lib64.conf
$SUDO ldconfig
hash gcc g++
gcc --version
export CC=gcc
export CXX=g++

22
ci/build-normal.sh Executable file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env bash
set -e -x
source default-config
[[ -d "${WORKSPACE}/sources" ]] || die "Run get-sources.sh first"
mkdir -p "${WORKSPACE}/build"
pushd "${WORKSPACE}/build"
if [[ "${ENABLE_EMBEDDED_COMPILER}" == 1 ]]; then
[[ "$USE_LLVM_LIBRARIES_FROM_SYSTEM" == 0 ]] && CMAKE_FLAGS="$CMAKE_FLAGS -DUSE_INTERNAL_LLVM_LIBRARY=1"
[[ "$USE_LLVM_LIBRARIES_FROM_SYSTEM" != 0 ]] && CMAKE_FLAGS="$CMAKE_FLAGS -DUSE_INTERNAL_LLVM_LIBRARY=0"
fi
cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DENABLE_EMBEDDED_COMPILER=${ENABLE_EMBEDDED_COMPILER} $CMAKE_FLAGS ../sources
[[ "$BUILD_TARGETS" != 'all' ]] && BUILD_TARGETS_STRING="--target $BUILD_TARGETS"
cmake --build . $BUILD_TARGETS_STRING -- -j $THREADS
popd

7
ci/check-docker.sh Executable file
View File

@ -0,0 +1,7 @@
#!/usr/bin/env bash
set -e -x
source default-config
command -v docker > /dev/null || die "You need to install Docker"
docker ps > /dev/null || die "You need to have access to Docker: run '$SUDO usermod -aG docker $USER' and relogin"

20
ci/check-syntax.sh Executable file
View File

@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -e -x
source default-config
./install-os-packages.sh jq
[[ -d "${WORKSPACE}/sources" ]] || die "Run get-sources.sh first"
mkdir -p "${WORKSPACE}/build"
pushd "${WORKSPACE}/build"
cmake -DCMAKE_BUILD_TYPE=Debug $CMAKE_FLAGS ../sources
make -j $THREADS re2_st # Generated headers
jq --raw-output '.[] | .command' compile_commands.json | grep -v -P -- '-c .+/contrib/' | sed -r -e 's/-o\s+\S+/-fsyntax-only/' > syntax-commands
xargs --arg-file=syntax-commands --max-procs=$THREADS --replace /bin/sh -c "{}"
popd

10
ci/create-sources-tarball.sh Executable file
View File

@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -e -x
source default-config
if [[ -d "${WORKSPACE}/sources" ]]; then
tar -c -z -f "${WORKSPACE}/sources.tar.gz" --directory "${WORKSPACE}/sources" .
else
die "Run get-sources first"
fi

65
ci/default-config Normal file
View File

@ -0,0 +1,65 @@
#!/usr/bin/env bash
set -e -x
if [[ -z "$INITIALIZED" ]]; then
INITIALIZED=1
SCRIPTPATH=$(pwd)
WORKSPACE=${SCRIPTPATH}/workspace
PROJECT_ROOT=$(cd $SCRIPTPATH/.. && pwd)
# Almost all scripts take no arguments. Arguments should be in config.
# get-sources
SOURCES_METHOD=local # clone, local, tarball
SOURCES_CLONE_URL="https://github.com/yandex/ClickHouse.git"
SOURCES_BRANCH="master"
SOURCES_COMMIT=HEAD # do checkout of this commit after clone
# prepare-toolchain
COMPILER=gcc # gcc, clang
COMPILER_INSTALL_METHOD=packages # packages, sources
COMPILER_PACKAGE_VERSION=7 # or 6.0 for clang
# install-compiler-from-sources
CLANG_SOURCES_BRANCH=trunk # or tags/RELEASE_600/final
GCC_SOURCES_VERSION=latest # or gcc-7.1.0
# install-libraries
USE_LLVM_LIBRARIES_FROM_SYSTEM=0 # 0 or 1
ENABLE_EMBEDDED_COMPILER=1
# build
BUILD_METHOD=normal # normal, debian
BUILD_TARGETS=clickhouse # tagtet name, all; only for "normal"
BUILD_TYPE=RelWithDebInfo # RelWithDebInfo, Debug, ASan, TSan
CMAKE_FLAGS=""
# prepare-docker-image-ubuntu
DOCKER_UBUNTU_VERSION=bionic
DOCKER_UBUNTU_ARCH=arm64 # How the architecture is named in a tarball at https://partner-images.canonical.com/core/
DOCKER_UBUNTU_QUEMU_ARCH=aarch64 # How the architecture is named in QEMU
DOCKER_UBUNTU_TAG_ARCH=arm64 # How the architecture is named in Docker
DOCKER_UBUNTU_QEMU_VER=v2.9.1
DOCKER_UBUNTU_REPO=multiarch/ubuntu-core
THREADS=$(grep -c ^processor /proc/cpuinfo || nproc || sysctl -a | grep -F 'hw.ncpu' | grep -oE '[0-9]+')
# All scripts should return 0 in case of success, 1 in case of permanent error,
# 2 in case of temporary error, any other code in case of permanent error.
function die {
echo ${1:-Error}
exit ${2:1}
}
[[ $EUID -ne 0 ]] && SUDO=sudo
./install-os-packages.sh prepare
# Configuration parameters may be overriden with CONFIG environment variable pointing to config file.
[[ -n "$CONFIG" ]] && source $CONFIG
mkdir -p $WORKSPACE
fi

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Multiarch
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.

View File

@ -0,0 +1,53 @@
Source: https://github.com/multiarch/ubuntu-core
Commit: 3972a7794b40a965615abd710759d3ed439c9a55
# :earth_africa: ubuntu-core
![](https://raw.githubusercontent.com/multiarch/dockerfile/master/logo.jpg)
Multiarch Ubuntu images for Docker.
Based on https://github.com/tianon/docker-brew-ubuntu-core/
* `multiarch/ubuntu-core` on [Docker Hub](https://hub.docker.com/r/multiarch/ubuntu-core/)
* [Available tags](https://hub.docker.com/r/multiarch/ubuntu-core/tags/)
## Usage
Once you need to configure binfmt-support on your Docker host.
This works locally or remotely (i.e using boot2docker or swarm).
```console
# configure binfmt-support on the Docker host (works locally or remotely, i.e: using boot2docker)
$ docker run --rm --privileged multiarch/qemu-user-static:register --reset
```
Then you can run an `armhf` image from your `x86_64` Docker host.
```console
$ docker run -it --rm multiarch/ubuntu-core:armhf-wily
root@a0818570f614:/# uname -a
Linux a0818570f614 4.1.13-boot2docker #1 SMP Fri Nov 20 19:05:50 UTC 2015 armv7l armv7l armv7l GNU/Linux
root@a0818570f614:/# exit
```
Or an `x86_64` image from your `x86_64` Docker host, directly, without qemu emulation.
```console
$ docker run -it --rm multiarch/ubuntu-core:amd64-wily
root@27fe384370c9:/# uname -a
Linux 27fe384370c9 4.1.13-boot2docker #1 SMP Fri Nov 20 19:05:50 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
root@27fe384370c9:/#
```
It also works for `arm64`
```console
$ docker run -it --rm multiarch/ubuntu-core:arm64-wily
root@723fb9f184fa:/# uname -a
Linux 723fb9f184fa 4.1.13-boot2docker #1 SMP Fri Nov 20 19:05:50 UTC 2015 aarch64 aarch64 aarch64 GNU/Linux
```
## License
MIT

96
ci/docker-multiarch/update.sh Executable file
View File

@ -0,0 +1,96 @@
#!/usr/bin/env bash
set -e -x
# A POSIX variable
OPTIND=1 # Reset in case getopts has been used previously in the shell.
while getopts "a:v:q:u:d:t:" opt; do
case "$opt" in
a) ARCH=$OPTARG
;;
v) VERSION=$OPTARG
;;
q) QEMU_ARCH=$OPTARG
;;
u) QEMU_VER=$OPTARG
;;
d) DOCKER_REPO=$OPTARG
;;
t) TAG_ARCH=$OPTARG
;;
esac
done
thisTarBase="ubuntu-$VERSION-core-cloudimg-$ARCH"
thisTar="$thisTarBase-root.tar.gz"
baseUrl="https://partner-images.canonical.com/core/$VERSION"
# install qemu-user-static
if [ -n "${QEMU_ARCH}" ]; then
if [ ! -f x86_64_qemu-${QEMU_ARCH}-static.tar.gz ]; then
wget -N https://github.com/multiarch/qemu-user-static/releases/download/${QEMU_VER}/x86_64_qemu-${QEMU_ARCH}-static.tar.gz
fi
tar -xvf x86_64_qemu-${QEMU_ARCH}-static.tar.gz -C $ROOTFS/usr/bin/
fi
# get the image
if \
wget -q --spider "$baseUrl/current" \
&& wget -q --spider "$baseUrl/current/$thisTar" \
; then
baseUrl+='/current'
fi
wget -qN "$baseUrl/"{{MD5,SHA{1,256}}SUMS{,.gpg},"$thisTarBase.manifest",'unpacked/build-info.txt'} || true
wget -N "$baseUrl/$thisTar"
# check checksum
if [ -f SHA256SUMS ]; then
sha256sum="$(sha256sum "$thisTar" | cut -d' ' -f1)"
if ! grep -q "$sha256sum" SHA256SUMS; then
echo >&2 "error: '$thisTar' has invalid SHA256"
exit 1
fi
fi
cat > Dockerfile <<-EOF
FROM scratch
ADD $thisTar /
ENV ARCH=${ARCH} UBUNTU_SUITE=${VERSION} DOCKER_REPO=${DOCKER_REPO}
EOF
# add qemu-user-static binary
if [ -n "${QEMU_ARCH}" ]; then
cat >> Dockerfile <<EOF
# Add qemu-user-static binary for amd64 builders
ADD x86_64_qemu-${QEMU_ARCH}-static.tar.gz /usr/bin
EOF
fi
cat >> Dockerfile <<-EOF
# a few minor docker-specific tweaks
# see https://github.com/docker/docker/blob/master/contrib/mkimage/debootstrap
RUN echo '#!/bin/sh' > /usr/sbin/policy-rc.d \\
&& echo 'exit 101' >> /usr/sbin/policy-rc.d \\
&& chmod +x /usr/sbin/policy-rc.d \\
&& dpkg-divert --local --rename --add /sbin/initctl \\
&& cp -a /usr/sbin/policy-rc.d /sbin/initctl \\
&& sed -i 's/^exit.*/exit 0/' /sbin/initctl \\
&& echo 'force-unsafe-io' > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup \\
&& echo 'DPkg::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' > /etc/apt/apt.conf.d/docker-clean \\
&& echo 'APT::Update::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' >> /etc/apt/apt.conf.d/docker-clean \\
&& echo 'Dir::Cache::pkgcache ""; Dir::Cache::srcpkgcache "";' >> /etc/apt/apt.conf.d/docker-clean \\
&& echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/docker-no-languages \\
&& echo 'Acquire::GzipIndexes "true"; Acquire::CompressionTypes::Order:: "gz";' > /etc/apt/apt.conf.d/docker-gzip-indexes
# enable the universe
RUN sed -i 's/^#\s*\(deb.*universe\)$/\1/g' /etc/apt/sources.list
# overwrite this with 'CMD []' in a dependent Dockerfile
CMD ["/bin/bash"]
EOF
docker build -t "${DOCKER_REPO}:${TAG_ARCH}-${VERSION}" .
docker run --rm "${DOCKER_REPO}:${TAG_ARCH}-${VERSION}" /bin/bash -ec "echo Hello from Ubuntu!"

18
ci/get-sources.sh Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env bash
set -e -x
source default-config
if [[ "$SOURCES_METHOD" == "clone" ]]; then
./install-os-packages.sh git
SOURCES_DIR="${WORKSPACE}/sources"
mkdir -p "${SOURCES_DIR}"
git clone --recursive --branch "$SOURCES_BRANCH" "$SOURCES_CLONE_URL" "${SOURCES_DIR}"
pushd "${SOURCES_DIR}"
git checkout --recurse-submodules "$SOURCES_COMMIT"
popd
elif [[ "$SOURCES_METHOD" == "local" ]]; then
ln -f -s "${PROJECT_ROOT}" "${WORKSPACE}/sources"
else
die "Unknown SOURCES_METHOD"
fi

View File

@ -0,0 +1,22 @@
#!/usr/bin/env bash
set -e -x
source default-config
# TODO Install from PPA on older Ubuntu
./install-os-packages.sh ${COMPILER}-${COMPILER_PACKAGE_VERSION}
if [[ "$COMPILER" == "gcc" ]]; then
if command -v gcc-${COMPILER_PACKAGE_VERSION}; then export CC=gcc-${COMPILER_PACKAGE_VERSION} CXX=g++-${COMPILER_PACKAGE_VERSION};
elif command -v gcc${COMPILER_PACKAGE_VERSION}; then export CC=gcc${COMPILER_PACKAGE_VERSION} CXX=g++${COMPILER_PACKAGE_VERSION};
elif command -v gcc; then export CC=gcc CXX=g++;
fi
elif [[ "$COMPILER" == "clang" ]]; then
if command -v clang-${COMPILER_PACKAGE_VERSION}; then export CC=clang-${COMPILER_PACKAGE_VERSION} CXX=clang++-${COMPILER_PACKAGE_VERSION};
elif command -v clang${COMPILER_PACKAGE_VERSION}; then export CC=clang${COMPILER_PACKAGE_VERSION} CXX=clang++${COMPILER_PACKAGE_VERSION};
elif command -v clang; then export CC=clang CXX=clang++;
fi
else
die "Unknown compiler specified"
fi

View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -e -x
source default-config
if [[ "$COMPILER" == "gcc" ]]; then
. build-gcc-from-sources.sh
elif [[ "$COMPILER" == "clang" ]]; then
. build-clang-from-sources.sh
else
die "Unknown COMPILER"
fi

14
ci/install-libraries.sh Executable file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -e -x
source default-config
./install-os-packages.sh libssl-dev
./install-os-packages.sh libicu-dev
./install-os-packages.sh libreadline-dev
./install-os-packages.sh libmariadbclient-dev
./install-os-packages.sh libunixodbc-dev
if [[ "$ENABLE_EMBEDDED_COMPILER" == 1 && "$USE_LLVM_LIBRARIES_FROM_SYSTEM" == 1 ]]; then
./install-os-packages.sh llvm-libs-5.0
fi

120
ci/install-os-packages.sh Executable file
View File

@ -0,0 +1,120 @@
#!/usr/bin/env bash
set -e -x
# Dispatches package installation on various OS and distributives
WHAT=$1
[[ $EUID -ne 0 ]] && SUDO=sudo
command -v apt-get && PACKAGE_MANAGER=apt
command -v yum && PACKAGE_MANAGER=yum
command -v pkg && PACKAGE_MANAGER=pkg
case $PACKAGE_MANAGER in
apt)
case $WHAT in
prepare)
$SUDO apt-get update
;;
svn)
$SUDO apt-get install -y subversion
;;
gcc*)
$SUDO apt-get install -y $WHAT ${WHAT/cc/++}
;;
clang*)
$SUDO apt-get install -y $WHAT libc++-dev libc++abi-dev
[[ $(uname -m) == "x86_64" ]] && $SUDO apt-get install -y ${WHAT/clang/lld} || true
;;
git)
$SUDO apt-get install -y git
;;
cmake)
$SUDO apt-get install -y cmake3 || $SUDO apt-get install -y cmake
;;
curl)
$SUDO apt-get install -y curl
;;
jq)
$SUDO apt-get install -y jq
;;
libssl-dev)
$SUDO apt-get install -y libssl-dev
;;
libicu-dev)
$SUDO apt-get install -y libicu-dev
;;
libreadline-dev)
$SUDO apt-get install -y libreadline-dev
;;
libunixodbc-dev)
$SUDO apt-get install -y unixodbc-dev
;;
libmariadbclient-dev)
$SUDO apt-get install -y libmariadbclient-dev
;;
llvm-libs*)
$SUDO apt-get install -y ${WHAT/llvm-libs/liblld}-dev ${WHAT/llvm-libs/libclang}-dev
;;
qemu-user-static)
$SUDO apt-get install -y qemu-user-static
;;
vagrant-virtualbox)
$SUDO apt-get install -y vagrant virtualbox
;;
*)
echo "Unknown package"; exit 1;
;;
esac
;;
pkg)
case $WHAT in
prepare)
;;
svn)
$SUDO pkg install -y subversion
;;
gcc*)
$SUDO pkg install -y ${WHAT/-/}
;;
clang*)
$SUDO pkg install -y clang-devel
;;
git)
$SUDO pkg install -y git
;;
cmake)
$SUDO pkg install -y cmake
;;
curl)
$SUDO pkg install -y curl
;;
jq)
$SUDO pkg install -y jq
;;
libssl-dev)
$SUDO pkg install -y openssl
;;
libicu-dev)
$SUDO pkg install -y icu
;;
libreadline-dev)
$SUDO pkg install -y readline
;;
libunixodbc-dev)
$SUDO pkg install -y unixODBC libltdl
;;
libmariadbclient-dev)
$SUDO pkg install -y mariadb102-client
;;
*)
echo "Unknown package"; exit 1;
;;
esac
;;
*)
echo "Unknown distributive"; exit 1;
;;
esac

View File

@ -0,0 +1,5 @@
## Build with debug mode and without many libraries
This job is intended as first check that build is not broken on wide variety of platforms.
Results of this build are not intended for production usage.

31
ci/jobs/quick-build/run.sh Executable file
View File

@ -0,0 +1,31 @@
#!/usr/bin/env bash
set -e -x
# How to run:
# From "ci" directory:
# jobs/quick-build/run.sh
# or:
# ./run-with-docker.sh ubuntu:bionic jobs/quick-build/run.sh
cd "$(dirname $0)"/../..
. default-config
SOURCES_METHOD=local
COMPILER=clang
COMPILER_INSTALL_METHOD=packages
COMPILER_PACKAGE_VERSION=6.0
USE_LLVM_LIBRARIES_FROM_SYSTEM=0
BUILD_METHOD=normal
BUILD_TARGETS=clickhouse
BUILD_TYPE=Debug
ENABLE_EMBEDDED_COMPILER=0
CMAKE_FLAGS="-D CMAKE_C_FLAGS_ADD=-g0 -D CMAKE_CXX_FLAGS_ADD=-g0 -D ENABLE_TCMALLOC=0 -D ENABLE_CAPNP=0 -D ENABLE_RDKAFKA=0 -D ENABLE_UNWIND=0 -D ENABLE_ICU=0 -D ENABLE_POCO_MONGODB=0 -D ENABLE_POCO_NETSSL=0 -D ENABLE_POCO_ODBC=0 -D ENABLE_MYSQL=0"
[[ $(uname) == "FreeBSD" ]] && COMPILER_PACKAGE_VERSION=devel && export COMPILER_PATH=/usr/local/bin
. get-sources.sh
. prepare-toolchain.sh
. install-libraries.sh
. build-normal.sh

View File

@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -e -x
source default-config
./check-docker.sh
# http://fl47l1n3.net/2015/12/24/binfmt/
./install-os-packages.sh qemu-user-static
pushd docker-multiarch
$SUDO ./update.sh \
-a "$DOCKER_UBUNTU_ARCH" \
-v "$DOCKER_UBUNTU_VERSION" \
-q "$DOCKER_UBUNTU_QUEMU_ARCH" \
-u "$DOCKER_UBUNTU_QEMU_VER" \
-d "$DOCKER_UBUNTU_REPO" \
-t "$DOCKER_UBUNTU_TAG_ARCH"
docker run --rm --privileged multiarch/qemu-user-static:register
popd

14
ci/prepare-toolchain.sh Executable file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -e -x
source default-config
./install-os-packages.sh cmake
if [[ "$COMPILER_INSTALL_METHOD" == "packages" ]]; then
. install-compiler-from-packages.sh
elif [[ "$COMPILER_INSTALL_METHOD" == "sources" ]]; then
. install-compiler-from-sources.sh
else
die "Unknown COMPILER_INSTALL_METHOD"
fi

View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -e -x
source default-config
./install-os-packages.sh vagrant-virtualbox
pushd "vagrant-freebsd"
vagrant up
vagrant ssh-config > vagrant-ssh
ssh -F vagrant-ssh default 'uname -a'
popd

View File

@ -0,0 +1,18 @@
#!/usr/bin/env bash
set -e -x
# Usage example:
# ./run-with-docker.sh centos:centos6 ./run-clickhouse-from-binaries.sh
source default-config
SERVER_BIN="${WORKSPACE}/build/dbms/src/Server/clickhouse"
SERVER_CONF="${WORKSPACE}/sources/dbms/src/Server/config.xml"
SERVER_DATADIR="${WORKSPACE}/clickhouse"
[[ -x "$SERVER_BIN" ]] || die "Run build-normal.sh first"
[[ -r "$SERVER_CONF" ]] || die "Run get-sources.sh first"
mkdir -p "${SERVER_DATADIR}"
$SERVER_BIN server --config-file "$SERVER_CONF" --pid-file="${WORKSPACE}/clickhouse.pid" -- --path "$SERVER_DATADIR"

9
ci/run-with-docker.sh Executable file
View File

@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -e -x
mkdir -p /var/cache/ccache
DOCKER_ENV+=" --mount=type=bind,source=/var/cache/ccache,destination=/ccache -e CCACHE_DIR=/ccache "
PROJECT_ROOT="$(cd "$(dirname "$0")/.."; pwd -P)"
[[ -n "$CONFIG" ]] && DOCKER_ENV="--env=CONFIG"
docker run -t --network=host --mount=type=bind,source=${PROJECT_ROOT},destination=/ClickHouse --workdir=/ClickHouse/ci $DOCKER_ENV "$1" "$2"

14
ci/run-with-vagrant.sh Executable file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -e -x
[[ -r "vagrant-${1}/vagrant-ssh" ]] || die "Run prepare-vagrant-image-... first."
pushd vagrant-$1
shopt -s extglob
vagrant ssh -c "mkdir -p ClickHouse"
scp -q -F vagrant-ssh -r ../../!(*build*) default:~/ClickHouse
vagrant ssh -c "cd ClickHouse/ci; $2"
popd

1
ci/vagrant-freebsd/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.vagrant

3
ci/vagrant-freebsd/Vagrantfile vendored Normal file
View File

@ -0,0 +1,3 @@
Vagrant.configure("2") do |config|
config.vm.box = "generic/freebsd11"
end

View File

@ -51,6 +51,7 @@
set(Poco_HINTS
/usr/local
/usr/local/include/Poco
C:/AppliedInformatics
${Poco_DIR}
$ENV{Poco_DIR}
@ -230,5 +231,3 @@ if(${Poco_OSP_FOUND})
endif()
message(STATUS "Found Poco: ${Poco_LIBRARIES}")

33
cmake/arch.cmake Normal file
View File

@ -0,0 +1,33 @@
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*)")
set (ARCH_AARCH64 1)
endif ()
if (ARCH_AARCH64 OR CMAKE_SYSTEM_PROCESSOR MATCHES "arm")
set (ARCH_ARM 1)
endif ()
if (CMAKE_LIBRARY_ARCHITECTURE MATCHES "i386")
set (ARCH_I386 1)
endif ()
if ( ( ARCH_ARM AND NOT ARCH_AARCH64 ) OR ARCH_I386)
set (ARCH_32 1)
message (WARNING "Support for 32bit platforms is highly experimental")
endif ()
if (CMAKE_SYSTEM MATCHES "Linux")
set (ARCH_LINUX 1)
endif ()
if (CMAKE_SYSTEM MATCHES "FreeBSD")
set (ARCH_FREEBSD 1)
endif ()
if (NOT MSVC)
set (NOT_MSVC 1)
endif ()
if (NOT APPLE)
set (NOT_APPLE 1)
endif ()
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set (COMPILER_GCC 1)
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set (COMPILER_CLANG 1)
endif ()

View File

@ -1,13 +1,10 @@
function(generate_function_register FUNCTION_AREA)
foreach(FUNCTION IN LISTS ARGN)
configure_file (registerFunction.h.in register${FUNCTION}.h)
configure_file (registerFunction.cpp.in register${FUNCTION}.cpp)
set(REGISTER_HEADERS "${REGISTER_HEADERS} #include \"register${FUNCTION}.h\"\n")
set(REGISTER_FUNCTIONS "${REGISTER_FUNCTIONS} register${FUNCTION}(factory);\n")
foreach(FUNCTION IN LISTS ARGN)
configure_file (registerFunction.h.in register${FUNCTION}.h)
configure_file (registerFunction.cpp.in register${FUNCTION}.cpp)
set(REGISTER_HEADERS "${REGISTER_HEADERS}#include \"register${FUNCTION}.h\"\n")
set(REGISTER_FUNCTIONS "${REGISTER_FUNCTIONS} register${FUNCTION}(factory);\n")
endforeach()
configure_file (registerFunctions_area.cpp.in registerFunctions${FUNCTION_AREA}.cpp)
endfunction()

View File

@ -1,5 +1,11 @@
option (USE_INTERNAL_BOOST_LIBRARY "Set to FALSE to use system boost library instead of bundled" ${NOT_UNBUNDLED})
# Test random file existing in all package variants
if (USE_INTERNAL_BOOST_LIBRARY AND NOT EXISTS "${ClickHouse_SOURCE_DIR}/contrib/boost/libs/system/src/error_code.cpp")
message (WARNING "submodules in contrib/boost is missing. to fix try run: \n git submodule update --init --recursive")
set (USE_INTERNAL_BOOST_LIBRARY 0)
endif ()
if (NOT USE_INTERNAL_BOOST_LIBRARY)
set (Boost_USE_STATIC_LIBS ${USE_STATIC_LIBRARIES})
set (BOOST_ROOT "/usr/local")
@ -10,7 +16,7 @@ if (NOT USE_INTERNAL_BOOST_LIBRARY)
# set (BOOST_PATHS "")
# find_library (Boost_PROGRAM_OPTIONS_LIBRARY boost_program_options PATHS ${BOOST_PATHS})
# find_library (Boost_SYSTEM_LIBRARY boost_system PATHS ${BOOST_PATHS})
# find_library (Boost_FILESYSTEM_LIBRARY boost_filesystem PATHS ${BOOST_PATHS})
# find_library (Boost_FILESYSTEM_LIBRARY boost_filesystem PATHS ${BOOST_PATHS})
# maybe found but incorrect version.
set (Boost_INCLUDE_DIRS "")
set (Boost_SYSTEM_LIBRARY "")
@ -23,7 +29,19 @@ if (NOT Boost_SYSTEM_LIBRARY)
set (Boost_PROGRAM_OPTIONS_LIBRARY boost_program_options_internal)
set (Boost_SYSTEM_LIBRARY boost_system_internal)
set (Boost_FILESYSTEM_LIBRARY boost_filesystem_internal)
set (Boost_INCLUDE_DIRS "${ClickHouse_SOURCE_DIR}/contrib/libboost/boost_1_65_0/")
set (Boost_INCLUDE_DIRS)
# For boost from github:
file (GLOB Boost_INCLUDE_DIRS_ "${ClickHouse_SOURCE_DIR}/contrib/boost/libs/*/include")
list (APPEND Boost_INCLUDE_DIRS ${Boost_INCLUDE_DIRS_})
# numeric has additional level
file (GLOB Boost_INCLUDE_DIRS_ "${ClickHouse_SOURCE_DIR}/contrib/boost/libs/numeric/*/include")
list (APPEND Boost_INCLUDE_DIRS ${Boost_INCLUDE_DIRS_})
# For packaged version:
list (APPEND Boost_INCLUDE_DIRS "${ClickHouse_SOURCE_DIR}/contrib/boost")
endif ()
message (STATUS "Using Boost: ${Boost_INCLUDE_DIRS} : ${Boost_PROGRAM_OPTIONS_LIBRARY},${Boost_SYSTEM_LIBRARY},${Boost_FILESYSTEM_LIBRARY}")

View File

@ -1,4 +1,4 @@
option (ENABLE_CAPNP "Enable Cap'n Proto" ON)
option (ENABLE_CAPNP "Enable Cap'n Proto" ${NOT_MSVC})
if (ENABLE_CAPNP)

View File

@ -1,6 +1,9 @@
if (ARCH_FREEBSD)
find_library (EXECINFO_LIBRARY execinfo)
find_library (ELF_LIBRARY elf)
message (STATUS "Using execinfo: ${EXECINFO_LIBRARY}")
message (STATUS "Using elf: ${ELF_LIBRARY}")
else ()
set (EXECINFO_LIBRARY "")
set (ELF_LIBRARY "")
endif ()

View File

@ -1,100 +1,57 @@
option (USE_EMBEDDED_COMPILER "Set to TRUE to enable support for 'compile' option for query execution" FALSE)
option (ENABLE_EMBEDDED_COMPILER "Set to TRUE to enable support for 'compile' option for query execution" 1)
option (USE_INTERNAL_LLVM_LIBRARY "Use bundled or system LLVM library. Default: system library for quicker developer builds." ${APPLE})
if (USE_EMBEDDED_COMPILER)
# Based on source code of YT.
# Authors: Ivan Puzyrevskiy, Alexey Lukyanchikov, Ruslan Savchenko.
if (ENABLE_EMBEDDED_COMPILER)
if (USE_INTERNAL_LLVM_LIBRARY AND NOT EXISTS "${ClickHouse_SOURCE_DIR}/contrib/llvm/llvm/CMakeLists.txt")
message (WARNING "submodule contrib/llvm is missing. to fix try run: \n git submodule update --init --recursive")
set (USE_INTERNAL_LLVM_LIBRARY 0)
endif ()
# Find LLVM includes and libraries.
#
# LLVM_VERSION - LLVM version.
# LLVM_INCLUDE_DIRS - Directory containing LLVM headers.
# LLVM_LIBRARY_DIRS - Directory containing LLVM libraries.
# LLVM_CXXFLAGS - C++ compiler flags for files that include LLVM headers.
# LLVM_FOUND - True if LLVM was found.
if (NOT USE_INTERNAL_LLVM_LIBRARY)
set (LLVM_PATHS "/usr/local/lib/llvm")
# llvm_map_components_to_libraries - Maps LLVM used components to required libraries.
# Usage: llvm_map_components_to_libraries(REQUIRED_LLVM_LIBRARIES core jit interpreter native ...)
if (LLVM_VERSION)
find_package(LLVM ${LLVM_VERSION} CONFIG PATHS ${LLVM_PATHS})
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
find_package(LLVM ${CMAKE_CXX_COMPILER_VERSION} CONFIG PATHS ${LLVM_PATHS})
else ()
find_package (LLVM 6 CONFIG PATHS ${LLVM_PATHS})
if (NOT LLVM_FOUND)
find_package (LLVM 5 CONFIG PATHS ${LLVM_PATHS})
endif ()
if (NOT LLVM_FOUND)
find_package (LLVM 7 CONFIG PATHS ${LLVM_PATHS})
endif ()
endif ()
if (ARCH_FREEBSD)
set(LLVM_VERSION_POSTFIX "50" CACHE INTERNAL "")
if (LLVM_FOUND)
# Remove dynamically-linked zlib and libedit from LLVM's dependencies:
set_target_properties(LLVMSupport PROPERTIES INTERFACE_LINK_LIBRARIES "-lpthread;LLVMDemangle")
set_target_properties(LLVMLineEditor PROPERTIES INTERFACE_LINK_LIBRARIES "LLVMSupport")
option(LLVM_HAS_RTTI "Enable if LLVM was build with RTTI enabled" ON)
set (USE_EMBEDDED_COMPILER 1)
endif()
else()
set(LLVM_VERSION_POSTFIX "-5.0" CACHE INTERNAL "")
set (LLVM_FOUND 1)
set (USE_EMBEDDED_COMPILER 1)
set (LLVM_VERSION "7.0.0bundled")
set (LLVM_INCLUDE_DIRS
${ClickHouse_SOURCE_DIR}/contrib/llvm/llvm/include
${ClickHouse_BINARY_DIR}/contrib/llvm/llvm/include
${ClickHouse_SOURCE_DIR}/contrib/llvm/clang/include
${ClickHouse_BINARY_DIR}/contrib/llvm/clang/include
${ClickHouse_BINARY_DIR}/contrib/llvm/llvm/tools/clang/include
${ClickHouse_SOURCE_DIR}/contrib/llvm/lld/include
${ClickHouse_BINARY_DIR}/contrib/llvm/lld/include
${ClickHouse_BINARY_DIR}/contrib/llvm/llvm/tools/lld/include)
set (LLVM_LIBRARY_DIRS ${ClickHouse_BINARY_DIR}/contrib/llvm/llvm)
endif()
find_program(LLVM_CONFIG_EXECUTABLE
NAMES llvm-config${LLVM_VERSION_POSTFIX} llvm-config llvm-config-devel
PATHS $ENV{LLVM_ROOT}/bin)
mark_as_advanced(LLVM_CONFIG_EXECUTABLE)
if(NOT LLVM_CONFIG_EXECUTABLE)
message(FATAL_ERROR "Cannot find LLVM (looking for `llvm-config`). Please, provide LLVM_ROOT environment variable.")
else()
set(LLVM_FOUND TRUE)
execute_process(
COMMAND ${LLVM_CONFIG_EXECUTABLE} --version
OUTPUT_VARIABLE LLVM_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(LLVM_VERSION VERSION_LESS "5")
message(FATAL_ERROR "LLVM 5+ is required. You have ${LLVM_VERSION} (${LLVM_CONFIG_EXECUTABLE})")
endif()
message(STATUS "LLVM config: ${LLVM_CONFIG_EXECUTABLE}; version: ${LLVM_VERSION}")
execute_process(
COMMAND ${LLVM_CONFIG_EXECUTABLE} --includedir
OUTPUT_VARIABLE LLVM_INCLUDE_DIRS
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(
COMMAND ${LLVM_CONFIG_EXECUTABLE} --libdir
OUTPUT_VARIABLE LLVM_LIBRARY_DIRS
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(
COMMAND ${LLVM_CONFIG_EXECUTABLE} --cxxflags
OUTPUT_VARIABLE LLVM_CXXFLAGS
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(
COMMAND ${LLVM_CONFIG_EXECUTABLE} --targets-built
OUTPUT_VARIABLE LLVM_TARGETS_BUILT
OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REPLACE " " ";" LLVM_TARGETS_BUILT "${LLVM_TARGETS_BUILT}")
if (USE_STATIC_LIBRARIES)
set (LLVM_CONFIG_ADD "--link-static")
endif()
# Get the link libs we need.
function(llvm_map_components_to_libraries RESULT)
execute_process(
COMMAND ${LLVM_CONFIG_EXECUTABLE} ${LLVM_CONFIG_ADD} --libs ${ARGN}
OUTPUT_VARIABLE _tmp
OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REPLACE " " ";" _libs_module "${_tmp}")
#message(STATUS "LLVM Libraries for '${ARGN}': ${_libs_module}")
execute_process(
COMMAND ${LLVM_CONFIG_EXECUTABLE} --system-libs ${ARGN}
OUTPUT_VARIABLE _libs_system
OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REPLACE "\n" " " _libs_system "${_libs_system}")
string(REPLACE " " " " _libs_system "${_libs_system}")
string(REPLACE " " ";" _libs_system "${_libs_system}")
set(${RESULT} ${_libs_module} ${_libs_system} PARENT_SCOPE)
endfunction(llvm_map_components_to_libraries)
message(STATUS "LLVM Include Directory: ${LLVM_INCLUDE_DIRS}")
message(STATUS "LLVM Library Directory: ${LLVM_LIBRARY_DIRS}")
message(STATUS "LLVM C++ Compiler: ${LLVM_CXXFLAGS}")
if (LLVM_FOUND)
message(STATUS "LLVM version: ${LLVM_PACKAGE_VERSION}")
message(STATUS "LLVM include Directory: ${LLVM_INCLUDE_DIRS}")
message(STATUS "LLVM library Directory: ${LLVM_LIBRARY_DIRS}")
message(STATUS "LLVM C++ compiler flags: ${LLVM_CXXFLAGS}")
endif()
endif()

View File

@ -1,23 +0,0 @@
set (OPENSSL_USE_STATIC_LIBS ${USE_STATIC_LIBRARIES})
if (APPLE)
set (OPENSSL_ROOT_DIR "/usr/local/opt/openssl")
# https://rt.openssl.org/Ticket/Display.html?user=guest&pass=guest&id=2232
if (USE_STATIC_LIBRARIES)
message(WARNING "Disable USE_STATIC_LIBRARIES if you have linking problems with OpenSSL on MacOS")
endif ()
endif ()
find_package (OpenSSL)
if (NOT OPENSSL_FOUND)
# Try to find manually.
set (OPENSSL_INCLUDE_PATHS "/usr/local/opt/openssl/include")
set (OPENSSL_PATHS "/usr/local/opt/openssl/lib")
find_path (OPENSSL_INCLUDE_DIR NAMES openssl/ssl.h PATHS ${OPENSSL_INCLUDE_PATHS})
find_library (OPENSSL_SSL_LIBRARY ssl PATHS ${OPENSSL_PATHS})
find_library (OPENSSL_CRYPTO_LIBRARY crypto PATHS ${OPENSSL_PATHS})
if (OPENSSL_SSL_LIBRARY AND OPENSSL_CRYPTO_LIBRARY AND OPENSSL_INCLUDE_DIR)
set (OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY})
set (OPENSSL_FOUND 1)
endif ()
endif ()
message (STATUS "Using openssl=${OPENSSL_FOUND}: ${OPENSSL_INCLUDE_DIR} : ${OPENSSL_LIBRARIES}")

View File

@ -8,8 +8,21 @@ if (NOT EXISTS "${ClickHouse_SOURCE_DIR}/contrib/poco/CMakeLists.txt")
set (MISSING_INTERNAL_POCO_LIBRARY 1)
endif ()
set (POCO_COMPONENTS Net XML SQL Data)
if (NOT DEFINED ENABLE_POCO_NETSSL OR ENABLE_POCO_NETSSL)
list (APPEND POCO_COMPONENTS Crypto NetSSL)
endif ()
if (NOT DEFINED ENABLE_POCO_MONGODB OR ENABLE_POCO_MONGODB)
list (APPEND POCO_COMPONENTS MongoDB)
endif ()
# TODO: after new poco release with SQL library rename ENABLE_POCO_ODBC -> ENABLE_POCO_SQLODBC
if (NOT DEFINED ENABLE_POCO_ODBC OR ENABLE_POCO_ODBC)
list (APPEND POCO_COMPONENTS DataODBC)
#list (APPEND POCO_COMPONENTS SQLODBC) # future
endif ()
if (NOT USE_INTERNAL_POCO_LIBRARY)
find_package (Poco COMPONENTS Net NetSSL XML Data Crypto DataODBC MongoDB)
find_package (Poco COMPONENTS ${POCO_COMPONENTS})
endif ()
if (Poco_INCLUDE_DIRS AND Poco_Foundation_LIBRARY)
@ -24,6 +37,15 @@ elseif (NOT MISSING_INTERNAL_POCO_LIBRARY)
set (ENABLE_DATA_SQLITE 0 CACHE BOOL "")
set (ENABLE_DATA_MYSQL 0 CACHE BOOL "")
set (ENABLE_DATA_POSTGRESQL 0 CACHE BOOL "")
# new after 2.0.0:
set (POCO_ENABLE_ZIP 0 CACHE BOOL "")
set (POCO_ENABLE_PAGECOMPILER 0 CACHE BOOL "")
set (POCO_ENABLE_PAGECOMPILER_FILE2PAGE 0 CACHE BOOL "")
set (POCO_ENABLE_REDIS 0 CACHE BOOL "")
set (POCO_ENABLE_SQL_SQLITE 0 CACHE BOOL "")
set (POCO_ENABLE_SQL_MYSQL 0 CACHE BOOL "")
set (POCO_ENABLE_SQL_POSTGRESQL 0 CACHE BOOL "")
set (POCO_UNBUNDLED 1 CACHE BOOL "")
set (POCO_UNBUNDLED_PCRE 0 CACHE BOOL "")
set (POCO_UNBUNDLED_EXPAT 0 CACHE BOOL "")
@ -37,39 +59,73 @@ elseif (NOT MISSING_INTERNAL_POCO_LIBRARY)
"${ClickHouse_SOURCE_DIR}/contrib/poco/Util/include/"
)
if (NOT DEFINED POCO_ENABLE_MONGODB OR POCO_ENABLE_MONGODB)
set (Poco_MongoDB_FOUND 1)
if (NOT DEFINED ENABLE_POCO_MONGODB OR ENABLE_POCO_MONGODB)
set (Poco_MongoDB_LIBRARY PocoMongoDB)
set (Poco_MongoDB_INCLUDE_DIRS "${ClickHouse_SOURCE_DIR}/contrib/poco/MongoDB/include/")
endif ()
if (ODBC_FOUND)
set (Poco_DataODBC_FOUND 1)
set (Poco_DataODBC_LIBRARY PocoDataODBC ${ODBC_LIBRARIES} ${LTDL_LIBRARY})
set (Poco_DataODBC_INCLUDE_DIRS "${ClickHouse_SOURCE_DIR}/contrib/poco/Data/ODBC/include/")
if (EXISTS "${ClickHouse_SOURCE_DIR}/contrib/poco/SQL/ODBC/include/")
set (Poco_SQL_FOUND 1)
set (Poco_SQL_LIBRARY PocoSQL)
set (Poco_SQL_INCLUDE_DIRS
"${ClickHouse_SOURCE_DIR}/contrib/poco/SQL/include"
"${ClickHouse_SOURCE_DIR}/contrib/poco/Data/include"
)
if ((NOT DEFINED ENABLE_POCO_ODBC OR ENABLE_POCO_ODBC) AND ODBC_FOUND)
set (Poco_SQLODBC_INCLUDE_DIRS
"${ClickHouse_SOURCE_DIR}/contrib/poco/SQL/ODBC/include/"
"${ClickHouse_SOURCE_DIR}/contrib/poco/Data/ODBC/include/"
${ODBC_INCLUDE_DIRECTORIES}
)
set (Poco_SQLODBC_LIBRARY PocoSQLODBC ${ODBC_LIBRARIES} ${LTDL_LIBRARY})
endif ()
else ()
set (Poco_Data_FOUND 1)
set (Poco_Data_INCLUDE_DIRS "${ClickHouse_SOURCE_DIR}/contrib/poco/Data/include")
set (Poco_Data_LIBRARY PocoData)
if ((NOT DEFINED ENABLE_POCO_ODBC OR ENABLE_POCO_ODBC) AND ODBC_FOUND)
set (USE_POCO_DATAODBC 1)
set (Poco_DataODBC_INCLUDE_DIRS
"${ClickHouse_SOURCE_DIR}/contrib/poco/Data/ODBC/include/"
${ODBC_INCLUDE_DIRECTORIES}
)
set (Poco_DataODBC_LIBRARY PocoDataODBC ${ODBC_LIBRARIES} ${LTDL_LIBRARY})
endif ()
endif ()
if (OPENSSL_FOUND)
set (Poco_NetSSL_FOUND 1)
# TODO! fix internal ssl
if (OPENSSL_FOUND AND NOT USE_INTERNAL_SSL_LIBRARY AND (NOT DEFINED ENABLE_POCO_NETSSL OR ENABLE_POCO_NETSSL))
set (Poco_NetSSL_LIBRARY PocoNetSSL)
set (Poco_Crypto_LIBRARY PocoCrypto)
endif ()
if (USE_STATIC_LIBRARIES AND USE_INTERNAL_ZLIB_LIBRARY)
list (APPEND Poco_INCLUDE_DIRS
"${ClickHouse_SOURCE_DIR}/contrib/zlib-ng/"
"${ClickHouse_BINARY_DIR}/contrib/zlib-ng/"
"${ClickHouse_SOURCE_DIR}/contrib/${INTERNAL_ZLIB_NAME}/"
"${ClickHouse_BINARY_DIR}/contrib/${INTERNAL_ZLIB_NAME}/"
)
endif ()
set (Poco_Foundation_LIBRARY PocoFoundation)
set (Poco_Util_LIBRARY PocoUtil)
set (Poco_Net_LIBRARY PocoNet)
set (Poco_Data_LIBRARY PocoData)
set (Poco_XML_LIBRARY PocoXML)
endif ()
message(STATUS "Using Poco: ${Poco_INCLUDE_DIRS} : ${Poco_Foundation_LIBRARY},${Poco_Util_LIBRARY},${Poco_Net_LIBRARY},${Poco_NetSSL_LIBRARY},${Poco_XML_LIBRARY},${Poco_Data_LIBRARY},${Poco_DataODBC_LIBRARY},${Poco_MongoDB_LIBRARY}; MongoDB=${Poco_MongoDB_FOUND}, DataODBC=${Poco_DataODBC_FOUND}, NetSSL=${Poco_NetSSL_FOUND}")
if (Poco_NetSSL_LIBRARY AND Poco_Crypto_LIBRARY)
set (USE_POCO_NETSSL 1)
endif ()
if (Poco_MongoDB_LIBRARY)
set (USE_POCO_MONGODB 1)
endif ()
if (Poco_DataODBC_LIBRARY)
set (USE_POCO_DATAODBC 1)
endif ()
if (Poco_SQLODBC_LIBRARY)
set (USE_POCO_SQLODBC 1)
endif ()
message(STATUS "Using Poco: ${Poco_INCLUDE_DIRS} : ${Poco_Foundation_LIBRARY},${Poco_Util_LIBRARY},${Poco_Net_LIBRARY},${Poco_NetSSL_LIBRARY},${Poco_Crypto_LIBRARY},${Poco_XML_LIBRARY},${Poco_Data_LIBRARY},${Poco_DataODBC_LIBRARY},${Poco_SQL_LIBRARY},${Poco_SQLODBC_LIBRARY},${Poco_MongoDB_LIBRARY}; MongoDB=${USE_POCO_MONGODB}, DataODBC=${USE_POCO_DATAODBC}, NetSSL=${USE_POCO_NETSSL}")
# How to make sutable poco:
# use branch:
@ -85,3 +141,5 @@ message(STATUS "Using Poco: ${Poco_INCLUDE_DIRS} : ${Poco_Foundation_LIBRARY},${
# ClickHouse-Extras/clickhouse_warning
# ClickHouse-Extras/clickhouse-purge-logs-on-no-space
# ClickHouse-Extras/clickhouse_freebsd
# ClickHouse-Extras/clikhouse_no_zlib
# ClickHouse-Extras/clickhouse-fix-atomic

View File

@ -1,4 +1,4 @@
option (ENABLE_RDKAFKA "Enable kafka" ON)
option (ENABLE_RDKAFKA "Enable kafka" ${NOT_MSVC})
if (ENABLE_RDKAFKA)
@ -24,6 +24,9 @@ if (RDKAFKA_LIB AND RDKAFKA_INCLUDE_DIR)
if (SASL2_LIBRARY)
list (APPEND RDKAFKA_LIBRARY ${SASL2_LIBRARY})
endif ()
if (LZ4_LIBRARY)
list (APPEND RDKAFKA_LIBRARY ${LZ4_LIBRARY})
endif ()
elseif (NOT MISSING_INTERNAL_RDKAFKA_LIBRARY)
set (USE_INTERNAL_RDKAFKA_LIBRARY 1)
set (RDKAFKA_INCLUDE_DIR "${ClickHouse_SOURCE_DIR}/contrib/librdkafka/src")

View File

@ -1,15 +1,10 @@
if (APPLE)
# lib from libs/libcommon
set (RT_LIBRARY "apple_rt")
else ()
elseif (ARCH_FREEBSD)
find_library (RT_LIBRARY rt)
else ()
set (RT_LIBRARY "")
endif ()
message(STATUS "Using rt: ${RT_LIBRARY}")
function (target_link_rt_by_force TARGET)
if (NOT APPLE)
set (FLAGS "-Wl,-no-as-needed -lrt -Wl,-as-needed")
set_property (TARGET ${TARGET} APPEND PROPERTY LINK_FLAGS "${FLAGS}")
endif ()
endfunction ()

44
cmake/find_ssl.cmake Normal file
View File

@ -0,0 +1,44 @@
option (USE_INTERNAL_SSL_LIBRARY "Set to FALSE to use system *ssl library instead of bundled" ${MSVC})
set (OPENSSL_USE_STATIC_LIBS ${USE_STATIC_LIBRARIES})
if (NOT USE_INTERNAL_SSL_LIBRARY)
if (APPLE)
set (OPENSSL_ROOT_DIR "/usr/local/opt/openssl")
# https://rt.openssl.org/Ticket/Display.html?user=guest&pass=guest&id=2232
if (USE_STATIC_LIBRARIES)
message(WARNING "Disable USE_STATIC_LIBRARIES if you have linking problems with OpenSSL on MacOS")
endif ()
endif ()
find_package (OpenSSL)
if (NOT OPENSSL_FOUND)
# Try to find manually.
set (OPENSSL_INCLUDE_PATHS "/usr/local/opt/openssl/include")
set (OPENSSL_PATHS "/usr/local/opt/openssl/lib")
find_path (OPENSSL_INCLUDE_DIR NAMES openssl/ssl.h PATHS ${OPENSSL_INCLUDE_PATHS})
find_library (OPENSSL_SSL_LIBRARY ssl PATHS ${OPENSSL_PATHS})
find_library (OPENSSL_CRYPTO_LIBRARY crypto PATHS ${OPENSSL_PATHS})
if (OPENSSL_SSL_LIBRARY AND OPENSSL_CRYPTO_LIBRARY AND OPENSSL_INCLUDE_DIR)
set (OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY})
set (OPENSSL_FOUND 1)
endif ()
endif ()
endif ()
if (NOT OPENSSL_FOUND)
set (USE_INTERNAL_SSL_LIBRARY 1)
set (OPENSSL_ROOT_DIR "${ClickHouse_SOURCE_DIR}/contrib/ssl")
set (OPENSSL_INCLUDE_DIR "${OPENSSL_ROOT_DIR}/include")
if (NOT USE_STATIC_LIBRARIES AND TARGET crypto-shared AND TARGET ssl-shared)
set (OPENSSL_CRYPTO_LIBRARY crypto-shared)
set (OPENSSL_SSL_LIBRARY ssl-shared)
else ()
set (OPENSSL_CRYPTO_LIBRARY crypto)
set (OPENSSL_SSL_LIBRARY ssl)
endif ()
set (OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY})
set (OPENSSL_FOUND 1)
endif ()
message (STATUS "Using ssl=${OPENSSL_FOUND}: ${OPENSSL_INCLUDE_DIR} : ${OPENSSL_LIBRARIES}")

5
cmake/find_termcap.cmake Normal file
View File

@ -0,0 +1,5 @@
find_library (TERMCAP_LIBRARY termcap)
if (NOT TERMCAP_LIBRARY)
find_library (TERMCAP_LIBRARY tinfo)
endif()
message (STATUS "Using termcap: ${TERMCAP_LIBRARY}")

View File

@ -5,6 +5,15 @@ if (NOT USE_INTERNAL_ZLIB_LIBRARY)
endif ()
if (NOT ZLIB_FOUND)
if (NOT MSVC)
set (INTERNAL_ZLIB_NAME "zlib-ng")
else ()
set (INTERNAL_ZLIB_NAME "zlib")
if (NOT EXISTS "${ClickHouse_SOURCE_DIR}/contrib/${INTERNAL_ZLIB_NAME}")
message (WARNING "Will use standard zlib, please clone manually:\n git clone https://github.com/madler/zlib.git ${ClickHouse_SOURCE_DIR}/contrib/${INTERNAL_ZLIB_NAME}")
endif ()
endif ()
set (USE_INTERNAL_ZLIB_LIBRARY 1)
set (ZLIB_COMPAT 1) # for zlib-ng, also enables WITH_GZFILEOP
set (WITH_NATIVE_INSTRUCTIONS ${ARCHNATIVE})
@ -15,7 +24,7 @@ if (NOT ZLIB_FOUND)
set(WITH_NEON 1 CACHE INTERNAL "")
set(WITH_ACLE 1 CACHE INTERNAL "")
endif ()
set (ZLIB_INCLUDE_DIR "${ClickHouse_SOURCE_DIR}/contrib/zlib-ng" "${ClickHouse_BINARY_DIR}/contrib/zlib-ng") # generated zconf.h
set (ZLIB_INCLUDE_DIR "${ClickHouse_SOURCE_DIR}/contrib/${INTERNAL_ZLIB_NAME}" "${ClickHouse_BINARY_DIR}/contrib/${INTERNAL_ZLIB_NAME}") # generated zconf.h
set (ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR}) # for poco
set (ZLIB_FOUND 1) # for poco
if (USE_STATIC_LIBRARIES)

View File

@ -1,35 +0,0 @@
if (ARCH_ARM)
# bundled have some asm broken for arm, use package libzookeeper-mt-dev
set(USE_INTERNAL_ZOOKEEPER_LIBRARY 0 CACHE BOOL "")
endif ()
option (USE_INTERNAL_ZOOKEEPER_LIBRARY "Set to FALSE to use system zookeeper library instead of bundled" ${NOT_UNBUNDLED})
if (USE_INTERNAL_ZOOKEEPER_LIBRARY AND NOT EXISTS "${ClickHouse_SOURCE_DIR}/contrib/zookeeper/src/c/CMakeLists.txt")
message (WARNING "submodule contrib/zookeeper is missing. to fix try run: \n git submodule update --init --recursive")
set (USE_INTERNAL_ZOOKEEPER_LIBRARY 0)
endif ()
if (NOT USE_INTERNAL_ZOOKEEPER_LIBRARY)
find_library (ZOOKEEPER_LIBRARY zookeeper_mt)
find_path (ZOOKEEPER_INCLUDE_DIR NAMES zookeeper/zookeeper.h PATHS ${ZOOKEEPER_INCLUDE_PATHS})
set(ZOOKEEPER_INCLUDE_DIR "${ZOOKEEPER_INCLUDE_DIR}/zookeeper")
endif ()
if (ZOOKEEPER_LIBRARY AND ZOOKEEPER_INCLUDE_DIR)
else ()
set (USE_INTERNAL_ZOOKEEPER_LIBRARY 1)
set(WANT_CPPUNIT 0 CACHE BOOL "")
set (ZOOKEEPER_LIBRARY zookeeper)
endif ()
message (STATUS "Using zookeeper: ${ZOOKEEPER_INCLUDE_DIR} : ${ZOOKEEPER_LIBRARY}")
# how to make clickhouse branch of https://github.com/ClickHouse-Extras/zookeeper.git :
# git remote add upstream https://github.com/apache/zookeeper.git
# git checkhout upstream/master
# git branch -D clickhouse
# git checkout -b clickhouse
# git merge clickhouse_misc
# git merge clickhouse_706

View File

@ -1,4 +1,3 @@
set(DIVIDE_INCLUDE_DIR ${ClickHouse_SOURCE_DIR}/contrib/libdivide)
set(CITYHASH_CONTRIB_INCLUDE_DIR ${ClickHouse_SOURCE_DIR}/contrib/libcityhash/include)
set(COMMON_INCLUDE_DIR ${ClickHouse_SOURCE_DIR}/libs/libcommon/include ${ClickHouse_BINARY_DIR}/libs/libcommon/include)

6
cmake/print_flags.cmake Normal file
View File

@ -0,0 +1,6 @@
set (FULL_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_UC}}")
set (FULL_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UC}}")
set (FULL_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UC}}")
message (STATUS "compiler C = ${CMAKE_C_COMPILER} ${FULL_C_FLAGS}")
message (STATUS "compiler CXX = ${CMAKE_CXX_COMPILER} ${FULL_CXX_FLAGS}")
message (STATUS "LINKER_FLAGS = ${FULL_EXE_LINKER_FLAGS}")

27
cmake/sanitize.cmake Normal file
View File

@ -0,0 +1,27 @@
set (SAN_FLAGS "${SAN_FLAGS} -g -fno-omit-frame-pointer -DSANITIZER")
if (SAN_DEBUG)
set (SAN_FLAGS "${SAN_FLAGS} -O0")
else ()
set (SAN_FLAGS "${SAN_FLAGS} -O3")
endif ()
set (CMAKE_CXX_FLAGS_ASAN "${CMAKE_CXX_FLAGS_ASAN} ${SAN_FLAGS} -fsanitize=address")
set (CMAKE_C_FLAGS_ASAN "${CMAKE_C_FLAGS_ASAN} ${SAN_FLAGS} -fsanitize=address")
set (CMAKE_EXE_LINKER_FLAGS_ASAN "${CMAKE_EXE_LINKER_FLAGS_ASAN} -fsanitize=address")
set (CMAKE_CXX_FLAGS_UBSAN "${CMAKE_CXX_FLAGS_UBSAN} ${SAN_FLAGS} -fsanitize=undefined")
set (CMAKE_C_FLAGS_UBSAN "${CMAKE_C_FLAGS_UBSAN} ${SAN_FLAGS} -fsanitize=undefined")
set (CMAKE_EXE_LINKER_FLAGS_UBSAN "${CMAKE_EXE_LINKER_FLAGS_UBSAN} -fsanitize=undefined")
set (CMAKE_CXX_FLAGS_MSAN "${CMAKE_CXX_FLAGS_MSAN} ${SAN_FLAGS} -fsanitize=memory")
set (CMAKE_C_FLAGS_MSAN "${CMAKE_C_FLAGS_MSAN} ${SAN_FLAGS} -fsanitize=memory")
set (CMAKE_EXE_LINKER_FLAGS_MSAN "${CMAKE_EXE_LINKER_FLAGS_MSAN} -fsanitize=memory")
set (CMAKE_CXX_FLAGS_TSAN "${CMAKE_CXX_FLAGS_TSAN} ${SAN_FLAGS} -fsanitize=thread")
set (CMAKE_C_FLAGS_TSAN "${CMAKE_C_FLAGS_TSAN} ${SAN_FLAGS} -fsanitize=thread")
set (CMAKE_EXE_LINKER_FLAGS_TSAN "${CMAKE_EXE_LINKER_FLAGS_TSAN} -fsanitize=thread")
# clang use static linking by default
if (MAKE_STATIC_LIBRARIES AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set (CMAKE_EXE_LINKER_FLAGS_ASAN "${CMAKE_EXE_LINKER_FLAGS_ASAN} -static-libasan")
set (CMAKE_EXE_LINKER_FLAGS_UBSAN "${CMAKE_EXE_LINKER_FLAGS_UBSAN} -static-libubsan")
set (CMAKE_EXE_LINKER_FLAGS_MSAN "${CMAKE_EXE_LINKER_FLAGS_MSAN} -static-libmsan")
set (CMAKE_EXE_LINKER_FLAGS_TSAN "${CMAKE_EXE_LINKER_FLAGS_TSAN} -static-libtsan")
endif ()

View File

@ -1,7 +1,9 @@
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-old-style-cast")
if (NOT MSVC)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-old-style-cast")
endif ()
if (USE_INTERNAL_BOOST_LIBRARY)
add_subdirectory (libboost)
add_subdirectory (boost-cmake)
endif ()
if (USE_INTERNAL_LZ4_LIBRARY)
@ -19,14 +21,10 @@ if (USE_INTERNAL_RE2_LIBRARY)
endif ()
if (USE_INTERNAL_DOUBLE_CONVERSION_LIBRARY)
set (BUILD_TESTING ${ENABLE_TESTS} CACHE INTERNAL "")
set (BUILD_TESTING 0 CACHE INTERNAL "")
add_subdirectory (double-conversion)
endif ()
if (USE_INTERNAL_ZOOKEEPER_LIBRARY)
add_subdirectory (zookeeper/src/c)
endif ()
if (USE_INTERNAL_CITYHASH_LIBRARY)
add_subdirectory (libcityhash)
endif ()
@ -48,7 +46,7 @@ if (USE_INTERNAL_UNWIND_LIBRARY)
endif ()
if (USE_INTERNAL_ZLIB_LIBRARY)
add_subdirectory (zlib-ng)
add_subdirectory (${INTERNAL_ZLIB_NAME})
# todo: make pull to Dead2/zlib-ng and remove:
# We should use same defines when including zlib.h as used when zlib compiled
target_compile_definitions (zlib PUBLIC ZLIB_COMPAT WITH_GZFILEOP)
@ -81,18 +79,41 @@ if (NOT ARCH_ARM)
add_subdirectory (libcpuid)
endif ()
if (USE_INTERNAL_SSL_LIBRARY)
if (NOT MAKE_STATIC_LIBRARIES)
set (BUILD_SHARED 1)
endif ()
set (USE_SHARED ${USE_STATIC_LIBRARIES})
add_subdirectory (ssl)
target_include_directories(${OPENSSL_CRYPTO_LIBRARY} PUBLIC ${OPENSSL_INCLUDE_DIR})
target_include_directories(${OPENSSL_SSL_LIBRARY} PUBLIC ${OPENSSL_INCLUDE_DIR})
endif ()
if (USE_INTERNAL_RDKAFKA_LIBRARY)
set (RDKAFKA_BUILD_EXAMPLES OFF CACHE INTERNAL "")
set (RDKAFKA_BUILD_TESTS OFF CACHE INTERNAL "")
set (RDKAFKA_BUILD_STATIC ON CACHE INTERNAL "")
set (RDKAFKA_BUILD_STATIC ${MAKE_STATIC_LIBRARIES} CACHE INTERNAL "")
mark_as_advanced (ZLIB_INCLUDE_DIR)
if (USE_INTERNAL_SSL_LIBRARY)
if (MAKE_STATIC_LIBRARIES)
add_library(bundled-ssl ALIAS ${OPENSSL_SSL_LIBRARY})
set (WITH_BUNDLED_SSL 1 CACHE INTERNAL "")
else ()
set (WITH_SSL 0 CACHE INTERNAL "")
endif ()
endif ()
add_subdirectory (librdkafka)
if (USE_INTERNAL_SSL_LIBRARY AND MAKE_STATIC_LIBRARIES)
target_include_directories(rdkafka PRIVATE BEFORE ${OPENSSL_INCLUDE_DIR})
endif ()
target_include_directories(rdkafka PRIVATE BEFORE ${ZLIB_INCLUDE_DIR})
endif ()
if (USE_INTERNAL_CAPNP_LIBRARY)
if (NOT APPLE) # tests never end
set (BUILD_TESTING ${ENABLE_TESTS} CACHE INTERNAL "")
endif ()
set (BUILD_TESTING 0 CACHE INTERNAL "")
set (_save ${CMAKE_CXX_EXTENSIONS})
set (CMAKE_CXX_EXTENSIONS)
add_subdirectory (capnproto/c++)
@ -107,13 +128,26 @@ if (USE_INTERNAL_POCO_LIBRARY)
set (_save ${ENABLE_TESTS})
set (ENABLE_TESTS 0)
set (CMAKE_DISABLE_FIND_PACKAGE_ZLIB 1)
if (USE_INTERNAL_SSL_LIBRARY OR (DEFINED ENABLE_POCO_NETSSL AND NOT ENABLE_POCO_NETSSL))
set (DISABLE_INTERNAL_OPENSSL 1 CACHE INTERNAL "")
set (ENABLE_NETSSL 0 CACHE INTERNAL "") # TODO!
set (ENABLE_CRYPTO 0 CACHE INTERNAL "") # TODO!
endif ()
if (MSVC)
set (ENABLE_DATA_ODBC 0 CACHE INTERNAL "") # TODO (build fail)
endif ()
add_subdirectory (poco)
unset (CMAKE_DISABLE_FIND_PACKAGE_ZLIB)
set (ENABLE_TESTS ${_save})
set (CMAKE_CXX_FLAGS ${save_CMAKE_CXX_FLAGS})
set (CMAKE_C_FLAGS ${save_CMAKE_C_FLAGS})
if (OPENSSL_FOUND)
if (OPENSSL_FOUND AND TARGET Crypto AND (NOT DEFINED ENABLE_POCO_NETSSL OR ENABLE_POCO_NETSSL))
# Bug in poco https://github.com/pocoproject/poco/pull/2100 found on macos
target_include_directories(Crypto PUBLIC ${OPENSSL_INCLUDE_DIR})
endif ()
endif ()
if (USE_INTERNAL_LLVM_LIBRARY)
add_subdirectory (llvm/llvm)
endif ()

1
contrib/boost vendored Submodule

@ -0,0 +1 @@
Subproject commit 2d5cb2c86f61126f4e1efe9ab97332efd44e7dea

View File

@ -0,0 +1,51 @@
# Supported contrib/boost source variants:
# 1. Default - Minimized vrsion from release archive : https://github.com/ClickHouse-Extras/boost
# 2. Release archive unpacked to contrib/boost
# 3. Full boost https://github.com/boostorg/boost
# if boostorg/boost connected as submodule: Update all boost internal submodules to tag:
# git submodule foreach "git fetch --all && git checkout boost-1.66.0 || true"
#
# Important boost patch: 094c18b
#
set (LIBRARY_DIR ${ClickHouse_SOURCE_DIR}/contrib/boost)
if (NOT MSVC)
add_definitions(-Wno-unused-variable -Wno-deprecated-declarations)
endif ()
add_library(boost_program_options_internal
${LIBRARY_DIR}/libs/program_options/src/cmdline.cpp
${LIBRARY_DIR}/libs/program_options/src/config_file.cpp
${LIBRARY_DIR}/libs/program_options/src/convert.cpp
${LIBRARY_DIR}/libs/program_options/src/options_description.cpp
${LIBRARY_DIR}/libs/program_options/src/parsers.cpp
${LIBRARY_DIR}/libs/program_options/src/positional_options.cpp
${LIBRARY_DIR}/libs/program_options/src/split.cpp
${LIBRARY_DIR}/libs/program_options/src/utf8_codecvt_facet.cpp
${LIBRARY_DIR}/libs/program_options/src/value_semantic.cpp
${LIBRARY_DIR}/libs/program_options/src/variables_map.cpp
${LIBRARY_DIR}/libs/program_options/src/winmain.cpp)
add_library(boost_filesystem_internal
${LIBRARY_DIR}/libs/filesystem/src/codecvt_error_category.cpp
${LIBRARY_DIR}/libs/filesystem/src/operations.cpp
${LIBRARY_DIR}/libs/filesystem/src/path.cpp
${LIBRARY_DIR}/libs/filesystem/src/path_traits.cpp
${LIBRARY_DIR}/libs/filesystem/src/portability.cpp
${LIBRARY_DIR}/libs/filesystem/src/unique_path.cpp
${LIBRARY_DIR}/libs/filesystem/src/utf8_codecvt_facet.cpp
${LIBRARY_DIR}/libs/filesystem/src/windows_file_codecvt.cpp)
add_library(boost_system_internal
${LIBRARY_DIR}/libs/system/src/error_code.cpp)
target_include_directories (boost_program_options_internal BEFORE PUBLIC ${Boost_INCLUDE_DIRS})
target_include_directories (boost_filesystem_internal BEFORE PUBLIC ${Boost_INCLUDE_DIRS})
target_include_directories (boost_system_internal BEFORE PUBLIC ${Boost_INCLUDE_DIRS})
target_compile_definitions (boost_program_options_internal PUBLIC BOOST_SYSTEM_NO_DEPRECATED)
target_compile_definitions (boost_filesystem_internal PUBLIC BOOST_SYSTEM_NO_DEPRECATED)
target_compile_definitions (boost_system_internal PUBLIC BOOST_SYSTEM_NO_DEPRECATED)

2
contrib/capnproto vendored

@ -1 +1 @@
Subproject commit c949a18da5f041a36cc218c5c4b79c7705999b4f
Subproject commit 7173ab638fdf144032411dc69fb1082cd473e08f

View File

@ -1,36 +0,0 @@
add_definitions(-Wno-unused-variable)
add_definitions(-Wno-deprecated-declarations)
add_library(boost_program_options_internal
boost_1_65_0/libs/program_options/src/cmdline.cpp
boost_1_65_0/libs/program_options/src/config_file.cpp
boost_1_65_0/libs/program_options/src/convert.cpp
boost_1_65_0/libs/program_options/src/options_description.cpp
boost_1_65_0/libs/program_options/src/parsers.cpp
boost_1_65_0/libs/program_options/src/positional_options.cpp
boost_1_65_0/libs/program_options/src/split.cpp
boost_1_65_0/libs/program_options/src/utf8_codecvt_facet.cpp
boost_1_65_0/libs/program_options/src/value_semantic.cpp
boost_1_65_0/libs/program_options/src/variables_map.cpp
boost_1_65_0/libs/program_options/src/winmain.cpp)
add_library(boost_filesystem_internal
boost_1_65_0/libs/filesystem/src/codecvt_error_category.cpp
boost_1_65_0/libs/filesystem/src/operations.cpp
boost_1_65_0/libs/filesystem/src/path.cpp
boost_1_65_0/libs/filesystem/src/path_traits.cpp
boost_1_65_0/libs/filesystem/src/portability.cpp
boost_1_65_0/libs/filesystem/src/unique_path.cpp
boost_1_65_0/libs/filesystem/src/utf8_codecvt_facet.cpp
boost_1_65_0/libs/filesystem/src/windows_file_codecvt.cpp)
add_library(boost_system_internal
boost_1_65_0/libs/system/src/error_code.cpp)
target_include_directories (boost_program_options_internal BEFORE PUBLIC ${Boost_INCLUDE_DIRS})
target_include_directories (boost_filesystem_internal BEFORE PUBLIC ${Boost_INCLUDE_DIRS})
target_include_directories (boost_system_internal BEFORE PUBLIC ${Boost_INCLUDE_DIRS})
target_compile_definitions (boost_program_options_internal PUBLIC BOOST_SYSTEM_NO_DEPRECATED)
target_compile_definitions (boost_filesystem_internal PUBLIC BOOST_SYSTEM_NO_DEPRECATED)
target_compile_definitions (boost_system_internal PUBLIC BOOST_SYSTEM_NO_DEPRECATED)

View File

@ -1,23 +0,0 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View File

@ -1,88 +0,0 @@
/*
Copyright (c) Marshall Clow 2014.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Revision history:
2 Dec 2014 mtc First version; power
*/
/// \file algorithm.hpp
/// \brief Misc Algorithms
/// \author Marshall Clow
///
#ifndef BOOST_ALGORITHM_HPP
#define BOOST_ALGORITHM_HPP
#include <functional> // for plus and multiplies
#include <boost/utility/enable_if.hpp> // for boost::disable_if
#include <boost/type_traits/is_integral.hpp>
namespace boost { namespace algorithm {
template <typename T>
T identity_operation ( std::multiplies<T> ) { return T(1); }
template <typename T>
T identity_operation ( std::plus<T> ) { return T(0); }
/// \fn power ( T x, Integer n )
/// \return the value "x" raised to the power "n"
///
/// \param x The value to be exponentiated
/// \param n The exponent (must be >= 0)
///
// \remark Taken from Knuth, The Art of Computer Programming, Volume 2:
// Seminumerical Algorithms, Section 4.6.3
template <typename T, typename Integer>
typename boost::enable_if<boost::is_integral<Integer>, T>::type
power (T x, Integer n) {
T y = 1; // Should be "T y{1};"
if (n == 0) return y;
while (true) {
if (n % 2 == 1) {
y = x * y;
if (n == 1)
return y;
}
n = n / 2;
x = x * x;
}
return y;
}
/// \fn power ( T x, Integer n, Operation op )
/// \return the value "x" raised to the power "n"
/// using the operation "op".
///
/// \param x The value to be exponentiated
/// \param n The exponent (must be >= 0)
/// \param op The operation used
///
// \remark Taken from Knuth, The Art of Computer Programming, Volume 2:
// Seminumerical Algorithms, Section 4.6.3
template <typename T, typename Integer, typename Operation>
typename boost::enable_if<boost::is_integral<Integer>, T>::type
power (T x, Integer n, Operation op) {
T y = identity_operation(op);
if (n == 0) return y;
while (true) {
if (n % 2 == 1) {
y = op(x, y);
if (n == 1)
return y;
}
n = n / 2;
x = op(x, x);
}
return y;
}
}}
#endif // BOOST_ALGORITHM_HPP

View File

@ -1,175 +0,0 @@
/*
Copyright (c) Marshall Clow 2008-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Revision history:
27 June 2009 mtc First version
23 Oct 2010 mtc Added predicate version
*/
/// \file clamp.hpp
/// \brief Clamp algorithm
/// \author Marshall Clow
///
/// Suggested by olafvdspek in https://svn.boost.org/trac/boost/ticket/3215
#ifndef BOOST_ALGORITHM_CLAMP_HPP
#define BOOST_ALGORITHM_CLAMP_HPP
#include <functional> // For std::less
#include <iterator> // For std::iterator_traits
#include <cassert>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/mpl/identity.hpp> // for identity
#include <boost/utility/enable_if.hpp> // for boost::disable_if
namespace boost { namespace algorithm {
/// \fn clamp ( T const& val,
/// typename boost::mpl::identity<T>::type const & lo,
/// typename boost::mpl::identity<T>::type const & hi, Pred p )
/// \return the value "val" brought into the range [ lo, hi ]
/// using the comparison predicate p.
/// If p ( val, lo ) return lo.
/// If p ( hi, val ) return hi.
/// Otherwise, return the original value.
///
/// \param val The value to be clamped
/// \param lo The lower bound of the range to be clamped to
/// \param hi The upper bound of the range to be clamped to
/// \param p A predicate to use to compare the values.
/// p ( a, b ) returns a boolean.
///
template<typename T, typename Pred>
T const & clamp ( T const& val,
typename boost::mpl::identity<T>::type const & lo,
typename boost::mpl::identity<T>::type const & hi, Pred p )
{
// assert ( !p ( hi, lo )); // Can't assert p ( lo, hi ) b/c they might be equal
return p ( val, lo ) ? lo : p ( hi, val ) ? hi : val;
}
/// \fn clamp ( T const& val,
/// typename boost::mpl::identity<T>::type const & lo,
/// typename boost::mpl::identity<T>::type const & hi )
/// \return the value "val" brought into the range [ lo, hi ].
/// If the value is less than lo, return lo.
/// If the value is greater than "hi", return hi.
/// Otherwise, return the original value.
///
/// \param val The value to be clamped
/// \param lo The lower bound of the range to be clamped to
/// \param hi The upper bound of the range to be clamped to
///
template<typename T>
T const& clamp ( const T& val,
typename boost::mpl::identity<T>::type const & lo,
typename boost::mpl::identity<T>::type const & hi )
{
return (clamp) ( val, lo, hi, std::less<T>());
}
/// \fn clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
/// std::iterator_traits<InputIterator>::value_type const & lo,
/// std::iterator_traits<InputIterator>::value_type const & hi )
/// \return clamp the sequence of values [first, last) into [ lo, hi ]
///
/// \param first The start of the range of values
/// \param last One past the end of the range of input values
/// \param out An output iterator to write the clamped values into
/// \param lo The lower bound of the range to be clamped to
/// \param hi The upper bound of the range to be clamped to
///
template<typename InputIterator, typename OutputIterator>
OutputIterator clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
typename std::iterator_traits<InputIterator>::value_type const & lo,
typename std::iterator_traits<InputIterator>::value_type const & hi )
{
// this could also be written with bind and std::transform
while ( first != last )
*out++ = clamp ( *first++, lo, hi );
return out;
}
/// \fn clamp_range ( const Range &r, OutputIterator out,
/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & lo,
/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & hi )
/// \return clamp the sequence of values [first, last) into [ lo, hi ]
///
/// \param r The range of values to be clamped
/// \param out An output iterator to write the clamped values into
/// \param lo The lower bound of the range to be clamped to
/// \param hi The upper bound of the range to be clamped to
///
template<typename Range, typename OutputIterator>
typename boost::disable_if_c<boost::is_same<Range, OutputIterator>::value, OutputIterator>::type
clamp_range ( const Range &r, OutputIterator out,
typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & lo,
typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & hi )
{
return clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi );
}
/// \fn clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
/// std::iterator_traits<InputIterator>::value_type const & lo,
/// std::iterator_traits<InputIterator>::value_type const & hi, Pred p )
/// \return clamp the sequence of values [first, last) into [ lo, hi ]
/// using the comparison predicate p.
///
/// \param first The start of the range of values
/// \param last One past the end of the range of input values
/// \param out An output iterator to write the clamped values into
/// \param lo The lower bound of the range to be clamped to
/// \param hi The upper bound of the range to be clamped to
/// \param p A predicate to use to compare the values.
/// p ( a, b ) returns a boolean.
///
template<typename InputIterator, typename OutputIterator, typename Pred>
OutputIterator clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
typename std::iterator_traits<InputIterator>::value_type const & lo,
typename std::iterator_traits<InputIterator>::value_type const & hi, Pred p )
{
// this could also be written with bind and std::transform
while ( first != last )
*out++ = clamp ( *first++, lo, hi, p );
return out;
}
/// \fn clamp_range ( const Range &r, OutputIterator out,
/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & lo,
/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & hi,
/// Pred p )
/// \return clamp the sequence of values [first, last) into [ lo, hi ]
/// using the comparison predicate p.
///
/// \param r The range of values to be clamped
/// \param out An output iterator to write the clamped values into
/// \param lo The lower bound of the range to be clamped to
/// \param hi The upper bound of the range to be clamped to
/// \param p A predicate to use to compare the values.
/// p ( a, b ) returns a boolean.
//
// Disable this template if the first two parameters are the same type;
// In that case, the user will get the two iterator version.
template<typename Range, typename OutputIterator, typename Pred>
typename boost::disable_if_c<boost::is_same<Range, OutputIterator>::value, OutputIterator>::type
clamp_range ( const Range &r, OutputIterator out,
typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & lo,
typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & hi,
Pred p )
{
return clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi, p );
}
}}
#endif // BOOST_ALGORITHM_CLAMP_HPP

View File

@ -1,83 +0,0 @@
/*
Copyright (c) Marshall Clow 2008-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
/// \file all_of.hpp
/// \brief Test ranges to see if all elements match a value or predicate.
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_ALL_OF_HPP
#define BOOST_ALGORITHM_ALL_OF_HPP
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
/// \fn all_of ( InputIterator first, InputIterator last, Predicate p )
/// \return true if all elements in [first, last) satisfy the predicate 'p'
/// \note returns true on an empty range
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param p A predicate for testing the elements of the sequence
///
/// \note This function is part of the C++2011 standard library.
template<typename InputIterator, typename Predicate>
bool all_of ( InputIterator first, InputIterator last, Predicate p )
{
for ( ; first != last; ++first )
if ( !p(*first))
return false;
return true;
}
/// \fn all_of ( const Range &r, Predicate p )
/// \return true if all elements in the range satisfy the predicate 'p'
/// \note returns true on an empty range
///
/// \param r The input range
/// \param p A predicate for testing the elements of the range
///
template<typename Range, typename Predicate>
bool all_of ( const Range &r, Predicate p )
{
return boost::algorithm::all_of ( boost::begin (r), boost::end (r), p );
}
/// \fn all_of_equal ( InputIterator first, InputIterator last, const T &val )
/// \return true if all elements in [first, last) are equal to 'val'
/// \note returns true on an empty range
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param val A value to compare against
///
template<typename InputIterator, typename T>
bool all_of_equal ( InputIterator first, InputIterator last, const T &val )
{
for ( ; first != last; ++first )
if ( val != *first )
return false;
return true;
}
/// \fn all_of_equal ( const Range &r, const T &val )
/// \return true if all elements in the range are equal to 'val'
/// \note returns true on an empty range
///
/// \param r The input range
/// \param val A value to compare against
///
template<typename Range, typename T>
bool all_of_equal ( const Range &r, const T &val )
{
return boost::algorithm::all_of_equal ( boost::begin (r), boost::end (r), val );
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_ALL_OF_HPP

View File

@ -1,84 +0,0 @@
/*
Copyright (c) Marshall Clow 2008-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
For more information, see http://www.boost.org
*/
/// \file
/// \brief Test ranges to see if any elements match a value or predicate.
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_ANY_OF_HPP
#define BOOST_ALGORITHM_ANY_OF_HPP
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
/// \fn any_of ( InputIterator first, InputIterator last, Predicate p )
/// \return true if any of the elements in [first, last) satisfy the predicate
/// \note returns false on an empty range
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param p A predicate for testing the elements of the sequence
///
template<typename InputIterator, typename Predicate>
bool any_of ( InputIterator first, InputIterator last, Predicate p )
{
for ( ; first != last; ++first )
if ( p(*first))
return true;
return false;
}
/// \fn any_of ( const Range &r, Predicate p )
/// \return true if any elements in the range satisfy the predicate 'p'
/// \note returns false on an empty range
///
/// \param r The input range
/// \param p A predicate for testing the elements of the range
///
template<typename Range, typename Predicate>
bool any_of ( const Range &r, Predicate p )
{
return boost::algorithm::any_of (boost::begin (r), boost::end (r), p);
}
/// \fn any_of_equal ( InputIterator first, InputIterator last, const V &val )
/// \return true if any of the elements in [first, last) are equal to 'val'
/// \note returns false on an empty range
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param val A value to compare against
///
template<typename InputIterator, typename V>
bool any_of_equal ( InputIterator first, InputIterator last, const V &val )
{
for ( ; first != last; ++first )
if ( val == *first )
return true;
return false;
}
/// \fn any_of_equal ( const Range &r, const V &val )
/// \return true if any of the elements in the range are equal to 'val'
/// \note returns false on an empty range
///
/// \param r The input range
/// \param val A value to compare against
///
template<typename Range, typename V>
bool any_of_equal ( const Range &r, const V &val )
{
return boost::algorithm::any_of_equal (boost::begin (r), boost::end (r), val);
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_ANY_OF_HPP

View File

@ -1,129 +0,0 @@
/*
Copyright (c) Marshall Clow 2008-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
/// \file copy_if.hpp
/// \brief Copy a subset of a sequence to a new sequence
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_COPY_IF_HPP
#define BOOST_ALGORITHM_COPY_IF_HPP
#include <utility> // for std::pair, std::make_pair
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
/// \fn copy_if ( InputIterator first, InputIterator last, OutputIterator result, Predicate p )
/// \brief Copies all the elements from the input range that satisfy the
/// predicate to the output range.
/// \return The updated output iterator
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param result An output iterator to write the results into
/// \param p A predicate for testing the elements of the range
/// \note This function is part of the C++2011 standard library.
template<typename InputIterator, typename OutputIterator, typename Predicate>
OutputIterator copy_if ( InputIterator first, InputIterator last, OutputIterator result, Predicate p )
{
for ( ; first != last; ++first )
if (p(*first))
*result++ = *first;
return result;
}
/// \fn copy_if ( const Range &r, OutputIterator result, Predicate p )
/// \brief Copies all the elements from the input range that satisfy the
/// predicate to the output range.
/// \return The updated output iterator
///
/// \param r The input range
/// \param result An output iterator to write the results into
/// \param p A predicate for testing the elements of the range
///
template<typename Range, typename OutputIterator, typename Predicate>
OutputIterator copy_if ( const Range &r, OutputIterator result, Predicate p )
{
return boost::algorithm::copy_if (boost::begin (r), boost::end(r), result, p);
}
/// \fn copy_while ( InputIterator first, InputIterator last, OutputIterator result, Predicate p )
/// \brief Copies all the elements at the start of the input range that
/// satisfy the predicate to the output range.
/// \return The updated input and output iterators
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param result An output iterator to write the results into
/// \param p A predicate for testing the elements of the range
///
template<typename InputIterator, typename OutputIterator, typename Predicate>
std::pair<InputIterator, OutputIterator>
copy_while ( InputIterator first, InputIterator last, OutputIterator result, Predicate p )
{
for ( ; first != last && p(*first); ++first )
*result++ = *first;
return std::make_pair(first, result);
}
/// \fn copy_while ( const Range &r, OutputIterator result, Predicate p )
/// \brief Copies all the elements at the start of the input range that
/// satisfy the predicate to the output range.
/// \return The updated input and output iterators
///
/// \param r The input range
/// \param result An output iterator to write the results into
/// \param p A predicate for testing the elements of the range
///
template<typename Range, typename OutputIterator, typename Predicate>
std::pair<typename boost::range_iterator<const Range>::type, OutputIterator>
copy_while ( const Range &r, OutputIterator result, Predicate p )
{
return boost::algorithm::copy_while (boost::begin (r), boost::end(r), result, p);
}
/// \fn copy_until ( InputIterator first, InputIterator last, OutputIterator result, Predicate p )
/// \brief Copies all the elements at the start of the input range that do not
/// satisfy the predicate to the output range.
/// \return The updated output iterator
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param result An output iterator to write the results into
/// \param p A predicate for testing the elements of the range
///
template<typename InputIterator, typename OutputIterator, typename Predicate>
std::pair<InputIterator, OutputIterator>
copy_until ( InputIterator first, InputIterator last, OutputIterator result, Predicate p )
{
for ( ; first != last && !p(*first); ++first )
*result++ = *first;
return std::make_pair(first, result);
}
/// \fn copy_until ( const Range &r, OutputIterator result, Predicate p )
/// \brief Copies all the elements at the start of the input range that do not
/// satisfy the predicate to the output range.
/// \return The updated output iterator
///
/// \param r The input range
/// \param result An output iterator to write the results into
/// \param p A predicate for testing the elements of the range
///
template<typename Range, typename OutputIterator, typename Predicate>
std::pair<typename boost::range_iterator<const Range>::type, OutputIterator>
copy_until ( const Range &r, OutputIterator result, Predicate p )
{
return boost::algorithm::copy_until (boost::begin (r), boost::end(r), result, p);
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_COPY_IF_HPP

View File

@ -1,35 +0,0 @@
/*
Copyright (c) Marshall Clow 2011-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
/// \file copy_n.hpp
/// \brief Copy n items from one sequence to another
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_COPY_N_HPP
#define BOOST_ALGORITHM_COPY_N_HPP
namespace boost { namespace algorithm {
/// \fn copy_n ( InputIterator first, Size n, OutputIterator result )
/// \brief Copies exactly n (n > 0) elements from the range starting at first to
/// the range starting at result.
/// \return The updated output iterator
///
/// \param first The start of the input sequence
/// \param n The number of elements to copy
/// \param result An output iterator to write the results into
/// \note This function is part of the C++2011 standard library.
template <typename InputIterator, typename Size, typename OutputIterator>
OutputIterator copy_n ( InputIterator first, Size n, OutputIterator result )
{
for ( ; n > 0; --n, ++first, ++result )
*result = *first;
return result;
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_COPY_IF_HPP

View File

@ -1,51 +0,0 @@
/*
Copyright (c) Marshall Clow 2011-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
/// \file find_if_not.hpp
/// \brief Find the first element in a sequence that does not satisfy a predicate.
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_FIND_IF_NOT_HPP
#define BOOST_ALGORITHM_FIND_IF_NOT_HPP
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
/// \fn find_if_not(InputIterator first, InputIterator last, Predicate p)
/// \brief Finds the first element in the sequence that does not satisfy the predicate.
/// \return The iterator pointing to the desired element.
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param p A predicate for testing the elements of the range
/// \note This function is part of the C++2011 standard library.
template<typename InputIterator, typename Predicate>
InputIterator find_if_not ( InputIterator first, InputIterator last, Predicate p )
{
for ( ; first != last; ++first )
if ( !p(*first))
break;
return first;
}
/// \fn find_if_not ( const Range &r, Predicate p )
/// \brief Finds the first element in the sequence that does not satisfy the predicate.
/// \return The iterator pointing to the desired element.
///
/// \param r The input range
/// \param p A predicate for testing the elements of the range
///
template<typename Range, typename Predicate>
typename boost::range_iterator<const Range>::type find_if_not ( const Range &r, Predicate p )
{
return boost::algorithm::find_if_not (boost::begin (r), boost::end(r), p);
}
}}
#endif // BOOST_ALGORITHM_FIND_IF_NOT_HPP

View File

@ -1,65 +0,0 @@
/*
Copyright (c) Marshall Clow 2008-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
/// \file iota.hpp
/// \brief Generate an increasing series
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_IOTA_HPP
#define BOOST_ALGORITHM_IOTA_HPP
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
/// \fn iota ( ForwardIterator first, ForwardIterator last, T value )
/// \brief Generates an increasing sequence of values, and stores them in [first, last)
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param value The initial value of the sequence to be generated
/// \note This function is part of the C++2011 standard library.
template <typename ForwardIterator, typename T>
void iota ( ForwardIterator first, ForwardIterator last, T value )
{
for ( ; first != last; ++first, ++value )
*first = value;
}
/// \fn iota ( Range &r, T value )
/// \brief Generates an increasing sequence of values, and stores them in the input Range.
///
/// \param r The input range
/// \param value The initial value of the sequence to be generated
///
template <typename Range, typename T>
void iota ( Range &r, T value )
{
boost::algorithm::iota (boost::begin(r), boost::end(r), value);
}
/// \fn iota_n ( OutputIterator out, T value, std::size_t n )
/// \brief Generates an increasing sequence of values, and stores them in the input Range.
///
/// \param out An output iterator to write the results into
/// \param value The initial value of the sequence to be generated
/// \param n The number of items to write
///
template <typename OutputIterator, typename T>
OutputIterator iota_n ( OutputIterator out, T value, std::size_t n )
{
for ( ; n > 0; --n, ++value )
*out++ = value;
return out;
}
}}
#endif // BOOST_ALGORITHM_IOTA_HPP

View File

@ -1,58 +0,0 @@
/*
Copyright (c) Marshall Clow 2011-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
/// \file is_partitioned.hpp
/// \brief Tell if a sequence is partitioned
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_IS_PARTITIONED_HPP
#define BOOST_ALGORITHM_IS_PARTITIONED_HPP
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
/// \fn is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p )
/// \brief Tests to see if a sequence is partitioned according to a predicate.
/// In other words, all the items in the sequence that satisfy the predicate are at the beginning of the sequence.
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param p The predicate to test the values with
/// \note This function is part of the C++2011 standard library.
template <typename InputIterator, typename UnaryPredicate>
bool is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p )
{
// Run through the part that satisfy the predicate
for ( ; first != last; ++first )
if ( !p (*first))
break;
// Now the part that does not satisfy the predicate
for ( ; first != last; ++first )
if ( p (*first))
return false;
return true;
}
/// \fn is_partitioned ( const Range &r, UnaryPredicate p )
/// \brief Tests to see if a sequence is partitioned according to a predicate.
/// In other words, all the items in the sequence that satisfy the predicate are at the beginning of the sequence.
///
/// \param r The input range
/// \param p The predicate to test the values with
///
template <typename Range, typename UnaryPredicate>
bool is_partitioned ( const Range &r, UnaryPredicate p )
{
return boost::algorithm::is_partitioned (boost::begin(r), boost::end(r), p);
}
}}
#endif // BOOST_ALGORITHM_IS_PARTITIONED_HPP

View File

@ -1,185 +0,0 @@
/*
Copyright (c) Marshall Clow 2011-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
/// \file is_permutation.hpp
/// \brief Is a sequence a permutation of another sequence
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_IS_PERMUTATION11_HPP
#define BOOST_ALGORITHM_IS_PERMUTATION11_HPP
#include <algorithm> // for std::find_if, count_if, mismatch
#include <utility> // for std::pair
#include <functional> // for std::equal_to
#include <iterator>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
namespace boost { namespace algorithm {
/// \cond DOXYGEN_HIDE
namespace detail {
template <typename Predicate, typename Iterator>
struct value_predicate {
value_predicate ( Predicate p, Iterator it ) : p_ ( p ), it_ ( it ) {}
template <typename T1>
bool operator () ( const T1 &t1 ) const { return p_ ( *it_, t1 ); }
private:
Predicate p_;
Iterator it_;
};
// Preconditions:
// 1. The sequences are the same length
// 2. Any common elements on the front have been removed (not necessary for correctness, just for performance)
template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate >
bool is_permutation_inner ( ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2, ForwardIterator2 last2,
BinaryPredicate p ) {
// for each unique value in the sequence [first1,last1), count how many times
// it occurs, and make sure it occurs the same number of times in [first2, last2)
for ( ForwardIterator1 iter = first1; iter != last1; ++iter ) {
value_predicate<BinaryPredicate, ForwardIterator1> pred ( p, iter );
/* For each value we haven't seen yet... */
if ( std::find_if ( first1, iter, pred ) == iter ) {
std::size_t dest_count = std::count_if ( first2, last2, pred );
if ( dest_count == 0 || dest_count != (std::size_t) std::count_if ( iter, last1, pred ))
return false;
}
}
return true;
}
template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>
bool is_permutation_tag ( ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2, ForwardIterator2 last2,
BinaryPredicate p,
std::forward_iterator_tag, std::forward_iterator_tag ) {
// Skip the common prefix (if any)
while ( first1 != last1 && first2 != last2 && p ( *first1, *first2 )) {
++first1;
++first2;
}
if ( first1 != last1 && first2 != last2 )
return boost::algorithm::detail::is_permutation_inner ( first1, last1, first2, last2,
std::equal_to<typename std::iterator_traits<ForwardIterator1>::value_type> ());
return first1 == last1 && first2 == last2;
}
template <class RandomAccessIterator1, class RandomAccessIterator2, class BinaryPredicate>
bool is_permutation_tag ( RandomAccessIterator1 first1, RandomAccessIterator1 last1,
RandomAccessIterator2 first2, RandomAccessIterator2 last2,
BinaryPredicate p,
std::random_access_iterator_tag, std::random_access_iterator_tag ) {
// Cheap check
if ( std::distance ( first1, last1 ) != std::distance ( first2, last2 ))
return false;
// Skip the common prefix (if any)
while ( first1 != last1 && first2 != last2 && p ( *first1, *first2 )) {
++first1;
++first2;
}
if ( first1 != last1 && first2 != last2 )
return is_permutation_inner (first1, last1, first2, last2, p);
return first1 == last1 && first2 == last2;
}
}
/// \endcond
/// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 first2, BinaryPredicate p )
/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
///
/// \param first1 The start of the input sequence
/// \param last1 One past the end of the input sequence
/// \param first2 The start of the second sequence
/// \param p The predicate to compare elements with
///
/// \note This function is part of the C++2011 standard library.
template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate >
bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2, BinaryPredicate p )
{
// Skip the common prefix (if any)
std::pair<ForwardIterator1, ForwardIterator2> eq = std::mismatch (first1, last1, first2, p);
first1 = eq.first;
first2 = eq.second;
if ( first1 != last1 ) {
// Create last2
ForwardIterator2 last2 = first2;
std::advance ( last2, std::distance (first1, last1));
return boost::algorithm::detail::is_permutation_inner ( first1, last1, first2, last2, p );
}
return true;
}
/// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 first2 )
/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
///
/// \param first1 The start of the input sequence
/// \param last2 One past the end of the input sequence
/// \param first2 The start of the second sequence
/// \note This function is part of the C++2011 standard library.
template< class ForwardIterator1, class ForwardIterator2 >
bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2 )
{
// How should I deal with the idea that ForwardIterator1::value_type
// and ForwardIterator2::value_type could be different? Define my own comparison predicate?
// Skip the common prefix (if any)
std::pair<ForwardIterator1, ForwardIterator2> eq = std::mismatch (first1, last1, first2 );
first1 = eq.first;
first2 = eq.second;
if ( first1 != last1 ) {
// Create last2
ForwardIterator2 last2 = first2;
std::advance ( last2, std::distance (first1, last1));
return boost::algorithm::detail::is_permutation_inner ( first1, last1, first2, last2,
std::equal_to<typename std::iterator_traits<ForwardIterator1>::value_type> ());
}
return true;
}
/// \fn is_permutation ( const Range &r, ForwardIterator first2 )
/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
///
/// \param r The input range
/// \param first2 The start of the second sequence
template <typename Range, typename ForwardIterator>
bool is_permutation ( const Range &r, ForwardIterator first2 )
{
return boost::algorithm::is_permutation (boost::begin (r), boost::end (r), first2 );
}
/// \fn is_permutation ( const Range &r, ForwardIterator first2, BinaryPredicate pred )
/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
///
/// \param r The input range
/// \param first2 The start of the second sequence
/// \param pred The predicate to compare elements with
///
// Disable this template when the first two parameters are the same type
// That way the non-range version will be chosen.
template <typename Range, typename ForwardIterator, typename BinaryPredicate>
typename boost::disable_if_c<boost::is_same<Range, ForwardIterator>::value, bool>::type
is_permutation ( const Range &r, ForwardIterator first2, BinaryPredicate pred )
{
return boost::algorithm::is_permutation (boost::begin (r), boost::end (r), first2, pred );
}
}}
#endif // BOOST_ALGORITHM_IS_PERMUTATION11_HPP

View File

@ -1,280 +0,0 @@
// Copyright (c) 2010 Nuovation System Designs, LLC
// Grant Erickson <gerickson@nuovations.com>
//
// Reworked somewhat by Marshall Clow; August 2010
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/ for latest version.
//
#ifndef BOOST_ALGORITHM_ORDERED_HPP
#define BOOST_ALGORITHM_ORDERED_HPP
#include <functional>
#include <iterator>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/identity.hpp>
namespace boost { namespace algorithm {
/// \fn is_sorted_until ( ForwardIterator first, ForwardIterator last, Pred p )
/// \return the point in the sequence [first, last) where the elements are unordered
/// (according to the comparison predicate 'p').
///
/// \param first The start of the sequence to be tested.
/// \param last One past the end of the sequence
/// \param p A binary predicate that returns true if two elements are ordered.
///
template <typename ForwardIterator, typename Pred>
ForwardIterator is_sorted_until ( ForwardIterator first, ForwardIterator last, Pred p )
{
if ( first == last ) return last; // the empty sequence is ordered
ForwardIterator next = first;
while ( ++next != last )
{
if ( p ( *next, *first ))
return next;
first = next;
}
return last;
}
/// \fn is_sorted_until ( ForwardIterator first, ForwardIterator last )
/// \return the point in the sequence [first, last) where the elements are unordered
///
/// \param first The start of the sequence to be tested.
/// \param last One past the end of the sequence
///
template <typename ForwardIterator>
ForwardIterator is_sorted_until ( ForwardIterator first, ForwardIterator last )
{
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type;
return boost::algorithm::is_sorted_until ( first, last, std::less<value_type>());
}
/// \fn is_sorted ( ForwardIterator first, ForwardIterator last, Pred p )
/// \return whether or not the entire sequence is sorted
///
/// \param first The start of the sequence to be tested.
/// \param last One past the end of the sequence
/// \param p A binary predicate that returns true if two elements are ordered.
///
template <typename ForwardIterator, typename Pred>
bool is_sorted ( ForwardIterator first, ForwardIterator last, Pred p )
{
return boost::algorithm::is_sorted_until (first, last, p) == last;
}
/// \fn is_sorted ( ForwardIterator first, ForwardIterator last )
/// \return whether or not the entire sequence is sorted
///
/// \param first The start of the sequence to be tested.
/// \param last One past the end of the sequence
///
template <typename ForwardIterator>
bool is_sorted ( ForwardIterator first, ForwardIterator last )
{
return boost::algorithm::is_sorted_until (first, last) == last;
}
///
/// -- Range based versions of the C++11 functions
///
/// \fn is_sorted_until ( const R &range, Pred p )
/// \return the point in the range R where the elements are unordered
/// (according to the comparison predicate 'p').
///
/// \param range The range to be tested.
/// \param p A binary predicate that returns true if two elements are ordered.
///
template <typename R, typename Pred>
typename boost::lazy_disable_if_c<
boost::is_same<R, Pred>::value,
typename boost::range_iterator<const R>
>::type is_sorted_until ( const R &range, Pred p )
{
return boost::algorithm::is_sorted_until ( boost::begin ( range ), boost::end ( range ), p );
}
/// \fn is_sorted_until ( const R &range )
/// \return the point in the range R where the elements are unordered
///
/// \param range The range to be tested.
///
template <typename R>
typename boost::range_iterator<const R>::type is_sorted_until ( const R &range )
{
return boost::algorithm::is_sorted_until ( boost::begin ( range ), boost::end ( range ));
}
/// \fn is_sorted ( const R &range, Pred p )
/// \return whether or not the entire range R is sorted
/// (according to the comparison predicate 'p').
///
/// \param range The range to be tested.
/// \param p A binary predicate that returns true if two elements are ordered.
///
template <typename R, typename Pred>
typename boost::lazy_disable_if_c< boost::is_same<R, Pred>::value, boost::mpl::identity<bool> >::type
is_sorted ( const R &range, Pred p )
{
return boost::algorithm::is_sorted ( boost::begin ( range ), boost::end ( range ), p );
}
/// \fn is_sorted ( const R &range )
/// \return whether or not the entire range R is sorted
///
/// \param range The range to be tested.
///
template <typename R>
bool is_sorted ( const R &range )
{
return boost::algorithm::is_sorted ( boost::begin ( range ), boost::end ( range ));
}
///
/// -- Range based versions of the C++11 functions
///
/// \fn is_increasing ( ForwardIterator first, ForwardIterator last )
/// \return true if the entire sequence is increasing; i.e, each item is greater than or
/// equal to the previous one.
///
/// \param first The start of the sequence to be tested.
/// \param last One past the end of the sequence
///
/// \note This function will return true for sequences that contain items that compare
/// equal. If that is not what you intended, you should use is_strictly_increasing instead.
template <typename ForwardIterator>
bool is_increasing ( ForwardIterator first, ForwardIterator last )
{
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type;
return boost::algorithm::is_sorted (first, last, std::less<value_type>());
}
/// \fn is_increasing ( const R &range )
/// \return true if the entire sequence is increasing; i.e, each item is greater than or
/// equal to the previous one.
///
/// \param range The range to be tested.
///
/// \note This function will return true for sequences that contain items that compare
/// equal. If that is not what you intended, you should use is_strictly_increasing instead.
template <typename R>
bool is_increasing ( const R &range )
{
return is_increasing ( boost::begin ( range ), boost::end ( range ));
}
/// \fn is_decreasing ( ForwardIterator first, ForwardIterator last )
/// \return true if the entire sequence is decreasing; i.e, each item is less than
/// or equal to the previous one.
///
/// \param first The start of the sequence to be tested.
/// \param last One past the end of the sequence
///
/// \note This function will return true for sequences that contain items that compare
/// equal. If that is not what you intended, you should use is_strictly_decreasing instead.
template <typename ForwardIterator>
bool is_decreasing ( ForwardIterator first, ForwardIterator last )
{
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type;
return boost::algorithm::is_sorted (first, last, std::greater<value_type>());
}
/// \fn is_decreasing ( const R &range )
/// \return true if the entire sequence is decreasing; i.e, each item is less than
/// or equal to the previous one.
///
/// \param range The range to be tested.
///
/// \note This function will return true for sequences that contain items that compare
/// equal. If that is not what you intended, you should use is_strictly_decreasing instead.
template <typename R>
bool is_decreasing ( const R &range )
{
return is_decreasing ( boost::begin ( range ), boost::end ( range ));
}
/// \fn is_strictly_increasing ( ForwardIterator first, ForwardIterator last )
/// \return true if the entire sequence is strictly increasing; i.e, each item is greater
/// than the previous one
///
/// \param first The start of the sequence to be tested.
/// \param last One past the end of the sequence
///
/// \note This function will return false for sequences that contain items that compare
/// equal. If that is not what you intended, you should use is_increasing instead.
template <typename ForwardIterator>
bool is_strictly_increasing ( ForwardIterator first, ForwardIterator last )
{
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type;
return boost::algorithm::is_sorted (first, last, std::less_equal<value_type>());
}
/// \fn is_strictly_increasing ( const R &range )
/// \return true if the entire sequence is strictly increasing; i.e, each item is greater
/// than the previous one
///
/// \param range The range to be tested.
///
/// \note This function will return false for sequences that contain items that compare
/// equal. If that is not what you intended, you should use is_increasing instead.
template <typename R>
bool is_strictly_increasing ( const R &range )
{
return is_strictly_increasing ( boost::begin ( range ), boost::end ( range ));
}
/// \fn is_strictly_decreasing ( ForwardIterator first, ForwardIterator last )
/// \return true if the entire sequence is strictly decreasing; i.e, each item is less than
/// the previous one
///
/// \param first The start of the sequence to be tested.
/// \param last One past the end of the sequence
///
/// \note This function will return false for sequences that contain items that compare
/// equal. If that is not what you intended, you should use is_decreasing instead.
template <typename ForwardIterator>
bool is_strictly_decreasing ( ForwardIterator first, ForwardIterator last )
{
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type;
return boost::algorithm::is_sorted (first, last, std::greater_equal<value_type>());
}
/// \fn is_strictly_decreasing ( const R &range )
/// \return true if the entire sequence is strictly decreasing; i.e, each item is less than
/// the previous one
///
/// \param range The range to be tested.
///
/// \note This function will return false for sequences that contain items that compare
/// equal. If that is not what you intended, you should use is_decreasing instead.
template <typename R>
bool is_strictly_decreasing ( const R &range )
{
return is_strictly_decreasing ( boost::begin ( range ), boost::end ( range ));
}
}} // namespace boost
#endif // BOOST_ALGORITHM_ORDERED_HPP

View File

@ -1,82 +0,0 @@
/*
Copyright (c) Marshall Clow 2008-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
/// \file none_of.hpp
/// \brief Test ranges to see if no elements match a value or predicate.
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_NONE_OF_HPP
#define BOOST_ALGORITHM_NONE_OF_HPP
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
/// \fn none_of ( InputIterator first, InputIterator last, Predicate p )
/// \return true if none of the elements in [first, last) satisfy the predicate 'p'
/// \note returns true on an empty range
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param p A predicate for testing the elements of the sequence
///
template<typename InputIterator, typename Predicate>
bool none_of ( InputIterator first, InputIterator last, Predicate p )
{
for ( ; first != last; ++first )
if ( p(*first))
return false;
return true;
}
/// \fn none_of ( const Range &r, Predicate p )
/// \return true if none of the elements in the range satisfy the predicate 'p'
/// \note returns true on an empty range
///
/// \param r The input range
/// \param p A predicate for testing the elements of the range
///
template<typename Range, typename Predicate>
bool none_of ( const Range &r, Predicate p )
{
return boost::algorithm::none_of (boost::begin (r), boost::end (r), p );
}
/// \fn none_of_equal ( InputIterator first, InputIterator last, const V &val )
/// \return true if none of the elements in [first, last) are equal to 'val'
/// \note returns true on an empty range
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param val A value to compare against
///
template<typename InputIterator, typename V>
bool none_of_equal ( InputIterator first, InputIterator last, const V &val )
{
for ( ; first != last; ++first )
if ( val == *first )
return false;
return true;
}
/// \fn none_of_equal ( const Range &r, const V &val )
/// \return true if none of the elements in the range are equal to 'val'
/// \note returns true on an empty range
///
/// \param r The input range
/// \param val A value to compare against
///
template<typename Range, typename V>
bool none_of_equal ( const Range &r, const V & val )
{
return boost::algorithm::none_of_equal (boost::begin (r), boost::end (r), val);
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_NONE_OF_HPP

View File

@ -1,82 +0,0 @@
/*
Copyright (c) Marshall Clow 2008-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
/// \file one_of.hpp
/// \brief Test ranges to see if only one element matches a value or predicate.
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_ONE_OF_HPP
#define BOOST_ALGORITHM_ONE_OF_HPP
#include <algorithm> // for std::find and std::find_if
#include <boost/algorithm/cxx11/none_of.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
/// \fn one_of ( InputIterator first, InputIterator last, Predicate p )
/// \return true if the predicate 'p' is true for exactly one item in [first, last).
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param p A predicate for testing the elements of the sequence
///
template<typename InputIterator, typename Predicate>
bool one_of ( InputIterator first, InputIterator last, Predicate p )
{
InputIterator i = std::find_if (first, last, p);
if (i == last)
return false; // Didn't occur at all
return boost::algorithm::none_of (++i, last, p);
}
/// \fn one_of ( const Range &r, Predicate p )
/// \return true if the predicate 'p' is true for exactly one item in the range.
///
/// \param r The input range
/// \param p A predicate for testing the elements of the range
///
template<typename Range, typename Predicate>
bool one_of ( const Range &r, Predicate p )
{
return boost::algorithm::one_of ( boost::begin (r), boost::end (r), p );
}
/// \fn one_of_equal ( InputIterator first, InputIterator last, const V &val )
/// \return true if the value 'val' exists only once in [first, last).
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param val A value to compare against
///
template<typename InputIterator, typename V>
bool one_of_equal ( InputIterator first, InputIterator last, const V &val )
{
InputIterator i = std::find (first, last, val); // find first occurrence of 'val'
if (i == last)
return false; // Didn't occur at all
return boost::algorithm::none_of_equal (++i, last, val);
}
/// \fn one_of_equal ( const Range &r, const V &val )
/// \return true if the value 'val' exists only once in the range.
///
/// \param r The input range
/// \param val A value to compare against
///
template<typename Range, typename V>
bool one_of_equal ( const Range &r, const V &val )
{
return boost::algorithm::one_of_equal ( boost::begin (r), boost::end (r), val );
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_ALL_HPP

View File

@ -1,70 +0,0 @@
/*
Copyright (c) Marshall Clow 2011-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
/// \file partition_copy.hpp
/// \brief Copy a subset of a sequence to a new sequence
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_PARTITION_COPY_HPP
#define BOOST_ALGORITHM_PARTITION_COPY_HPP
#include <utility> // for std::pair
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
/// \fn partition_copy ( InputIterator first, InputIterator last,
/// OutputIterator1 out_true, OutputIterator2 out_false, UnaryPredicate p )
/// \brief Copies the elements that satisfy the predicate p from the range [first, last)
/// to the range beginning at d_first_true, and
/// copies the elements that do not satisfy p to the range beginning at d_first_false.
///
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param out_true An output iterator to write the elements that satisfy the predicate into
/// \param out_false An output iterator to write the elements that do not satisfy the predicate into
/// \param p A predicate for dividing the elements of the input sequence.
///
/// \note This function is part of the C++2011 standard library.
template <typename InputIterator,
typename OutputIterator1, typename OutputIterator2, typename UnaryPredicate>
std::pair<OutputIterator1, OutputIterator2>
partition_copy ( InputIterator first, InputIterator last,
OutputIterator1 out_true, OutputIterator2 out_false, UnaryPredicate p )
{
for ( ; first != last; ++first )
if ( p (*first))
*out_true++ = *first;
else
*out_false++ = *first;
return std::pair<OutputIterator1, OutputIterator2> ( out_true, out_false );
}
/// \fn partition_copy ( const Range &r,
/// OutputIterator1 out_true, OutputIterator2 out_false, UnaryPredicate p )
///
/// \param r The input range
/// \param out_true An output iterator to write the elements that satisfy the predicate into
/// \param out_false An output iterator to write the elements that do not satisfy the predicate into
/// \param p A predicate for dividing the elements of the input sequence.
///
template <typename Range, typename OutputIterator1, typename OutputIterator2,
typename UnaryPredicate>
std::pair<OutputIterator1, OutputIterator2>
partition_copy ( const Range &r, OutputIterator1 out_true, OutputIterator2 out_false,
UnaryPredicate p )
{
return boost::algorithm::partition_copy
(boost::begin(r), boost::end(r), out_true, out_false, p );
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_PARTITION_COPY_HPP

View File

@ -1,65 +0,0 @@
/*
Copyright (c) Marshall Clow 2011-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
/// \file partition_point.hpp
/// \brief Find the partition point in a sequence
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_PARTITION_POINT_HPP
#define BOOST_ALGORITHM_PARTITION_POINT_HPP
#include <iterator> // for std::distance, advance
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
/// \fn partition_point ( ForwardIterator first, ForwardIterator last, Predicate p )
/// \brief Given a partitioned range, returns the partition point, i.e, the first element
/// that does not satisfy p
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param p The predicate to test the values with
/// \note This function is part of the C++2011 standard library.
template <typename ForwardIterator, typename Predicate>
ForwardIterator partition_point ( ForwardIterator first, ForwardIterator last, Predicate p )
{
std::size_t dist = std::distance ( first, last );
while ( first != last ) {
std::size_t d2 = dist / 2;
ForwardIterator ret_val = first;
std::advance (ret_val, d2);
if (p (*ret_val)) {
first = ++ret_val;
dist -= d2 + 1;
}
else {
last = ret_val;
dist = d2;
}
}
return first;
}
/// \fn partition_point ( Range &r, Predicate p )
/// \brief Given a partitioned range, returns the partition point
///
/// \param r The input range
/// \param p The predicate to test the values with
///
template <typename Range, typename Predicate>
typename boost::range_iterator<Range>::type partition_point ( Range &r, Predicate p )
{
return boost::algorithm::partition_point (boost::begin(r), boost::end(r), p);
}
}}
#endif // BOOST_ALGORITHM_PARTITION_POINT_HPP

View File

@ -1,97 +0,0 @@
/*
Copyright (c) Marshall Clow 2008-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
/// \file equal.hpp
/// \brief Test ranges to if they are equal
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_EQUAL_HPP
#define BOOST_ALGORITHM_EQUAL_HPP
#include <algorithm> // for std::equal
#include <iterator>
namespace boost { namespace algorithm {
namespace detail {
template <class T1, class T2>
struct eq {
bool operator () ( const T1& v1, const T2& v2 ) const { return v1 == v2 ;}
};
template <class RandomAccessIterator1, class RandomAccessIterator2, class BinaryPredicate>
bool equal ( RandomAccessIterator1 first1, RandomAccessIterator1 last1,
RandomAccessIterator2 first2, RandomAccessIterator2 last2, BinaryPredicate pred,
std::random_access_iterator_tag, std::random_access_iterator_tag )
{
// Random-access iterators let is check the sizes in constant time
if ( std::distance ( first1, last1 ) != std::distance ( first2, last2 ))
return false;
// If we know that the sequences are the same size, the original version is fine
return std::equal ( first1, last1, first2, pred );
}
template <class InputIterator1, class InputIterator2, class BinaryPredicate>
bool equal ( InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred,
std::input_iterator_tag, std::input_iterator_tag )
{
for (; first1 != last1 && first2 != last2; ++first1, ++first2 )
if ( !pred(*first1, *first2 ))
return false;
return first1 == last1 && first2 == last2;
}
}
/// \fn equal ( InputIterator1 first1, InputIterator1 last1,
/// InputIterator2 first2, InputIterator2 last2,
/// BinaryPredicate pred )
/// \return true if all elements in the two ranges are equal
///
/// \param first1 The start of the first range.
/// \param last1 One past the end of the first range.
/// \param first2 The start of the second range.
/// \param last2 One past the end of the second range.
/// \param pred A predicate for comparing the elements of the ranges
template <class InputIterator1, class InputIterator2, class BinaryPredicate>
bool equal ( InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred )
{
return boost::algorithm::detail::equal (
first1, last1, first2, last2, pred,
typename std::iterator_traits<InputIterator1>::iterator_category (),
typename std::iterator_traits<InputIterator2>::iterator_category ());
}
/// \fn equal ( InputIterator1 first1, InputIterator1 last1,
/// InputIterator2 first2, InputIterator2 last2 )
/// \return true if all elements in the two ranges are equal
///
/// \param first1 The start of the first range.
/// \param last1 One past the end of the first range.
/// \param first2 The start of the second range.
/// \param last2 One past the end of the second range.
template <class InputIterator1, class InputIterator2>
bool equal ( InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2 )
{
return boost::algorithm::detail::equal (
first1, last1, first2, last2,
boost::algorithm::detail::eq<
typename std::iterator_traits<InputIterator1>::value_type,
typename std::iterator_traits<InputIterator2>::value_type> (),
typename std::iterator_traits<InputIterator1>::iterator_category (),
typename std::iterator_traits<InputIterator2>::iterator_category ());
}
// There are already range-based versions of these.
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_EQUAL_HPP

View File

@ -1,79 +0,0 @@
/*
Copyright (c) Marshall Clow 2014.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
/// \file is_permutation.hpp
/// \brief Is a sequence a permutation of another sequence (four iterator versions)
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_IS_PERMUTATION14_HPP
#define BOOST_ALGORITHM_IS_PERMUTATION14_HPP
#include <utility> // for std::pair
#include <functional> // for std::equal_to
#include <iterator>
#include <boost/algorithm/cxx11/is_permutation.hpp>
#include <boost/algorithm/cxx14/mismatch.hpp>
namespace boost { namespace algorithm {
/// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last,
/// ForwardIterator2 first2, ForwardIterator2 last2 )
/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
///
/// \param first1 The start of the input sequence
/// \param last2 One past the end of the input sequence
/// \param first2 The start of the second sequence
/// \param last1 One past the end of the second sequence
/// \note This function is part of the C++2014 standard library.
template< class ForwardIterator1, class ForwardIterator2 >
bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2, ForwardIterator2 last2 )
{
// How should I deal with the idea that ForwardIterator1::value_type
// and ForwardIterator2::value_type could be different? Define my own comparison predicate?
std::pair<ForwardIterator1, ForwardIterator2> eq = boost::algorithm::mismatch
( first1, last1, first2, last2 );
if ( eq.first == last1 && eq.second == last2)
return true;
return boost::algorithm::detail::is_permutation_tag (
eq.first, last1, eq.second, last2,
std::equal_to<typename std::iterator_traits<ForwardIterator1>::value_type> (),
typename std::iterator_traits<ForwardIterator1>::iterator_category (),
typename std::iterator_traits<ForwardIterator2>::iterator_category ());
}
/// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last,
/// ForwardIterator2 first2, ForwardIterator2 last2,
/// BinaryPredicate p )
/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
///
/// \param first1 The start of the input sequence
/// \param last1 One past the end of the input sequence
/// \param first2 The start of the second sequence
/// \param last2 One past the end of the second sequence
/// \param pred The predicate to compare elements with
///
/// \note This function is part of the C++2014 standard library.
template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate >
bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2, ForwardIterator2 last2,
BinaryPredicate pred )
{
std::pair<ForwardIterator1, ForwardIterator2> eq = boost::algorithm::mismatch
( first1, last1, first2, last2, pred );
if ( eq.first == last1 && eq.second == last2)
return true;
return boost::algorithm::detail::is_permutation_tag (
first1, last1, first2, last2, pred,
typename std::iterator_traits<ForwardIterator1>::iterator_category (),
typename std::iterator_traits<ForwardIterator2>::iterator_category ());
}
}}
#endif // BOOST_ALGORITHM_IS_PERMUTATION14_HPP

View File

@ -1,64 +0,0 @@
/*
Copyright (c) Marshall Clow 2008-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
*/
/// \file mismatch.hpp
/// \brief Find the first mismatched element in a sequence
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_MISMATCH_HPP
#define BOOST_ALGORITHM_MISMATCH_HPP
#include <utility> // for std::pair
namespace boost { namespace algorithm {
/// \fn mismatch ( InputIterator1 first1, InputIterator1 last1,
/// InputIterator2 first2, InputIterator2 last2,
/// BinaryPredicate pred )
/// \return a pair of iterators pointing to the first elements in the sequence that do not match
///
/// \param first1 The start of the first range.
/// \param last1 One past the end of the first range.
/// \param first2 The start of the second range.
/// \param last2 One past the end of the second range.
/// \param pred A predicate for comparing the elements of the ranges
template <class InputIterator1, class InputIterator2, class BinaryPredicate>
std::pair<InputIterator1, InputIterator2> mismatch (
InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
BinaryPredicate pred )
{
for (; first1 != last1 && first2 != last2; ++first1, ++first2)
if ( !pred ( *first1, *first2 ))
break;
return std::pair<InputIterator1, InputIterator2>(first1, first2);
}
/// \fn mismatch ( InputIterator1 first1, InputIterator1 last1,
/// InputIterator2 first2, InputIterator2 last2 )
/// \return a pair of iterators pointing to the first elements in the sequence that do not match
///
/// \param first1 The start of the first range.
/// \param last1 One past the end of the first range.
/// \param first2 The start of the second range.
/// \param last2 One past the end of the second range.
template <class InputIterator1, class InputIterator2>
std::pair<InputIterator1, InputIterator2> mismatch (
InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2 )
{
for (; first1 != last1 && first2 != last2; ++first1, ++first2)
if ( *first1 != *first2 )
break;
return std::pair<InputIterator1, InputIterator2>(first1, first2);
}
// There are already range-based versions of these.
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_MISMATCH_HPP

View File

@ -1,52 +0,0 @@
/*
Copyright (c) Marshall Clow 2017.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
*/
/// \file exclusive_scan.hpp
/// \brief ???
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_EXCLUSIVE_SCAN_HPP
#define BOOST_ALGORITHM_EXCLUSIVE_SCAN_HPP
#include <functional> // for std::plus
#include <iterator> // for std::iterator_traits
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/value_type.hpp>
namespace boost { namespace algorithm {
template<class InputIterator, class OutputIterator, class T, class BinaryOperation>
OutputIterator exclusive_scan(InputIterator first, InputIterator last,
OutputIterator result, T init, BinaryOperation bOp)
{
if (first != last)
{
T saved = init;
do
{
init = bOp(init, *first);
*result = saved;
saved = init;
++result;
} while (++first != last);
}
return result;
}
template<class InputIterator, class OutputIterator, class T>
OutputIterator exclusive_scan(InputIterator first, InputIterator last,
OutputIterator result, T init)
{
typedef typename std::iterator_traits<InputIterator>::value_type VT;
return exclusive_scan(first, last, result, init, std::plus<VT>());
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_EXCLUSIVE_SCAN_HPP

View File

@ -1,37 +0,0 @@
/*
Copyright (c) Marshall Clow 2017.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
*/
/// \file for_each_n.hpp
/// \brief Apply a functor to the elements of a sequence
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_FOR_EACH_N_HPP
#define BOOST_ALGORITHM_FOR_EACH_N_HPP
#include <utility> // for std::pair
namespace boost { namespace algorithm {
/// \fn for_each_n(InputIterator first, Size n, Function f);
/// \return first + n
///
/// \param first The start of the first range.
/// \param n One past the end of the first range.
/// \param f A functor to apply to the elements of the sequence
/// \note If f returns a result, the result is ignored.
template<class InputIterator, class Size, class Function>
InputIterator for_each_n(InputIterator first, Size n, Function f)
{
for ( ; n > 0; --n, ++first )
f(*first);
return first;
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_FOR_EACH_N_HPP

View File

@ -1,60 +0,0 @@
/*
Copyright (c) Marshall Clow 2017.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
*/
/// \file transform_reduce.hpp
/// \brief Combine the (transformed) elements of a sequence (or two) into a single value.
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
#define BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
#include <functional> // for std::plus
#include <iterator> // for std::iterator_traits
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/value_type.hpp>
namespace boost { namespace algorithm {
template<class InputIterator, class OutputIterator, class T, class BinaryOperation>
OutputIterator inclusive_scan(InputIterator first, InputIterator last,
OutputIterator result, BinaryOperation bOp, T init)
{
for (; first != last; ++first, (void) ++result) {
init = bOp(init, *first);
*result = init;
}
return result;
}
template<class InputIterator, class OutputIterator, class BinaryOperation>
OutputIterator inclusive_scan(InputIterator first, InputIterator last,
OutputIterator result, BinaryOperation bOp)
{
if (first != last) {
typename std::iterator_traits<InputIterator>::value_type init = *first;
*result++ = init;
if (++first != last)
return inclusive_scan(first, last, result, bOp, init);
}
return result;
}
template<class InputIterator, class OutputIterator>
OutputIterator inclusive_scan(InputIterator first, InputIterator last,
OutputIterator result)
{
typedef typename std::iterator_traits<InputIterator>::value_type VT;
return inclusive_scan(first, last, result, std::plus<VT>());
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP

View File

@ -1,72 +0,0 @@
/*
Copyright (c) Marshall Clow 2017.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
*/
/// \file reduce.hpp
/// \brief Combine the elements of a sequence into a single value
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_REDUCE_HPP
#define BOOST_ALGORITHM_REDUCE_HPP
#include <functional> // for std::plus
#include <iterator> // for std::iterator_traits
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/value_type.hpp>
namespace boost { namespace algorithm {
template<class InputIterator, class T, class BinaryOperation>
T reduce(InputIterator first, InputIterator last, T init, BinaryOperation bOp)
{
;
for (; first != last; ++first)
init = bOp(init, *first);
return init;
}
template<class InputIterator, class T>
T reduce(InputIterator first, InputIterator last, T init)
{
typedef typename std::iterator_traits<InputIterator>::value_type VT;
return reduce(first, last, init, std::plus<VT>());
}
template<class InputIterator>
typename std::iterator_traits<InputIterator>::value_type
reduce(InputIterator first, InputIterator last)
{
return reduce(first, last,
typename std::iterator_traits<InputIterator>::value_type());
}
template<class Range>
typename boost::range_value<Range>::type
reduce(const Range &r)
{
return reduce(boost::begin(r), boost::end(r));
}
// Not sure that this won't be ambiguous (1)
template<class Range, class T>
T reduce(const Range &r, T init)
{
return reduce(boost::begin (r), boost::end (r), init);
}
// Not sure that this won't be ambiguous (2)
template<class Range, class T, class BinaryOperation>
T reduce(const Range &r, T init, BinaryOperation bOp)
{
return reduce(boost::begin(r), boost::end(r), init, bOp);
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_REDUCE_HPP

View File

@ -1,46 +0,0 @@
/*
Copyright (c) Marshall Clow 2017.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
*/
/// \file transform_exclusive_scan.hpp
/// \brief ????
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_TRANSFORM_EXCLUSIVE_SCAN_HPP
#define BOOST_ALGORITHM_TRANSFORM_EXCLUSIVE_SCAN_HPP
#include <functional> // for std::plus
#include <iterator> // for std::iterator_traits
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/value_type.hpp>
namespace boost { namespace algorithm {
template<class InputIterator, class OutputIterator, class T,
class BinaryOperation, class UnaryOperation>
OutputIterator transform_exclusive_scan(InputIterator first, InputIterator last,
OutputIterator result, T init,
BinaryOperation bOp, UnaryOperation uOp)
{
if (first != last)
{
T saved = init;
do
{
init = bOp(init, uOp(*first));
*result = saved;
saved = init;
++result;
} while (++first != last);
}
return result;
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_TRANSFORM_EXCLUSIVE_SCAN_HPP

View File

@ -1,58 +0,0 @@
/*
Copyright (c) Marshall Clow 2017.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
*/
/// \file transform_reduce.hpp
/// \brief Combine the (transformed) elements of a sequence (or two) into a single value.
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
#define BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
#include <functional> // for std::plus
#include <iterator> // for std::iterator_traits
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/value_type.hpp>
namespace boost { namespace algorithm {
template<class InputIterator, class OutputIterator,
class BinaryOperation, class UnaryOperation, class T>
OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last,
OutputIterator result,
BinaryOperation bOp, UnaryOperation uOp,
T init)
{
for (; first != last; ++first, (void) ++result) {
init = bOp(init, uOp(*first));
*result = init;
}
return result;
}
template<class InputIterator, class OutputIterator,
class BinaryOperation, class UnaryOperation>
OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last,
OutputIterator result,
BinaryOperation bOp, UnaryOperation uOp)
{
if (first != last) {
typename std::iterator_traits<InputIterator>::value_type init = uOp(*first);
*result++ = init;
if (++first != last)
return transform_inclusive_scan(first, last, result, bOp, uOp, init);
}
return result;
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP

View File

@ -1,55 +0,0 @@
/*
Copyright (c) Marshall Clow 2017.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
*/
/// \file transform_reduce.hpp
/// \brief Combine the (transformed) elements of a sequence (or two) into a single value.
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
#define BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
#include <functional> // for std::plus
#include <iterator> // for std::iterator_traits
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/value_type.hpp>
namespace boost { namespace algorithm {
template<class InputIterator1, class InputIterator2, class T,
class BinaryOperation1, class BinaryOperation2>
T transform_reduce(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, T init,
BinaryOperation1 bOp1, BinaryOperation2 bOp2)
{
for (; first1 != last1; ++first1, (void) ++first2)
init = bOp1(init, bOp2(*first1, *first2));
return init;
}
template<class InputIterator, class T,
class BinaryOperation, class UnaryOperation>
T transform_reduce(InputIterator first, InputIterator last,
T init, BinaryOperation bOp, UnaryOperation uOp)
{
for (; first != last; ++first)
init = bOp(init, uOp(*first));
return init;
}
template<class InputIterator1, class InputIterator2, class T>
T transform_reduce(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, T init)
{
return transform_reduce(first1, last1, first2, init,
std::plus<T>(), std::multiplies<T>());
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP

View File

@ -1,123 +0,0 @@
/*
Copyright 2008 Adobe Systems Incorporated
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Revision history:
January 2008 mtc Version for Adobe Source Library
January 2013 mtc Version for Boost.Algorithm
*/
/**************************************************************************************************/
/*!
\author Marshall Clow
\date January 2008
*/
#ifndef BOOST_ALGORITHM_GATHER_HPP
#define BOOST_ALGORITHM_GATHER_HPP
#include <algorithm> // for std::stable_partition
#include <functional>
#include <boost/bind.hpp> // for boost::bind
#include <boost/range/begin.hpp> // for boost::begin(range)
#include <boost/range/end.hpp> // for boost::end(range)
/**************************************************************************************************/
/*!
\defgroup gather gather
\ingroup mutating_algorithm
\c gather() takes a collection of elements defined by a pair of iterators and moves
the ones satisfying a predicate to them to a position (called the pivot) within
the sequence. The algorithm is stable. The result is a pair of iterators that
contains the items that satisfy the predicate.
Given an sequence containing:
<pre>
0 1 2 3 4 5 6 7 8 9
</pre>
a call to gather ( arr, arr + 10, arr + 4, IsEven ()) will result in:
<pre>
1 3 0 2 4 6 8 5 7 9
|---|-----|
first | second
pivot
</pre>
The problem is broken down into two basic steps, namely, moving the items before the pivot
and then moving the items from the pivot to the end. These "moves" are done with calls to
stable_partition.
\par Storage Requirements:
The algorithm uses stable_partition, which will attempt to allocate temporary memory,
but will work in-situ if there is none available.
\par Time Complexity:
If there is sufficient memory available, the run time is linear in <code>N</code>.
If there is not any memory available, then the run time is <code>O(N log N)</code>.
*/
/**************************************************************************************************/
namespace boost { namespace algorithm {
/**************************************************************************************************/
/*!
\ingroup gather
\brief iterator-based gather implementation
*/
template <
typename BidirectionalIterator, // Iter models BidirectionalIterator
typename Pred> // Pred models UnaryPredicate
std::pair<BidirectionalIterator, BidirectionalIterator> gather
( BidirectionalIterator first, BidirectionalIterator last, BidirectionalIterator pivot, Pred pred )
{
// The first call partitions everything up to (but not including) the pivot element,
// while the second call partitions the rest of the sequence.
return std::make_pair (
std::stable_partition ( first, pivot, !boost::bind<bool> ( pred, _1 )),
std::stable_partition ( pivot, last, boost::bind<bool> ( pred, _1 )));
}
/**************************************************************************************************/
/*!
\ingroup gather
\brief range-based gather implementation
*/
template <
typename BidirectionalRange, //
typename Pred> // Pred models UnaryPredicate
std::pair<
typename boost::range_iterator<const BidirectionalRange>::type,
typename boost::range_iterator<const BidirectionalRange>::type>
gather (
const BidirectionalRange &range,
typename boost::range_iterator<const BidirectionalRange>::type pivot,
Pred pred )
{
return boost::algorithm::gather ( boost::begin ( range ), boost::end ( range ), pivot, pred );
}
/**************************************************************************************************/
}} // namespace
/**************************************************************************************************/
#endif

View File

@ -1,325 +0,0 @@
/*
Copyright (c) Marshall Clow 2011-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Thanks to Nevin for his comments/help.
*/
/*
General problem - turn a sequence of integral types into a sequence of hexadecimal characters.
- and back.
*/
/// \file hex.hpp
/// \brief Convert sequence of integral types into a sequence of hexadecimal
/// characters and back. Based on the MySQL functions HEX and UNHEX
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_HEXHPP
#define BOOST_ALGORITHM_HEXHPP
#include <iterator> // for std::iterator_traits
#include <stdexcept>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/exception/exception.hpp>
#include <boost/exception/info.hpp>
#include <boost/throw_exception.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_integral.hpp>
namespace boost { namespace algorithm {
/*!
\struct hex_decode_error
\brief Base exception class for all hex decoding errors
*/ /*!
\struct non_hex_input
\brief Thrown when a non-hex value (0-9, A-F) encountered when decoding.
Contains the offending character
*/ /*!
\struct not_enough_input
\brief Thrown when the input sequence unexpectedly ends
*/
struct hex_decode_error : virtual boost::exception, virtual std::exception {};
struct not_enough_input : virtual hex_decode_error {};
struct non_hex_input : virtual hex_decode_error {};
typedef boost::error_info<struct bad_char_,char> bad_char;
namespace detail {
/// \cond DOXYGEN_HIDE
template <typename T, typename OutputIterator>
OutputIterator encode_one ( T val, OutputIterator out, const char * hexDigits ) {
const std::size_t num_hex_digits = 2 * sizeof ( T );
char res [ num_hex_digits ];
char *p = res + num_hex_digits;
for ( std::size_t i = 0; i < num_hex_digits; ++i, val >>= 4 )
*--p = hexDigits [ val & 0x0F ];
return std::copy ( res, res + num_hex_digits, out );
}
template <typename T>
unsigned char hex_char_to_int ( T val ) {
char c = static_cast<char> ( val );
unsigned retval = 0;
if ( c >= '0' && c <= '9' ) retval = c - '0';
else if ( c >= 'A' && c <= 'F' ) retval = c - 'A' + 10;
else if ( c >= 'a' && c <= 'f' ) retval = c - 'a' + 10;
else BOOST_THROW_EXCEPTION (non_hex_input() << bad_char (c));
return static_cast<char>(retval);
}
// My own iterator_traits class.
// It is here so that I can "reach inside" some kinds of output iterators
// and get the type to write.
template <typename Iterator>
struct hex_iterator_traits {
typedef typename std::iterator_traits<Iterator>::value_type value_type;
};
template<typename Container>
struct hex_iterator_traits< std::back_insert_iterator<Container> > {
typedef typename Container::value_type value_type;
};
template<typename Container>
struct hex_iterator_traits< std::front_insert_iterator<Container> > {
typedef typename Container::value_type value_type;
};
template<typename Container>
struct hex_iterator_traits< std::insert_iterator<Container> > {
typedef typename Container::value_type value_type;
};
// ostream_iterators have three template parameters.
// The first one is the output type, the second one is the character type of
// the underlying stream, the third is the character traits.
// We only care about the first one.
template<typename T, typename charType, typename traits>
struct hex_iterator_traits< std::ostream_iterator<T, charType, traits> > {
typedef T value_type;
};
template <typename Iterator>
bool iter_end ( Iterator current, Iterator last ) { return current == last; }
template <typename T>
bool ptr_end ( const T* ptr, const T* /*end*/ ) { return *ptr == '\0'; }
// What can we assume here about the inputs?
// is std::iterator_traits<InputIterator>::value_type always 'char' ?
// Could it be wchar_t, say? Does it matter?
// We are assuming ASCII for the values - but what about the storage?
template <typename InputIterator, typename OutputIterator, typename EndPred>
typename boost::enable_if<boost::is_integral<typename hex_iterator_traits<OutputIterator>::value_type>, OutputIterator>::type
decode_one ( InputIterator &first, InputIterator last, OutputIterator out, EndPred pred ) {
typedef typename hex_iterator_traits<OutputIterator>::value_type T;
T res (0);
// Need to make sure that we get can read that many chars here.
for ( std::size_t i = 0; i < 2 * sizeof ( T ); ++i, ++first ) {
if ( pred ( first, last ))
BOOST_THROW_EXCEPTION (not_enough_input ());
res = ( 16 * res ) + hex_char_to_int (*first);
}
*out = res;
return ++out;
}
/// \endcond
}
/// \fn hex ( InputIterator first, InputIterator last, OutputIterator out )
/// \brief Converts a sequence of integral types into a hexadecimal sequence of characters.
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param out An output iterator to the results into
/// \return The updated output iterator
/// \note Based on the MySQL function of the same name
template <typename InputIterator, typename OutputIterator>
typename boost::enable_if<boost::is_integral<typename detail::hex_iterator_traits<InputIterator>::value_type>, OutputIterator>::type
hex ( InputIterator first, InputIterator last, OutputIterator out ) {
for ( ; first != last; ++first )
out = detail::encode_one ( *first, out, "0123456789ABCDEF" );
return out;
}
/// \fn hex_lower ( InputIterator first, InputIterator last, OutputIterator out )
/// \brief Converts a sequence of integral types into a lower case hexadecimal sequence of characters.
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param out An output iterator to the results into
/// \return The updated output iterator
/// \note Based on the MySQL function of the same name
template <typename InputIterator, typename OutputIterator>
typename boost::enable_if<boost::is_integral<typename detail::hex_iterator_traits<InputIterator>::value_type>, OutputIterator>::type
hex_lower ( InputIterator first, InputIterator last, OutputIterator out ) {
for ( ; first != last; ++first )
out = detail::encode_one ( *first, out, "0123456789abcdef" );
return out;
}
/// \fn hex ( const T *ptr, OutputIterator out )
/// \brief Converts a sequence of integral types into a hexadecimal sequence of characters.
///
/// \param ptr A pointer to a 0-terminated sequence of data.
/// \param out An output iterator to the results into
/// \return The updated output iterator
/// \note Based on the MySQL function of the same name
template <typename T, typename OutputIterator>
typename boost::enable_if<boost::is_integral<T>, OutputIterator>::type
hex ( const T *ptr, OutputIterator out ) {
while ( *ptr )
out = detail::encode_one ( *ptr++, out, "0123456789ABCDEF" );
return out;
}
/// \fn hex_lower ( const T *ptr, OutputIterator out )
/// \brief Converts a sequence of integral types into a lower case hexadecimal sequence of characters.
///
/// \param ptr A pointer to a 0-terminated sequence of data.
/// \param out An output iterator to the results into
/// \return The updated output iterator
/// \note Based on the MySQL function of the same name
template <typename T, typename OutputIterator>
typename boost::enable_if<boost::is_integral<T>, OutputIterator>::type
hex_lower ( const T *ptr, OutputIterator out ) {
while ( *ptr )
out = detail::encode_one ( *ptr++, out, "0123456789abcdef" );
return out;
}
/// \fn hex ( const Range &r, OutputIterator out )
/// \brief Converts a sequence of integral types into a hexadecimal sequence of characters.
///
/// \param r The input range
/// \param out An output iterator to the results into
/// \return The updated output iterator
/// \note Based on the MySQL function of the same name
template <typename Range, typename OutputIterator>
typename boost::enable_if<boost::is_integral<typename detail::hex_iterator_traits<typename Range::iterator>::value_type>, OutputIterator>::type
hex ( const Range &r, OutputIterator out ) {
return hex (boost::begin(r), boost::end(r), out);
}
/// \fn hex_lower ( const Range &r, OutputIterator out )
/// \brief Converts a sequence of integral types into a lower case hexadecimal sequence of characters.
///
/// \param r The input range
/// \param out An output iterator to the results into
/// \return The updated output iterator
/// \note Based on the MySQL function of the same name
template <typename Range, typename OutputIterator>
typename boost::enable_if<boost::is_integral<typename detail::hex_iterator_traits<typename Range::iterator>::value_type>, OutputIterator>::type
hex_lower ( const Range &r, OutputIterator out ) {
return hex_lower (boost::begin(r), boost::end(r), out);
}
/// \fn unhex ( InputIterator first, InputIterator last, OutputIterator out )
/// \brief Converts a sequence of hexadecimal characters into a sequence of integers.
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param out An output iterator to the results into
/// \return The updated output iterator
/// \note Based on the MySQL function of the same name
template <typename InputIterator, typename OutputIterator>
OutputIterator unhex ( InputIterator first, InputIterator last, OutputIterator out ) {
while ( first != last )
out = detail::decode_one ( first, last, out, detail::iter_end<InputIterator> );
return out;
}
/// \fn unhex ( const T *ptr, OutputIterator out )
/// \brief Converts a sequence of hexadecimal characters into a sequence of integers.
///
/// \param ptr A pointer to a null-terminated input sequence.
/// \param out An output iterator to the results into
/// \return The updated output iterator
/// \note Based on the MySQL function of the same name
template <typename T, typename OutputIterator>
OutputIterator unhex ( const T *ptr, OutputIterator out ) {
// If we run into the terminator while decoding, we will throw a
// malformed input exception. It would be nicer to throw a 'Not enough input'
// exception - but how much extra work would that require?
while ( *ptr )
out = detail::decode_one ( ptr, (const T *) NULL, out, detail::ptr_end<T> );
return out;
}
/// \fn OutputIterator unhex ( const Range &r, OutputIterator out )
/// \brief Converts a sequence of hexadecimal characters into a sequence of integers.
///
/// \param r The input range
/// \param out An output iterator to the results into
/// \return The updated output iterator
/// \note Based on the MySQL function of the same name
template <typename Range, typename OutputIterator>
OutputIterator unhex ( const Range &r, OutputIterator out ) {
return unhex (boost::begin(r), boost::end(r), out);
}
/// \fn String hex ( const String &input )
/// \brief Converts a sequence of integral types into a hexadecimal sequence of characters.
///
/// \param input A container to be converted
/// \return A container with the encoded text
template<typename String>
String hex ( const String &input ) {
String output;
output.reserve (input.size () * (2 * sizeof (typename String::value_type)));
(void) hex (input, std::back_inserter (output));
return output;
}
/// \fn String hex_lower ( const String &input )
/// \brief Converts a sequence of integral types into a lower case hexadecimal sequence of characters.
///
/// \param input A container to be converted
/// \return A container with the encoded text
template<typename String>
String hex_lower ( const String &input ) {
String output;
output.reserve (input.size () * (2 * sizeof (typename String::value_type)));
(void) hex_lower (input, std::back_inserter (output));
return output;
}
/// \fn String unhex ( const String &input )
/// \brief Converts a sequence of hexadecimal characters into a sequence of characters.
///
/// \param input A container to be converted
/// \return A container with the decoded text
template<typename String>
String unhex ( const String &input ) {
String output;
output.reserve (input.size () / (2 * sizeof (typename String::value_type)));
(void) unhex (input, std::back_inserter (output));
return output;
}
}}
#endif // BOOST_ALGORITHM_HEXHPP

View File

@ -1,140 +0,0 @@
/*
Copyright (c) Alexander Zaitsev <zamazan4ik@gmail.com>, 2016
Distributed under the Boost Software License, Version 1.0. (See
accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
See http://www.boost.org/ for latest version.
*/
/// \file is_palindrome.hpp
/// \brief Checks the input sequence on palindrome.
/// \author Alexander Zaitsev
#ifndef BOOST_ALGORITHM_IS_PALINDROME_HPP
#define BOOST_ALGORITHM_IS_PALINDROME_HPP
#include <iterator>
#include <functional>
#include <cstring>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
/// \fn is_palindrome ( BidirectionalIterator begin, BidirectionalIterator end, Predicate p )
/// \return true if the entire sequence is palindrome
///
/// \param begin The start of the input sequence
/// \param end One past the end of the input sequence
/// \param p A predicate used to compare the values.
///
/// \note This function will return true for empty sequences and for palindromes.
/// For other sequences function will return false.
/// Complexity: O(N).
template <typename BidirectionalIterator, typename Predicate>
bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end, Predicate p)
{
if(begin == end)
{
return true;
}
--end;
while(begin != end)
{
if(!p(*begin, *end))
{
return false;
}
++begin;
if(begin == end)
{
break;
}
--end;
}
return true;
}
/// \fn is_palindrome ( BidirectionalIterator begin, BidirectionalIterator end )
/// \return true if the entire sequence is palindrome
///
/// \param begin The start of the input sequence
/// \param end One past the end of the input sequence
///
/// \note This function will return true for empty sequences and for palindromes.
/// For other sequences function will return false.
/// Complexity: O(N).
template <typename BidirectionalIterator>
bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end)
{
return is_palindrome(begin, end,
std::equal_to<typename std::iterator_traits<BidirectionalIterator>::value_type> ());
}
/// \fn is_palindrome ( const R& range )
/// \return true if the entire sequence is palindrome
///
/// \param range The range to be tested.
///
/// \note This function will return true for empty sequences and for palindromes.
/// For other sequences function will return false.
/// Complexity: O(N).
template <typename R>
bool is_palindrome(const R& range)
{
return is_palindrome(boost::begin(range), boost::end(range));
}
/// \fn is_palindrome ( const R& range, Predicate p )
/// \return true if the entire sequence is palindrome
///
/// \param range The range to be tested.
/// \param p A predicate used to compare the values.
///
/// \note This function will return true for empty sequences and for palindromes.
/// For other sequences function will return false.
/// Complexity: O(N).
template <typename R, typename Predicate>
bool is_palindrome(const R& range, Predicate p)
{
return is_palindrome(boost::begin(range), boost::end(range), p);
}
/// \fn is_palindrome ( const char* str )
/// \return true if the entire sequence is palindrome
///
/// \param str C-string to be tested.
///
/// \note This function will return true for empty sequences and for palindromes.
/// For other sequences function will return false.
/// Complexity: O(N).
bool is_palindrome(const char* str)
{
if(!str)
return true;
return is_palindrome(str, str + strlen(str));
}
/// \fn is_palindrome ( const char* str, Predicate p )
/// \return true if the entire sequence is palindrome
///
/// \param str C-string to be tested.
/// \param p A predicate used to compare the values.
///
/// \note This function will return true for empty sequences and for palindromes.
/// For other sequences function will return false.
/// Complexity: O(N).
template<typename Predicate>
bool is_palindrome(const char* str, Predicate p)
{
if(!str)
return true;
return is_palindrome(str, str + strlen(str), p);
}
}}
#endif // BOOST_ALGORITHM_IS_PALINDROME_HPP

View File

@ -1,63 +0,0 @@
/*
Copyright (c) Alexander Zaitsev <zamazan4ik@gmail.by>, 2017.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
/// \file is_partitioned_until.hpp
/// \brief Tell if a sequence is partitioned
/// \author Alexander Zaitsev
#ifndef BOOST_ALGORITHM_IS_PARTITIONED_UNTIL_HPP
#define BOOST_ALGORITHM_IS_PARTITIONED_UNTIL_HPP
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
/// \fn is_partitioned_until ( InputIterator first, InputIterator last, UnaryPredicate p )
/// \brief Tests to see if a sequence is partitioned according to a predicate.
/// In other words, all the items in the sequence that satisfy the predicate are at the beginning of the sequence.
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param p The predicate to test the values with
///
/// \note Returns the first iterator 'it' in the sequence [first, last) for which is_partitioned(first, it, p) is false.
/// Returns last if the entire sequence is partitioned.
/// Complexity: O(N).
template <typename InputIterator, typename UnaryPredicate>
InputIterator is_partitioned_until ( InputIterator first, InputIterator last, UnaryPredicate p )
{
// Run through the part that satisfy the predicate
for ( ; first != last; ++first )
if ( !p (*first))
break;
// Now the part that does not satisfy the predicate
for ( ; first != last; ++first )
if ( p (*first))
return first;
return last;
}
/// \fn is_partitioned_until ( const Range &r, UnaryPredicate p )
/// \brief Tests to see if a sequence is partitioned according to a predicate.
/// In other words, all the items in the sequence that satisfy the predicate are at the beginning of the sequence.
///
/// \param r The input range
/// \param p The predicate to test the values with
///
/// \note Returns the first iterator 'it' in the sequence [first, last) for which is_partitioned(first, it, p) is false.
/// Returns last if the entire sequence is partitioned.
/// Complexity: O(N).
template <typename Range, typename UnaryPredicate>
typename boost::range_iterator<const Range>::type is_partitioned_until ( const Range &r, UnaryPredicate p )
{
return boost::algorithm::is_partitioned_until (boost::begin(r), boost::end(r), p);
}
}}
#endif // BOOST_ALGORITHM_IS_PARTITIONED_UNTIL_HPP

View File

@ -1,47 +0,0 @@
// (C) Copyright Herve Bronnimann 2004.
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/*
Revision history:
1 July 2004
Split the code into two headers to lessen dependence on
Boost.tuple. (Herve)
26 June 2004
Added the code for the boost minmax library. (Herve)
*/
#ifndef BOOST_ALGORITHM_MINMAX_HPP
#define BOOST_ALGORITHM_MINMAX_HPP
/* PROPOSED STANDARD EXTENSIONS:
*
* minmax(a, b)
* Effect: (b<a) ? std::make_pair(b,a) : std::make_pair(a,b);
*
* minmax(a, b, comp)
* Effect: comp(b,a) ? std::make_pair(b,a) : std::make_pair(a,b);
*
*/
#include <boost/tuple/tuple.hpp> // for using pairs with boost::cref
#include <boost/ref.hpp>
namespace boost {
template <typename T>
tuple< T const&, T const& >
minmax(T const& a, T const& b) {
return (b<a) ? make_tuple(cref(b),cref(a)) : make_tuple(cref(a),cref(b));
}
template <typename T, class BinaryPredicate>
tuple< T const&, T const& >
minmax(T const& a, T const& b, BinaryPredicate comp) {
return comp(b,a) ? make_tuple(cref(b),cref(a)) : make_tuple(cref(a),cref(b));
}
} // namespace boost
#endif // BOOST_ALGORITHM_MINMAX_HPP

View File

@ -1,553 +0,0 @@
// (C) Copyright Herve Bronnimann 2004.
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/*
Revision history:
1 July 2004
Split the code into two headers to lessen dependence on
Boost.tuple. (Herve)
26 June 2004
Added the code for the boost minmax library. (Herve)
*/
#ifndef BOOST_ALGORITHM_MINMAX_ELEMENT_HPP
#define BOOST_ALGORITHM_MINMAX_ELEMENT_HPP
/* PROPOSED STANDARD EXTENSIONS:
*
* minmax_element(first, last)
* Effect: std::make_pair( std::min_element(first, last),
* std::max_element(first, last) );
*
* minmax_element(first, last, comp)
* Effect: std::make_pair( std::min_element(first, last, comp),
* std::max_element(first, last, comp) );
*/
#include <utility> // for std::pair and std::make_pair
namespace boost {
namespace detail { // for obtaining a uniform version of minmax_element
// that compiles with VC++ 6.0 -- avoid the iterator_traits by
// having comparison object over iterator, not over dereferenced value
template <typename Iterator>
struct less_over_iter {
bool operator()(Iterator const& it1,
Iterator const& it2) const { return *it1 < *it2; }
};
template <typename Iterator, class BinaryPredicate>
struct binary_pred_over_iter {
explicit binary_pred_over_iter(BinaryPredicate const& p ) : m_p( p ) {}
bool operator()(Iterator const& it1,
Iterator const& it2) const { return m_p(*it1, *it2); }
private:
BinaryPredicate m_p;
};
// common base for the two minmax_element overloads
template <typename ForwardIter, class Compare >
std::pair<ForwardIter,ForwardIter>
basic_minmax_element(ForwardIter first, ForwardIter last, Compare comp)
{
if (first == last)
return std::make_pair(last,last);
ForwardIter min_result = first;
ForwardIter max_result = first;
// if only one element
ForwardIter second = first; ++second;
if (second == last)
return std::make_pair(min_result, max_result);
// treat first pair separately (only one comparison for first two elements)
ForwardIter potential_min_result = last;
if (comp(first, second))
max_result = second;
else {
min_result = second;
potential_min_result = first;
}
// then each element by pairs, with at most 3 comparisons per pair
first = ++second; if (first != last) ++second;
while (second != last) {
if (comp(first, second)) {
if (comp(first, min_result)) {
min_result = first;
potential_min_result = last;
}
if (comp(max_result, second))
max_result = second;
} else {
if (comp(second, min_result)) {
min_result = second;
potential_min_result = first;
}
if (comp(max_result, first))
max_result = first;
}
first = ++second;
if (first != last) ++second;
}
// if odd number of elements, treat last element
if (first != last) { // odd number of elements
if (comp(first, min_result)) {
min_result = first;
potential_min_result = last;
}
else if (comp(max_result, first))
max_result = first;
}
// resolve min_result being incorrect with one extra comparison
// (in which case potential_min_result is necessarily the correct result)
if (potential_min_result != last
&& !comp(min_result, potential_min_result))
min_result = potential_min_result;
return std::make_pair(min_result,max_result);
}
} // namespace detail
template <typename ForwardIter>
std::pair<ForwardIter,ForwardIter>
minmax_element(ForwardIter first, ForwardIter last)
{
return detail::basic_minmax_element(first, last,
detail::less_over_iter<ForwardIter>() );
}
template <typename ForwardIter, class BinaryPredicate>
std::pair<ForwardIter,ForwardIter>
minmax_element(ForwardIter first, ForwardIter last, BinaryPredicate comp)
{
return detail::basic_minmax_element(first, last,
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
}
}
/* PROPOSED BOOST EXTENSIONS
* In the description below, [rfirst,rlast) denotes the reversed range
* of [first,last). Even though the iterator type of first and last may
* be only a Forward Iterator, it is possible to explain the semantics
* by assuming that it is a Bidirectional Iterator. In the sequel,
* reverse(ForwardIterator&) returns the reverse_iterator adaptor.
* This is not how the functions would be implemented!
*
* first_min_element(first, last)
* Effect: std::min_element(first, last);
*
* first_min_element(first, last, comp)
* Effect: std::min_element(first, last, comp);
*
* last_min_element(first, last)
* Effect: reverse( std::min_element(reverse(last), reverse(first)) );
*
* last_min_element(first, last, comp)
* Effect: reverse( std::min_element(reverse(last), reverse(first), comp) );
*
* first_max_element(first, last)
* Effect: std::max_element(first, last);
*
* first_max_element(first, last, comp)
* Effect: max_element(first, last);
*
* last_max_element(first, last)
* Effect: reverse( std::max_element(reverse(last), reverse(first)) );
*
* last_max_element(first, last, comp)
* Effect: reverse( std::max_element(reverse(last), reverse(first), comp) );
*
* first_min_first_max_element(first, last)
* Effect: std::make_pair( first_min_element(first, last),
* first_max_element(first, last) );
*
* first_min_first_max_element(first, last, comp)
* Effect: std::make_pair( first_min_element(first, last, comp),
* first_max_element(first, last, comp) );
*
* first_min_last_max_element(first, last)
* Effect: std::make_pair( first_min_element(first, last),
* last_max_element(first, last) );
*
* first_min_last_max_element(first, last, comp)
* Effect: std::make_pair( first_min_element(first, last, comp),
* last_max_element(first, last, comp) );
*
* last_min_first_max_element(first, last)
* Effect: std::make_pair( last_min_element(first, last),
* first_max_element(first, last) );
*
* last_min_first_max_element(first, last, comp)
* Effect: std::make_pair( last_min_element(first, last, comp),
* first_max_element(first, last, comp) );
*
* last_min_last_max_element(first, last)
* Effect: std::make_pair( last_min_element(first, last),
* last_max_element(first, last) );
*
* last_min_last_max_element(first, last, comp)
* Effect: std::make_pair( last_min_element(first, last, comp),
* last_max_element(first, last, comp) );
*/
namespace boost {
// Min_element and max_element variants
namespace detail { // common base for the overloads
template <typename ForwardIter, class BinaryPredicate>
ForwardIter
basic_first_min_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
if (first == last) return last;
ForwardIter min_result = first;
while (++first != last)
if (comp(first, min_result))
min_result = first;
return min_result;
}
template <typename ForwardIter, class BinaryPredicate>
ForwardIter
basic_last_min_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
if (first == last) return last;
ForwardIter min_result = first;
while (++first != last)
if (!comp(min_result, first))
min_result = first;
return min_result;
}
template <typename ForwardIter, class BinaryPredicate>
ForwardIter
basic_first_max_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
if (first == last) return last;
ForwardIter max_result = first;
while (++first != last)
if (comp(max_result, first))
max_result = first;
return max_result;
}
template <typename ForwardIter, class BinaryPredicate>
ForwardIter
basic_last_max_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
if (first == last) return last;
ForwardIter max_result = first;
while (++first != last)
if (!comp(first, max_result))
max_result = first;
return max_result;
}
} // namespace detail
template <typename ForwardIter>
ForwardIter
first_min_element(ForwardIter first, ForwardIter last)
{
return detail::basic_first_min_element(first, last,
detail::less_over_iter<ForwardIter>() );
}
template <typename ForwardIter, class BinaryPredicate>
ForwardIter
first_min_element(ForwardIter first, ForwardIter last, BinaryPredicate comp)
{
return detail::basic_first_min_element(first, last,
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
}
template <typename ForwardIter>
ForwardIter
last_min_element(ForwardIter first, ForwardIter last)
{
return detail::basic_last_min_element(first, last,
detail::less_over_iter<ForwardIter>() );
}
template <typename ForwardIter, class BinaryPredicate>
ForwardIter
last_min_element(ForwardIter first, ForwardIter last, BinaryPredicate comp)
{
return detail::basic_last_min_element(first, last,
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
}
template <typename ForwardIter>
ForwardIter
first_max_element(ForwardIter first, ForwardIter last)
{
return detail::basic_first_max_element(first, last,
detail::less_over_iter<ForwardIter>() );
}
template <typename ForwardIter, class BinaryPredicate>
ForwardIter
first_max_element(ForwardIter first, ForwardIter last, BinaryPredicate comp)
{
return detail::basic_first_max_element(first, last,
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
}
template <typename ForwardIter>
ForwardIter
last_max_element(ForwardIter first, ForwardIter last)
{
return detail::basic_last_max_element(first, last,
detail::less_over_iter<ForwardIter>() );
}
template <typename ForwardIter, class BinaryPredicate>
ForwardIter
last_max_element(ForwardIter first, ForwardIter last, BinaryPredicate comp)
{
return detail::basic_last_max_element(first, last,
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
}
// Minmax_element variants -- comments removed
namespace detail {
template <typename ForwardIter, class BinaryPredicate>
std::pair<ForwardIter,ForwardIter>
basic_first_min_last_max_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
if (first == last)
return std::make_pair(last,last);
ForwardIter min_result = first;
ForwardIter max_result = first;
ForwardIter second = ++first;
if (second == last)
return std::make_pair(min_result, max_result);
if (comp(second, min_result))
min_result = second;
else
max_result = second;
first = ++second; if (first != last) ++second;
while (second != last) {
if (!comp(second, first)) {
if (comp(first, min_result))
min_result = first;
if (!comp(second, max_result))
max_result = second;
} else {
if (comp(second, min_result))
min_result = second;
if (!comp(first, max_result))
max_result = first;
}
first = ++second; if (first != last) ++second;
}
if (first != last) {
if (comp(first, min_result))
min_result = first;
else if (!comp(first, max_result))
max_result = first;
}
return std::make_pair(min_result, max_result);
}
template <typename ForwardIter, class BinaryPredicate>
std::pair<ForwardIter,ForwardIter>
basic_last_min_first_max_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
if (first == last) return std::make_pair(last,last);
ForwardIter min_result = first;
ForwardIter max_result = first;
ForwardIter second = ++first;
if (second == last)
return std::make_pair(min_result, max_result);
if (comp(max_result, second))
max_result = second;
else
min_result = second;
first = ++second; if (first != last) ++second;
while (second != last) {
if (comp(first, second)) {
if (!comp(min_result, first))
min_result = first;
if (comp(max_result, second))
max_result = second;
} else {
if (!comp(min_result, second))
min_result = second;
if (comp(max_result, first))
max_result = first;
}
first = ++second; if (first != last) ++second;
}
if (first != last) {
if (!comp(min_result, first))
min_result = first;
else if (comp(max_result, first))
max_result = first;
}
return std::make_pair(min_result, max_result);
}
template <typename ForwardIter, class BinaryPredicate>
std::pair<ForwardIter,ForwardIter>
basic_last_min_last_max_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
if (first == last) return std::make_pair(last,last);
ForwardIter min_result = first;
ForwardIter max_result = first;
ForwardIter second = first; ++second;
if (second == last)
return std::make_pair(min_result,max_result);
ForwardIter potential_max_result = last;
if (comp(first, second))
max_result = second;
else {
min_result = second;
potential_max_result = second;
}
first = ++second; if (first != last) ++second;
while (second != last) {
if (comp(first, second)) {
if (!comp(min_result, first))
min_result = first;
if (!comp(second, max_result)) {
max_result = second;
potential_max_result = last;
}
} else {
if (!comp(min_result, second))
min_result = second;
if (!comp(first, max_result)) {
max_result = first;
potential_max_result = second;
}
}
first = ++second;
if (first != last) ++second;
}
if (first != last) {
if (!comp(min_result, first))
min_result = first;
if (!comp(first, max_result)) {
max_result = first;
potential_max_result = last;
}
}
if (potential_max_result != last
&& !comp(potential_max_result, max_result))
max_result = potential_max_result;
return std::make_pair(min_result,max_result);
}
} // namespace detail
template <typename ForwardIter>
inline std::pair<ForwardIter,ForwardIter>
first_min_first_max_element(ForwardIter first, ForwardIter last)
{
return minmax_element(first, last);
}
template <typename ForwardIter, class BinaryPredicate>
inline std::pair<ForwardIter,ForwardIter>
first_min_first_max_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
return minmax_element(first, last, comp);
}
template <typename ForwardIter>
std::pair<ForwardIter,ForwardIter>
first_min_last_max_element(ForwardIter first, ForwardIter last)
{
return detail::basic_first_min_last_max_element(first, last,
detail::less_over_iter<ForwardIter>() );
}
template <typename ForwardIter, class BinaryPredicate>
inline std::pair<ForwardIter,ForwardIter>
first_min_last_max_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
return detail::basic_first_min_last_max_element(first, last,
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
}
template <typename ForwardIter>
std::pair<ForwardIter,ForwardIter>
last_min_first_max_element(ForwardIter first, ForwardIter last)
{
return detail::basic_last_min_first_max_element(first, last,
detail::less_over_iter<ForwardIter>() );
}
template <typename ForwardIter, class BinaryPredicate>
inline std::pair<ForwardIter,ForwardIter>
last_min_first_max_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
return detail::basic_last_min_first_max_element(first, last,
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
}
template <typename ForwardIter>
std::pair<ForwardIter,ForwardIter>
last_min_last_max_element(ForwardIter first, ForwardIter last)
{
return detail::basic_last_min_last_max_element(first, last,
detail::less_over_iter<ForwardIter>() );
}
template <typename ForwardIter, class BinaryPredicate>
inline std::pair<ForwardIter,ForwardIter>
last_min_last_max_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
return detail::basic_last_min_last_max_element(first, last,
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
}
} // namespace boost
#endif // BOOST_ALGORITHM_MINMAX_ELEMENT_HPP

View File

@ -1,272 +0,0 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
For more information, see http://www.boost.org
*/
#ifndef BOOST_ALGORITHM_BOYER_MOORE_SEARCH_HPP
#define BOOST_ALGORITHM_BOYER_MOORE_SEARCH_HPP
#include <iterator> // for std::iterator_traits
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/algorithm/searching/detail/bm_traits.hpp>
#include <boost/algorithm/searching/detail/debugging.hpp>
namespace boost { namespace algorithm {
/*
A templated version of the boyer-moore searching algorithm.
References:
http://www.cs.utexas.edu/users/moore/best-ideas/string-searching/
http://www.cs.utexas.edu/~moore/publications/fstrpos.pdf
Explanations:
http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm
http://www.movsd.com/bm.htm
http://www.cs.ucdavis.edu/~gusfield/cs224f09/bnotes.pdf
The Boyer-Moore search algorithm uses two tables, a "bad character" table
to tell how far to skip ahead when it hits a character that is not in the pattern,
and a "good character" table to tell how far to skip ahead when it hits a
mismatch on a character that _is_ in the pattern.
Requirements:
* Random access iterators
* The two iterator types (patIter and corpusIter) must
"point to" the same underlying type and be comparable.
* Additional requirements may be imposed but the skip table, such as:
** Numeric type (array-based skip table)
** Hashable type (map-based skip table)
*/
template <typename patIter, typename traits = detail::BM_traits<patIter> >
class boyer_moore {
typedef typename std::iterator_traits<patIter>::difference_type difference_type;
public:
boyer_moore ( patIter first, patIter last )
: pat_first ( first ), pat_last ( last ),
k_pattern_length ( std::distance ( pat_first, pat_last )),
skip_ ( k_pattern_length, -1 ),
suffix_ ( k_pattern_length + 1 )
{
this->build_skip_table ( first, last );
this->build_suffix_table ( first, last );
}
~boyer_moore () {}
/// \fn operator ( corpusIter corpus_first, corpusIter corpus_last )
/// \brief Searches the corpus for the pattern that was passed into the constructor
///
/// \param corpus_first The start of the data to search (Random Access Iterator)
/// \param corpus_last One past the end of the data to search
///
template <typename corpusIter>
std::pair<corpusIter, corpusIter>
operator () ( corpusIter corpus_first, corpusIter corpus_last ) const {
BOOST_STATIC_ASSERT (( boost::is_same<
typename std::iterator_traits<patIter>::value_type,
typename std::iterator_traits<corpusIter>::value_type>::value ));
if ( corpus_first == corpus_last ) return std::make_pair(corpus_last, corpus_last); // if nothing to search, we didn't find it!
if ( pat_first == pat_last ) return std::make_pair(corpus_first, corpus_first); // empty pattern matches at start
const difference_type k_corpus_length = std::distance ( corpus_first, corpus_last );
// If the pattern is larger than the corpus, we can't find it!
if ( k_corpus_length < k_pattern_length )
return std::make_pair(corpus_last, corpus_last);
// Do the search
return this->do_search ( corpus_first, corpus_last );
}
template <typename Range>
std::pair<typename boost::range_iterator<Range>::type, typename boost::range_iterator<Range>::type>
operator () ( Range &r ) const {
return (*this) (boost::begin(r), boost::end(r));
}
private:
/// \cond DOXYGEN_HIDE
patIter pat_first, pat_last;
const difference_type k_pattern_length;
typename traits::skip_table_t skip_;
std::vector <difference_type> suffix_;
/// \fn operator ( corpusIter corpus_first, corpusIter corpus_last, Pred p )
/// \brief Searches the corpus for the pattern that was passed into the constructor
///
/// \param corpus_first The start of the data to search (Random Access Iterator)
/// \param corpus_last One past the end of the data to search
/// \param p A predicate used for the search comparisons.
///
template <typename corpusIter>
std::pair<corpusIter, corpusIter>
do_search ( corpusIter corpus_first, corpusIter corpus_last ) const {
/* ---- Do the matching ---- */
corpusIter curPos = corpus_first;
const corpusIter lastPos = corpus_last - k_pattern_length;
difference_type j, k, m;
while ( curPos <= lastPos ) {
/* while ( std::distance ( curPos, corpus_last ) >= k_pattern_length ) { */
// Do we match right where we are?
j = k_pattern_length;
while ( pat_first [j-1] == curPos [j-1] ) {
j--;
// We matched - we're done!
if ( j == 0 )
return std::make_pair(curPos, curPos + k_pattern_length);
}
// Since we didn't match, figure out how far to skip forward
k = skip_ [ curPos [ j - 1 ]];
m = j - k - 1;
if ( k < j && m > suffix_ [ j ] )
curPos += m;
else
curPos += suffix_ [ j ];
}
return std::make_pair(corpus_last, corpus_last); // We didn't find anything
}
void build_skip_table ( patIter first, patIter last ) {
for ( std::size_t i = 0; first != last; ++first, ++i )
skip_.insert ( *first, i );
}
template<typename Iter, typename Container>
void compute_bm_prefix ( Iter first, Iter last, Container &prefix ) {
const std::size_t count = std::distance ( first, last );
BOOST_ASSERT ( count > 0 );
BOOST_ASSERT ( prefix.size () == count );
prefix[0] = 0;
std::size_t k = 0;
for ( std::size_t i = 1; i < count; ++i ) {
BOOST_ASSERT ( k < count );
while ( k > 0 && ( first[k] != first[i] )) {
BOOST_ASSERT ( k < count );
k = prefix [ k - 1 ];
}
if ( first[k] == first[i] )
k++;
prefix [ i ] = k;
}
}
void build_suffix_table ( patIter first, patIter last ) {
const std::size_t count = (std::size_t) std::distance ( first, last );
if ( count > 0 ) { // empty pattern
std::vector<typename std::iterator_traits<patIter>::value_type> reversed(count);
(void) std::reverse_copy ( first, last, reversed.begin ());
std::vector<difference_type> prefix (count);
compute_bm_prefix ( first, last, prefix );
std::vector<difference_type> prefix_reversed (count);
compute_bm_prefix ( reversed.begin (), reversed.end (), prefix_reversed );
for ( std::size_t i = 0; i <= count; i++ )
suffix_[i] = count - prefix [count-1];
for ( std::size_t i = 0; i < count; i++ ) {
const std::size_t j = count - prefix_reversed[i];
const difference_type k = i - prefix_reversed[i] + 1;
if (suffix_[j] > k)
suffix_[j] = k;
}
}
}
/// \endcond
};
/* Two ranges as inputs gives us four possibilities; with 2,3,3,4 parameters
Use a bit of TMP to disambiguate the 3-argument templates */
/// \fn boyer_moore_search ( corpusIter corpus_first, corpusIter corpus_last,
/// patIter pat_first, patIter pat_last )
/// \brief Searches the corpus for the pattern.
///
/// \param corpus_first The start of the data to search (Random Access Iterator)
/// \param corpus_last One past the end of the data to search
/// \param pat_first The start of the pattern to search for (Random Access Iterator)
/// \param pat_last One past the end of the data to search for
///
template <typename patIter, typename corpusIter>
std::pair<corpusIter, corpusIter> boyer_moore_search (
corpusIter corpus_first, corpusIter corpus_last,
patIter pat_first, patIter pat_last )
{
boyer_moore<patIter> bm ( pat_first, pat_last );
return bm ( corpus_first, corpus_last );
}
template <typename PatternRange, typename corpusIter>
std::pair<corpusIter, corpusIter> boyer_moore_search (
corpusIter corpus_first, corpusIter corpus_last, const PatternRange &pattern )
{
typedef typename boost::range_iterator<const PatternRange>::type pattern_iterator;
boyer_moore<pattern_iterator> bm ( boost::begin(pattern), boost::end (pattern));
return bm ( corpus_first, corpus_last );
}
template <typename patIter, typename CorpusRange>
typename boost::disable_if_c<
boost::is_same<CorpusRange, patIter>::value,
std::pair<typename boost::range_iterator<CorpusRange>::type, typename boost::range_iterator<CorpusRange>::type> >
::type
boyer_moore_search ( CorpusRange &corpus, patIter pat_first, patIter pat_last )
{
boyer_moore<patIter> bm ( pat_first, pat_last );
return bm (boost::begin (corpus), boost::end (corpus));
}
template <typename PatternRange, typename CorpusRange>
std::pair<typename boost::range_iterator<CorpusRange>::type, typename boost::range_iterator<CorpusRange>::type>
boyer_moore_search ( CorpusRange &corpus, const PatternRange &pattern )
{
typedef typename boost::range_iterator<const PatternRange>::type pattern_iterator;
boyer_moore<pattern_iterator> bm ( boost::begin(pattern), boost::end (pattern));
return bm (boost::begin (corpus), boost::end (corpus));
}
// Creator functions -- take a pattern range, return an object
template <typename Range>
boost::algorithm::boyer_moore<typename boost::range_iterator<const Range>::type>
make_boyer_moore ( const Range &r ) {
return boost::algorithm::boyer_moore
<typename boost::range_iterator<const Range>::type> (boost::begin(r), boost::end(r));
}
template <typename Range>
boost::algorithm::boyer_moore<typename boost::range_iterator<Range>::type>
make_boyer_moore ( Range &r ) {
return boost::algorithm::boyer_moore
<typename boost::range_iterator<Range>::type> (boost::begin(r), boost::end(r));
}
}}
#endif // BOOST_ALGORITHM_BOYER_MOORE_SEARCH_HPP

View File

@ -1,202 +0,0 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
For more information, see http://www.boost.org
*/
#ifndef BOOST_ALGORITHM_BOYER_MOORE_HORSPOOOL_SEARCH_HPP
#define BOOST_ALGORITHM_BOYER_MOORE_HORSPOOOL_SEARCH_HPP
#include <iterator> // for std::iterator_traits
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/algorithm/searching/detail/bm_traits.hpp>
#include <boost/algorithm/searching/detail/debugging.hpp>
// #define BOOST_ALGORITHM_BOYER_MOORE_HORSPOOL_DEBUG_HPP
namespace boost { namespace algorithm {
/*
A templated version of the boyer-moore-horspool searching algorithm.
Requirements:
* Random access iterators
* The two iterator types (patIter and corpusIter) must
"point to" the same underlying type.
* Additional requirements may be imposed buy the skip table, such as:
** Numeric type (array-based skip table)
** Hashable type (map-based skip table)
http://www-igm.univ-mlv.fr/%7Elecroq/string/node18.html
*/
template <typename patIter, typename traits = detail::BM_traits<patIter> >
class boyer_moore_horspool {
typedef typename std::iterator_traits<patIter>::difference_type difference_type;
public:
boyer_moore_horspool ( patIter first, patIter last )
: pat_first ( first ), pat_last ( last ),
k_pattern_length ( std::distance ( pat_first, pat_last )),
skip_ ( k_pattern_length, k_pattern_length ) {
// Build the skip table
std::size_t i = 0;
if ( first != last ) // empty pattern?
for ( patIter iter = first; iter != last-1; ++iter, ++i )
skip_.insert ( *iter, k_pattern_length - 1 - i );
#ifdef BOOST_ALGORITHM_BOYER_MOORE_HORSPOOL_DEBUG_HPP
skip_.PrintSkipTable ();
#endif
}
~boyer_moore_horspool () {}
/// \fn operator ( corpusIter corpus_first, corpusIter corpus_last)
/// \brief Searches the corpus for the pattern that was passed into the constructor
///
/// \param corpus_first The start of the data to search (Random Access Iterator)
/// \param corpus_last One past the end of the data to search
///
template <typename corpusIter>
std::pair<corpusIter, corpusIter>
operator () ( corpusIter corpus_first, corpusIter corpus_last ) const {
BOOST_STATIC_ASSERT (( boost::is_same<
typename std::iterator_traits<patIter>::value_type,
typename std::iterator_traits<corpusIter>::value_type>::value ));
if ( corpus_first == corpus_last ) return std::make_pair(corpus_last, corpus_last); // if nothing to search, we didn't find it!
if ( pat_first == pat_last ) return std::make_pair(corpus_first, corpus_first); // empty pattern matches at start
const difference_type k_corpus_length = std::distance ( corpus_first, corpus_last );
// If the pattern is larger than the corpus, we can't find it!
if ( k_corpus_length < k_pattern_length )
return std::make_pair(corpus_last, corpus_last);
// Do the search
return this->do_search ( corpus_first, corpus_last );
}
template <typename Range>
std::pair<typename boost::range_iterator<Range>::type, typename boost::range_iterator<Range>::type>
operator () ( Range &r ) const {
return (*this) (boost::begin(r), boost::end(r));
}
private:
/// \cond DOXYGEN_HIDE
patIter pat_first, pat_last;
const difference_type k_pattern_length;
typename traits::skip_table_t skip_;
/// \fn do_search ( corpusIter corpus_first, corpusIter corpus_last )
/// \brief Searches the corpus for the pattern that was passed into the constructor
///
/// \param corpus_first The start of the data to search (Random Access Iterator)
/// \param corpus_last One past the end of the data to search
/// \param k_corpus_length The length of the corpus to search
///
template <typename corpusIter>
std::pair<corpusIter, corpusIter>
do_search ( corpusIter corpus_first, corpusIter corpus_last ) const {
corpusIter curPos = corpus_first;
const corpusIter lastPos = corpus_last - k_pattern_length;
while ( curPos <= lastPos ) {
// Do we match right where we are?
std::size_t j = k_pattern_length - 1;
while ( pat_first [j] == curPos [j] ) {
// We matched - we're done!
if ( j == 0 )
return std::make_pair(curPos, curPos + k_pattern_length);
j--;
}
curPos += skip_ [ curPos [ k_pattern_length - 1 ]];
}
return std::make_pair(corpus_last, corpus_last);
}
// \endcond
};
/* Two ranges as inputs gives us four possibilities; with 2,3,3,4 parameters
Use a bit of TMP to disambiguate the 3-argument templates */
/// \fn boyer_moore_horspool_search ( corpusIter corpus_first, corpusIter corpus_last,
/// patIter pat_first, patIter pat_last )
/// \brief Searches the corpus for the pattern.
///
/// \param corpus_first The start of the data to search (Random Access Iterator)
/// \param corpus_last One past the end of the data to search
/// \param pat_first The start of the pattern to search for (Random Access Iterator)
/// \param pat_last One past the end of the data to search for
///
template <typename patIter, typename corpusIter>
std::pair<corpusIter, corpusIter> boyer_moore_horspool_search (
corpusIter corpus_first, corpusIter corpus_last,
patIter pat_first, patIter pat_last )
{
boyer_moore_horspool<patIter> bmh ( pat_first, pat_last );
return bmh ( corpus_first, corpus_last );
}
template <typename PatternRange, typename corpusIter>
std::pair<corpusIter, corpusIter> boyer_moore_horspool_search (
corpusIter corpus_first, corpusIter corpus_last, const PatternRange &pattern )
{
typedef typename boost::range_iterator<const PatternRange>::type pattern_iterator;
boyer_moore_horspool<pattern_iterator> bmh ( boost::begin(pattern), boost::end (pattern));
return bmh ( corpus_first, corpus_last );
}
template <typename patIter, typename CorpusRange>
typename boost::disable_if_c<
boost::is_same<CorpusRange, patIter>::value,
std::pair<typename boost::range_iterator<CorpusRange>::type, typename boost::range_iterator<CorpusRange>::type> >
::type
boyer_moore_horspool_search ( CorpusRange &corpus, patIter pat_first, patIter pat_last )
{
boyer_moore_horspool<patIter> bmh ( pat_first, pat_last );
return bm (boost::begin (corpus), boost::end (corpus));
}
template <typename PatternRange, typename CorpusRange>
std::pair<typename boost::range_iterator<CorpusRange>::type, typename boost::range_iterator<CorpusRange>::type>
boyer_moore_horspool_search ( CorpusRange &corpus, const PatternRange &pattern )
{
typedef typename boost::range_iterator<const PatternRange>::type pattern_iterator;
boyer_moore_horspool<pattern_iterator> bmh ( boost::begin(pattern), boost::end (pattern));
return bmh (boost::begin (corpus), boost::end (corpus));
}
// Creator functions -- take a pattern range, return an object
template <typename Range>
boost::algorithm::boyer_moore_horspool<typename boost::range_iterator<const Range>::type>
make_boyer_moore_horspool ( const Range &r ) {
return boost::algorithm::boyer_moore_horspool
<typename boost::range_iterator<const Range>::type> (boost::begin(r), boost::end(r));
}
template <typename Range>
boost::algorithm::boyer_moore_horspool<typename boost::range_iterator<Range>::type>
make_boyer_moore_horspool ( Range &r ) {
return boost::algorithm::boyer_moore_horspool
<typename boost::range_iterator<Range>::type> (boost::begin(r), boost::end(r));
}
}}
#endif // BOOST_ALGORITHM_BOYER_MOORE_HORSPOOOL_SEARCH_HPP

View File

@ -1,113 +0,0 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
For more information, see http://www.boost.org
*/
#ifndef BOOST_ALGORITHM_SEARCH_DETAIL_BM_TRAITS_HPP
#define BOOST_ALGORITHM_SEARCH_DETAIL_BM_TRAITS_HPP
#include <climits> // for CHAR_BIT
#include <vector>
#include <iterator> // for std::iterator_traits
#include <boost/type_traits/make_unsigned.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/array.hpp>
#ifdef BOOST_NO_CXX11_HDR_UNORDERED_MAP
#include <boost/unordered_map.hpp>
#else
#include <unordered_map>
#endif
#include <boost/algorithm/searching/detail/debugging.hpp>
namespace boost { namespace algorithm { namespace detail {
//
// Default implementations of the skip tables for B-M and B-M-H
//
template<typename key_type, typename value_type, bool /*useArray*/> class skip_table;
// General case for data searching other than bytes; use a map
template<typename key_type, typename value_type>
class skip_table<key_type, value_type, false> {
private:
#ifdef BOOST_NO_CXX11_HDR_UNORDERED_MAP
typedef boost::unordered_map<key_type, value_type> skip_map;
#else
typedef std::unordered_map<key_type, value_type> skip_map;
#endif
const value_type k_default_value;
skip_map skip_;
public:
skip_table ( std::size_t patSize, value_type default_value )
: k_default_value ( default_value ), skip_ ( patSize ) {}
void insert ( key_type key, value_type val ) {
skip_ [ key ] = val; // Would skip_.insert (val) be better here?
}
value_type operator [] ( key_type key ) const {
typename skip_map::const_iterator it = skip_.find ( key );
return it == skip_.end () ? k_default_value : it->second;
}
void PrintSkipTable () const {
std::cout << "BM(H) Skip Table <unordered_map>:" << std::endl;
for ( typename skip_map::const_iterator it = skip_.begin (); it != skip_.end (); ++it )
if ( it->second != k_default_value )
std::cout << " " << it->first << ": " << it->second << std::endl;
std::cout << std::endl;
}
};
// Special case small numeric values; use an array
template<typename key_type, typename value_type>
class skip_table<key_type, value_type, true> {
private:
typedef typename boost::make_unsigned<key_type>::type unsigned_key_type;
typedef boost::array<value_type, 1U << (CHAR_BIT * sizeof(key_type))> skip_map;
skip_map skip_;
const value_type k_default_value;
public:
skip_table ( std::size_t /*patSize*/, value_type default_value ) : k_default_value ( default_value ) {
std::fill_n ( skip_.begin(), skip_.size(), default_value );
}
void insert ( key_type key, value_type val ) {
skip_ [ static_cast<unsigned_key_type> ( key ) ] = val;
}
value_type operator [] ( key_type key ) const {
return skip_ [ static_cast<unsigned_key_type> ( key ) ];
}
void PrintSkipTable () const {
std::cout << "BM(H) Skip Table <boost:array>:" << std::endl;
for ( typename skip_map::const_iterator it = skip_.begin (); it != skip_.end (); ++it )
if ( *it != k_default_value )
std::cout << " " << std::distance (skip_.begin (), it) << ": " << *it << std::endl;
std::cout << std::endl;
}
};
template<typename Iterator>
struct BM_traits {
typedef typename std::iterator_traits<Iterator>::difference_type value_type;
typedef typename std::iterator_traits<Iterator>::value_type key_type;
typedef boost::algorithm::detail::skip_table<key_type, value_type,
boost::is_integral<key_type>::value && (sizeof(key_type)==1)> skip_table_t;
};
}}} // namespaces
#endif // BOOST_ALGORITHM_SEARCH_DETAIL_BM_TRAITS_HPP

View File

@ -1,30 +0,0 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
For more information, see http://www.boost.org
*/
#ifndef BOOST_ALGORITHM_SEARCH_DETAIL_DEBUG_HPP
#define BOOST_ALGORITHM_SEARCH_DETAIL_DEBUG_HPP
#include <iostream>
/// \cond DOXYGEN_HIDE
namespace boost { namespace algorithm { namespace detail {
// Debugging support
template <typename Iter>
void PrintTable ( Iter first, Iter last ) {
std::cout << std::distance ( first, last ) << ": { ";
for ( Iter iter = first; iter != last; ++iter )
std::cout << *iter << " ";
std::cout << "}" << std::endl;
}
}}}
/// \endcond
#endif // BOOST_ALGORITHM_SEARCH_DETAIL_DEBUG_HPP

View File

@ -1,263 +0,0 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
For more information, see http://www.boost.org
*/
#ifndef BOOST_ALGORITHM_KNUTH_MORRIS_PRATT_SEARCH_HPP
#define BOOST_ALGORITHM_KNUTH_MORRIS_PRATT_SEARCH_HPP
#include <vector>
#include <iterator> // for std::iterator_traits
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/algorithm/searching/detail/debugging.hpp>
// #define BOOST_ALGORITHM_KNUTH_MORRIS_PRATT_DEBUG
namespace boost { namespace algorithm {
// #define NEW_KMP
/*
A templated version of the Knuth-Morris-Pratt searching algorithm.
Requirements:
* Random-access iterators
* The two iterator types (I1 and I2) must "point to" the same underlying type.
http://en.wikipedia.org/wiki/Knuth-Morris-Pratt_algorithm
http://www.inf.fh-flensburg.de/lang/algorithmen/pattern/kmpen.htm
*/
template <typename patIter>
class knuth_morris_pratt {
typedef typename std::iterator_traits<patIter>::difference_type difference_type;
public:
knuth_morris_pratt ( patIter first, patIter last )
: pat_first ( first ), pat_last ( last ),
k_pattern_length ( std::distance ( pat_first, pat_last )),
skip_ ( k_pattern_length + 1 ) {
#ifdef NEW_KMP
preKmp ( pat_first, pat_last );
#else
init_skip_table ( pat_first, pat_last );
#endif
#ifdef BOOST_ALGORITHM_KNUTH_MORRIS_PRATT_DEBUG
detail::PrintTable ( skip_.begin (), skip_.end ());
#endif
}
~knuth_morris_pratt () {}
/// \fn operator ( corpusIter corpus_first, corpusIter corpus_last, Pred p )
/// \brief Searches the corpus for the pattern that was passed into the constructor
///
/// \param corpus_first The start of the data to search (Random Access Iterator)
/// \param corpus_last One past the end of the data to search
/// \param p A predicate used for the search comparisons.
///
template <typename corpusIter>
std::pair<corpusIter, corpusIter>
operator () ( corpusIter corpus_first, corpusIter corpus_last ) const {
BOOST_STATIC_ASSERT (( boost::is_same<
typename std::iterator_traits<patIter>::value_type,
typename std::iterator_traits<corpusIter>::value_type>::value ));
if ( corpus_first == corpus_last ) return std::make_pair(corpus_last, corpus_last); // if nothing to search, we didn't find it!
if ( pat_first == pat_last ) return std::make_pair(corpus_first, corpus_first); // empty pattern matches at start
const difference_type k_corpus_length = std::distance ( corpus_first, corpus_last );
// If the pattern is larger than the corpus, we can't find it!
if ( k_corpus_length < k_pattern_length )
return std::make_pair(corpus_last, corpus_last);
return do_search ( corpus_first, corpus_last, k_corpus_length );
}
template <typename Range>
std::pair<typename boost::range_iterator<Range>::type, typename boost::range_iterator<Range>::type>
operator () ( Range &r ) const {
return (*this) (boost::begin(r), boost::end(r));
}
private:
/// \cond DOXYGEN_HIDE
patIter pat_first, pat_last;
const difference_type k_pattern_length;
std::vector <difference_type> skip_;
/// \fn operator ( corpusIter corpus_first, corpusIter corpus_last, Pred p )
/// \brief Searches the corpus for the pattern that was passed into the constructor
///
/// \param corpus_first The start of the data to search (Random Access Iterator)
/// \param corpus_last One past the end of the data to search
/// \param p A predicate used for the search comparisons.
///
template <typename corpusIter>
std::pair<corpusIter, corpusIter>
do_search ( corpusIter corpus_first, corpusIter corpus_last,
difference_type k_corpus_length ) const {
difference_type match_start = 0; // position in the corpus that we're matching
#ifdef NEW_KMP
int patternIdx = 0;
while ( match_start < k_corpus_length ) {
while ( patternIdx > -1 && pat_first[patternIdx] != corpus_first [match_start] )
patternIdx = skip_ [patternIdx]; //<--- Shifting the pattern on mismatch
patternIdx++;
match_start++; //<--- corpus is always increased by 1
if ( patternIdx >= (int) k_pattern_length )
return corpus_first + match_start - patternIdx;
}
#else
// At this point, we know:
// k_pattern_length <= k_corpus_length
// for all elements of skip, it holds -1 .. k_pattern_length
//
// In the loop, we have the following invariants
// idx is in the range 0 .. k_pattern_length
// match_start is in the range 0 .. k_corpus_length - k_pattern_length + 1
const difference_type last_match = k_corpus_length - k_pattern_length;
difference_type idx = 0; // position in the pattern we're comparing
while ( match_start <= last_match ) {
while ( pat_first [ idx ] == corpus_first [ match_start + idx ] ) {
if ( ++idx == k_pattern_length )
return std::make_pair(corpus_first + match_start, corpus_first + match_start + k_pattern_length);
}
// Figure out where to start searching again
// assert ( idx - skip_ [ idx ] > 0 ); // we're always moving forward
match_start += idx - skip_ [ idx ];
idx = skip_ [ idx ] >= 0 ? skip_ [ idx ] : 0;
// assert ( idx >= 0 && idx < k_pattern_length );
}
#endif
// We didn't find anything
return std::make_pair(corpus_last, corpus_last);
}
void preKmp ( patIter first, patIter last ) {
const difference_type count = std::distance ( first, last );
difference_type i, j;
i = 0;
j = skip_[0] = -1;
while (i < count) {
while (j > -1 && first[i] != first[j])
j = skip_[j];
i++;
j++;
if (first[i] == first[j])
skip_[i] = skip_[j];
else
skip_[i] = j;
}
}
void init_skip_table ( patIter first, patIter last ) {
const difference_type count = std::distance ( first, last );
difference_type j;
skip_ [ 0 ] = -1;
for ( int i = 1; i <= count; ++i ) {
j = skip_ [ i - 1 ];
while ( j >= 0 ) {
if ( first [ j ] == first [ i - 1 ] )
break;
j = skip_ [ j ];
}
skip_ [ i ] = j + 1;
}
}
// \endcond
};
/* Two ranges as inputs gives us four possibilities; with 2,3,3,4 parameters
Use a bit of TMP to disambiguate the 3-argument templates */
/// \fn knuth_morris_pratt_search ( corpusIter corpus_first, corpusIter corpus_last,
/// patIter pat_first, patIter pat_last )
/// \brief Searches the corpus for the pattern.
///
/// \param corpus_first The start of the data to search (Random Access Iterator)
/// \param corpus_last One past the end of the data to search
/// \param pat_first The start of the pattern to search for (Random Access Iterator)
/// \param pat_last One past the end of the data to search for
///
template <typename patIter, typename corpusIter>
std::pair<corpusIter, corpusIter> knuth_morris_pratt_search (
corpusIter corpus_first, corpusIter corpus_last,
patIter pat_first, patIter pat_last )
{
knuth_morris_pratt<patIter> kmp ( pat_first, pat_last );
return kmp ( corpus_first, corpus_last );
}
template <typename PatternRange, typename corpusIter>
std::pair<corpusIter, corpusIter> knuth_morris_pratt_search (
corpusIter corpus_first, corpusIter corpus_last, const PatternRange &pattern )
{
typedef typename boost::range_iterator<const PatternRange>::type pattern_iterator;
knuth_morris_pratt<pattern_iterator> kmp ( boost::begin(pattern), boost::end (pattern));
return kmp ( corpus_first, corpus_last );
}
template <typename patIter, typename CorpusRange>
typename boost::disable_if_c<
boost::is_same<CorpusRange, patIter>::value,
std::pair<typename boost::range_iterator<CorpusRange>::type, typename boost::range_iterator<CorpusRange>::type> >
::type
knuth_morris_pratt_search ( CorpusRange &corpus, patIter pat_first, patIter pat_last )
{
knuth_morris_pratt<patIter> kmp ( pat_first, pat_last );
return kmp (boost::begin (corpus), boost::end (corpus));
}
template <typename PatternRange, typename CorpusRange>
std::pair<typename boost::range_iterator<CorpusRange>::type, typename boost::range_iterator<CorpusRange>::type>
knuth_morris_pratt_search ( CorpusRange &corpus, const PatternRange &pattern )
{
typedef typename boost::range_iterator<const PatternRange>::type pattern_iterator;
knuth_morris_pratt<pattern_iterator> kmp ( boost::begin(pattern), boost::end (pattern));
return kmp (boost::begin (corpus), boost::end (corpus));
}
// Creator functions -- take a pattern range, return an object
template <typename Range>
boost::algorithm::knuth_morris_pratt<typename boost::range_iterator<const Range>::type>
make_knuth_morris_pratt ( const Range &r ) {
return boost::algorithm::knuth_morris_pratt
<typename boost::range_iterator<const Range>::type> (boost::begin(r), boost::end(r));
}
template <typename Range>
boost::algorithm::knuth_morris_pratt<typename boost::range_iterator<Range>::type>
make_knuth_morris_pratt ( Range &r ) {
return boost::algorithm::knuth_morris_pratt
<typename boost::range_iterator<Range>::type> (boost::begin(r), boost::end(r));
}
}}
#endif // BOOST_ALGORITHM_KNUTH_MORRIS_PRATT_SEARCH_HPP

View File

@ -1,109 +0,0 @@
/*
Copyright (c) Marshall Clow 2008-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Revision history:
28 Sep 2015 mtc First version
*/
/// \file sort_subrange.hpp
/// \brief Sort a subrange
/// \author Marshall Clow
///
/// Suggested by Sean Parent in his CppCon 2015 keynote
#ifndef BOOST_ALGORITHM_SORT_SUBRANGE_HPP
#define BOOST_ALGORITHM_SORT_SUBRANGE_HPP
#include <functional> // For std::less
#include <iterator> // For std::iterator_traits
#include <algorithm> // For nth_element and partial_sort
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
/// \fn sort_subrange ( T const& val,
/// Iterator first, Iterator last,
/// Iterator sub_first, Iterator sub_last,
/// Pred p )
/// \brief Sort the subrange [sub_first, sub_last) that is inside
/// the range [first, last) as if you had sorted the entire range.
///
/// \param first The start of the larger range
/// \param last The end of the larger range
/// \param sub_first The start of the sub range
/// \param sub_last The end of the sub range
/// \param p A predicate to use to compare the values.
/// p ( a, b ) returns a boolean.
///
template<typename Iterator, typename Pred>
void sort_subrange (
Iterator first, Iterator last,
Iterator sub_first, Iterator sub_last,
Pred p)
{
if (sub_first == sub_last) return; // the empty sub-range is already sorted.
if (sub_first != first) { // sub-range is at the start, don't need to partition
(void) std::nth_element(first, sub_first, last, p);
++sub_first;
}
std::partial_sort(sub_first, sub_last, last, p);
}
template<typename Iterator>
void sort_subrange (Iterator first, Iterator last, Iterator sub_first, Iterator sub_last)
{
typedef typename std::iterator_traits<Iterator>::value_type value_type;
return sort_subrange(first, last, sub_first, sub_last, std::less<value_type>());
}
/// range versions?
/// \fn partition_subrange ( T const& val,
/// Iterator first, Iterator last,
/// Iterator sub_first, Iterator sub_last,
/// Pred p )
/// \brief Gather the elements of the subrange [sub_first, sub_last) that is
/// inside the range [first, last) as if you had sorted the entire range.
///
/// \param first The start of the larger range
/// \param last The end of the larger range
/// \param sub_first The start of the sub range
/// \param sub_last The end of the sub range
/// \param p A predicate to use to compare the values.
/// p ( a, b ) returns a boolean.
///
template<typename Iterator, typename Pred>
void partition_subrange (
Iterator first, Iterator last,
Iterator sub_first, Iterator sub_last,
Pred p)
{
if (sub_first != first) {
(void) std::nth_element(first, sub_first, last, p);
++sub_first;
}
if (sub_last != last)
(void) std::nth_element(sub_first, sub_last, last, p);
}
template<typename Iterator>
void partition_subrange (Iterator first, Iterator last, Iterator sub_first, Iterator sub_last)
{
typedef typename std::iterator_traits<Iterator>::value_type value_type;
return partition_subrange(first, last, sub_first, sub_last, std::less<value_type>());
}
}}
#endif // BOOST_ALGORITHM_SORT_SUBRANGE_HPP

View File

@ -1,31 +0,0 @@
// Boost string_algo library string_algo.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2004.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_ALGO_HPP
#define BOOST_STRING_ALGO_HPP
/*! \file
Cumulative include for string_algo library
*/
#include <boost/algorithm/string/std_containers_traits.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/find.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/erase.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/find_iterator.hpp>
#endif // BOOST_STRING_ALGO_HPP

Some files were not shown because too many files have changed in this diff Show More