Merge commit '3c2d228ddc74b75122b07a87bbd06263092a9661' into next
This commit is contained in:
commit
0e82bd0d63
58 changed files with 2354 additions and 178 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -1,3 +0,0 @@
|
|||
[submodule "lib/utfcpp"]
|
||||
path = lib/utfcpp
|
||||
url = http://github.com/ledger/utfcpp.git
|
||||
102
.travis.yml
102
.travis.yml
|
|
@ -2,34 +2,106 @@
|
|||
# provides GNU GCC 4.6, which does not support -std=c++11 GNU GCC 4.8 is installed
|
||||
|
||||
# NOTE: Please validate this file after editing it using
|
||||
# Travis WebLint http://lint.travis-ci.org/
|
||||
# or travis-yaml https://github.com/travis-ci/travis-yaml
|
||||
# Travis WebLint https://lint.travis-ci.org/
|
||||
# or travis-lint https://github.com/travis-ci/travis-lint
|
||||
|
||||
language: cpp
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
- clang
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
sudo: false
|
||||
cache:
|
||||
apt: true
|
||||
|
||||
env:
|
||||
global:
|
||||
# Boost version to use:
|
||||
# _MIN is used when building the master branch
|
||||
# _MAX is used when building any other branch
|
||||
- BOOST_VERSION_MIN="1.49.0"
|
||||
- BOOST_VERSION_MAX="1.58.0"
|
||||
# List of required boost libraries to build
|
||||
- BOOST_LIBS="date_time,filesystem,iostreams,python,regex,system,test"
|
||||
# List of required Homebrew formulae to install
|
||||
- BREWS="gmp,mpfr"
|
||||
# Encrypted COVERITY_SCAN_TOKEN
|
||||
- secure: "mYNxD1B8WNSvUeKzInehZ7syi2g1jH2ymeSQxoeKKD2duq3pvNWPdZdc4o9MlWQcAqcz58rhFZRIpuEWCnP0LbbJaG+MyuemMn9uAmg9Y4gFpMsBPHuTdf8pO3rDex+tkrr9puEJFgL+QV/TehxO6NDDpx7UdYvJb+4aZD/auYI="
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- os: linux
|
||||
compiler: clang
|
||||
# Compiling ledger on Linux with clang
|
||||
# either crashes clang or results in a ledger binary that crashes with SIGSEGV.
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
# On Mac OS X building ledger with GNU GCC 4.8 fails due to
|
||||
# undefined symbols, maybe because boost was not being built with g++-4.8.
|
||||
# Undefined symbols for architecture x86_64:
|
||||
# "boost::re_detail::perl_matcher<char const*, std::allocator<boost::sub_match<char const*> >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::construct_init(boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > const&, boost::regex_constants::_match_flags)", referenced from:
|
||||
# boost::re_detail::perl_matcher<char const*, std::allocator<boost::sub_match<char const*> >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::perl_matcher(char const*, char const*, boost::match_results<char const*, std::allocator<boost::sub_match<char const*> > >&, boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > const&, boost::regex_constants::_match_flags, char const*) in main.cc.o
|
||||
# boost::re_detail::perl_matcher<char const*, std::allocator<boost::sub_match<char const*> >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::perl_matcher(char const*, char const*, boost::match_results<char const*, std::allocator<boost::sub_match<char const*> > >&, boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > const&, boost::regex_constants::_match_flags, char const*) in global.cc.o
|
||||
# "boost::re_detail::perl_matcher<char const*, std::allocator<boost::sub_match<char const*> >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::find()", referenced from:
|
||||
# bool boost::regex_search<char const*, char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >(char const*, char const*, boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > const&, boost::regex_constants::_match_flags) in main.cc.o
|
||||
# bool boost::regex_search<char const*, char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >(char const*, char const*, boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > const&, boost::regex_constants::_match_flags) in global.cc.o
|
||||
|
||||
addons:
|
||||
coverity_scan:
|
||||
project:
|
||||
name: "ledger/ledger"
|
||||
description: "Build submitted via Travis CI"
|
||||
build_command_prepend: "cmake . -DUSE_PYTHON=ON -DBUILD_DEBUG=ON -DCLANG_GCOV=ON"
|
||||
build_command: "make"
|
||||
branch_pattern: coverity
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
#- boost-latest
|
||||
packages:
|
||||
- gcc-4.8
|
||||
- g++-4.8
|
||||
- libgmp-dev
|
||||
- libmpfr-dev
|
||||
- libedit-dev
|
||||
#- libboost1.55-dev
|
||||
#- libboost-test1.55-dev
|
||||
#- libboost-regex1.55-dev
|
||||
#- libboost-python1.55-dev
|
||||
#- libboost-system1.55-dev
|
||||
#- libboost-date-time1.55-dev
|
||||
#- libboost-iostreams1.55-dev
|
||||
#- libboost-filesystem1.55-dev
|
||||
#- libboost-serialization1.55-dev
|
||||
|
||||
before_install:
|
||||
# Add software package repositories with recent versions of gcc and boost
|
||||
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test --yes
|
||||
- sudo add-apt-repository ppa:boost-latest/ppa --yes
|
||||
- sudo apt-get update -qq
|
||||
- if [ "${TRAVIS_BRANCH}" = "master" ]; then export BOOST_VERSION="${BOOST_VERSION_MIN}"; else export BOOST_VERSION="${BOOST_VERSION_MAX}"; fi
|
||||
- if [ -n "${BOOST_VERSION}" ]; then export BOOST_ROOT="${TRAVIS_BUILD_DIR}/../boost-trunk"; export CMAKE_MODULE_PATH="${BOOST_ROOT}"; fi
|
||||
- if [ "${CXX}" = "g++" ]; then export CXX="$(which g++-4.8)"; export CC="$(which gcc-4.8)"; fi
|
||||
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then export DYLD_LIBRARY_PATH="${BOOST_ROOT}/lib"; fi
|
||||
# c++ is a symlink to clang++, but the compiler behaves differently when invoked as c++
|
||||
- if [ "${TRAVIS_OS_NAME}" = "osx" -a "${CXX}" = "clang++" ]; then export CXX="$(which c++)"; export CC="$(which cc)"; fi
|
||||
- tools/travis-before_install.sh
|
||||
|
||||
install:
|
||||
# Install GNU GCC 4.8 required by use of C++11
|
||||
- if [ "$CXX" = "g++" ]; then sudo apt-get install -qq g++-4.8 gcc-4.8; fi
|
||||
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi
|
||||
# Install Ledger dependencies
|
||||
- sudo apt-get install -qq libboost1.55 libgmp-dev libmpfr-dev libeditline-dev
|
||||
install:
|
||||
- tools/travis-install.sh
|
||||
|
||||
before_script:
|
||||
- ./acprep debug make --python
|
||||
- cmake . -DUSE_PYTHON=ON -DBUILD_DEBUG=ON
|
||||
- make
|
||||
|
||||
script:
|
||||
- ./acprep check --jobs $(nproc) -- --output-on-failure
|
||||
- ctest --output-on-failure
|
||||
- PYTHONPATH=. python python/demo.py
|
||||
|
||||
after_script:
|
||||
# These scripts are run for informational purposes and
|
||||
# should be reintegrated into CTest once they reliably verify the documentation.
|
||||
- python test/CheckTexinfo.py -l ledger -s .
|
||||
- python test/CheckManpage.py -l ledger -s .
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: change
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ set(Ledger_VERSION_PATCH 1)
|
|||
set(Ledger_VERSION_PRERELEASE "-alpha.1")
|
||||
set(Ledger_VERSION_DATE 20141005)
|
||||
|
||||
# Point CMake at any custom modules we may ship
|
||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_definitions(-std=c++11)
|
||||
|
|
@ -225,7 +228,7 @@ macro(add_ledger_library_dependencies _target)
|
|||
target_link_libraries(${_target} ${INTL_LIB})
|
||||
endif()
|
||||
if (HAVE_BOOST_PYTHON)
|
||||
if(APPLE)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
|
||||
# Don't link directly to a Python framework on OS X, to avoid segfaults
|
||||
# when the module is imported from a different interpreter
|
||||
target_link_libraries(${_target} ${Boost_LIBRARIES})
|
||||
|
|
@ -244,13 +247,20 @@ endmacro(add_ledger_library_dependencies _target)
|
|||
|
||||
########################################################################
|
||||
|
||||
include(FindUtfcpp)
|
||||
if (UTFCPP_FOUND)
|
||||
include_directories("${UTFCPP_INCLUDE_DIR}")
|
||||
else()
|
||||
message(FATAL_ERROR "Missing required header file: utf8.h\n"
|
||||
"Define UTFCPP_PATH or install utfcpp locally into the source tree below lib/utfcpp/."
|
||||
)
|
||||
endif()
|
||||
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
|
||||
# add the binary tree to the search path for include files so that we will
|
||||
# find TutorialConfig.h
|
||||
include_directories("${PROJECT_SOURCE_DIR}/lib")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/lib/utfcpp/source")
|
||||
# find system.hh
|
||||
include_directories("${PROJECT_BINARY_DIR}")
|
||||
|
||||
configure_file(
|
||||
|
|
|
|||
11
README.md
11
README.md
|
|
@ -1,7 +1,8 @@
|
|||
[](https://travis-ci.org/ledger/ledger)
|
||||
[](https://travis-ci.org/ledger/ledger)
|
||||
[](https://travis-ci.org/ledger/ledger)
|
||||
[](https://github.com/ledger/ledger/pulse/monthly)
|
||||
[](http://opensource.org/licenses/BSD-3-Clause)
|
||||
[](https://github.com/ledger/ledger/releases)
|
||||
[](https://github.com/ledger/ledger/releases)
|
||||
|
||||
|
||||
# Ledger: Command-Line Accounting
|
||||
|
|
@ -147,9 +148,9 @@ Or, for Ubuntu 12.04:
|
|||
Debian squeeze (6.0): the version of boost in squeeze is too old
|
||||
for ledger and unfortunately no backport is available at the moment.
|
||||
|
||||
Debian 7 (wheezy) and Debian 8 (jessie) contain all components needed to
|
||||
build ledger. You can install all required build dependencies using the
|
||||
following command:
|
||||
Debian 7 (wheezy), Debian 8 (jessie), Debian testing (stretch) and Debian
|
||||
unstable (sid) contain all components needed to build ledger. You can
|
||||
install all required build dependencies using the following command:
|
||||
|
||||
$ sudo apt-get install build-essential cmake autopoint texinfo python-dev \
|
||||
zlib1g-dev libbz2-dev libgmp3-dev gettext libmpfr-dev \
|
||||
|
|
|
|||
10
acprep
10
acprep
|
|
@ -490,17 +490,10 @@ class PrepareBuild(CommandLineApp):
|
|||
# Update local files with the latest information #
|
||||
#########################################################################
|
||||
|
||||
def phase_submodule(self, *args):
|
||||
self.log.info('Executing phase: submodule')
|
||||
if self.git_working_tree():
|
||||
self.execute('git', 'submodule', 'init')
|
||||
self.execute('git', 'submodule', 'update')
|
||||
|
||||
def phase_pull(self, *args):
|
||||
self.log.info('Executing phase: pull')
|
||||
if self.git_working_tree():
|
||||
self.execute('git', 'pull')
|
||||
self.phase_submodule()
|
||||
|
||||
#########################################################################
|
||||
# Automatic installation of build dependencies #
|
||||
|
|
@ -569,6 +562,7 @@ class PrepareBuild(CommandLineApp):
|
|||
'libedit-dev',
|
||||
'texinfo',
|
||||
'lcov',
|
||||
'libutfcpp-dev',
|
||||
'sloccount'
|
||||
] + BoostInfo().dependencies('ubuntu-trusty')
|
||||
elif re.search('saucy', info):
|
||||
|
|
@ -606,6 +600,7 @@ class PrepareBuild(CommandLineApp):
|
|||
'libedit-dev',
|
||||
'texinfo',
|
||||
'lcov',
|
||||
'libutfcpp-dev',
|
||||
'sloccount'
|
||||
] + BoostInfo().dependencies('ubuntu-precise')
|
||||
else:
|
||||
|
|
@ -885,7 +880,6 @@ class PrepareBuild(CommandLineApp):
|
|||
|
||||
def phase_config(self, *args):
|
||||
self.log.info('Executing phase: config')
|
||||
self.phase_submodule()
|
||||
self.phase_configure(*args)
|
||||
if self.should_clean:
|
||||
self.phase_clean()
|
||||
|
|
|
|||
30
cmake/FindUtfcpp.cmake
Normal file
30
cmake/FindUtfcpp.cmake
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# - Try to find utfcpp
|
||||
# Once done, this will define
|
||||
#
|
||||
# UTFCPP_FOUND - system has utfcpp's utf8.h
|
||||
# UTFCPP_PATH - the utfcpp include directories
|
||||
|
||||
include(CheckCXXSourceCompiles)
|
||||
|
||||
set(UTFCPP_FOUND FALSE)
|
||||
|
||||
find_path(UTFCPP_INCLUDE_DIR
|
||||
NAMES utf8.h
|
||||
HINTS "${UTFCPP_PATH}" "${PROJECT_SOURCE_DIR}/lib/utfcpp/v2_0/source"
|
||||
)
|
||||
|
||||
if (UTFCPP_INCLUDE_DIR)
|
||||
set(CMAKE_REQUIRED_INCLUDES "${UTFCPP_INCLUDE_DIR}")
|
||||
set(UTFCPP_FOUND TRUE)
|
||||
endif()
|
||||
|
||||
check_cxx_source_compiles("
|
||||
#include <string>
|
||||
#include \"utf8.h\"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
std::string input = std::string(\"utfcpp\");
|
||||
const char * p = input.c_str();
|
||||
std::size_t len = input.length();
|
||||
utf8::is_valid(p, p + len);
|
||||
}" HAVE_WORKING_UTFCPP)
|
||||
24
doc/NEWS
24
doc/NEWS
|
|
@ -1,5 +1,29 @@
|
|||
Ledger NEWS
|
||||
|
||||
* 3.x.x
|
||||
|
||||
- Added a --no-revalued option
|
||||
|
||||
- Improved Embedded Python Support
|
||||
|
||||
- Fixed parsing of transactions with single-character payees and comments
|
||||
|
||||
- Fixed crash when using -M with empty result
|
||||
|
||||
- Fixed sorting for option --auto-match
|
||||
|
||||
- Fixed treatment of "year 2015" and "Y2014" directives
|
||||
|
||||
- Fixed crash when using --trace 10 or above
|
||||
|
||||
- Build fix for boost 1.56
|
||||
|
||||
- Build fix for Cygwin
|
||||
|
||||
- Fixed Util and Math tests on Mac OS X
|
||||
|
||||
- Various documentation improvements
|
||||
|
||||
* 3.1
|
||||
|
||||
- Changed the definition of cost basis to preserve the original cost basis
|
||||
|
|
|
|||
15
doc/ledger.1
15
doc/ledger.1
|
|
@ -574,7 +574,12 @@ posting occurring in that period.
|
|||
Display values in terms of the given
|
||||
.Ar COMMODITY .
|
||||
The latest available price is used.
|
||||
.\".It Fl \-explicit
|
||||
.It Fl \-explicit
|
||||
Direct
|
||||
.Nm
|
||||
to require pre-declarations for entities (such as accounts,
|
||||
commodities and tags) rather than taking entities from cleared
|
||||
transactions as defined.
|
||||
.It Fl \-file Ar FILE
|
||||
Read journal data from
|
||||
.Ar FILE .
|
||||
|
|
@ -716,9 +721,15 @@ Aliases are completely ignored.
|
|||
Suppress any color TTY output.
|
||||
.It Fl \-no-pager
|
||||
Disables the pager on TTY output.
|
||||
.It Fl \-no-revalued
|
||||
Stop
|
||||
.Nm
|
||||
from showing
|
||||
<Revalued>
|
||||
postings.
|
||||
.It Fl \-no-rounding
|
||||
Don't output
|
||||
.Qq Li <Rounding>
|
||||
.Qq Li <Adjustment>
|
||||
postings. Note that this will cause the
|
||||
running total to often not add up! Its main use is for
|
||||
.Fl \-amount-data Pq Fl j
|
||||
|
|
|
|||
|
|
@ -2105,6 +2105,7 @@ the syntax @code{[ACTUAL_DATE]} or @code{[=EFFECTIVE_DATE]} or
|
|||
@item P
|
||||
@findex --download
|
||||
@findex P
|
||||
@cindex historical prices
|
||||
Specifies a historical price for a commodity. These are usually found
|
||||
in a pricing history file (see the @option{--download (-Q)} option).
|
||||
The syntax is:
|
||||
|
|
@ -2114,6 +2115,9 @@ P DATE SYMBOL PRICE
|
|||
@end smallexample
|
||||
|
||||
@item =
|
||||
@findex =
|
||||
@cindex automated transaction
|
||||
@cindex transaction, automated
|
||||
An automated transaction. A value expression must appear after the
|
||||
equal sign.
|
||||
|
||||
|
|
@ -2124,17 +2128,23 @@ posting is matched by the value expression (@pxref{Automated
|
|||
Transactions}).
|
||||
|
||||
@item ~
|
||||
@findex ~
|
||||
@cindex periodic transaction
|
||||
@cindex transaction, periodic
|
||||
A periodic transaction. A period expression must appear after the tilde.
|
||||
|
||||
After this initial line there should be a set of one or more
|
||||
postings, just as if it were a normal transaction.
|
||||
|
||||
@item ; # % | *
|
||||
@findex comment
|
||||
@cindex comments
|
||||
A line beginning with a semicolon, pound, percent, bar or asterisk
|
||||
indicates a comment, and is ignored. Comments will not be returned in
|
||||
a ``print'' response.
|
||||
|
||||
@item indented ;
|
||||
@cindex tags
|
||||
If the semicolon is indented and occurs inside a transaction, it is
|
||||
parsed as a persistent note for its preceding category. These notes or
|
||||
tags can be used to augment the reporting and filtering capabilities of
|
||||
|
|
@ -2154,6 +2164,8 @@ Command directives must occur at the beginning of a line. Use of
|
|||
@samp{!} and @samp{@@} is deprecated.
|
||||
|
||||
@item account
|
||||
@findex account
|
||||
@cindex pre-declare account
|
||||
Pre-declare valid account names. This only has an effect if
|
||||
@option{--strict} or @option{--pedantic} is used (see below). The
|
||||
@code{account} directive supports several optional sub-directives, if
|
||||
|
|
@ -2203,6 +2215,7 @@ used as the ``balancing account'' for any future transactions that
|
|||
contain only a single posting.
|
||||
|
||||
@item apply account
|
||||
@findex apply account
|
||||
@c instance_t::master_account_directive
|
||||
Sets the root for all accounts following this directive. Ledger
|
||||
supports a hierarchical tree of accounts. It may be convenient to
|
||||
|
|
@ -2225,6 +2238,8 @@ Would result in all postings going into
|
|||
until an @samp{end apply account} directive was found.
|
||||
|
||||
@item alias
|
||||
@findex alias
|
||||
@cindex account, alias
|
||||
@c instance_t::alias_directive
|
||||
Define an alias for an account name. If you have a deeply nested tree
|
||||
of accounts, it may be convenient to define an alias, for example:
|
||||
|
|
@ -2276,6 +2291,8 @@ The option @option{--no-aliases} completely disables alias expansion.
|
|||
All accounts are read verbatim as they are in the ledger file.
|
||||
|
||||
@item assert
|
||||
@findex assert
|
||||
@cindex assertions
|
||||
@c instance_t::assert_directive
|
||||
An assertion can throw an error if a condition is not met during
|
||||
Ledger's run.
|
||||
|
|
@ -2286,6 +2303,8 @@ assert <VALUE EXPRESSION BOOLEAN RESULT>
|
|||
|
||||
@item bucket
|
||||
@anchor{bucket}
|
||||
@findex bucket
|
||||
@cindex bucket
|
||||
@c instance_t::default_account_directive
|
||||
Defines the default account to use for balancing transactions.
|
||||
Normally, each transaction has at least two postings, which must
|
||||
|
|
@ -2311,6 +2330,7 @@ bucket Assets:Checking
|
|||
|
||||
@item capture
|
||||
@c instance_t::account_mapping_directive
|
||||
@findex capture
|
||||
@findex print
|
||||
@findex register
|
||||
|
||||
|
|
@ -2328,6 +2348,8 @@ Ledger will display the mapped payees in @command{print} and
|
|||
@command{register} reports.
|
||||
|
||||
@item check
|
||||
@findex check
|
||||
@cindex assertions
|
||||
@c instance_t::check_directive in textual.cc
|
||||
A check issues a warning if a condition is not met during Ledger's
|
||||
run.
|
||||
|
|
@ -2337,10 +2359,14 @@ check <VALUE EXPRESSION BOOLEAN RESULT>
|
|||
@end smallexample
|
||||
|
||||
@item comment
|
||||
@findex comment
|
||||
@cindex comments
|
||||
@c instance_t::comment_directive in textual.cc
|
||||
Start a block comment, closed by @code{end comment}.
|
||||
|
||||
@item commodity
|
||||
@findex commodity
|
||||
@cindex pre-declare commodity
|
||||
Pre-declare commodity names. This only has an effect if
|
||||
@option{--strict} or @option{--pedantic} is used (see below).
|
||||
|
||||
|
|
@ -2375,6 +2401,7 @@ should never be auto-downloaded.
|
|||
The @code{default} sub-directive marks this as the ``default'' commodity.
|
||||
|
||||
@item define
|
||||
@findex define
|
||||
@c instance_t::define_directive in textual.cc
|
||||
Allows you to define value expressions for future use. For example:
|
||||
|
||||
|
|
@ -2389,13 +2416,17 @@ define var_name=$100
|
|||
The posting will have a cost of $400.
|
||||
|
||||
@item end
|
||||
@findex end
|
||||
@c instance_t::end_directive in textual.cc
|
||||
Closes block commands like @code{tag} or @code{comment}.
|
||||
|
||||
@item expr
|
||||
@findex expr
|
||||
@c instance_t::expr_directive in textual.cc
|
||||
|
||||
@item fixed
|
||||
@findex fixed
|
||||
@cindex fixated prices
|
||||
@c instance_t::fixed_directive in textual.cc
|
||||
|
||||
A fixed block is used to set fixated prices (@pxref{Fixated prices and
|
||||
|
|
@ -2437,10 +2468,12 @@ For the moment, users may wish to study
|
|||
before using the @code{fixed} directive in production.
|
||||
|
||||
@item include
|
||||
@findex include
|
||||
@c instance_t::include_directive in textual.cc
|
||||
Include the stated file as if it were part of the current file.
|
||||
|
||||
@item payee
|
||||
@findex payee
|
||||
@c instance_t::payee_alias_mapping_directive in textual.cc
|
||||
@c instance_t::payee_uuid_mapping_directive in textual.cc
|
||||
@findex print
|
||||
|
|
@ -2475,6 +2508,7 @@ Ledger will display the mapped payees in @command{print} and
|
|||
@command{register} reports.
|
||||
|
||||
@item apply tag
|
||||
@findex apply tag
|
||||
@c instance_t::tag_directive in textual.cc
|
||||
Allows you to designate a block of transactions and assign the same
|
||||
tag to all. Tags can have values and may be nested.
|
||||
|
|
@ -2532,6 +2566,8 @@ is the equivalent of:
|
|||
@c track.
|
||||
|
||||
@item tag
|
||||
@findex tag
|
||||
@cindex pre-declare tag
|
||||
Pre-declares tag names. This only has an effect if @option{--strict} or
|
||||
@option{--pedantic} is used (see below).
|
||||
|
||||
|
|
@ -2558,11 +2594,14 @@ but a string if typed metadata is used!). Such checks or assertions are
|
|||
not called if no value is given.
|
||||
|
||||
@item test
|
||||
@findex test
|
||||
@cindex comments
|
||||
@c instance_t::comment_directive in textual.cc
|
||||
This is a synonym for @code{comment} and must be closed by an
|
||||
@code{end} tag.
|
||||
|
||||
@item year
|
||||
@findex year
|
||||
@anchor{year}
|
||||
@c instance_t::year_directive in textual.cc
|
||||
Denotes the year used for all subsequent transactions that give a date
|
||||
|
|
@ -2580,10 +2619,12 @@ alone, for backwards compatibility with older Ledger versions.
|
|||
|
||||
@item A
|
||||
@findex A
|
||||
@findex bucket
|
||||
@xref{bucket}.
|
||||
|
||||
@item Y
|
||||
@findex Y
|
||||
@findex year
|
||||
@xref{year}.
|
||||
|
||||
@item N SYMBOL
|
||||
|
|
@ -2601,7 +2642,6 @@ N SYMBOL
|
|||
@item D AMOUNT
|
||||
@findex xact
|
||||
@findex D
|
||||
|
||||
Specifies the default commodity to use, by specifying an amount in the
|
||||
expected format. The @command{xact} command will use this commodity as
|
||||
the default when none other can be determined. This command may be used
|
||||
|
|
@ -5970,8 +6010,10 @@ Direct Ledger to download prices.
|
|||
@c @option{--getquote @var{FILE}}.
|
||||
|
||||
@item --explicit
|
||||
@c see test/baseline/opt-explicit.test
|
||||
@value{FIXME:UNDOCUMENTED}
|
||||
Direct Ledger to require pre-declarations for entities (such as accounts,
|
||||
commodities and tags) rather than taking entities from cleared
|
||||
transactions as defined. This option is useful in combination with
|
||||
@option{--strict} or @option{--pedantic}.
|
||||
|
||||
@item --file @var{FILE}
|
||||
@itemx -f @var{FILE}
|
||||
|
|
@ -6536,8 +6578,12 @@ Suppress any color TTY output.
|
|||
@item --no-pager
|
||||
Direct output to stdout, avoiding pager program.
|
||||
|
||||
@item --no-revalued
|
||||
Stop Ledger from showing @code{<Revalued>} postings. This option is useful
|
||||
in combination with the @option{--exchange} or @option{--market} option.
|
||||
|
||||
@item --no-rounding
|
||||
Don't output @samp{<Rounding>} postings. Note that this will cause the
|
||||
Don't output @samp{<Adjustment>} postings. Note that this will cause the
|
||||
running total to often not add up! Its main use is for
|
||||
@option{--amount-data (-j)} and @option{--total-data (-J)} reports.
|
||||
|
||||
|
|
@ -7868,6 +7914,13 @@ considering children.
|
|||
The cost of a posting; the cost of an account, without its
|
||||
children.
|
||||
|
||||
@item v
|
||||
The market value of a posting or an account, without its children.
|
||||
|
||||
@item g
|
||||
The net gain (market value minus cost basis), for a posting or an
|
||||
account, without its children. It is the same as @samp{v-b}.
|
||||
|
||||
@item l
|
||||
The depth (``level'') of an account. If an account has one parent,
|
||||
its depth is one.
|
||||
|
|
@ -8107,7 +8160,7 @@ Render the given @var{expression} as a string, applying the proper ANSI escape
|
|||
codes to display it in the given @var{color} if @var{bool} is true. It
|
||||
typically checks the value of the option @option{--color}. Since ANSI escape
|
||||
codes include non-printable character sequences, such as escape @kbd{^[}
|
||||
the following example may not appear as the final result on the commandline.
|
||||
the following example may not appear as the final result on the command-line.
|
||||
@smallexample @c command:4D836EE,with_input:3406FC1
|
||||
$ ledger -f expr.dat --format "%(ansify_if(account, blue, options.color))\n" reg
|
||||
@end smallexample
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 2233ec933f5661c7050b94d3b14f5f9f51ae3d55
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
Copyright 2006 Nemanja Trifunovic
|
||||
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
|
||||
18
lib/utfcpp/v2_0/buildrelease.pl
Executable file
18
lib/utfcpp/v2_0/buildrelease.pl
Executable file
|
|
@ -0,0 +1,18 @@
|
|||
#! /usr/bin/perl
|
||||
|
||||
$release_files = 'source/utf8.h source/utf8/core.h source/utf8/checked.h source/utf8/unchecked.h doc/utf8cpp.html doc/ReleaseNotes';
|
||||
|
||||
# First get the latest version
|
||||
`svn update`;
|
||||
|
||||
# Then construct the name of the zip file
|
||||
$argc = @ARGV;
|
||||
if ($argc > 0) {
|
||||
$zip_name = $ARGV[0];
|
||||
}
|
||||
else {
|
||||
$zip_name = "utf8";
|
||||
}
|
||||
|
||||
# Zip the files to an archive
|
||||
`zip $zip_name $release_files`;
|
||||
5
lib/utfcpp/v2_0/samples/Makefile
Normal file
5
lib/utfcpp/v2_0/samples/Makefile
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
CC = g++
|
||||
CFLAGS = -g -Wall -pedantic
|
||||
|
||||
docsample: docsample.cpp ../source/utf8.h
|
||||
$(CC) $(CFLAGS) docsample.cpp -odocsample
|
||||
52
lib/utfcpp/v2_0/samples/docsample.cpp
Normal file
52
lib/utfcpp/v2_0/samples/docsample.cpp
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#include "../source/utf8.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
cout << "\nUsage: docsample filename\n";
|
||||
return 0;
|
||||
}
|
||||
const char* test_file_path = argv[1];
|
||||
// Open the test file (must be UTF-8 encoded)
|
||||
ifstream fs8(test_file_path);
|
||||
if (!fs8.is_open()) {
|
||||
cout << "Could not open " << test_file_path << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned line_count = 1;
|
||||
string line;
|
||||
// Play with all the lines in the file
|
||||
while (getline(fs8, line)) {
|
||||
// check for invalid utf-8 (for a simple yes/no check, there is also utf8::is_valid function)
|
||||
string::iterator end_it = utf8::find_invalid(line.begin(), line.end());
|
||||
if (end_it != line.end()) {
|
||||
cout << "Invalid UTF-8 encoding detected at line " << line_count << "\n";
|
||||
cout << "This part is fine: " << string(line.begin(), end_it) << "\n";
|
||||
}
|
||||
// Get the line length (at least for the valid part)
|
||||
int length = utf8::distance(line.begin(), end_it);
|
||||
cout << "Length of line " << line_count << " is " << length << "\n";
|
||||
|
||||
// Convert it to utf-16
|
||||
vector<unsigned short> utf16line;
|
||||
utf8::utf8to16(line.begin(), end_it, back_inserter(utf16line));
|
||||
// And back to utf-8;
|
||||
string utf8line;
|
||||
utf8::utf16to8(utf16line.begin(), utf16line.end(), back_inserter(utf8line));
|
||||
// Confirm that the conversion went OK:
|
||||
if (utf8line != string(line.begin(), end_it))
|
||||
cout << "Error in UTF-16 conversion at line: " << line_count << "\n";
|
||||
|
||||
line_count++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
34
lib/utfcpp/v2_0/source/utf8.h
Normal file
34
lib/utfcpp/v2_0/source/utf8.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2006 Nemanja Trifunovic
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
|
||||
#include "utf8/checked.h"
|
||||
#include "utf8/unchecked.h"
|
||||
|
||||
#endif // header guard
|
||||
327
lib/utfcpp/v2_0/source/utf8/checked.h
Normal file
327
lib/utfcpp/v2_0/source/utf8/checked.h
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
// Copyright 2006 Nemanja Trifunovic
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
|
||||
#include "core.h"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace utf8
|
||||
{
|
||||
// Base for the exceptions that may be thrown from the library
|
||||
class exception : public ::std::exception {
|
||||
};
|
||||
|
||||
// Exceptions that may be thrown from the library functions.
|
||||
class invalid_code_point : public exception {
|
||||
uint32_t cp;
|
||||
public:
|
||||
invalid_code_point(uint32_t cp) : cp(cp) {}
|
||||
virtual const char* what() const throw() { return "Invalid code point"; }
|
||||
uint32_t code_point() const {return cp;}
|
||||
};
|
||||
|
||||
class invalid_utf8 : public exception {
|
||||
uint8_t u8;
|
||||
public:
|
||||
invalid_utf8 (uint8_t u) : u8(u) {}
|
||||
virtual const char* what() const throw() { return "Invalid UTF-8"; }
|
||||
uint8_t utf8_octet() const {return u8;}
|
||||
};
|
||||
|
||||
class invalid_utf16 : public exception {
|
||||
uint16_t u16;
|
||||
public:
|
||||
invalid_utf16 (uint16_t u) : u16(u) {}
|
||||
virtual const char* what() const throw() { return "Invalid UTF-16"; }
|
||||
uint16_t utf16_word() const {return u16;}
|
||||
};
|
||||
|
||||
class not_enough_room : public exception {
|
||||
public:
|
||||
virtual const char* what() const throw() { return "Not enough space"; }
|
||||
};
|
||||
|
||||
/// The library API - functions intended to be called by the users
|
||||
|
||||
template <typename octet_iterator>
|
||||
octet_iterator append(uint32_t cp, octet_iterator result)
|
||||
{
|
||||
if (!utf8::internal::is_code_point_valid(cp))
|
||||
throw invalid_code_point(cp);
|
||||
|
||||
if (cp < 0x80) // one octet
|
||||
*(result++) = static_cast<uint8_t>(cp);
|
||||
else if (cp < 0x800) { // two octets
|
||||
*(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
|
||||
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||
}
|
||||
else if (cp < 0x10000) { // three octets
|
||||
*(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
|
||||
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
|
||||
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||
}
|
||||
else { // four octets
|
||||
*(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
|
||||
*(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f) | 0x80);
|
||||
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
|
||||
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename output_iterator>
|
||||
output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement)
|
||||
{
|
||||
while (start != end) {
|
||||
octet_iterator sequence_start = start;
|
||||
internal::utf_error err_code = utf8::internal::validate_next(start, end);
|
||||
switch (err_code) {
|
||||
case internal::UTF8_OK :
|
||||
for (octet_iterator it = sequence_start; it != start; ++it)
|
||||
*out++ = *it;
|
||||
break;
|
||||
case internal::NOT_ENOUGH_ROOM:
|
||||
throw not_enough_room();
|
||||
case internal::INVALID_LEAD:
|
||||
out = utf8::append (replacement, out);
|
||||
++start;
|
||||
break;
|
||||
case internal::INCOMPLETE_SEQUENCE:
|
||||
case internal::OVERLONG_SEQUENCE:
|
||||
case internal::INVALID_CODE_POINT:
|
||||
out = utf8::append (replacement, out);
|
||||
++start;
|
||||
// just one replacement mark for the sequence
|
||||
while (start != end && utf8::internal::is_trail(*start))
|
||||
++start;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename output_iterator>
|
||||
inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out)
|
||||
{
|
||||
static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd);
|
||||
return utf8::replace_invalid(start, end, out, replacement_marker);
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
uint32_t next(octet_iterator& it, octet_iterator end)
|
||||
{
|
||||
uint32_t cp = 0;
|
||||
internal::utf_error err_code = utf8::internal::validate_next(it, end, cp);
|
||||
switch (err_code) {
|
||||
case internal::UTF8_OK :
|
||||
break;
|
||||
case internal::NOT_ENOUGH_ROOM :
|
||||
throw not_enough_room();
|
||||
case internal::INVALID_LEAD :
|
||||
case internal::INCOMPLETE_SEQUENCE :
|
||||
case internal::OVERLONG_SEQUENCE :
|
||||
throw invalid_utf8(*it);
|
||||
case internal::INVALID_CODE_POINT :
|
||||
throw invalid_code_point(cp);
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
uint32_t peek_next(octet_iterator it, octet_iterator end)
|
||||
{
|
||||
return utf8::next(it, end);
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
uint32_t prior(octet_iterator& it, octet_iterator start)
|
||||
{
|
||||
// can't do much if it == start
|
||||
if (it == start)
|
||||
throw not_enough_room();
|
||||
|
||||
octet_iterator end = it;
|
||||
// Go back until we hit either a lead octet or start
|
||||
while (utf8::internal::is_trail(*(--it)))
|
||||
if (it == start)
|
||||
throw invalid_utf8(*it); // error - no lead byte in the sequence
|
||||
return utf8::peek_next(it, end);
|
||||
}
|
||||
|
||||
/// Deprecated in versions that include "prior"
|
||||
template <typename octet_iterator>
|
||||
uint32_t previous(octet_iterator& it, octet_iterator pass_start)
|
||||
{
|
||||
octet_iterator end = it;
|
||||
while (utf8::internal::is_trail(*(--it)))
|
||||
if (it == pass_start)
|
||||
throw invalid_utf8(*it); // error - no lead byte in the sequence
|
||||
octet_iterator temp = it;
|
||||
return utf8::next(temp, end);
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename distance_type>
|
||||
void advance (octet_iterator& it, distance_type n, octet_iterator end)
|
||||
{
|
||||
for (distance_type i = 0; i < n; ++i)
|
||||
utf8::next(it, end);
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
typename std::iterator_traits<octet_iterator>::difference_type
|
||||
distance (octet_iterator first, octet_iterator last)
|
||||
{
|
||||
typename std::iterator_traits<octet_iterator>::difference_type dist;
|
||||
for (dist = 0; first < last; ++dist)
|
||||
utf8::next(first, last);
|
||||
return dist;
|
||||
}
|
||||
|
||||
template <typename u16bit_iterator, typename octet_iterator>
|
||||
octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
|
||||
{
|
||||
while (start != end) {
|
||||
uint32_t cp = utf8::internal::mask16(*start++);
|
||||
// Take care of surrogate pairs first
|
||||
if (utf8::internal::is_lead_surrogate(cp)) {
|
||||
if (start != end) {
|
||||
uint32_t trail_surrogate = utf8::internal::mask16(*start++);
|
||||
if (utf8::internal::is_trail_surrogate(trail_surrogate))
|
||||
cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
|
||||
else
|
||||
throw invalid_utf16(static_cast<uint16_t>(trail_surrogate));
|
||||
}
|
||||
else
|
||||
throw invalid_utf16(static_cast<uint16_t>(cp));
|
||||
|
||||
}
|
||||
// Lone trail surrogate
|
||||
else if (utf8::internal::is_trail_surrogate(cp))
|
||||
throw invalid_utf16(static_cast<uint16_t>(cp));
|
||||
|
||||
result = utf8::append(cp, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename u16bit_iterator, typename octet_iterator>
|
||||
u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
|
||||
{
|
||||
while (start != end) {
|
||||
uint32_t cp = utf8::next(start, end);
|
||||
if (cp > 0xffff) { //make a surrogate pair
|
||||
*result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
|
||||
*result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
|
||||
}
|
||||
else
|
||||
*result++ = static_cast<uint16_t>(cp);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename u32bit_iterator>
|
||||
octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
|
||||
{
|
||||
while (start != end)
|
||||
result = utf8::append(*(start++), result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename u32bit_iterator>
|
||||
u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
|
||||
{
|
||||
while (start != end)
|
||||
(*result++) = utf8::next(start, end);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// The iterator class
|
||||
template <typename octet_iterator>
|
||||
class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
|
||||
octet_iterator it;
|
||||
octet_iterator range_start;
|
||||
octet_iterator range_end;
|
||||
public:
|
||||
iterator () {}
|
||||
explicit iterator (const octet_iterator& octet_it,
|
||||
const octet_iterator& range_start,
|
||||
const octet_iterator& range_end) :
|
||||
it(octet_it), range_start(range_start), range_end(range_end)
|
||||
{
|
||||
if (it < range_start || it > range_end)
|
||||
throw std::out_of_range("Invalid utf-8 iterator position");
|
||||
}
|
||||
// the default "big three" are OK
|
||||
octet_iterator base () const { return it; }
|
||||
uint32_t operator * () const
|
||||
{
|
||||
octet_iterator temp = it;
|
||||
return utf8::next(temp, range_end);
|
||||
}
|
||||
bool operator == (const iterator& rhs) const
|
||||
{
|
||||
if (range_start != rhs.range_start || range_end != rhs.range_end)
|
||||
throw std::logic_error("Comparing utf-8 iterators defined with different ranges");
|
||||
return (it == rhs.it);
|
||||
}
|
||||
bool operator != (const iterator& rhs) const
|
||||
{
|
||||
return !(operator == (rhs));
|
||||
}
|
||||
iterator& operator ++ ()
|
||||
{
|
||||
utf8::next(it, range_end);
|
||||
return *this;
|
||||
}
|
||||
iterator operator ++ (int)
|
||||
{
|
||||
iterator temp = *this;
|
||||
utf8::next(it, range_end);
|
||||
return temp;
|
||||
}
|
||||
iterator& operator -- ()
|
||||
{
|
||||
utf8::prior(it, range_start);
|
||||
return *this;
|
||||
}
|
||||
iterator operator -- (int)
|
||||
{
|
||||
iterator temp = *this;
|
||||
utf8::prior(it, range_start);
|
||||
return temp;
|
||||
}
|
||||
}; // class iterator
|
||||
|
||||
} // namespace utf8
|
||||
|
||||
#endif //header guard
|
||||
|
||||
|
||||
329
lib/utfcpp/v2_0/source/utf8/core.h
Normal file
329
lib/utfcpp/v2_0/source/utf8/core.h
Normal file
|
|
@ -0,0 +1,329 @@
|
|||
// Copyright 2006 Nemanja Trifunovic
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
|
||||
#include <iterator>
|
||||
|
||||
namespace utf8
|
||||
{
|
||||
// The typedefs for 8-bit, 16-bit and 32-bit unsigned integers
|
||||
// You may need to change them to match your system.
|
||||
// These typedefs have the same names as ones from cstdint, or boost/cstdint
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
|
||||
// Helper code - not intended to be directly called by the library users. May be changed at any time
|
||||
namespace internal
|
||||
{
|
||||
// Unicode constants
|
||||
// Leading (high) surrogates: 0xd800 - 0xdbff
|
||||
// Trailing (low) surrogates: 0xdc00 - 0xdfff
|
||||
const uint16_t LEAD_SURROGATE_MIN = 0xd800u;
|
||||
const uint16_t LEAD_SURROGATE_MAX = 0xdbffu;
|
||||
const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u;
|
||||
const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu;
|
||||
const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10);
|
||||
const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN;
|
||||
|
||||
// Maximum valid value for a Unicode code point
|
||||
const uint32_t CODE_POINT_MAX = 0x0010ffffu;
|
||||
|
||||
template<typename octet_type>
|
||||
inline uint8_t mask8(octet_type oc)
|
||||
{
|
||||
return static_cast<uint8_t>(0xff & oc);
|
||||
}
|
||||
template<typename u16_type>
|
||||
inline uint16_t mask16(u16_type oc)
|
||||
{
|
||||
return static_cast<uint16_t>(0xffff & oc);
|
||||
}
|
||||
template<typename octet_type>
|
||||
inline bool is_trail(octet_type oc)
|
||||
{
|
||||
return ((utf8::internal::mask8(oc) >> 6) == 0x2);
|
||||
}
|
||||
|
||||
template <typename u16>
|
||||
inline bool is_lead_surrogate(u16 cp)
|
||||
{
|
||||
return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX);
|
||||
}
|
||||
|
||||
template <typename u16>
|
||||
inline bool is_trail_surrogate(u16 cp)
|
||||
{
|
||||
return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
|
||||
}
|
||||
|
||||
template <typename u16>
|
||||
inline bool is_surrogate(u16 cp)
|
||||
{
|
||||
return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
|
||||
}
|
||||
|
||||
template <typename u32>
|
||||
inline bool is_code_point_valid(u32 cp)
|
||||
{
|
||||
return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp));
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
inline typename std::iterator_traits<octet_iterator>::difference_type
|
||||
sequence_length(octet_iterator lead_it)
|
||||
{
|
||||
uint8_t lead = utf8::internal::mask8(*lead_it);
|
||||
if (lead < 0x80)
|
||||
return 1;
|
||||
else if ((lead >> 5) == 0x6)
|
||||
return 2;
|
||||
else if ((lead >> 4) == 0xe)
|
||||
return 3;
|
||||
else if ((lead >> 3) == 0x1e)
|
||||
return 4;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename octet_difference_type>
|
||||
inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length)
|
||||
{
|
||||
if (cp < 0x80) {
|
||||
if (length != 1)
|
||||
return true;
|
||||
}
|
||||
else if (cp < 0x800) {
|
||||
if (length != 2)
|
||||
return true;
|
||||
}
|
||||
else if (cp < 0x10000) {
|
||||
if (length != 3)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT};
|
||||
|
||||
/// Helper for get_sequence_x
|
||||
template <typename octet_iterator>
|
||||
utf_error increase_safely(octet_iterator& it, octet_iterator end)
|
||||
{
|
||||
if (++it == end)
|
||||
return NOT_ENOUGH_ROOM;
|
||||
|
||||
if (!utf8::internal::is_trail(*it))
|
||||
return INCOMPLETE_SEQUENCE;
|
||||
|
||||
return UTF8_OK;
|
||||
}
|
||||
|
||||
#define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;}
|
||||
|
||||
/// get_sequence_x functions decode utf-8 sequences of the length x
|
||||
template <typename octet_iterator>
|
||||
utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point)
|
||||
{
|
||||
if (it == end)
|
||||
return NOT_ENOUGH_ROOM;
|
||||
|
||||
code_point = utf8::internal::mask8(*it);
|
||||
|
||||
return UTF8_OK;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point)
|
||||
{
|
||||
if (it == end)
|
||||
return NOT_ENOUGH_ROOM;
|
||||
|
||||
code_point = utf8::internal::mask8(*it);
|
||||
|
||||
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
|
||||
|
||||
code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f);
|
||||
|
||||
return UTF8_OK;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point)
|
||||
{
|
||||
if (it == end)
|
||||
return NOT_ENOUGH_ROOM;
|
||||
|
||||
code_point = utf8::internal::mask8(*it);
|
||||
|
||||
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
|
||||
|
||||
code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
|
||||
|
||||
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
|
||||
|
||||
code_point += (*it) & 0x3f;
|
||||
|
||||
return UTF8_OK;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point)
|
||||
{
|
||||
if (it == end)
|
||||
return NOT_ENOUGH_ROOM;
|
||||
|
||||
code_point = utf8::internal::mask8(*it);
|
||||
|
||||
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
|
||||
|
||||
code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
|
||||
|
||||
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
|
||||
|
||||
code_point += (utf8::internal::mask8(*it) << 6) & 0xfff;
|
||||
|
||||
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
|
||||
|
||||
code_point += (*it) & 0x3f;
|
||||
|
||||
return UTF8_OK;
|
||||
}
|
||||
|
||||
#undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR
|
||||
|
||||
template <typename octet_iterator>
|
||||
utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point)
|
||||
{
|
||||
// Save the original value of it so we can go back in case of failure
|
||||
// Of course, it does not make much sense with i.e. stream iterators
|
||||
octet_iterator original_it = it;
|
||||
|
||||
uint32_t cp = 0;
|
||||
// Determine the sequence length based on the lead octet
|
||||
typedef typename std::iterator_traits<octet_iterator>::difference_type octet_difference_type;
|
||||
const octet_difference_type length = utf8::internal::sequence_length(it);
|
||||
|
||||
// Get trail octets and calculate the code point
|
||||
utf_error err = UTF8_OK;
|
||||
switch (length) {
|
||||
case 0:
|
||||
return INVALID_LEAD;
|
||||
case 1:
|
||||
err = utf8::internal::get_sequence_1(it, end, cp);
|
||||
break;
|
||||
case 2:
|
||||
err = utf8::internal::get_sequence_2(it, end, cp);
|
||||
break;
|
||||
case 3:
|
||||
err = utf8::internal::get_sequence_3(it, end, cp);
|
||||
break;
|
||||
case 4:
|
||||
err = utf8::internal::get_sequence_4(it, end, cp);
|
||||
break;
|
||||
}
|
||||
|
||||
if (err == UTF8_OK) {
|
||||
// Decoding succeeded. Now, security checks...
|
||||
if (utf8::internal::is_code_point_valid(cp)) {
|
||||
if (!utf8::internal::is_overlong_sequence(cp, length)){
|
||||
// Passed! Return here.
|
||||
code_point = cp;
|
||||
++it;
|
||||
return UTF8_OK;
|
||||
}
|
||||
else
|
||||
err = OVERLONG_SEQUENCE;
|
||||
}
|
||||
else
|
||||
err = INVALID_CODE_POINT;
|
||||
}
|
||||
|
||||
// Failure branch - restore the original value of the iterator
|
||||
it = original_it;
|
||||
return err;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
inline utf_error validate_next(octet_iterator& it, octet_iterator end) {
|
||||
uint32_t ignored;
|
||||
return utf8::internal::validate_next(it, end, ignored);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/// The library API - functions intended to be called by the users
|
||||
|
||||
// Byte order mark
|
||||
const uint8_t bom[] = {0xef, 0xbb, 0xbf};
|
||||
|
||||
template <typename octet_iterator>
|
||||
octet_iterator find_invalid(octet_iterator start, octet_iterator end)
|
||||
{
|
||||
octet_iterator result = start;
|
||||
while (result != end) {
|
||||
utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end);
|
||||
if (err_code != internal::UTF8_OK)
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
inline bool is_valid(octet_iterator start, octet_iterator end)
|
||||
{
|
||||
return (utf8::find_invalid(start, end) == end);
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
inline bool starts_with_bom (octet_iterator it, octet_iterator end)
|
||||
{
|
||||
return (
|
||||
((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) &&
|
||||
((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) &&
|
||||
((it != end) && (utf8::internal::mask8(*it)) == bom[2])
|
||||
);
|
||||
}
|
||||
|
||||
//Deprecated in release 2.3
|
||||
template <typename octet_iterator>
|
||||
inline bool is_bom (octet_iterator it)
|
||||
{
|
||||
return (
|
||||
(utf8::internal::mask8(*it++)) == bom[0] &&
|
||||
(utf8::internal::mask8(*it++)) == bom[1] &&
|
||||
(utf8::internal::mask8(*it)) == bom[2]
|
||||
);
|
||||
}
|
||||
} // namespace utf8
|
||||
|
||||
#endif // header guard
|
||||
|
||||
|
||||
228
lib/utfcpp/v2_0/source/utf8/unchecked.h
Normal file
228
lib/utfcpp/v2_0/source/utf8/unchecked.h
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
// Copyright 2006 Nemanja Trifunovic
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
|
||||
#include "core.h"
|
||||
|
||||
namespace utf8
|
||||
{
|
||||
namespace unchecked
|
||||
{
|
||||
template <typename octet_iterator>
|
||||
octet_iterator append(uint32_t cp, octet_iterator result)
|
||||
{
|
||||
if (cp < 0x80) // one octet
|
||||
*(result++) = static_cast<uint8_t>(cp);
|
||||
else if (cp < 0x800) { // two octets
|
||||
*(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
|
||||
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||
}
|
||||
else if (cp < 0x10000) { // three octets
|
||||
*(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
|
||||
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
|
||||
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||
}
|
||||
else { // four octets
|
||||
*(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
|
||||
*(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f)| 0x80);
|
||||
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
|
||||
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
uint32_t next(octet_iterator& it)
|
||||
{
|
||||
uint32_t cp = utf8::internal::mask8(*it);
|
||||
typename std::iterator_traits<octet_iterator>::difference_type length = utf8::internal::sequence_length(it);
|
||||
switch (length) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
it++;
|
||||
cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f);
|
||||
break;
|
||||
case 3:
|
||||
++it;
|
||||
cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
|
||||
++it;
|
||||
cp += (*it) & 0x3f;
|
||||
break;
|
||||
case 4:
|
||||
++it;
|
||||
cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
|
||||
++it;
|
||||
cp += (utf8::internal::mask8(*it) << 6) & 0xfff;
|
||||
++it;
|
||||
cp += (*it) & 0x3f;
|
||||
break;
|
||||
}
|
||||
++it;
|
||||
return cp;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
uint32_t peek_next(octet_iterator it)
|
||||
{
|
||||
return utf8::unchecked::next(it);
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
uint32_t prior(octet_iterator& it)
|
||||
{
|
||||
while (utf8::internal::is_trail(*(--it))) ;
|
||||
octet_iterator temp = it;
|
||||
return utf8::unchecked::next(temp);
|
||||
}
|
||||
|
||||
// Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous)
|
||||
template <typename octet_iterator>
|
||||
inline uint32_t previous(octet_iterator& it)
|
||||
{
|
||||
return utf8::unchecked::prior(it);
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename distance_type>
|
||||
void advance (octet_iterator& it, distance_type n)
|
||||
{
|
||||
for (distance_type i = 0; i < n; ++i)
|
||||
utf8::unchecked::next(it);
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
typename std::iterator_traits<octet_iterator>::difference_type
|
||||
distance (octet_iterator first, octet_iterator last)
|
||||
{
|
||||
typename std::iterator_traits<octet_iterator>::difference_type dist;
|
||||
for (dist = 0; first < last; ++dist)
|
||||
utf8::unchecked::next(first);
|
||||
return dist;
|
||||
}
|
||||
|
||||
template <typename u16bit_iterator, typename octet_iterator>
|
||||
octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
|
||||
{
|
||||
while (start != end) {
|
||||
uint32_t cp = utf8::internal::mask16(*start++);
|
||||
// Take care of surrogate pairs first
|
||||
if (utf8::internal::is_lead_surrogate(cp)) {
|
||||
uint32_t trail_surrogate = utf8::internal::mask16(*start++);
|
||||
cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
|
||||
}
|
||||
result = utf8::unchecked::append(cp, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename u16bit_iterator, typename octet_iterator>
|
||||
u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
|
||||
{
|
||||
while (start < end) {
|
||||
uint32_t cp = utf8::unchecked::next(start);
|
||||
if (cp > 0xffff) { //make a surrogate pair
|
||||
*result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
|
||||
*result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
|
||||
}
|
||||
else
|
||||
*result++ = static_cast<uint16_t>(cp);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename u32bit_iterator>
|
||||
octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
|
||||
{
|
||||
while (start != end)
|
||||
result = utf8::unchecked::append(*(start++), result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename u32bit_iterator>
|
||||
u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
|
||||
{
|
||||
while (start < end)
|
||||
(*result++) = utf8::unchecked::next(start);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// The iterator class
|
||||
template <typename octet_iterator>
|
||||
class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
|
||||
octet_iterator it;
|
||||
public:
|
||||
iterator () {}
|
||||
explicit iterator (const octet_iterator& octet_it): it(octet_it) {}
|
||||
// the default "big three" are OK
|
||||
octet_iterator base () const { return it; }
|
||||
uint32_t operator * () const
|
||||
{
|
||||
octet_iterator temp = it;
|
||||
return utf8::unchecked::next(temp);
|
||||
}
|
||||
bool operator == (const iterator& rhs) const
|
||||
{
|
||||
return (it == rhs.it);
|
||||
}
|
||||
bool operator != (const iterator& rhs) const
|
||||
{
|
||||
return !(operator == (rhs));
|
||||
}
|
||||
iterator& operator ++ ()
|
||||
{
|
||||
::std::advance(it, utf8::internal::sequence_length(it));
|
||||
return *this;
|
||||
}
|
||||
iterator operator ++ (int)
|
||||
{
|
||||
iterator temp = *this;
|
||||
::std::advance(it, utf8::internal::sequence_length(it));
|
||||
return temp;
|
||||
}
|
||||
iterator& operator -- ()
|
||||
{
|
||||
utf8::unchecked::prior(it);
|
||||
return *this;
|
||||
}
|
||||
iterator operator -- (int)
|
||||
{
|
||||
iterator temp = *this;
|
||||
utf8::unchecked::prior(it);
|
||||
return temp;
|
||||
}
|
||||
}; // class iterator
|
||||
|
||||
} // namespace utf8::unchecked
|
||||
} // namespace utf8
|
||||
|
||||
|
||||
#endif // header guard
|
||||
|
||||
|
|
@ -152,7 +152,7 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|||
-Wno-unused-parameter
|
||||
-Wno-c++98-compat
|
||||
-fno-limit-debug-info)
|
||||
|
||||
|
||||
macro(ADD_PCH_RULE _header_filename _src_list _other_srcs)
|
||||
set(_pch_filename "${_header_filename}.pch")
|
||||
|
||||
|
|
@ -188,7 +188,7 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|||
COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} ${_args}
|
||||
DEPENDS ${_header_filename})
|
||||
endmacro(ADD_PCH_RULE _header_filename _src_list _other_srcs)
|
||||
|
||||
|
||||
elseif(CMAKE_CXX_COMPILER MATCHES "g\\+\\+")
|
||||
set(GXX_WARNING_FLAGS
|
||||
-pedantic
|
||||
|
|
@ -210,7 +210,7 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|||
-Wno-strict-aliasing)
|
||||
|
||||
add_definitions(${GXX_WARNING_FLAGS})
|
||||
|
||||
|
||||
macro(ADD_PCH_RULE _header_filename _src_list _other_srcs)
|
||||
set(_gch_filename "${_header_filename}.gch")
|
||||
|
||||
|
|
@ -247,7 +247,7 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|||
COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} ${_args}
|
||||
DEPENDS ${_header_filename})
|
||||
endmacro(ADD_PCH_RULE _header_filename _src_list _other_srcs)
|
||||
|
||||
|
||||
else()
|
||||
macro(ADD_PCH_RULE _header_filename _src_list _other_srcs)
|
||||
endmacro(ADD_PCH_RULE _header_filename _src_list _other_srcs)
|
||||
|
|
@ -273,6 +273,9 @@ if (BUILD_LIBRARY)
|
|||
|
||||
add_executable(ledger main.cc global.cc)
|
||||
target_link_libraries(ledger libledger)
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL Darwin AND HAVE_BOOST_PYTHON)
|
||||
target_link_libraries(ledger ${PYTHON_LIBRARIES})
|
||||
endif()
|
||||
|
||||
install(TARGETS libledger DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(FILES ${LEDGER_INCLUDES}
|
||||
|
|
@ -294,7 +297,7 @@ print(s.get_python_lib(True, prefix=''))"
|
|||
if (PYTHON_SITE_PACKAGES)
|
||||
if (WIN32 AND NOT CYGWIN)
|
||||
set(_ledger_python_module_name "ledger.pyd")
|
||||
elseif(CMAKE_HOST_APPLE)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL Darwin)
|
||||
set(_ledger_python_module_name "ledger.so")
|
||||
else()
|
||||
set(_ledger_python_module_name "ledger${CMAKE_SHARED_LIBRARY_SUFFIX}")
|
||||
|
|
|
|||
|
|
@ -261,11 +261,7 @@ public:
|
|||
mutable optional<xdata_t> xdata_;
|
||||
|
||||
bool has_xdata() const {
|
||||
#if BOOST_VERSION >= 105600
|
||||
return xdata_ != NULL;
|
||||
#else
|
||||
return xdata_;
|
||||
#endif
|
||||
return static_cast<bool>(xdata_);
|
||||
}
|
||||
void clear_xdata();
|
||||
xdata_t& xdata() {
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ public:
|
|||
out.flush();
|
||||
}
|
||||
virtual void operator()(post_t& post);
|
||||
virtual string escape_string(string raw);
|
||||
virtual string escape_string(string raw);
|
||||
};
|
||||
|
||||
} // namespace ledger
|
||||
|
|
|
|||
|
|
@ -707,7 +707,7 @@ namespace {
|
|||
insert_prices_in_map(price_map_t& _all_prices)
|
||||
: all_prices(_all_prices) {}
|
||||
|
||||
void operator()(datetime_t& date, const amount_t& price) {
|
||||
void operator()(const datetime_t& date, const amount_t& price) {
|
||||
all_prices.insert(price_map_t::value_type(date, price));
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -475,7 +475,7 @@ commodity_history_impl_t::find_price(const commodity_t& source,
|
|||
#endif
|
||||
|
||||
vertex_descriptor v = tv;
|
||||
for (vertex_descriptor u = predecessorMap[v];
|
||||
for (vertex_descriptor u = predecessorMap[v];
|
||||
u != v;
|
||||
v = u, u = predecessorMap[v])
|
||||
{
|
||||
|
|
|
|||
|
|
@ -174,11 +174,7 @@ public:
|
|||
static bool use_aux_date;
|
||||
|
||||
virtual bool has_date() const {
|
||||
#if BOOST_VERSION >= 105600
|
||||
return _date != NULL;
|
||||
#else
|
||||
return _date;
|
||||
#endif
|
||||
return static_cast<bool>(_date);
|
||||
}
|
||||
|
||||
virtual date_t date() const {
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ namespace {
|
|||
TRACE_DTOR(create_price_xact);
|
||||
}
|
||||
|
||||
void operator()(datetime_t& date, const amount_t& price) {
|
||||
void operator()(const datetime_t& date, const amount_t& price) {
|
||||
xact_t * xact;
|
||||
string symbol = price.commodity().symbol();
|
||||
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ public:
|
|||
|
||||
ptr_op_t parse(std::istream& in,
|
||||
const parse_flags_t& flags = PARSE_DEFAULT,
|
||||
const optional<string>& original_string = NULL);
|
||||
const optional<string>& original_string = boost::none);
|
||||
};
|
||||
|
||||
} // namespace ledger
|
||||
|
|
|
|||
|
|
@ -78,8 +78,8 @@ public:
|
|||
commodity_t * default_commodity;
|
||||
|
||||
bool keep_base; // --base
|
||||
optional<path> price_db; // --price-db=
|
||||
long quote_leeway; // --leeway=
|
||||
optional<path> price_db; // --price-db=
|
||||
long quote_leeway; // --leeway=
|
||||
bool get_quotes; // --download
|
||||
|
||||
function<optional<price_point_t>
|
||||
|
|
|
|||
|
|
@ -205,11 +205,7 @@ public:
|
|||
mutable optional<xdata_t> xdata_;
|
||||
|
||||
bool has_xdata() const {
|
||||
#if BOOST_VERSION >= 105600
|
||||
return xdata_ != NULL;
|
||||
#else
|
||||
return xdata_;
|
||||
#endif
|
||||
return static_cast<bool>(xdata_);
|
||||
}
|
||||
void clear_xdata() {
|
||||
xdata_ = none;
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ public:
|
|||
if (name != "__main__")
|
||||
main_module->define_global(name, mod->module_object);
|
||||
return mod;
|
||||
}
|
||||
}
|
||||
|
||||
python_interpreter_t() : session_t(), is_initialized(false) {
|
||||
TRACE_CTOR(python_interpreter_t, "");
|
||||
|
|
|
|||
|
|
@ -396,7 +396,7 @@ value_t select_command(call_scope_t& args)
|
|||
#if 0
|
||||
query_t query;
|
||||
keep_details_t keeper(true, true, true);
|
||||
expr_t::ptr_op_t expr =
|
||||
expr_t::ptr_op_t expr =
|
||||
query.parse_args(string_value(arg).to_sequence(), keeper, false, true);
|
||||
report.HANDLER(limit_).on("#select", query.get_query(query_t::QUERY_LIMIT));
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -127,47 +127,14 @@ std::size_t session_t::read_data(const string& master_account)
|
|||
|
||||
if (HANDLED(value_expr_))
|
||||
journal->value_expr = HANDLER(value_expr_).str();
|
||||
if (price_db_path) {
|
||||
if (exists(*price_db_path)) {
|
||||
parsing_context.push(*price_db_path);
|
||||
parsing_context.get_current().journal = journal.get();
|
||||
try {
|
||||
if (journal->read(parsing_context) > 0)
|
||||
throw_(parse_error, _("Transactions not allowed in price history file"));
|
||||
}
|
||||
catch (...) {
|
||||
parsing_context.pop();
|
||||
throw;
|
||||
}
|
||||
parsing_context.pop();
|
||||
}
|
||||
}
|
||||
|
||||
foreach (const path& pathname, HANDLER(file_).data_files) {
|
||||
if (pathname == "-" || pathname == "/dev/stdin") {
|
||||
// To avoid problems with stdin and pipes, etc., we read the entire
|
||||
// file in beforehand into a memory buffer, and then parcel it out
|
||||
// from there.
|
||||
std::ostringstream buffer;
|
||||
|
||||
while (std::cin.good() && ! std::cin.eof()) {
|
||||
char line[8192];
|
||||
std::cin.read(line, 8192);
|
||||
std::streamsize count = std::cin.gcount();
|
||||
buffer.write(line, count);
|
||||
}
|
||||
buffer.flush();
|
||||
|
||||
shared_ptr<std::istream> stream(new std::istringstream(buffer.str()));
|
||||
parsing_context.push(stream);
|
||||
} else {
|
||||
parsing_context.push(pathname);
|
||||
}
|
||||
|
||||
if (price_db_path) {
|
||||
if (exists(*price_db_path)) {
|
||||
parsing_context.push(*price_db_path);
|
||||
parsing_context.get_current().journal = journal.get();
|
||||
parsing_context.get_current().master = acct;
|
||||
try {
|
||||
xact_count += journal->read(parsing_context);
|
||||
if (journal->read(parsing_context) > 0)
|
||||
throw_(parse_error, _("Transactions not allowed in price history file"));
|
||||
}
|
||||
catch (...) {
|
||||
parsing_context.pop();
|
||||
|
|
@ -175,10 +142,44 @@ std::size_t session_t::read_data(const string& master_account)
|
|||
}
|
||||
parsing_context.pop();
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG("ledger.read", "xact_count [" << xact_count
|
||||
<< "] == journal->xacts.size() [" << journal->xacts.size() << "]");
|
||||
assert(xact_count == journal->xacts.size());
|
||||
foreach (const path& pathname, HANDLER(file_).data_files) {
|
||||
if (pathname == "-" || pathname == "/dev/stdin") {
|
||||
// To avoid problems with stdin and pipes, etc., we read the entire
|
||||
// file in beforehand into a memory buffer, and then parcel it out
|
||||
// from there.
|
||||
std::ostringstream buffer;
|
||||
|
||||
while (std::cin.good() && ! std::cin.eof()) {
|
||||
char line[8192];
|
||||
std::cin.read(line, 8192);
|
||||
std::streamsize count = std::cin.gcount();
|
||||
buffer.write(line, count);
|
||||
}
|
||||
buffer.flush();
|
||||
|
||||
shared_ptr<std::istream> stream(new std::istringstream(buffer.str()));
|
||||
parsing_context.push(stream);
|
||||
} else {
|
||||
parsing_context.push(pathname);
|
||||
}
|
||||
|
||||
parsing_context.get_current().journal = journal.get();
|
||||
parsing_context.get_current().master = acct;
|
||||
try {
|
||||
xact_count += journal->read(parsing_context);
|
||||
}
|
||||
catch (...) {
|
||||
parsing_context.pop();
|
||||
throw;
|
||||
}
|
||||
parsing_context.pop();
|
||||
}
|
||||
|
||||
DEBUG("ledger.read", "xact_count [" << xact_count
|
||||
<< "] == journal->xacts.size() [" << journal->xacts.size() << "]");
|
||||
assert(xact_count == journal->xacts.size());
|
||||
|
||||
if (populated_data_files)
|
||||
HANDLER(file_).data_files.clear();
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ static char* _strptime(const char *s, const char *format, struct tm *tm) {
|
|||
if (tm->tm_wday == -1) return NULL;
|
||||
s += len;
|
||||
break;
|
||||
|
||||
|
||||
// month name.
|
||||
case 'b':
|
||||
case 'B':
|
||||
|
|
|
|||
|
|
@ -500,11 +500,7 @@ public:
|
|||
void stabilize(const optional<date_t>& date = none);
|
||||
|
||||
bool is_valid() const {
|
||||
#if BOOST_VERSION >= 105600
|
||||
return start != NULL;
|
||||
#else
|
||||
return start;
|
||||
#endif
|
||||
return static_cast<bool>(start);
|
||||
}
|
||||
|
||||
/** Find the current or next period containing date. Returns false if
|
||||
|
|
|
|||
|
|
@ -341,6 +341,10 @@ value_t& value_t::operator+=(const value_t& val)
|
|||
}
|
||||
|
||||
switch (type()) {
|
||||
case VOID:
|
||||
*this = value_t(val);
|
||||
return *this;
|
||||
|
||||
case DATETIME:
|
||||
switch (val.type()) {
|
||||
case INTEGER:
|
||||
|
|
|
|||
|
|
@ -435,7 +435,7 @@ public:
|
|||
return temp;
|
||||
}
|
||||
void in_place_roundto(int places);
|
||||
|
||||
|
||||
value_t truncated() const {
|
||||
value_t temp(*this);
|
||||
temp.in_place_truncate();
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ public:
|
|||
optional<string> note() const {
|
||||
return ptr()->note;
|
||||
}
|
||||
|
||||
|
||||
bool has_tag(const string& tag) const {
|
||||
return ptr()->has_tag(tag);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ int mk_wcwidth(boost::uint32_t ucs)
|
|||
|
||||
/* if we arrive here, ucs is not a combining or C0/C1 control character */
|
||||
|
||||
return 1 +
|
||||
return 1 +
|
||||
(ucs >= 0x1100 &&
|
||||
(ucs <= 0x115f || /* Hangul Jamo init. consonants */
|
||||
ucs == 0x2329 || ucs == 0x232a ||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,9 @@ if (PYTHONINTERP_FOUND)
|
|||
set_target_properties(check PROPERTIES DEPENDS ${_class}Test_${TestFile_Name})
|
||||
endforeach()
|
||||
|
||||
list(APPEND CheckOptions CheckManpage CheckTexinfo CheckBaselineTests)
|
||||
# CheckManpage and CheckTexinfo are disabled, since they do not work
|
||||
# reliably yet, instead they are being run as a Travis CI report.
|
||||
list(APPEND CheckOptions CheckBaselineTests) #CheckManpage CheckTexinfo
|
||||
foreach(_class ${CheckOptions})
|
||||
add_test(NAME ${_class}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/test/${_class}.py
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ class CheckBaselineTests (CheckOptions):
|
|||
'args-only',
|
||||
'debug',
|
||||
'download',
|
||||
'file',
|
||||
'force-color',
|
||||
'force-pager',
|
||||
'generated',
|
||||
|
|
@ -33,6 +32,7 @@ class CheckBaselineTests (CheckOptions):
|
|||
'no-pager',
|
||||
'options',
|
||||
'price-exp',
|
||||
'revalued-total',
|
||||
'seed',
|
||||
'trace',
|
||||
'verbose',
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ class CheckOptions (object):
|
|||
self.missing_functions.add(function)
|
||||
else:
|
||||
functions.remove(function)
|
||||
known_functions = ['tag', 'has_tag']
|
||||
known_functions = ['tag', 'has_tag', 'meta', 'has_meta']
|
||||
self.unknown_functions = {function for function in functions if function not in known_functions}
|
||||
|
||||
if len(self.missing_options):
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ class DocTests:
|
|||
validate_command = False
|
||||
try:
|
||||
command = example[self.testin_token][self.testin_token]
|
||||
command = re.sub(r'\\\n', '', command)
|
||||
except KeyError:
|
||||
if self.validate_dat_token in example:
|
||||
command = '$ ledger bal'
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ end test
|
|||
|
||||
test -f /dev/null --input-date-format "%m/%d/%Y" convert test/baseline/cmd-convert3.dat -> 1
|
||||
__ERROR__
|
||||
While parsing file "$sourcepath/test/baseline/cmd-convert3.dat", line 1:
|
||||
While parsing file "$sourcepath/test/baseline/cmd-convert3.dat", line 1:
|
||||
While parsing CSV line:
|
||||
01/01/2011,,
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ end test
|
|||
|
||||
test -f /dev/null convert test/baseline/cmd-convert4.dat -> 1
|
||||
__ERROR__
|
||||
While parsing file "$sourcepath/test/baseline/cmd-convert4.dat", line 1:
|
||||
While parsing file "$sourcepath/test/baseline/cmd-convert4.dat", line 1:
|
||||
While parsing CSV line:
|
||||
bogus,$10,
|
||||
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
test cleared --file test/input/drewr3.dat --cleared-format "%-30(account) %15(get_at(total_expr, 0)) %15(get_at(total_expr, 1))\n%/"
|
||||
Assets $ -3,804.00 $ 775.00
|
||||
Assets:Checking $ 1,396.00 $ 775.00
|
||||
Assets:Checking:Business $ 30.00 0
|
||||
Assets:Savings $ -5,200.00 0
|
||||
Equity:Opening Balances $ -1,000.00 $ -1,000.00
|
||||
Expenses $ 6,654.00 $ 225.00
|
||||
Expenses:Auto $ 5,500.00 0
|
||||
Expenses:Books $ 20.00 0
|
||||
Expenses:Escrow $ 300.00 0
|
||||
Expenses:Food:Groceries $ 334.00 $ 225.00
|
||||
Expenses:Interest:Mortgage $ 500.00 0
|
||||
Income $ -2,030.00 0
|
||||
Income:Salary $ -2,000.00 0
|
||||
Income:Sales $ -30.00 0
|
||||
Liabilities $ -63.60 0
|
||||
Liabilities:MasterCard $ -20.00 0
|
||||
Liabilities:Mortgage:Principal $ 200.00 0
|
||||
Liabilities:Tithe $ -243.60 0
|
||||
end test
|
||||
|
|
@ -2,16 +2,18 @@ account Assets:Cash
|
|||
account Expenses:Phone
|
||||
account Expenses:Rent
|
||||
commodity GBP
|
||||
tag bar
|
||||
|
||||
2012-03-20 Phone
|
||||
2012-03-20 * Phone
|
||||
; :bar:
|
||||
Expenses:Phone 20.00 GBP
|
||||
Assets:Cash
|
||||
|
||||
2012-03-21 Rent
|
||||
2012-03-21 * Rent
|
||||
Expenses:Rent 550.00 GBP
|
||||
Assets:Cash
|
||||
|
||||
2012-03-22 Food
|
||||
2012-03-22 * Food
|
||||
; :food:
|
||||
Expenses:Food 20.00 EUR
|
||||
Assets:Cash
|
||||
|
|
@ -27,8 +29,8 @@ test bal --explicit --strict
|
|||
--------------------
|
||||
0
|
||||
__ERROR__
|
||||
Warning: "$FILE", line 16: Unknown account 'Expenses:Food'
|
||||
Warning: "$FILE", line 16: Unknown commodity 'EUR'
|
||||
Warning: "$FILE", line 17: Unknown metadata tag 'food'
|
||||
Warning: "$FILE", line 18: Unknown account 'Expenses:Food'
|
||||
Warning: "$FILE", line 18: Unknown commodity 'EUR'
|
||||
Warning: "$FILE", line 19: Unknown metadata tag 'food'
|
||||
end test
|
||||
|
||||
|
|
|
|||
58
test/baseline/opt-no-revalued.test
Normal file
58
test/baseline/opt-no-revalued.test
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
2009/01/01 Sample 1a
|
||||
Assets:Brokerage:Stocks 100 S
|
||||
Assets:Brokerage:Cash -100 P
|
||||
|
||||
P 2009/01/01 00:00:00 S 2 P
|
||||
|
||||
2009/02/01 Sample 2a
|
||||
Assets:Brokerage:Stocks 100 S @ 1 P
|
||||
Assets:Brokerage:Cash
|
||||
|
||||
P 2009/02/01 00:00:00 S 4 P
|
||||
|
||||
2009/03/01 Sample 3a
|
||||
Assets:Brokerage:Stocks 100 S @@ 100 P
|
||||
Assets:Brokerage:Cash
|
||||
|
||||
P 2009/03/01 00:00:00 S 8 P
|
||||
|
||||
2009/04/01 Sample 4a
|
||||
Assets:Brokerage:Cash 100 P
|
||||
Assets:Brokerage:Stocks -100 S {1 P}
|
||||
|
||||
P 2009/04/01 00:00:00 S 16 P
|
||||
|
||||
; In this usage case, the top amount is always secondary
|
||||
; 2010/01/01 Sample 1b
|
||||
; Assets:Brokerage:Cash -100 P
|
||||
; Assets:Brokerage:Stocks 100 S
|
||||
;
|
||||
; P 2010/01/01 00:00:00 S 2 P
|
||||
|
||||
2010/02/01 Sample 2b
|
||||
Assets:Brokerage:Cash
|
||||
Assets:Brokerage:Stocks 100 S @ 1 P
|
||||
|
||||
P 2010/02/01 00:00:00 S 4 P
|
||||
|
||||
2010/03/01 Sample 3b
|
||||
Assets:Brokerage:Cash
|
||||
Assets:Brokerage:Stocks 100 S @@ 100 P
|
||||
|
||||
P 2010/03/01 00:00:00 S 8 P
|
||||
|
||||
2010/04/01 Sample 4b
|
||||
Assets:Brokerage:Stocks -100 S {1 P}
|
||||
Assets:Brokerage:Cash 100 P
|
||||
|
||||
P 2010/04/01 00:00:00 S 16 P
|
||||
|
||||
test reg --market --no-revalued stocks
|
||||
09-Jan-01 Sample 1a Asset:Brokerage:Stocks 200 P 200 P
|
||||
09-Feb-01 Sample 2a Asset:Brokerage:Stocks 400 P 800 P
|
||||
09-Mar-01 Sample 3a Asset:Brokerage:Stocks 800 P 2400 P
|
||||
09-Apr-01 Sample 4a Asset:Brokerage:Stocks -1600 P 3200 P
|
||||
10-Feb-01 Sample 2b Asset:Brokerage:Stocks 400 P 1200 P
|
||||
10-Mar-01 Sample 3b Asset:Brokerage:Stocks 800 P 3200 P
|
||||
10-Apr-01 Sample 4b Asset:Brokerage:Stocks -1600 P 4800 P
|
||||
end test
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
2012-01-01 * Opening balance
|
||||
Assets:Current 17.43 EUR
|
||||
Assets:Investments 200 "LU02" @ 24.77 EUR
|
||||
Assets:Investments 58 "LU02" @ 24.79900855 EUR
|
||||
Equity:Opening balance
|
||||
|
||||
2012-01-01 * Opening balance
|
||||
Assets:Pension 785.44 GBP
|
||||
Assets:Pension 97.0017 "H2" @ 5.342999720204 GBP
|
||||
Assets:Pension 4.3441 "H1" @ 5.289999915108 GBP
|
||||
Equity:Opening balance
|
||||
|
||||
2012-01-01 * Opening balance: misc
|
||||
Assets:Piggy bank 3.51 GBP
|
||||
Equity:Opening balance
|
||||
|
||||
2012-01-01 * Opening balance
|
||||
Assets:Rewards 9836 AAdvantage
|
||||
Equity:Opening balance
|
||||
|
||||
2012-01-03 * Receivable
|
||||
Assets:Current
|
||||
Assets:Receivable -161.06 EUR
|
||||
Assets:Receivable -9.99 GBP @@ 11.65 EUR
|
||||
|
||||
2012-01-27 * Test
|
||||
Income:Test -2759.50 GBP
|
||||
Income:Test -110.76 GBP
|
||||
Assets:Foo 345.57 GBP
|
||||
Expenses:Test 16.47 GBP
|
||||
Expenses:Test 6.33 GBP
|
||||
Expenses:Test 261.39 GBP
|
||||
Assets:Current
|
||||
|
||||
test reg -X EUR -H --no-rounding
|
||||
12-Jan-01 Opening balance Assets:Current 17.43 EUR 17.43 EUR
|
||||
Assets:Investments 4959.80 EUR 4977.23 EUR
|
||||
Assets:Investments 1438.34 EUR 6415.57 EUR
|
||||
Equity:Opening balance -6409.77 EUR 5.80 EUR
|
||||
12-Jan-01 Opening balance Assets:Pension 785.44 GBP 5.80 EUR
|
||||
785.44 GBP
|
||||
Assets:Pension 97.0017 H2 5.80 EUR
|
||||
785.44 GBP
|
||||
97.0017 H2
|
||||
Assets:Pension 4.3441 H1 5.80 EUR
|
||||
785.44 GBP
|
||||
4.3441 H1
|
||||
97.0017 H2
|
||||
Equity:Opening balance -1326.70 GBP 5.80 EUR
|
||||
-541.26 GBP
|
||||
4.3441 H1
|
||||
97.0017 H2
|
||||
12-Jan-01 Opening balance: misc Assets:Piggy bank 3.51 GBP 5.80 EUR
|
||||
-537.75 GBP
|
||||
4.3441 H1
|
||||
97.0017 H2
|
||||
Equity:Opening balance -3.51 GBP 5.80 EUR
|
||||
-541.26 GBP
|
||||
4.3441 H1
|
||||
97.0017 H2
|
||||
12-Jan-01 Opening balance Assets:Rewards 9836 AAdvantage 9836 AAdvantage
|
||||
5.80 EUR
|
||||
-541.26 GBP
|
||||
4.3441 H1
|
||||
97.0017 H2
|
||||
Equity:Opening balance -9836 AAdvantage 5.80 EUR
|
||||
-541.26 GBP
|
||||
4.3441 H1
|
||||
97.0017 H2
|
||||
12-Jan-03 Commodities revalued <Revalued> 0 5.80 EUR
|
||||
12-Jan-03 Receivable Assets:Current 172.71 EUR 178.51 EUR
|
||||
Assets:Receivable -161.06 EUR 17.45 EUR
|
||||
Assets:Receivable -11.65 EUR 5.80 EUR
|
||||
12-Jan-27 Test Income:Test -3218.04 EUR -3212.23 EUR
|
||||
Income:Test -129.16 EUR -3341.40 EUR
|
||||
Assets:Foo 402.99 EUR -2938.41 EUR
|
||||
Expenses:Test 19.21 EUR -2919.20 EUR
|
||||
Expenses:Test 7.38 EUR -2911.82 EUR
|
||||
Expenses:Test 304.82 EUR -2606.99 EUR
|
||||
Assets:Current 2612.80 EUR 5.80 EUR
|
||||
end test
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
|
||||
D 1000.00 EUR
|
||||
D 1000.00 USD
|
||||
D 1000.00 DM
|
||||
|
||||
2015-01-01 * Buy 2 FOO
|
||||
Assets:Investments 2 FOO @@ 20.00 EUR
|
||||
Assets:Cash -20.00 EUR
|
||||
|
||||
2015-05-01 * Spend on food
|
||||
Expenses:Food 20.00 USD
|
||||
; Just to be silly, always valuate *these* $20 as 30 DM, no matter what
|
||||
; the user asks for with -V or -X
|
||||
; VALUE:: 30 DM
|
||||
Assets:Cash -20.00 USD
|
||||
|
||||
P 2015-05-01 USD 20 DM
|
||||
|
||||
P 2015-06-01 USD 22 DM
|
||||
|
||||
test bal assets:investments -V --value-expr "25.00 EUR"
|
||||
50.00 EUR Assets:Investments
|
||||
end test
|
||||
|
||||
test bal assets:investments -G --value-expr "date < [March 2015] ? 22.00 EUR : 25.00 EUR" --now "2015-02-20"
|
||||
24.00 EUR Assets:Investments
|
||||
end test
|
||||
|
||||
test bal assets:investments -G --value-expr "date < [March 2015] ? 22.00 EUR : 25.00 EUR" --now "2015-03-20"
|
||||
30.00 EUR Assets:Investments
|
||||
end test
|
||||
|
||||
test bal expenses:food
|
||||
20.00 USD Expenses:Food
|
||||
end test
|
||||
|
||||
test bal expenses:food -V
|
||||
600.00 DM Expenses:Food
|
||||
end test
|
||||
|
||||
test bal expenses:food -X "DM" --now "2015-05-02"
|
||||
600.00 DM Expenses:Food
|
||||
end test
|
||||
|
||||
test bal expenses:food -X "DM" --now "2015-06-02"
|
||||
600.00 DM Expenses:Food
|
||||
end test
|
||||
|
||||
11
test/regress/1057.test
Normal file
11
test/regress/1057.test
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
2014/04/03 www.amazon.fr
|
||||
Dépense:Loisir:Ordi:Matériel 101,50 € ; disque dur portable 2,5" 2000 Go
|
||||
Dépense:Maison:Service:Poste
|
||||
* Passif:Crédit:BanqueAccord -171,63 €
|
||||
|
||||
test -f test/regress/1057.test --now=2014/06/27 emacs
|
||||
(("$sourcepath/test/regress/1057.test" 1 (21308 34912 0) nil "www.amazon.fr"
|
||||
(2 "Dépense:Loisir:Ordi:Matériel" "101,50 €" nil " disque dur portable 2,5\" 2000 Go")
|
||||
(3 "Dépense:Maison:Service:Poste" "70,13 €" nil)
|
||||
(4 "Passif:Crédit:BanqueAccord" "-171,63 €" t)))
|
||||
end test
|
||||
61
test/regress/25A099C9.test
Normal file
61
test/regress/25A099C9.test
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
test -f test/garbage-input.dat reg -> 29
|
||||
__ERROR__
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 1:
|
||||
Error: Directive '/*' requires an argument
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 32:
|
||||
Error: Directive '/**' requires an argument
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 36:
|
||||
Error: Directive '/**' requires an argument
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 66:
|
||||
Error: No quantity specified for amount
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 69:
|
||||
Error: Unexpected whitespace at beginning of line
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 78:
|
||||
Error: Directive '};' requires an argument
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 82:
|
||||
Error: Directive '/**' requires an argument
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 93:
|
||||
Error: Unexpected whitespace at beginning of line
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 97:
|
||||
Error: Directive '{' requires an argument
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 98:
|
||||
Error: Directive 'public:' requires an argument
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 120:
|
||||
Error: Directive 'protected:' requires an argument
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 131:
|
||||
Error: Directive 'public:' requires an argument
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 711:
|
||||
Error: Unexpected whitespace at beginning of line
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 740:
|
||||
Error: Directive 'private:' requires an argument
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 749:
|
||||
Error: Unexpected whitespace at beginning of line
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 750:
|
||||
Error: Directive '};' requires an argument
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 752:
|
||||
Error: Invalid date/time: line amount_t amoun
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 756:
|
||||
Error: Directive '}' requires an argument
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 758:
|
||||
Error: Invalid date/time: line string amount_
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 762:
|
||||
Error: Directive '}' requires an argument
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 764:
|
||||
Error: Invalid date/time: line string amount_
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 768:
|
||||
Error: Directive '}' requires an argument
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 770:
|
||||
Error: Invalid date/time: line string amount_
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 774:
|
||||
Error: Directive '}' requires an argument
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 776:
|
||||
Error: Invalid date/time: line std::ostream&
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 782:
|
||||
Error: Directive '}' requires an argument
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 783:
|
||||
Error: Invalid date/time: line std::istream&
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 786:
|
||||
Error: Directive '}' requires an argument
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 789:
|
||||
Error: Unexpected whitespace at beginning of line
|
||||
end test
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
test -f test/garbage-input.dat reg -> 20
|
||||
__ERROR__
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 2:
|
||||
Error: Unexpected whitespace at beginning of line
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 33:
|
||||
Error: Unexpected whitespace at beginning of line
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 37:
|
||||
Error: Unexpected whitespace at beginning of line
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 66:
|
||||
Error: No quantity specified for amount
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 69:
|
||||
Error: Unexpected whitespace at beginning of line
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 83:
|
||||
Error: Unexpected whitespace at beginning of line
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 93:
|
||||
Error: Unexpected whitespace at beginning of line
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 99:
|
||||
Error: Unexpected whitespace at beginning of line
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 121:
|
||||
Error: Unexpected whitespace at beginning of line
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 132:
|
||||
Error: Unexpected whitespace at beginning of line
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 711:
|
||||
Error: Unexpected whitespace at beginning of line
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 741:
|
||||
Error: Unexpected whitespace at beginning of line
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 749:
|
||||
Error: Unexpected whitespace at beginning of line
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 752:
|
||||
Error: Invalid date/time: line amount_t amoun
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 758:
|
||||
Error: Invalid date/time: line string amount_
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 764:
|
||||
Error: Invalid date/time: line string amount_
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 770:
|
||||
Error: Invalid date/time: line string amount_
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 776:
|
||||
Error: Invalid date/time: line std::ostream&
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 783:
|
||||
Error: Invalid date/time: line std::istream&
|
||||
While parsing file "$sourcepath/test/garbage-input.dat", line 789:
|
||||
Error: Unexpected whitespace at beginning of line
|
||||
end test
|
||||
|
|
@ -7,9 +7,16 @@ include_directories(${PROJECT_SOURCE_DIR}/src)
|
|||
|
||||
if (BUILD_LIBRARY)
|
||||
add_executable(UtilTests t_times.cc)
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL Darwin AND HAVE_BOOST_PYTHON)
|
||||
target_link_libraries(UtilTests ${PYTHON_LIBRARIES})
|
||||
endif()
|
||||
add_ledger_test(UtilTests)
|
||||
|
||||
add_executable(MathTests t_amount.cc t_commodity.cc t_balance.cc t_expr.cc)
|
||||
add_executable(MathTests t_amount.cc t_commodity.cc t_balance.cc t_expr.cc t_value.cc)
|
||||
set_source_files_properties(t_amount.cc PROPERTIES COMPILE_FLAGS "-Wno-unused-comparison")
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL Darwin AND HAVE_BOOST_PYTHON)
|
||||
target_link_libraries(MathTests ${PYTHON_LIBRARIES})
|
||||
endif()
|
||||
add_ledger_test(MathTests)
|
||||
|
||||
set_target_properties(check PROPERTIES DEPENDS LedgerUtilTests)
|
||||
|
|
|
|||
714
test/unit/t_value.cc
Normal file
714
test/unit/t_value.cc
Normal file
|
|
@ -0,0 +1,714 @@
|
|||
#define BOOST_TEST_DYN_LINK
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <system.hh>
|
||||
|
||||
#include "value.h"
|
||||
|
||||
using namespace ledger;
|
||||
|
||||
struct value_fixture {
|
||||
value_fixture() {
|
||||
times_initialize();
|
||||
amount_t::initialize();
|
||||
value_t::initialize();
|
||||
|
||||
|
||||
// Cause the display precision for dollars to be initialized to 2.
|
||||
amount_t x1("$1.00");
|
||||
BOOST_CHECK(x1);
|
||||
|
||||
amount_t::stream_fullstrings = true; // make reports from UnitTests accurate
|
||||
}
|
||||
|
||||
~value_fixture()
|
||||
{
|
||||
amount_t::stream_fullstrings = false;
|
||||
amount_t::shutdown();
|
||||
times_shutdown();
|
||||
value_t::shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(value, value_fixture)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(testConstructors)
|
||||
{
|
||||
value_t::sequence_t s1;
|
||||
value_t v1;
|
||||
value_t v2(true);
|
||||
value_t v3(boost::posix_time::from_time_t(time_t(NULL)));
|
||||
value_t v4(date_t(parse_date("2014/08/14")));
|
||||
value_t v5(2L);
|
||||
value_t v6(4UL);
|
||||
value_t v7(1.00);
|
||||
value_t v8(amount_t("4 GBP"));
|
||||
value_t v9(balance_t("3 EUR"));
|
||||
value_t v10(mask_t("regex"));
|
||||
value_t v11(s1);
|
||||
value_t v12(string("$1"));
|
||||
value_t v13("2 CAD");
|
||||
value_t v14("comment", true);
|
||||
value_t v15(string("tag"), true);
|
||||
|
||||
BOOST_CHECK(v1.valid());
|
||||
BOOST_CHECK(v2.valid());
|
||||
BOOST_CHECK(v3.valid());
|
||||
BOOST_CHECK(v4.valid());
|
||||
BOOST_CHECK(v5.valid());
|
||||
BOOST_CHECK(v6.valid());
|
||||
BOOST_CHECK(v7.valid());
|
||||
BOOST_CHECK(v8.valid());
|
||||
BOOST_CHECK(v9.valid());
|
||||
BOOST_CHECK(v10.valid());
|
||||
BOOST_CHECK(v11.valid());
|
||||
BOOST_CHECK(v12.valid());
|
||||
BOOST_CHECK(v13.valid());
|
||||
BOOST_CHECK(v14.valid());
|
||||
BOOST_CHECK(v15.valid());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(testAssignment)
|
||||
{
|
||||
value_t::sequence_t s1;
|
||||
value_t v1;
|
||||
value_t v2 = true;
|
||||
value_t v3 = boost::posix_time::from_time_t(time_t(NULL));
|
||||
value_t v4 = date_t(parse_date("2014/08/14"));
|
||||
value_t v5 = -2L;
|
||||
value_t v6 = 4UL;
|
||||
value_t v7 = 1.00;
|
||||
value_t v8 = amount_t("4 GBP");
|
||||
value_t v9 = balance_t("3 EUR");
|
||||
value_t v10 = mask_t("regex");
|
||||
value_t v11 = s1;
|
||||
value_t v12 = value_t(string("$1"));
|
||||
value_t v13 = value_t("2 CAD");
|
||||
value_t v14 = value_t("comment", true);
|
||||
value_t v15 = value_t(string("tag"), true);
|
||||
|
||||
BOOST_CHECK(v1.valid());
|
||||
BOOST_CHECK(v2.valid());
|
||||
BOOST_CHECK(v3.valid());
|
||||
BOOST_CHECK(v4.valid());
|
||||
BOOST_CHECK(v5.valid());
|
||||
BOOST_CHECK(v6.valid());
|
||||
BOOST_CHECK(v7.valid());
|
||||
BOOST_CHECK(v8.valid());
|
||||
BOOST_CHECK(v9.valid());
|
||||
BOOST_CHECK(v10.valid());
|
||||
BOOST_CHECK(v11.valid());
|
||||
BOOST_CHECK(v12.valid());
|
||||
BOOST_CHECK(v13.valid());
|
||||
BOOST_CHECK(v14.valid());
|
||||
BOOST_CHECK(v15.valid());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(testEquality)
|
||||
{
|
||||
struct tm localtime;
|
||||
strptime("10 February 2010", "%d %b %Y", &localtime);
|
||||
time_t time_var = mktime(&localtime);
|
||||
value_t::sequence_t s1;
|
||||
|
||||
value_t v1;
|
||||
value_t v2(true);
|
||||
value_t v3(boost::posix_time::from_time_t(time_var));
|
||||
value_t v4(date_t(parse_date("2014/08/14")));
|
||||
value_t v5(2L);
|
||||
value_t v6(2UL);
|
||||
value_t v7(1.00);
|
||||
value_t v8(amount_t("4 GBP"));
|
||||
value_t v9(balance_t("4 GBP"));
|
||||
value_t v10(mask_t("regex"));
|
||||
value_t v11(s1);
|
||||
value_t v12(string("$1"));
|
||||
value_t v13("2 CAD");
|
||||
value_t v14("comment", true);
|
||||
value_t v15(string("comment"), true);
|
||||
value_t v16;
|
||||
|
||||
BOOST_CHECK_EQUAL(v1, value_t());
|
||||
BOOST_CHECK_EQUAL(v2, value_t(true));
|
||||
BOOST_CHECK_EQUAL(v3, value_t(boost::posix_time::from_time_t(time_var)));
|
||||
BOOST_CHECK(!(v4 == value_t(date_t(parse_date("2014/08/15")))));
|
||||
|
||||
value_t v19(amount_t("2"));
|
||||
value_t v20(balance_t("2"));
|
||||
BOOST_CHECK_EQUAL(v5, v6);
|
||||
BOOST_CHECK_EQUAL(v5, v19);
|
||||
BOOST_CHECK_EQUAL(v5, v20);
|
||||
BOOST_CHECK(v19 == v5);
|
||||
BOOST_CHECK(v19 == v20);
|
||||
BOOST_CHECK(v19 == value_t(amount_t("2")));
|
||||
BOOST_CHECK(v20 == v5);
|
||||
BOOST_CHECK(v20 == v19);
|
||||
BOOST_CHECK(v20 == value_t(balance_t(2L)));
|
||||
BOOST_CHECK(v14 == v15);
|
||||
BOOST_CHECK(v10 == value_t(mask_t("regex")));
|
||||
BOOST_CHECK(v11 == value_t(s1));
|
||||
|
||||
BOOST_CHECK_THROW(v8 == v10, value_error);
|
||||
|
||||
BOOST_CHECK(v1.valid());
|
||||
BOOST_CHECK(v2.valid());
|
||||
BOOST_CHECK(v3.valid());
|
||||
BOOST_CHECK(v4.valid());
|
||||
BOOST_CHECK(v5.valid());
|
||||
BOOST_CHECK(v6.valid());
|
||||
BOOST_CHECK(v7.valid());
|
||||
BOOST_CHECK(v8.valid());
|
||||
BOOST_CHECK(v9.valid());
|
||||
BOOST_CHECK(v10.valid());
|
||||
BOOST_CHECK(v11.valid());
|
||||
BOOST_CHECK(v12.valid());
|
||||
BOOST_CHECK(v13.valid());
|
||||
BOOST_CHECK(v14.valid());
|
||||
BOOST_CHECK(v15.valid());
|
||||
BOOST_CHECK(v19.valid());
|
||||
BOOST_CHECK(v20.valid());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(testSequence)
|
||||
{
|
||||
value_t::sequence_t s1;
|
||||
value_t v1(s1);
|
||||
BOOST_CHECK(v1.is_sequence());
|
||||
v1.push_back(value_t(2L));
|
||||
v1.push_back(value_t("3 GBP"));
|
||||
|
||||
value_t v2("3 GBP");
|
||||
value_t seq(v1);
|
||||
const value_t v3(seq);
|
||||
|
||||
value_t::sequence_t::iterator i = std::find(seq.begin(), seq.end(), v2);
|
||||
if (i != seq.end())
|
||||
BOOST_CHECK(v2 == *i);
|
||||
|
||||
value_t::sequence_t::const_iterator j = std::find(v3.begin(), v3.end(), v2);
|
||||
if (j != v3.end())
|
||||
BOOST_CHECK(v2 == *j);
|
||||
|
||||
BOOST_CHECK(v2 == seq[1]);
|
||||
BOOST_CHECK(v2 == v3[1]);
|
||||
v1.pop_back();
|
||||
v1.pop_back();
|
||||
v1.push_front(v2);
|
||||
v1.push_front(value_t(2L));
|
||||
BOOST_CHECK(v2 == v1[1]);
|
||||
BOOST_CHECK(seq == v1);
|
||||
|
||||
BOOST_CHECK(v1.valid());
|
||||
BOOST_CHECK(v2.valid());
|
||||
BOOST_CHECK(v3.valid());
|
||||
BOOST_CHECK(seq.valid());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(testAddition)
|
||||
{
|
||||
struct tm localtime;
|
||||
strptime("10 February 2010 00:00:00", "%d %b %Y %H:%M:%S", &localtime);
|
||||
time_t time_var = mktime(&localtime);
|
||||
value_t::sequence_t s1;
|
||||
|
||||
value_t v1;
|
||||
value_t v2(true);
|
||||
value_t v3(boost::posix_time::from_time_t(time_var));
|
||||
value_t v4(date_t(parse_date("2014/08/14")));
|
||||
value_t v5(2L);
|
||||
value_t v6(2UL);
|
||||
value_t v7(1.00);
|
||||
value_t v8(amount_t("4 GBP"));
|
||||
value_t v9(balance_t("4 GBP"));
|
||||
value_t v10(mask_t("regex"));
|
||||
value_t v11(s1);
|
||||
value_t v12(string("$1"));
|
||||
value_t v13("2 CAD");
|
||||
value_t v14("comment", true);
|
||||
value_t v15(string("comment"), true);
|
||||
value_t v16(amount_t("2"));
|
||||
|
||||
v14 += v15;
|
||||
BOOST_CHECK_EQUAL(v14, value_t(string("commentcomment"), true));
|
||||
v14 += v12;
|
||||
BOOST_CHECK_EQUAL(v14, value_t(string("commentcomment$1.00"), true));
|
||||
|
||||
v3 += value_t(2L);
|
||||
strptime("10 February 2010 00:00:02", "%d %b %Y %H:%M:%S", &localtime);
|
||||
BOOST_CHECK_EQUAL(v3, value_t(boost::posix_time::from_time_t(mktime(&localtime))));
|
||||
v3 += value_t(amount_t("2"));
|
||||
strptime("10 February 2010 00:00:04", "%d %b %Y %H:%M:%S", &localtime);
|
||||
BOOST_CHECK_EQUAL(v3, value_t(boost::posix_time::from_time_t(mktime(&localtime))));
|
||||
|
||||
v4 += value_t(2L);
|
||||
BOOST_CHECK_EQUAL(v4, value_t(date_t(parse_date("2014/08/16"))));
|
||||
v4 += value_t(amount_t("2"));
|
||||
BOOST_CHECK_EQUAL(v4, value_t(date_t(parse_date("2014/08/18"))));
|
||||
|
||||
v5 += value_t(2L);
|
||||
BOOST_CHECK_EQUAL(v5, value_t(4L));
|
||||
v5 += value_t(amount_t("2"));
|
||||
BOOST_CHECK_EQUAL(v5, value_t(amount_t("6")));
|
||||
v5 += v8;
|
||||
|
||||
v16 += value_t(2L);
|
||||
v16 += value_t(amount_t("2"));
|
||||
v16 += v8;
|
||||
BOOST_CHECK_EQUAL(v5, v16);
|
||||
|
||||
v8 += value_t("6");
|
||||
BOOST_CHECK_EQUAL(v8, v16);
|
||||
|
||||
value_t v17(6L);
|
||||
v17 += value_t(amount_t("4 GBP"));
|
||||
BOOST_CHECK_EQUAL(v8, v17);
|
||||
|
||||
value_t v18(6L);
|
||||
v18 += v9;
|
||||
value_t v19(amount_t("6"));
|
||||
v19 += v9;
|
||||
BOOST_CHECK_EQUAL(v18, v19);
|
||||
|
||||
v9 += value_t(2L);
|
||||
v9 += value_t(amount_t("4"));
|
||||
v9 += v19;
|
||||
v18 += v19;
|
||||
BOOST_CHECK_EQUAL(v9, v18);
|
||||
|
||||
value_t v20(s1);
|
||||
v11 += value_t(2L);
|
||||
v11 += value_t("4 GBP");
|
||||
BOOST_CHECK_THROW(v11 += v20,value_error);
|
||||
BOOST_CHECK_THROW(v10 += v8, value_error);
|
||||
|
||||
v20 += value_t(2L);
|
||||
v20 += value_t("4 GBP");
|
||||
BOOST_CHECK_EQUAL(v11, v20);
|
||||
v11 += v20;
|
||||
v20 += v20;
|
||||
BOOST_CHECK_EQUAL(v11, v20);
|
||||
|
||||
BOOST_CHECK(v1.valid());
|
||||
BOOST_CHECK(v2.valid());
|
||||
BOOST_CHECK(v3.valid());
|
||||
BOOST_CHECK(v4.valid());
|
||||
BOOST_CHECK(v5.valid());
|
||||
BOOST_CHECK(v6.valid());
|
||||
BOOST_CHECK(v7.valid());
|
||||
BOOST_CHECK(v8.valid());
|
||||
BOOST_CHECK(v9.valid());
|
||||
BOOST_CHECK(v10.valid());
|
||||
BOOST_CHECK(v11.valid());
|
||||
BOOST_CHECK(v12.valid());
|
||||
BOOST_CHECK(v13.valid());
|
||||
BOOST_CHECK(v14.valid());
|
||||
BOOST_CHECK(v15.valid());
|
||||
BOOST_CHECK(v16.valid());
|
||||
BOOST_CHECK(v17.valid());
|
||||
BOOST_CHECK(v18.valid());
|
||||
BOOST_CHECK(v19.valid());
|
||||
BOOST_CHECK(v20.valid());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(testSubtraction)
|
||||
{
|
||||
struct tm localtime;
|
||||
strptime("10 February 2010 00:00:04", "%d %b %Y %H:%M:%S", &localtime);
|
||||
time_t time_var = mktime(&localtime);
|
||||
value_t::sequence_t s1;
|
||||
|
||||
value_t v1;
|
||||
value_t v2(true);
|
||||
value_t v3(boost::posix_time::from_time_t(time_var));
|
||||
value_t v4(date_t(parse_date("2014/08/18")));
|
||||
value_t v5(6L);
|
||||
value_t v6(6UL);
|
||||
value_t v7(1.00);
|
||||
value_t v8(amount_t("4 GBP"));
|
||||
value_t v9(balance_t("4 GBP"));
|
||||
value_t v10(mask_t("regex"));
|
||||
value_t v11(s1);
|
||||
value_t v12(string("$1"));
|
||||
value_t v13("2 CAD");
|
||||
value_t v14("comment", true);
|
||||
value_t v15(string("comment"), true);
|
||||
value_t v16(amount_t("6"));
|
||||
|
||||
v3 -= value_t(2L);
|
||||
strptime("10 February 2010 00:00:02", "%d %b %Y %H:%M:%S", &localtime);
|
||||
BOOST_CHECK_EQUAL(v3, value_t(boost::posix_time::from_time_t(mktime(&localtime))));
|
||||
v3 -= value_t(amount_t("2"));
|
||||
strptime("10 February 2010 00:00:00", "%d %b %Y %H:%M:%S", &localtime);
|
||||
BOOST_CHECK_EQUAL(v3, value_t(boost::posix_time::from_time_t(mktime(&localtime))));
|
||||
|
||||
v4 -= value_t(2L);
|
||||
BOOST_CHECK_EQUAL(v4, value_t(date_t(parse_date("2014/08/16"))));
|
||||
v4 -= value_t(amount_t("2"));
|
||||
BOOST_CHECK_EQUAL(v4, value_t(date_t(parse_date("2014/08/14"))));
|
||||
|
||||
v5 -= value_t(2L);
|
||||
BOOST_CHECK_EQUAL(v5, value_t(4L));
|
||||
v5 -= value_t(amount_t("2"));
|
||||
BOOST_CHECK_EQUAL(v5, value_t(amount_t("2")));
|
||||
v5 -= v8;
|
||||
|
||||
v16 -= value_t(2L);
|
||||
v16 -= value_t(amount_t("2"));
|
||||
v16 -= v8;
|
||||
BOOST_CHECK_EQUAL(v5, v16);
|
||||
|
||||
v8 -= value_t("2");
|
||||
BOOST_CHECK_EQUAL(-v8, v16);
|
||||
|
||||
value_t v18(6L);
|
||||
v18 -= v9;
|
||||
value_t v19(amount_t("6"));
|
||||
v19 -= v9;
|
||||
BOOST_CHECK_EQUAL(v18, v19);
|
||||
|
||||
v9 -= value_t(-2L);
|
||||
v9 -= value_t(amount_t("-10"));
|
||||
v9 -= value_t(amount_t("12 GBP"));
|
||||
v9 -= v19;
|
||||
BOOST_CHECK_EQUAL(v9, v18);
|
||||
v18 -=v19;
|
||||
BOOST_CHECK_EQUAL(v18, value_t("0"));
|
||||
|
||||
value_t v20(s1);
|
||||
value_t v21(2L);
|
||||
value_t v22("4 GBP");
|
||||
v11.push_back(v21);
|
||||
v11.push_back(v22);
|
||||
BOOST_CHECK_THROW(v11 -= v20,value_error);
|
||||
BOOST_CHECK_THROW(v10 -= v8, value_error);
|
||||
|
||||
v20.push_back(v21);
|
||||
v20.push_back(v22);
|
||||
v11 -= v20;
|
||||
value_t v23(s1);
|
||||
v23.push_back(value_t(0L));
|
||||
v23.push_back(value_t("0"));
|
||||
BOOST_CHECK_EQUAL(v11, v23);
|
||||
v20 -= v21;
|
||||
v20 -= v22;
|
||||
BOOST_CHECK_EQUAL(v20, value_t(s1));
|
||||
|
||||
BOOST_CHECK(v1.valid());
|
||||
BOOST_CHECK(v2.valid());
|
||||
BOOST_CHECK(v3.valid());
|
||||
BOOST_CHECK(v4.valid());
|
||||
BOOST_CHECK(v5.valid());
|
||||
BOOST_CHECK(v6.valid());
|
||||
BOOST_CHECK(v7.valid());
|
||||
BOOST_CHECK(v8.valid());
|
||||
BOOST_CHECK(v9.valid());
|
||||
BOOST_CHECK(v10.valid());
|
||||
BOOST_CHECK(v11.valid());
|
||||
BOOST_CHECK(v12.valid());
|
||||
BOOST_CHECK(v13.valid());
|
||||
BOOST_CHECK(v14.valid());
|
||||
BOOST_CHECK(v15.valid());
|
||||
BOOST_CHECK(v16.valid());
|
||||
BOOST_CHECK(v18.valid());
|
||||
BOOST_CHECK(v19.valid());
|
||||
BOOST_CHECK(v20.valid());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(testMultiplication)
|
||||
{
|
||||
struct tm localtime;
|
||||
strptime("10 February 2010 00:00:00", "%d %b %Y %H:%M:%S", &localtime);
|
||||
time_t time_var = mktime(&localtime);
|
||||
value_t::sequence_t s1;
|
||||
|
||||
value_t v1;
|
||||
value_t v2(true);
|
||||
value_t v3(boost::posix_time::from_time_t(time_var));
|
||||
value_t v4(date_t(parse_date("2014/08/14")));
|
||||
value_t v5(2L);
|
||||
value_t v6(2UL);
|
||||
value_t v7(1.00);
|
||||
value_t v8(amount_t("4 GBP"));
|
||||
value_t v9(balance_t("4 GBP"));
|
||||
value_t v10(mask_t("regex"));
|
||||
value_t v11(s1);
|
||||
value_t v12(string("$1"));
|
||||
value_t v13("2 CAD");
|
||||
value_t v14("comment", true);
|
||||
value_t v15(string("comment"), true);
|
||||
value_t v16(amount_t("2"));
|
||||
|
||||
v14 *= value_t(2L);
|
||||
BOOST_CHECK_EQUAL(v14, value_t(string("commentcomment"), true));
|
||||
|
||||
v5 *= value_t(2L);
|
||||
BOOST_CHECK_EQUAL(v5, value_t(4L));
|
||||
v5 *= value_t(amount_t("2"));
|
||||
BOOST_CHECK_EQUAL(v5, value_t(amount_t("8")));
|
||||
|
||||
v16 *= value_t(2L);
|
||||
v16 *= value_t(amount_t("2"));
|
||||
BOOST_CHECK_EQUAL(v5, v16);
|
||||
|
||||
v8 *= v9;
|
||||
BOOST_CHECK_EQUAL(v8, value_t("16 GBP"));
|
||||
|
||||
value_t v17(v9);
|
||||
v9 *= value_t(2L);
|
||||
BOOST_CHECK_EQUAL(v9, value_t("8 GBP"));
|
||||
v17 += value_t(2L);
|
||||
v17 *= value_t(2L);
|
||||
value_t v18("8 GBP");
|
||||
v18 += value_t(4L);
|
||||
BOOST_CHECK_EQUAL(v17, v18);
|
||||
|
||||
value_t v20(s1);
|
||||
v11.push_back(value_t(2L));
|
||||
v11.push_back(value_t("2 GBP"));
|
||||
v20.push_back(value_t(4L));
|
||||
v20.push_back(value_t("4 GBP"));
|
||||
v11 *= value_t(2L);
|
||||
BOOST_CHECK_EQUAL(v11 ,v20);
|
||||
|
||||
BOOST_CHECK_THROW(v10 *= v8, value_error);
|
||||
BOOST_CHECK(v1.valid());
|
||||
BOOST_CHECK(v2.valid());
|
||||
BOOST_CHECK(v3.valid());
|
||||
BOOST_CHECK(v4.valid());
|
||||
BOOST_CHECK(v5.valid());
|
||||
BOOST_CHECK(v6.valid());
|
||||
BOOST_CHECK(v7.valid());
|
||||
BOOST_CHECK(v8.valid());
|
||||
BOOST_CHECK(v9.valid());
|
||||
BOOST_CHECK(v10.valid());
|
||||
BOOST_CHECK(v11.valid());
|
||||
BOOST_CHECK(v12.valid());
|
||||
BOOST_CHECK(v13.valid());
|
||||
BOOST_CHECK(v14.valid());
|
||||
BOOST_CHECK(v15.valid());
|
||||
BOOST_CHECK(v16.valid());
|
||||
BOOST_CHECK(v17.valid());
|
||||
BOOST_CHECK(v18.valid());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(testDivision)
|
||||
{
|
||||
struct tm localtime;
|
||||
strptime("10 February 2010 00:00:00", "%d %b %Y %H:%M:%S", &localtime);
|
||||
time_t time_var = mktime(&localtime);
|
||||
value_t::sequence_t s1;
|
||||
|
||||
value_t v1;
|
||||
value_t v2(true);
|
||||
value_t v3(boost::posix_time::from_time_t(time_var));
|
||||
value_t v4(date_t(parse_date("2014/08/14")));
|
||||
value_t v5(8L);
|
||||
value_t v6(2UL);
|
||||
value_t v7(1.00);
|
||||
value_t v8(amount_t("4 GBP"));
|
||||
value_t v9(balance_t("4 GBP"));
|
||||
value_t v10(mask_t("regex"));
|
||||
value_t v11(s1);
|
||||
value_t v12(string("$1"));
|
||||
value_t v13("2 CAD");
|
||||
value_t v14("comment", true);
|
||||
value_t v15(string("comment"), true);
|
||||
value_t v16(amount_t("8"));
|
||||
|
||||
v5 /= value_t(2L);
|
||||
BOOST_CHECK_EQUAL(v5, value_t(4L));
|
||||
v5 /= value_t(amount_t("8"));
|
||||
BOOST_CHECK_EQUAL(v5, value_t(amount_t("2")));
|
||||
|
||||
v16 /= value_t(2L);
|
||||
v16 /= value_t(amount_t("2"));
|
||||
BOOST_CHECK_EQUAL(v5, v16);
|
||||
|
||||
v8 /= v9;
|
||||
v8 /= value_t(balance_t(2L));
|
||||
BOOST_CHECK_EQUAL(v8, value_t("0.5 GBP"));
|
||||
|
||||
value_t v17(v9);
|
||||
v9 /= value_t(2L);
|
||||
BOOST_CHECK_EQUAL(v9, value_t("2 GBP"));
|
||||
v17 /= value_t("2 GBP");
|
||||
v17 /= value_t("2");
|
||||
BOOST_CHECK_EQUAL(v17, value_t(balance_t("1 GBP")));
|
||||
|
||||
BOOST_CHECK_THROW(v10 /= v8, value_error);
|
||||
BOOST_CHECK(v1.valid());
|
||||
BOOST_CHECK(v2.valid());
|
||||
BOOST_CHECK(v3.valid());
|
||||
BOOST_CHECK(v4.valid());
|
||||
BOOST_CHECK(v5.valid());
|
||||
BOOST_CHECK(v6.valid());
|
||||
BOOST_CHECK(v7.valid());
|
||||
BOOST_CHECK(v8.valid());
|
||||
BOOST_CHECK(v9.valid());
|
||||
BOOST_CHECK(v10.valid());
|
||||
BOOST_CHECK(v11.valid());
|
||||
BOOST_CHECK(v12.valid());
|
||||
BOOST_CHECK(v13.valid());
|
||||
BOOST_CHECK(v14.valid());
|
||||
BOOST_CHECK(v15.valid());
|
||||
BOOST_CHECK(v16.valid());
|
||||
BOOST_CHECK(v17.valid());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(testType)
|
||||
{
|
||||
value_t::sequence_t s1;
|
||||
value_t v1;
|
||||
value_t v2(true);
|
||||
value_t v3(boost::posix_time::from_time_t(time_t(NULL)));
|
||||
value_t v4(date_t(parse_date("2014/08/14")));
|
||||
value_t v5(2L);
|
||||
value_t v6(4UL);
|
||||
value_t v7(1.00);
|
||||
value_t v8(amount_t("4 GBP"));
|
||||
value_t v9(balance_t("3 EUR"));
|
||||
value_t v10(mask_t("regex"));
|
||||
value_t v11(s1);
|
||||
value_t v12(string("$1"));
|
||||
value_t v13("2 CAD");
|
||||
value_t v14("comment", true);
|
||||
value_t v15(string("tag"), true);
|
||||
|
||||
BOOST_CHECK(v1.is_null());
|
||||
BOOST_CHECK(v2.is_boolean());
|
||||
BOOST_CHECK(v3.is_datetime());
|
||||
BOOST_CHECK(v4.is_date());
|
||||
BOOST_CHECK(v5.is_long());
|
||||
BOOST_CHECK(v6.is_amount());
|
||||
BOOST_CHECK(v7.is_amount());
|
||||
BOOST_CHECK(v8.is_amount());
|
||||
BOOST_CHECK(v9.is_balance());
|
||||
BOOST_CHECK(v10.is_mask());
|
||||
BOOST_CHECK(v11.is_sequence());
|
||||
BOOST_CHECK(v12.is_amount());
|
||||
BOOST_CHECK(v13.is_amount());
|
||||
BOOST_CHECK(v14.is_string());
|
||||
BOOST_CHECK(v15.is_string());
|
||||
|
||||
BOOST_CHECK(v1.valid());
|
||||
BOOST_CHECK(v2.valid());
|
||||
BOOST_CHECK(v3.valid());
|
||||
BOOST_CHECK(v4.valid());
|
||||
BOOST_CHECK(v5.valid());
|
||||
BOOST_CHECK(v6.valid());
|
||||
BOOST_CHECK(v7.valid());
|
||||
BOOST_CHECK(v8.valid());
|
||||
BOOST_CHECK(v9.valid());
|
||||
BOOST_CHECK(v10.valid());
|
||||
BOOST_CHECK(v11.valid());
|
||||
BOOST_CHECK(v12.valid());
|
||||
BOOST_CHECK(v13.valid());
|
||||
BOOST_CHECK(v14.valid());
|
||||
BOOST_CHECK(v15.valid());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(testForZero)
|
||||
{
|
||||
value_t::sequence_t s1;
|
||||
value_t v1;
|
||||
value_t v2(true);
|
||||
value_t v3(boost::posix_time::from_time_t(time_t(NULL)));
|
||||
value_t v4(date_t(0));
|
||||
value_t v5(2L);
|
||||
value_t v6(0UL);
|
||||
value_t v7(1.00);
|
||||
value_t v8(amount_t("4 GBP"));
|
||||
value_t v9(balance_t("0"));
|
||||
value_t v10(mask_t(""));
|
||||
value_t v11(s1);
|
||||
value_t v12(string("$1"));
|
||||
value_t v13("2 CAD");
|
||||
value_t v14("comment", true);
|
||||
value_t v15(string(""), true);
|
||||
|
||||
BOOST_CHECK(v1.is_null());
|
||||
BOOST_CHECK(v2.is_nonzero());
|
||||
BOOST_CHECK(!v3.is_zero());
|
||||
BOOST_CHECK(v4.is_nonzero());
|
||||
BOOST_CHECK(v5.is_nonzero());
|
||||
BOOST_CHECK(v6.is_realzero());
|
||||
BOOST_CHECK(v7.is_nonzero());
|
||||
BOOST_CHECK(v8.is_nonzero());
|
||||
BOOST_CHECK(v9.is_zero());
|
||||
BOOST_CHECK_THROW(v10.is_zero(), value_error);
|
||||
BOOST_CHECK(v11.is_zero());
|
||||
BOOST_CHECK(v12.is_nonzero());
|
||||
BOOST_CHECK(v13.is_nonzero());
|
||||
BOOST_CHECK(v14.is_nonzero());
|
||||
BOOST_CHECK(v15.is_zero());
|
||||
|
||||
v11.push_back(v6);
|
||||
BOOST_CHECK(v11.is_nonzero());
|
||||
|
||||
BOOST_CHECK(v1.valid());
|
||||
BOOST_CHECK(v2.valid());
|
||||
BOOST_CHECK(v3.valid());
|
||||
BOOST_CHECK(v4.valid());
|
||||
BOOST_CHECK(v5.valid());
|
||||
BOOST_CHECK(v6.valid());
|
||||
BOOST_CHECK(v7.valid());
|
||||
BOOST_CHECK(v8.valid());
|
||||
BOOST_CHECK(v9.valid());
|
||||
BOOST_CHECK(v10.valid());
|
||||
BOOST_CHECK(v11.valid());
|
||||
BOOST_CHECK(v12.valid());
|
||||
BOOST_CHECK(v13.valid());
|
||||
BOOST_CHECK(v14.valid());
|
||||
BOOST_CHECK(v15.valid());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(testNegation)
|
||||
{
|
||||
value_t::sequence_t s1;
|
||||
value_t v1;
|
||||
value_t v2(true);
|
||||
value_t v3(boost::posix_time::from_time_t(time_t(NULL)));
|
||||
value_t v4(date_t(parse_date("2014/08/09")));
|
||||
value_t v5(2L);
|
||||
value_t v6(0UL);
|
||||
value_t v7(1.00);
|
||||
value_t v8(amount_t("4 GBP"));
|
||||
value_t v9(balance_t("4 GBP"));
|
||||
value_t v10(mask_t(""));
|
||||
value_t v11(s1);
|
||||
value_t v12(string("$1"));
|
||||
value_t v13("$-1");
|
||||
value_t v14("comment", true);
|
||||
value_t v15(string("comment"), true);
|
||||
|
||||
BOOST_CHECK_THROW(v1.negated(), value_error);
|
||||
BOOST_CHECK_EQUAL(v2.negated(), value_t(false));
|
||||
v5.in_place_negate();
|
||||
BOOST_CHECK_EQUAL(v5, value_t(-2L));
|
||||
v8.in_place_negate();
|
||||
v9.in_place_negate();
|
||||
BOOST_CHECK_EQUAL(v8, v9);
|
||||
BOOST_CHECK_THROW(v10.negated(), value_error);
|
||||
BOOST_CHECK_EQUAL(-v12, v13);
|
||||
BOOST_CHECK_THROW(-v14, value_error);
|
||||
|
||||
BOOST_CHECK(v1.valid());
|
||||
BOOST_CHECK(v2.valid());
|
||||
BOOST_CHECK(v3.valid());
|
||||
BOOST_CHECK(v4.valid());
|
||||
BOOST_CHECK(v5.valid());
|
||||
BOOST_CHECK(v6.valid());
|
||||
BOOST_CHECK(v7.valid());
|
||||
BOOST_CHECK(v8.valid());
|
||||
BOOST_CHECK(v9.valid());
|
||||
BOOST_CHECK(v10.valid());
|
||||
BOOST_CHECK(v11.valid());
|
||||
BOOST_CHECK(v12.valid());
|
||||
BOOST_CHECK(v13.valid());
|
||||
BOOST_CHECK(v14.valid());
|
||||
BOOST_CHECK(v15.valid());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
16
tools/travis-before_install.sh
Executable file
16
tools/travis-before_install.sh
Executable file
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
#set -x
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
if [ "${TRAVIS_OS_NAME}" = "osx" ]; then
|
||||
brew update
|
||||
fi
|
||||
|
||||
if [ -n "${BOOST_VERSION}" ]; then
|
||||
mkdir -p $BOOST_ROOT
|
||||
wget --no-verbose --output-document=- \
|
||||
http://sourceforge.net/projects/boost/files/boost/${BOOST_VERSION}/boost_${BOOST_VERSION//./_}.tar.bz2/download \
|
||||
| tar jxf - --strip-components=1 -C "${BOOST_ROOT}"
|
||||
fi
|
||||
22
tools/travis-install.sh
Executable file
22
tools/travis-install.sh
Executable file
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
#set -x
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
if [ "${TRAVIS_OS_NAME}" = "osx" ]; then
|
||||
for formula in $(echo "${BREWS//,/ }"); do
|
||||
echo "Checking ${formula} formula"
|
||||
brew outdated "${formula}" \
|
||||
|| (brew unlink "${formula}"
|
||||
brew install "${formula}"
|
||||
)
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -d "${BOOST_ROOT}" ]; then
|
||||
(cd "${BOOST_ROOT}"
|
||||
./bootstrap.sh --with-libraries="${BOOST_LIBS}"
|
||||
./b2 threading=multi --prefix="${BOOST_ROOT}" -d0 install
|
||||
)
|
||||
fi
|
||||
Loading…
Add table
Reference in a new issue