vendor c++17 backport with my changes to make it compile in xcode

pull/1/head
Ryan Tharp 6 years ago
parent 72bc32dcf4
commit 9d5a79ab18

@ -0,0 +1,27 @@
Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of cppbackport nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

@ -0,0 +1,60 @@
This is a backport of the current C++ standard library to C++03/11/14. Obviously not everything
can be backported, but quite a bit can.
Quick Start
===========
There are a couple of small examples to give you an idea of usage. If you have make and g++
you can build things quickly enough:
- clone the repo to /some/place/cppbackport
- make a temp dir /wherever/you/wanna/build
- cd /wherever/you/wanna/build
- make -f /some/place/cppbackport/examples/Makefile
The examples are all setup to compile the cppbackport files as a static library (libcppbackport.a),
and then link it with one of the main example files (ex., gibberish.cpp).
Installation
============
I recommend copying the lib directory into your project, and calling the included Makefile
to create libcppbackport.a. Link that into your project, and add the appropriate include
flags (ex., -iquotecppbackport).
Usage
=====
Basically, #include "filesystem.h" or similar. Then use cpp namespace in place of std namespace.
The headers are all named after their official counterparts, with the addition of the .h
extension.
FAQ
===
**Who is this library suitable for?**
Anyone, really. There are a few use cases:
- The primary use case is to provide some newer features to people who are stuck with/choose to use an older compiler
- Another use would be to soften the requirements of your own project (i.e., so your users can use an older compiler)
- In some cases, this project may provide usable code before compilers support a standard. For example, C++17 at the moment isn't even standardized, *but* we basically know what's in it so we can start supporting it.
**What's the license?**
BSD 3-clause. Use it. Contribute if you like. Don't blame us for things.
**What compiler(s)/platforms are supported**
The development environment is Fedora 24 with GCC 6.1.1. I've used it with earlier versions
of GCC (4.7.4, I think), and a semi-recent version of Clang. I've not tested under Windows, yet.
**Will this use C++11/14/17 if available?**
Yes. Based on the value of the __cplusplus define, the files will simply #include the
system header (as appropriate).
**Why not header-only?**
I actually like the interface/implementation distinction. Header-only implementations (IMO)
get way too large and the files are difficult to navigate. Also, save the compiler some work.
Also, installing a lib isn't really that hard.
**Does it work on Windows?**
Sorry, POSIX mostly. Would love for some Windows devs to help.
**Why not use Boost?**
There's some overlap, but there are differences, too. And none of these things, *individually*
are that big.

@ -0,0 +1,2 @@
// Add predefined macros for your project here. For example:
// #define THE_ANSWER 42

@ -0,0 +1,144 @@
examples/any.cpp
examples/clock.cpp
examples/directory_listing.cpp
examples/fbind.cpp
examples/gibberish.cpp
examples/hash.cpp
examples/histogram.cpp
examples/lshere.cpp
examples/mathfns.cpp
examples/maxalign.cpp
examples/multithreading.cpp
examples/multitype.cpp
examples/now.cpp
examples/optional.cpp
examples/pathiter.cpp
examples/singlell.cpp
examples/smartptr.cpp
examples/tempdir.cpp
examples/testtraits.cpp
examples/two_threads.cpp
lib/algorithm.h
lib/any.h
lib/array.h
lib/atomic.h
lib/chrono.cpp
lib/chrono.h
lib/cmath.cpp
lib/cmath.h
lib/condition_variable.cpp
lib/condition_variable.h
lib/config/arch.h
lib/config/os.h
lib/cstdarg.h
lib/cstddef.h
lib/cstdint.h
lib/cstdlib.h
lib/filesystem.h
lib/forward_list.h
lib/fs/absolute.cpp
lib/fs/absolute.h
lib/fs/basename.cpp
lib/fs/basename.h
lib/fs/cleanpath.cpp
lib/fs/cleanpath.h
lib/fs/copyfile.cpp
lib/fs/copyfile.h
lib/fs/create_directory.cpp
lib/fs/create_directory.h
lib/fs/current_path.cpp
lib/fs/current_path.h
lib/fs/direntry.cpp
lib/fs/direntry.h
lib/fs/diriter.cpp
lib/fs/diriter.h
lib/fs/equivalent.cpp
lib/fs/equivalent.h
lib/fs/filestatus.cpp
lib/fs/filestatus.h
lib/fs/filetype.cpp
lib/fs/filetype.h
lib/fs/path.cpp
lib/fs/path.h
lib/fs/perms.cpp
lib/fs/perms.h
lib/fs/remove.cpp
lib/fs/remove.h
lib/fs/rename.cpp
lib/fs/rename.h
lib/fs/tempdir.cpp
lib/fs/tempdir.h
lib/functional.h
lib/future.h
lib/iterator.h
lib/locale.h
lib/memory.h
lib/mutex.cpp
lib/mutex.h
lib/numeric.h
lib/optional.h
lib/random.cpp
lib/random.h
lib/ratio.h
lib/rvalueref.h
lib/shared_mutex.cpp
lib/shared_mutex.h
lib/string.h
lib/string_view.h
lib/system_error.h
lib/thread.cpp
lib/thread.h
lib/traits/add_cv.h
lib/traits/add_pointer.h
lib/traits/add_reference.h
lib/traits/alignment.h
lib/traits/common_type.h
lib/traits/conditional.h
lib/traits/decay.h
lib/traits/declval.h
lib/traits/enable_if.h
lib/traits/extent.h
lib/traits/integral_constant.h
lib/traits/is_arithmetic.h
lib/traits/is_array.h
lib/traits/is_base_of.h
lib/traits/is_class_or_union.h
lib/traits/is_compound.h
lib/traits/is_const.h
lib/traits/is_convertible.h
lib/traits/is_enum.h
lib/traits/is_floating_point.h
lib/traits/is_function.h
lib/traits/is_fundamental.h
lib/traits/is_integral.h
lib/traits/is_member_pointer.h
lib/traits/is_null_pointer.h
lib/traits/is_object.h
lib/traits/is_pointer.h
lib/traits/is_reference.h
lib/traits/is_same.h
lib/traits/is_scalar.h
lib/traits/is_signed.h
lib/traits/is_unsigned.h
lib/traits/is_void.h
lib/traits/is_volatile.h
lib/traits/make_signed.h
lib/traits/make_unsigned.h
lib/traits/rank.h
lib/traits/remove_cv.h
lib/traits/remove_extent.h
lib/traits/remove_pointer.h
lib/traits/remove_reference.h
lib/traits/result_of.h
lib/traits/underlying_type.h
lib/traits/void_t.h
lib/traits/yesno.h
lib/tuple.h
lib/type_traits.h
lib/unordered_map.h
lib/unordered_set.h
lib/utility.h
lib/variant.h
lib/version.h
LICENSE
README.md

@ -0,0 +1,55 @@
# Sources are located relative to Makefile
MAKEFILE_DIR := $(shell readlink -f $(dir $(word $(words $(MAKEFILE_LIST)), $(MAKEFILE_LIST))))
LIB_DIR := $(MAKEFILE_DIR)/../lib
# The path of the invoking module
vpath %.cpp $(MAKEFILE_DIR)
default: examples
include $(MAKEFILE_DIR)/../make.inc
CXXFLAGS += -pthread
INCLUDE += -iquote$(LIB_DIR)
LDFLAGS += -pthread
LIBNAME = cppbackport
EXAMPLES = any fbind histogram maxalign optional smartptr two_threads clock gibberish \
lshere multithreading multitype pathiter tempdir directory_listing hash mathfns now singlell \
testtraits
.PHONY: default lib examples
lib:
$(MAKE) -f $(LIB_DIR)/Makefile
$(EXAMPLES): lib
examples: $(EXAMPLES)
any: any.o
clock: clock.o
directory_listing: directory_listing.o
fbind: fbind.o
gibberish: gibberish.o
hash: hash.o
histogram: histogram.o
lshere: lshere.o
mathfns: mathfns.o
maxalign: maxalign.o
multithreading: multithreading.o
multitype: multitype.o
now: now.o
optional: optional.o
pathiter: pathiter.o
singlell: singlell.o
smartptr: smartptr.o
tempdir: tempdir.o
testtraits: testtraits.o
two_threads: two_threads.o
$(EXAMPLES):
$(LD) $(LDFLAGS) $(@).o -L. -l$(LIBNAME) -o $@
clean:
$(MAKE) -f $(LIB_DIR)/Makefile clean
@$(RM) $(EXAMPLES) $(EXAMPLES:%=%.o)

@ -0,0 +1,58 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include "any.h"
int main()
{
cpp::any x;
x = 3;
std::cout << "Get value out of an any: " << cpp::any_cast< int >(x) << std::endl;
std::cout << std::endl;
std::cout << "Get a pointer to the stored value: " << cpp::any_cast< int >(&x) << std::endl;
std::cout << std::endl;
std::cout << "Cause a bad cast" << std::endl;
try
{
std::cout << cpp::any_cast< float >(x) << std::endl;
}
catch ( cpp::bad_any_cast& e )
{
std::cerr << "Error converting 'any' to type: " << e.what() << std::endl;
}
std::cout << std::endl;
x.reset();
std::cout << "Get a pointer to a cleared value: " << cpp::any_cast< int >(&x) << std::endl;
std::cout << std::endl;
}

@ -0,0 +1,38 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "chrono.h"
#include <iostream>
int main()
{
std::time_t t = cpp::chrono::system_clock::to_time_t( cpp::chrono::system_clock::now() );
std::cout << std::ctime(&t) << std::endl;
}

@ -0,0 +1,55 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include "filesystem.h"
namespace fs = cpp::filesystem;
int main()
{
typedef fs::recursive_directory_iterator iterator;
// typedef fs::directory_iterator iterator;
// List all files in the working directory
for ( iterator it("."), last; it != last; ++it )
{
const std::string r = it->path();
const fs::path s = fs::absolute(r);
std::cout << "Relative path:\t" << r << std::endl;
std::cout << it->status() << std::endl;
std::cout << "Absolute path:\t" << s << std::endl;
std::cout << "Basename: \t" << s.filename() << std::endl;
std::cout << "Dirname: \t" << s.parent_path() << std::endl;
std::cout << "Simplified: \t" << fs::cleanpath(s) << std::endl;
std::cout << std::endl;
}
}

@ -0,0 +1,57 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include <string>
#include "functional.h"
class Foo
{
public:
explicit Foo(const std::string& s_)
: s(s_)
{
}
void hello() const
{
std::cout << "My name is " << s << std::endl;
}
private:
std::string s;
};
int main()
{
Foo foo("herpderp");
::cpp::function< void() > f = ::cpp::bind(&Foo::hello, &foo);
foo = Foo("new guy");
f();
}

@ -0,0 +1,47 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include <string>
#include "random.h"
int main()
{
const std::string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
cpp::default_random_engine g;
cpp::uniform_int_distribution< unsigned > u(0, 25);
for ( int i = 0; i < 100; ++i )
{
std::cout << alphabet.at( u(g) );
}
std::cout << std::endl;
}

@ -0,0 +1,53 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include <string>
#include "unordered_set.h"
#include "unordered_map.h"
int main()
{
cpp::unordered_set< int > h;
h.insert(1);
h.insert(99);
for ( cpp::unordered_set< int >::iterator it = h.begin(); it != h.end(); ++it )
{
std::cout << *it << std::endl;
}
cpp::unordered_map< int, std::string > m;
m[3] = "Hello";
for ( cpp::unordered_map< int, std::string >::iterator it = m.begin(); it != m.end(); ++it )
{
std::cout << it->first << "," << it->second << std::endl;
}
}

@ -0,0 +1,53 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include <string>
#include <map>
#include "random.h"
int main()
{
std::map< int, int > hist;
cpp::random_device rd;
cpp::mt19937 gen( rd() );
cpp::uniform_int_distribution< int > dist(0, 9);
for ( int n = 0; n < 20000; ++n )
{
++hist[dist(gen)];
}
for ( std::map< int, int >::const_iterator it = hist.begin(); it != hist.end(); ++it )
{
std::cout << it->first << " : " << std::string(it->second / 100, '*') << '\n';
}
}

@ -0,0 +1,43 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include "filesystem.h"
namespace fs = cpp::filesystem;
int main()
{
fs::path here = fs::current_path();
for ( fs::directory_iterator it(here), last; it != last; ++it )
{
std::cout << it->path() << std::endl;
}
}

@ -0,0 +1,44 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include "cmath.h"
int main()
{
int q = 0;
std::cout << cpp::remainder(5, 1.5) << std::endl;
std::cout << cpp::remquo(5, 1.5, &q) << std::endl;
std::cout << q << std::endl;
std::cout << cpp::fma(3., 4., 5.) << std::endl;
std::cout << cpp::fmax(3, 4) << std::endl;
std::cout << cpp::fmin(3, 4) << std::endl;
std::cout << cpp::fdim(100, 66) << std::endl;
std::cout << cpp::exp2(3) << std::endl;
}

@ -0,0 +1,67 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Allocate raw storage for a type
*/
#include <iostream>
#include "type_traits.h"
// A POD with high alignment
union maxalign
{
unsigned long long x;
long double y;
void* z;
};
// a type that has 16 byte alignment
typedef int v4si __attribute__(( vector_size(16) ));
int main()
{
// The type we are checking
typedef int test_type;
// Various ways to check alignment.
std::cout << "Alignment" << std::endl;
// The GCC way. Non-portable, but definitive
std::cout << "GCC: " << __alignof__(test_type) << std::endl;
// Our implementation of C++11's alignment_of
std::cout << "alignment_of: " << cpp::alignment_of< test_type >::value << std::endl;
// Our implementaiton of C++11's aligned_union
std::cout << "aligned_union: " << __alignof__(cpp::aligned_union< 1, test_type >::type) << std::endl;
std::cout << std::endl;
std::cout << "sizeof" << std::endl;
std::cout << "type: " << sizeof( test_type ) << std::endl;
std::cout << "raw storage: " << sizeof( cpp::aligned_union< 1, test_type >::type ) << std::endl;
}

@ -0,0 +1,52 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include <string>
#include "thread.h"
void f(const std::string& s)
{
for ( int i = 0; i < 10; ++i )
{
std::cout << ( s + "\n" );
cpp::this_thread::sleep_for( cpp::chrono::milliseconds(10) );
}
}
int main()
{
std::string a = "Thread 1";
std::string b = "Thread 2";
cpp::thread t1(f, a);
cpp::thread t2(f, b);
t1.join();
t2.join();
}

@ -0,0 +1,43 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include <string>
#include <vector>
#include "variant.h"
int main()
{
cpp::variant< int, std::string > v(3);
v = "Hello";
std::cout << cpp::get< std::string >(v) << std::endl;
std::cout << cpp::get< 1 >(v) << std::endl;
v = 1;
std::cout << cpp::holds_alternative< int >(v) << std::endl;
}

@ -0,0 +1,41 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include <ctime>
#include "chrono.h"
int main()
{
cpp::chrono::system_clock::time_point now = cpp::chrono::system_clock::now();
std::time_t t = cpp::chrono::system_clock::to_time_t(now);
std::cout << std::ctime(&t) << std::endl;
}

@ -0,0 +1,100 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <vector>
#include <iostream>
#include "optional.h"
typedef std::vector< int > test_type;
const test_type value(3, 5);
// set a value
void example1()
{
std::cout << "Example 1" << std::endl;
cpp::optional< test_type > y;
if ( y )
{
std::cout << "y is set" << std::endl;
}
else
{
std::cout << "y is not set" << std::endl;
}
y = value;
if ( y )
{
std::cout << "y is set" << std::endl;
std::cout << "Size of vector is " << y->size() << std::endl;
}
else
{
std::cout << "y is not set" << std::endl;
}
std::cout << std::endl;
}
// clear a value
void example2()
{
std::cout << "Example 2" << std::endl;
cpp::optional< test_type > y(value);
if ( y )
{
std::cout << "y is set" << std::endl;
}
else
{
std::cout << "y is not set" << std::endl;
}
y = cpp::none;
if ( y )
{
std::cout << "y is set" << std::endl;
}
else
{
std::cout << "y is not set" << std::endl;
}
std::cout << std::endl;
}
int main()
{
example1();
example2();
}

@ -0,0 +1,83 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include "filesystem.h"
#include "iterator.h"
namespace fs = cpp::filesystem;
void print_ancestors(const fs::path& p)
{
for ( fs::path::const_iterator it = p.begin(); it != p.end(); ++it )
{
std::cout << "\t" << "'" << *it << "'";
}
std::cout << std::endl;
}
void print_reverse(const fs::path& p)
{
fs::path::const_iterator first = p.begin();
fs::path::const_iterator it = p.end();
while ( it != first )
{
--it;
std::cout << "\t" << "'" << *it << "'";
}
std::cout << std::endl;
}
const fs::path test[] =
{
"",
"/",
"///",
"/absolute",
"/absolute/",
"/absolute/file",
"/absolute/dir/",
"relative",
"relative/",
"relative/file",
"relative/dir/"
};
int main()
{
for ( const fs::path* it = cpp::begin(test), * last = cpp::end(test); it != last; ++it )
{
std::cout << "'" << *it << "'" << std::endl;
print_ancestors(*it);
print_reverse(*it);
}
}

@ -0,0 +1,51 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include <cstdlib>
#include <climits>
#include <stdexcept>
#include "forward_list.h"
int main()
{
cpp::forward_list< int > list;
for ( int i = 0; i < 100; ++i )
{
list.push_front( rand() );
}
list.sort();
list.reverse();
for ( cpp::forward_list< int >::iterator it = list.begin(); it != list.end(); ++it )
{
std::cout << *it << std::endl;
}
}

@ -0,0 +1,66 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include "memory.h"
cpp::unique_ptr< int > f()
{
return cpp::unique_ptr< int >( new int(123456789) );
}
void test_unique_pointer()
{
cpp::unique_ptr< int > v = f();
cpp::unique_ptr< int[] > w(new int[5]);
for ( int i = 0; i < 5; ++i )
{
w[i] = 6 * i;
}
std::cout << *v << std::endl;
std::cout << w[2] << std::endl;
}
void test_shared_pointer()
{
cpp::shared_ptr< int > x( new int(21048204) );
cpp::shared_ptr< int > y = x;
std::cout << *y << std::endl;
}
int main()
{
test_unique_pointer();
return 0;
}

@ -0,0 +1,35 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include "filesystem.h"
int main()
{
std::cout << cpp::filesystem::temp_directory_path() << std::endl;
}

@ -0,0 +1,561 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include <typeinfo>
#include <string>
#include <cstdlib>
#include <cxxabi.h>
#include "type_traits.h"
template< typename T >
struct meta
{
static std::string name()
{
const std::type_info& first = typeid( T );
const char* name = first.name();
int status;
std::string s;
if ( char* realname = abi::__cxa_demangle(name, 0, 0, &status) )
{
s = realname;
free(realname);
}
return s;
}
};
template< typename T >
struct meta< T& >
{
static std::string name()
{
return meta< T >::name() + "&";
}
};
template< typename T >
struct meta< const T >
{
static std::string name()
{
return meta< T >::name() + " const";
}
};
template< typename T >
struct meta< volatile T >
{
static std::string name()
{
return meta< T >::name() + " volatile";
}
};
template< typename T >
struct meta< const volatile T >
{
static std::string name()
{
return meta< T >::name() + " const volatile";
}
};
template< template< class, class > class T, typename U, typename V >
void print_relation()
{
std::cout << "\t(" << meta< U >::name() << ", " << meta< V >::name() << "): " << T< U, V >::value << std::endl;
}
/// @todo rename derived, pod, etc.
class Base
{
};
class Derived
: public Base
{
};
class C
{
public:
void do_nothing() const
{
}
};
class ConvertsToC
{
public: operator C() const
{
C x;
return x;
}
};
class Explicit
{
public:
explicit Explicit(const Base&)
{
}
};
class ConvertsFromDerived
{
public:
ConvertsFromDerived(const Derived&)
{
}
};
union Union
{
double d;
unsigned long l;
};
enum fruit {APPLE, ORANGE, BANANA};
/// @todo pointer to members
/// @todo For each type, also check pointer to that type, ref, cv-qualified,...
template< template< class > class T >
struct trait_test
{
template< typename U >
struct apply_trait
{
template< typename V >
static void print_variation()
{
if ( !cpp::is_same< U, V >::value )
{
std::cout << "\t" << meta< V >::name() << ": " << T< V >::value << std::endl;
}
}
static void print()
{
std::cout << "\t" << meta< U >::name() << ": " << T< U >::value << std::endl;
print_variation< typename cpp::add_pointer< U >::type >();
print_variation< typename cpp::add_const< U >::type >();
print_variation< typename cpp::add_volatile< U >::type >();
print_variation< typename cpp::add_cv< U >::type >();
print_variation< typename cpp::add_lvalue_reference< U >::type >();
print_variation< typename cpp::remove_pointer< U >::type >();
print_variation< typename cpp::remove_const< U >::type >();
print_variation< typename cpp::remove_volatile< U >::type >();
print_variation< typename cpp::remove_cv< U >::type >();
print_variation< typename cpp::remove_reference< U >::type >();
print_variation< typename cpp::remove_extent< U >::type >();
print_variation< typename cpp::remove_all_extents< U >::type >();
}
};
static void test_all()
{
std::cout << "Void and variations" << std::endl;
apply_trait< void >::print();
std::cout << "Integral types and variations:" << std::endl;
apply_trait< char >::print();
apply_trait< signed char >::print();
apply_trait< unsigned char >::print();
apply_trait< bool >::print();
apply_trait< short >::print();
apply_trait< unsigned short >::print();
apply_trait< int >::print();
apply_trait< unsigned int >::print();
apply_trait< long >::print();
apply_trait< unsigned long >::print();
apply_trait< bool >::print();
std::cout << "Floating point types and variations:" << std::endl;
apply_trait< float >::print();
apply_trait< double >::print();
apply_trait< long double >::print();
std::cout << "Enum types and variations: " << std::endl;
apply_trait< fruit >::print();
std::cout << "Pointer types and variations:" << std::endl;
apply_trait< void* >::print();
apply_trait< int* >::print();
apply_trait< const int* const* >::print();
apply_trait< Base* >::print();
apply_trait< Derived* >::print();
std::cout << "Reference types and variations:" << std::endl;
apply_trait< int& >::print();
apply_trait< const int& >::print();
std::cout << "Array types and variations:" << std::endl;
apply_trait< int[2] >::print();
std::cout << "Function types and variations:" << std::endl;
apply_trait< void() >::print();
apply_trait< int() >::print();
apply_trait< int ( * )() >::print();
apply_trait< int(&) ( ) >::print();
apply_trait< int(...) >::print();
apply_trait< int ( * )(...) >::print();
apply_trait< int(&) ( ... ) >::print();
apply_trait< int(int) >::print();
apply_trait< int ( * )(int) >::print();
apply_trait< int(&) (int) >::print();
apply_trait< int(int, ...) >::print();
apply_trait< int ( * )(int, ...) >::print();
apply_trait< int(&) ( int, ... ) >::print();
apply_trait< int(char, int) >::print();
apply_trait< int ( * )(char, int) >::print();
apply_trait< int(&) ( char, int ) >::print();
apply_trait< int(char, int, ...) >::print();
apply_trait< int ( * )(char, int, ...) >::print();
apply_trait< int(&) ( char, int, ... ) >::print();
std::cout << "Class types and variations: " << std::endl;
apply_trait< Base >::print();
apply_trait< Derived >::print();
apply_trait< C >::print();
apply_trait< ConvertsToC >::print();
apply_trait< Explicit >::print();
apply_trait< Union >::print();
std::cout << "Function pointer types and variations:" << std::endl;
apply_trait< int ( * )(int) >::print();
std::cout << std::endl;
}
};
template< template< class, class > class T >
void relation_test()
{
std::cout << "CV qualification:" << std::endl;
print_relation< T, int, const int >();
std::cout << "\tint, const int: " << T< int, const int >::value << std::endl;
std::cout << "Builtins:" << std::endl;
print_relation< T, int, float >();
print_relation< T, long, void >();
print_relation< T, void, long >();
std::cout << "Pointers:" << std::endl;
print_relation< T, void*, Base* >();
print_relation< T, Base*, void* >();
print_relation< T, Derived*, Base* >();
print_relation< T, Base*, Derived* >();
print_relation< T, Derived*, C* >();
print_relation< T, ConvertsToC*, bool >();
std::cout << "References:" << std::endl;
print_relation< T, Derived&, Base& >();
print_relation< T, Base&, Derived& >();
print_relation< T, Derived&, C& >();
std::cout << "Arrays:" << std::endl;
print_relation< T, int[2], const int* >();
print_relation< T, int[2], float* >();
std::cout << "Conversion via operator:" << std::endl;
print_relation< T, ConvertsToC, C >();
std::cout << "Conversion via constructor:" << std::endl;
print_relation< T, Base, Explicit >();
print_relation< T, Derived, ConvertsFromDerived >();
std::cout << std::endl;
}
template< typename T >
struct trivially_true
: cpp::true_type
{
};
template< typename T >
struct is_signed_integral
: cpp::bool_constant< cpp::is_integral< T >::value&& !cpp::is_same< typename cpp::remove_cv< T >::type, bool >::value&& !cpp::is_enum< T >::value >
{
};
template< template< class > class T, template< class > class Predicate = trivially_true >
struct test_transform
{
template< bool >
struct tag {};
template< typename U >
static void print_variation(tag< true >)
{
std::cout << "\t" << meta< U >::name() << " -> " << meta< typename T< U >::type >::name() << std::endl;
}
template< typename U >
static void print_variation(tag< false >)
{
// do nothing
}
template< typename U >
struct apply_transform
{
static void print()
{
tag< Predicate< U >::value > t;
print_variation< U >(t);
print_maybe< typename cpp::add_pointer< U >::type >();
print_maybe< typename cpp::add_const< U >::type >();
print_maybe< typename cpp::add_volatile< U >::type >();
print_maybe< typename cpp::add_cv< U >::type >();
print_maybe< typename cpp::add_lvalue_reference< U >::type >();
print_maybe< typename cpp::remove_pointer< U >::type >();
print_maybe< typename cpp::remove_const< U >::type >();
print_maybe< typename cpp::remove_volatile< U >::type >();
print_maybe< typename cpp::remove_cv< U >::type >();
print_maybe< typename cpp::remove_reference< U >::type >();
print_maybe< typename cpp::remove_extent< U >::type >();
print_maybe< typename cpp::remove_all_extents< U >::type >();
}
template< typename V >
static void print_maybe()
{
if ( !cpp::is_same< U, V >::value )
{
tag< Predicate< V >::value > t;
print_variation< V >(t);
}
}
};
static void test_all()
{
std::cout << "Void" << std::endl;
apply_transform< void >::print();
std::cout << "Integral types:" << std::endl;
apply_transform< char >::print();
apply_transform< signed char >::print();
apply_transform< unsigned char >::print();
apply_transform< short >::print();
apply_transform< unsigned short >::print();
apply_transform< int >::print();
apply_transform< unsigned int >::print();
apply_transform< long >::print();
apply_transform< unsigned long >::print();
apply_transform< bool >::print();
std::cout << "Floating point types:" << std::endl;
apply_transform< float >::print();
apply_transform< double >::print();
apply_transform< long double >::print();
std::cout << "Enum types:" << std::endl;
apply_transform< fruit >::print();
std::cout << "Pointer types:" << std::endl;
apply_transform< void* >::print();
apply_transform< int* >::print();
apply_transform< int const* const* >::print();
apply_transform< Base* >::print();
apply_transform< Derived* >::print();
std::cout << "Reference types:" << std::endl;
apply_transform< int& >::print();
apply_transform< const int& >::print();
std::cout << "Array types:" << std::endl;
apply_transform< int[2] >::print();
std::cout << "Function types:" << std::endl;
apply_transform< void() >::print();
apply_transform< int() >::print();
apply_transform< int(int) >::print();
std::cout << "Class types: " << std::endl;
apply_transform< Base >::print();
apply_transform< Derived >::print();
apply_transform< C >::print();
apply_transform< ConvertsToC >::print();
apply_transform< Explicit >::print();
apply_transform< Union >::print();
std::cout << "Function pointer types:" << std::endl;
apply_transform< int ( * )(int) >::print();
std::cout << std::endl;
}
};
/* Test each type trait with a variety of types
*/
int main()
{
std::cout << std::boolalpha;
std::cout << "== is_arithmetic =============================================" << std::endl;
trait_test< cpp::is_arithmetic >::test_all();
std::cout << "== is_array ==================================================" << std::endl;
trait_test< cpp::is_array >::test_all();
std::cout << "== is_compound ===============================================" << std::endl;
trait_test< cpp::is_compound >::test_all();
std::cout << "== is_const ==================================================" << std::endl;
trait_test< cpp::is_const >::test_all();
std::cout << "== is_enum ===================================================" << std::endl;
trait_test< cpp::is_enum >::test_all();
std::cout << "== is_floating_point =========================================" << std::endl;
trait_test< cpp::is_floating_point >::test_all();
std::cout << "== is_function ===============================================" << std::endl;
trait_test< cpp::is_function >::test_all();
std::cout << "== is_fundamental ============================================" << std::endl;
trait_test< cpp::is_fundamental >::test_all();
std::cout << "== is_integral ===============================================" << std::endl;
trait_test< cpp::is_integral >::test_all();
std::cout << "== is_member_pointer =========================================" << std::endl;
trait_test< cpp::is_member_pointer >::test_all();
std::cout << "== is_member_function_pointer ================================" << std::endl;
trait_test< cpp::is_member_function_pointer >::test_all();
std::cout << "== is_member_object_pointer ==================================" << std::endl;
trait_test< cpp::is_member_object_pointer >::test_all();
std::cout << "== is_null_pointer ===========================================" << std::endl;
trait_test< cpp::is_null_pointer >::test_all();
std::cout << "== is_object =================================================" << std::endl;
trait_test< cpp::is_object >::test_all();
std::cout << "== is_pointer ================================================" << std::endl;
trait_test< cpp::is_pointer >::test_all();
std::cout << "== is_reference ==============================================" << std::endl;
trait_test< cpp::is_reference >::test_all();
std::cout << "== is_scalar =================================================" << std::endl;
trait_test< cpp::is_scalar >::test_all();
std::cout << "== is_signed =================================================" << std::endl;
trait_test< cpp::is_signed >::test_all();
std::cout << "== is_unsigned ===============================================" << std::endl;
trait_test< cpp::is_unsigned >::test_all();
std::cout << "== is_void ===================================================" << std::endl;
trait_test< cpp::is_void >::test_all();
std::cout << "== is_volatile ===============================================" << std::endl;
trait_test< cpp::is_volatile >::test_all();
std::cout << "== is_base_of ================================================" << std::endl;
relation_test< cpp::is_base_of >();
std::cout << "== is_convertible ============================================" << std::endl;
relation_test< cpp::is_convertible >();
std::cout << "== add_const =================================================" << std::endl;
test_transform< cpp::add_const >::test_all();
std::cout << "== add_volatile ==============================================" << std::endl;
test_transform< cpp::add_volatile >::test_all();
std::cout << "== add_cv ====================================================" << std::endl;
test_transform< cpp::add_cv >::test_all();
std::cout << "== add_pointer ===============================================" << std::endl;
test_transform< cpp::add_pointer >::test_all();
std::cout << "== add_lvalue_reference ======================================" << std::endl;
test_transform< cpp::add_lvalue_reference >::test_all();
std::cout << "== decay =====================================================" << std::endl;
test_transform< cpp::decay >::test_all();
std::cout << "== make_signed ===============================================" << std::endl;
test_transform< cpp::make_signed, is_signed_integral >::test_all();
std::cout << "== make_unsigned =============================================" << std::endl;
test_transform< cpp::make_unsigned, is_signed_integral >::test_all();
std::cout << "== remove_cv =================================================" << std::endl;
test_transform< cpp::remove_cv >::test_all();
std::cout << "== remove_const ==============================================" << std::endl;
test_transform< cpp::remove_const >::test_all();
std::cout << "== remove_volatile ===========================================" << std::endl;
test_transform< cpp::remove_volatile >::test_all();
std::cout << "== remove_extent =============================================" << std::endl;
test_transform< cpp::remove_extent >::test_all();
std::cout << "== remove_all_extents ========================================" << std::endl;
test_transform< cpp::remove_all_extents >::test_all();
std::cout << "== remove_pointer ============================================" << std::endl;
test_transform< cpp::remove_pointer >::test_all();
std::cout << "== remove_reference ==========================================" << std::endl;
test_transform< cpp::remove_reference >::test_all();
}

@ -0,0 +1,52 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// g++ -I.. thread.cpp ../cpp/thread.cpp -lpthread
#include <iostream>
#include "thread.h"
void f()
{
for ( int i = 0; i < 1000; ++i )
{
std::cout << "Thread 2: " << i << std::endl;
}
}
int main()
{
cpp::thread t1(f);
for ( int i = 0; i < 1000; ++i )
{
std::cout << "Thread main: " << i << std::endl;
}
t1.join();
}

@ -0,0 +1,56 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CONFIG_ARCH_H
#define PBL_CONFIG_ARCH_H
#include <climits>
/* Whether or not the compiler supports long long and unsigned long long
*/
#ifndef HAS_LONG_LONG
#if __cplusplus >= 201103L
#define HAS_LONG_LONG
#else
#ifdef __GNUG__
#ifdef __SIZEOF_LONG_LONG__
#define HAS_LONG_LONG
#endif
#endif
#endif
#endif
/* The character type that char matches (i.e., signed or unsigned)
*/
#if CHAR_MIN < 0
typedef signed char underlying_char_type;
#else
typedef unsigned char underlying_char_type;
#endif
#endif // PBL_CONFIG_ARCH_H

@ -0,0 +1,131 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** Provide types, macros, and functions for the operating system
*
* This file provides a stable way to work with the OS. It provides
* - namespaces and typedefs that can be used portably between OS's
* - feature macros for enabling specific operating system capabilities
*
* @todo May want to rethink OS_POSIX as feature test macros since posix can
* sorta be in Windows (ex., Cygwin)
*/
#ifndef PBL_CONFIG_OS_H
#define PBL_CONFIG_OS_H
// =============================================================================
// Determine the platform. Ex., Windows or POSIX. Define feature macros
#if ( defined( __unix__ ) || defined( __unix ) || ( defined( __APPLE__ ) && defined( __MACH__ ) ) )
#include <unistd.h>
#ifdef _POSIX_VERSION
// ISO POSIX.1 aka IEEE 1003.1
/// OS_POSIX - unistd.h is included and _POSIX_VERSION is defined
#define OS_POSIX
#if _POSIX_VERSION >= 199506L
// ISO POSIX.1-1996 aka IEEE 1003.1-1996
#define POSIX_THREADS
#if ( _POSIX_VERSION >= 200112L )
// ISO POSIX.1-2001 aka IEEE 1003.1-2001, aka Issue 6, aka SUSv3
#define POSIX_ISSUE_6
#if ( _POSIX_VERSION >= 200809L )
// ISO POSIX.1-2008, aka IEEE 1003.1-2008, aka Issue 7, aka SUSv4
#define POSIX_ISSUE_7
#endif // 2008
#endif // 2001
#endif // 1996
#endif // ifdef _POSIX_VERSION
#endif // if ( defined( __unix__ ) || defined( __unix ) || ( defined( __APPLE__ ) && defined( __MACH__ )))
#if defined( _WIN64 ) || defined( _WIN32 )
#include <windows.h> /* MS Windows operating systems */
#define OS_WINDOWS
#endif
// =============================================================================
// Determine basic types
#ifdef OS_POSIX
#include <sys/types.h>
namespace pbl
{
namespace os
{
// Identifies a user
typedef uid_t user_id_type;
// Identifies a process
typedef pid_t pid_type;
}
}
#else
#ifdef OS_WINDOWS
namespace pbl
{
namespace os
{
typedef DWORD pid_type;
}
}
#endif // Windows
#endif // ifdef OS_POSIX
// =============================================================================
// Determine multithreading types
#ifdef POSIX_THREADS
#include <pthread.h>
namespace pbl
{
namespace os
{
typedef pthread_t thread_type;
typedef pthread_mutex_t mutex_type;
typedef pthread_rwlock_t shared_mutex_type;
typedef pthread_cond_t condition_variable_type;
}
}
#else
#ifdef OS_WINDOWS
namespace pbl
{
namespace os
{
typedef HANDLE thread_type;
typedef CRITICAL_SECTION mutex_type;
}
}
#endif
#endif // ifdef POSIX_THREADS
#endif // PBL_CONFIG_OS_H

@ -0,0 +1,55 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_FILESYSTEM_H
#define PBL_CPP_FILESYSTEM_H
#include "version.h"
#if defined(CPP17) && __has_include(<filesystem>)
#include <filesystem>
#else
#include "fs/absolute.h"
#include "fs/basename.h"
#include "fs/cleanpath.h"
#include "fs/copyfile.h"
#include "fs/create_directory.h"
#include "fs/current_path.h"
#include "fs/direntry.h"
#include "fs/diriter.h"
#include "fs/equivalent.h"
#include "fs/filestatus.h"
#include "fs/filetype.h"
#include "fs/path.h"
#include "fs/perms.h"
#include "fs/rename.h"
#include "fs/remove.h"
#include "fs/tempdir.h"
#endif
#endif // PBL_CPP_FILESYSTEM_H

@ -0,0 +1,90 @@
/* Copyright (c) 2014, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "absolute.h"
#include <climits>
#include <cstdlib>
#include "../config/os.h"
namespace cpp17
{
namespace filesystem
{
path absolute(const path& filename)
{
if ( !filename.empty() )
{
#if (( defined( _POSIX_VERSION ) && _POSIX_VERSION >= 200809l ) || defined( __GLIBC__ ))
// Preferred - POSIX-2008 and glibc will allocate the path buffer
char* res = ::realpath(filename.c_str(), NULL);
if ( res )
{
path s = res;
::free(res);
return s;
}
#else
#ifdef _GNU_SOURCE
// Maybe we can rely on the GNU extension
char* res = ::canonicalize_file_name( filename.c_str() );
if ( res )
{
std::string s = res;
::free(res);
return s;
}
#elif ((( defined( _POSIX_VERSION ) && _POSIX_VERSION >= 200112L ) || ( defined( _XOPEN_VERSION ) && _XOPEN_VERSION >= 500 )) && defined( PATH_MAX ))
/// @todo PATH_MAX may be huge or -1, according to man pages for realpath
char resolved[PATH_MAX + 1];
char* res = ::realpath(filename.c_str(), resolved);
if ( res )
{
return resolved;
}
#else
#error "No way to get absolute file path!"
#endif // if 1
#endif // if ( defined( _POSIX_VERSION ) && _POSIX_VERSION >= 200809l )
}
return path();
}
}
}

@ -0,0 +1,50 @@
/* Copyright (c) 2015, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_FS_ABSOLUTE_H
#define PBL_CPP_FS_ABSOLUTE_H
#include "path.h"
namespace cpp17
{
namespace filesystem
{
/** Get an absolute path of a file
*
* @param filepath The path of an (existing) file
* @returns An absolute path that corresponds to the same file as filepath, or
* an empty string if there is an error.
*/
path absolute(const path& filepath);
}
}
#endif // PBL_CPP_FS_ABSOLUTE_H

@ -0,0 +1,200 @@
/* Copyright (c) 2014, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "basename.h"
#include "../config/os.h"
#include "cleanpath.h"
namespace
{
// the position following the previous occurrence of c (relative to position j),
// or 0 if not. In this file, the first letter of a path component.
std::size_t after_last(
const std::string& s,
char c,
std::size_t j
)
{
std::size_t i = s.find_last_of(c, j);
return i == std::string::npos ? 0 : i + 1;
}
// (first character, length) of last path component in s or (0,0) for "."
// or (npos, 0) if error
std::pair< std::size_t, std::size_t > locate_last_path_component(const std::string& s)
{
if ( s.empty() )
{
// error
return std::pair< std::size_t, std::size_t >(std::string::npos, 0);
}
// j points to the last character in a component
std::size_t j = s.find_last_not_of('/');
unsigned depth = 0;
while ( j != std::string::npos )
{
// i points to first character of a component
// i <= j, because j never points to a '/'
const std::size_t i = after_last(s, '/', j);
if ( j - i + 1 == 1 && s[i] == '.' )
{
// component is ".", basically ignore this component
}
else if ( j - i + 1 == 2 && s[i] == '.' && s[i + 1] == '.' )
{
// component is "..", ignore the next component
++depth;
}
else
{
// found a "normal" path component
if ( depth == 0 )
{
return std::pair< std::size_t, std::size_t >(i, j - i + 1);
}
// ..but we're ignoring it
--depth;
}
if ( i == 0 )
{
if ( depth == 0 )
{
// "."
return std::pair< std::size_t, std::size_t >(0, 0);
}
else
{
// error, path is malformed
return std::pair< std::size_t, std::size_t >(std::string::npos, 0);
}
}
j = s.find_last_not_of('/', i - 1);
}
// all slashes
return std::pair< std::size_t, std::size_t >(0, 1);
}
std::string basename_posix(const std::string& s)
{
const std::pair< std::size_t, std::size_t > range = locate_last_path_component(s);
if ( range.first == std::string::npos )
{
return std::string();
}
if ( range.first == 0 && range.second == 0 )
{
return ".";
}
return s.substr(range.first, range.second);
}
std::string dirname_posix(const std::string& s)
{
const std::pair< std::size_t, std::size_t > range = locate_last_path_component(s);
// path was malformed
if ( range.first == std::string::npos )
{
return std::string();
}
if ( range.first == 0 )
{
if ( range.second == 0 )
{
return "..";
}
// could be '/', or could be a unpathed filename
if ( s[0] == '/' )
{
return "/";
}
return ".";
}
else
{
// leading directory
return s.substr(0, range.first);
}
}
}
namespace cpp17
{
namespace filesystem
{
// Calls the basename_xxx appropriate for this platform
std::string basename(const std::string& s)
{
#ifdef OS_POSIX
return basename_posix(s);
#else
#error "No implementation of basename is available for this platform"
#endif
}
std::string dirname(const std::string& s)
{
#ifdef OS_POSIX
const std::string& t = dirname_posix(s);
if ( t == "." )
{
return t;
}
return cleanpath(t);
#else
#error "No implementation of dirname is available for this platform"
#endif
}
}
}

@ -0,0 +1,85 @@
/* Copyright (c) 2015, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_FS_BASENAME_H
#define PBL_CPP_FS_BASENAME_H
#include <string>
namespace cpp17
{
namespace filesystem
{
/** Return the name of the file system component indicated by path
*
* @param path A file path
* @returns The name of the directory or file that the path points to, or the
* empty string if there's an error
*
* The exact behavior of this function is platform dependent, because paths are.
* However, whatever the platform, it should return the name of the file or
* directory pathed. Ex., on POSIX platforms it should return "readme.txt" for
* "/home/user/documents/readme.txt"; similarly it should return "readme.txt"
* for "C:\Windows\readme.txt" on Windows platforms.
*
* This function does not access the file system. It merely parses the string.
* In particular, it does not check if the path is valid and/or accessible. It
* also does not check that the component before "." or ".." is, in fact, a
* directory.
*
* If the last component cannot be determined for whatever reason, the string is
* considered malformed and the empty string is returned.
*
* @note Although the empty string is considered a malformed path, "." (and
* anything equivalent) will return ".".
*/
std::string basename(const std::string& path);
/** Return the directory which has the last path component
*
* @param path A file path
*
* Determines the last path component as in basename, then returns directory
* which contains that file system object. Ex., the dirname of
* "/home/user/documents/readme.txt" is "/home/user/documents".
*
* As special cases, the dirname of a bare filename is "."; the dirname of
* "." (or equivalent) is ".."; the dirname of the root directory is still the
* root.
*
* If the path is malformed, the empty string is returned.
*
* @sa basename
*/
std::string dirname(const std::string& path);
}
}
#endif // PBL_FS_BASENAME_H

@ -0,0 +1,138 @@
/* Copyright (c) 2014, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "cleanpath.h"
namespace cpp17
{
namespace filesystem
{
/// @todo Probably belongs in path.cpp
std::string cleanpath(const std::string& s)
{
std::string t;
if ( s.empty() )
{
// error
return t;
}
const std::size_t n = s.length();
for ( std::size_t i = 0; i < n;)
{
if ( s[i] == '/' )
{
// directory separator
t.push_back('/');
i = s.find_first_not_of('/', i);
}
else
{
// path component
const std::size_t j = std::min(s.find('/', i), n);
if ( s.compare(i, j - i, ".", 1) == 0 )
{
// handle dot
if ( j < n )
{
i = s.find_first_not_of('/', j);
}
else
{
i = n;
}
}
else if ( s.compare(i, j - i, "..", 2) == 0 )
{
// handle dot-dot
const std::size_t l = t.length();
if ( l == 0 )
{
// no previous component (ex., "../src")
t.assign("..", 2);
i = j;
}
else
{
// remove previously copied component (unless root)
if ( l >= 2 )
{
const std::size_t k = t.find_last_of('/', l - 2);
if ( k == std::string::npos )
{
t.clear();
}
else
{
t.resize(k + 1);
}
}
if ( j < n )
{
i = s.find_first_not_of('/', j);
}
else
{
i = n;
}
}
}
else
{
// append path component
t.append(s, i, j - i);
i = j;
}
}
}
if ( t.empty() )
{
return ".";
}
// drop trailing slashes
const std::size_t i = t.find_last_not_of('/');
if ( i != std::string::npos )
{
t.resize(i + 1);
}
return t;
}
}
}

@ -0,0 +1,61 @@
/* Copyright (c) 2015, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_FS_CLEANPATH_H
#define PBL_CPP_FS_CLEANPATH_H
#include <string>
namespace cpp17
{
namespace filesystem
{
/** Return a simplified version of path
*
* @param path A file system path
*
* Collapses multiple path separators (ex., as in "/home//user"); replaces
* "name/." with "name" and "parent/child/.." with "parent"; removes trailing
* slashes.
*
* The returned path is equivalent to the original path in the sense that it
* identifies the same file system object. Specifically, relative paths are
* preserved (ex., no simplification is done to the dot-dot in "../here").
*
* If the path is malformed, the empty string is returned. For this function,
* really only the empty string itself is "malformed".
*
* @note This is a textual operation. It does not validate the string against
* the file system or otherwise touch the file system.
* @bug foo/bar/../baz may not point to /foo/baz if bar symlinks to flip/flop
*/
std::string cleanpath(const std::string& path);
}
}
#endif // PBL_FS_CLEANPATH_H

@ -0,0 +1,174 @@
/* Copyright (c) 2014, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "copyfile.h"
#include <cerrno>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
namespace cpp17
{
namespace filesystem
{
/** Try to do copy the file as safely as possible (esp., gracefully handle
* errors, avoid race conditions).
*
* @bug If there's an error while overwriting a file, the original is lost
*/
bool copy_file(
const path& source,
const path& dest,
copy_options opt
)
{
const int in = ::open(source.c_str(), O_RDONLY | O_CLOEXEC);
if ( in != -1 )
{
struct stat instat;
if ( ::fstat(in, &instat) == 0 && ( S_ISREG(instat.st_mode) || S_ISLNK(instat.st_mode) ) )
{
// Get the destination file
int out = ::open(dest.c_str(), O_CREAT | O_EXCL | O_WRONLY | O_CLOEXEC, S_IWUSR);
if ( out == -1 && errno == EEXIST )
{
// File already exists -- maybe we will overwrite it
out = ::open(dest.c_str(), O_WRONLY | O_CLOEXEC);
if ( out != -1 )
{
bool err = false;
struct stat outstat;
if ( ( ::fstat(out, &outstat) != 0 ) || ( instat.st_dev == outstat.st_dev && instat.st_ino == outstat.st_ino ) || ( ( opt & 7 ) == 0 ) )
{
// Couldn't stat, Same file, or bad copy_options
err = true;
}
else
{
// Replace file or not, depending on flags
if ( (opt& copy_options::overwrite_existing) || ( (opt& copy_options::update_existing) && ( instat.st_mtime > outstat.st_mtime ) ) )
{
// replace the existing file
if ( ::ftruncate(out, 0) != 0 )
{
err = true;
}
}
else
{
// do nothing
::close(out);
::close(in);
return false;
}
}
if ( err )
{
::close(out);
out = -1;
}
}
}
// Do we have a destination file?
if ( out != -1 )
{
bool err = false;
while ( !err )
{
char buf[4096];
const ssize_t n = ::read( in, buf, sizeof( buf ) );
if ( n == -1 )
{
err = true;
}
else if ( n == 0 )
{
// EOF - copy has been successful
::fchmod(out, instat.st_mode & 0777);
::close(out);
::close(in);
return true;
}
else
{
const char* p = buf;
while ( p - buf < n )
{
const ssize_t m = ::write( out, p, static_cast< std::size_t >( n - ( p - buf ) ) );
if ( m == -1 )
{
err = true;
break;
}
p += m;
}
}
}
// Remove the incomplete file
::unlink( dest.c_str() );
::close(out);
}
}
::close(in);
}
return false;
}
bool copy_file(
const path& source,
const path& dest
)
{
return copy_file(source, dest, ::copy_options::none);
}
}
}

@ -0,0 +1,81 @@
/* Copyright (c) 2015, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_FS_COPYFILE_H
#define PBL_CPP_FS_COPYFILE_H
#include "path.h"
namespace copy_options
{
enum copy_options
{
none = 0,
skip_existing = 1,
overwrite_existing = 2,
update_existing = 4,
recursive = 8,
copy_symlinks = 16,
skip_symlinks = 32,
directories_only = 64,
create_symlinks = 128,
create_hard_links = 256
};
}
namespace cpp17
{
namespace filesystem
{
typedef ::copy_options::copy_options copy_options;
/** Copy the file at source to dest
*
* @param source A file to copy
* @param dest A file (including name) of the file to create
* @returns true iff dest exists and is a copy of source
*
* If source does not exist or is not a file, the copy will fail.
*
* If dest exists, it will be overwritten. Dest will have the same file
* permissions of source, if possible (subject to umask).
*
* This function copies the source file "safely". That is, in the event of an
* error, dest is unaltered (or, if it didn't exist, continues to not exist).
*
* @todo The std::experimental::fs namespace defines copy and copy_file. This
* function should be renamed accordingly.
*/
bool copy_file(const path &source, const path &dest, copy_options);
bool copy_file(const path& source, const path& dest);
}
}
#endif // PBL_CPP_FS_COPYFILE_H

@ -0,0 +1,69 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "create_directory.h"
#include <sys/stat.h>
#include "perms.h"
#include "filestatus.h"
namespace cpp17
{
namespace filesystem
{
bool create_directory(const path& s, std::error_code& ec)
{
if ( s.empty() )
{
return false;
}
return ::mkdir( s.c_str(), static_cast< int >( perms::all ) ) == 0;
}
bool create_directories(const path& s, std::error_code& ec)
{
path p = s.parent_path();
if ( !p.empty() )
{
std::error_code ec, ec2;
if ( !exists(p, ec) && !create_directories(p, ec2) )
{
return false;
}
}
std::error_code ec3;
return create_directory(s, ec3);
}
}
}

@ -0,0 +1,45 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_FS_CREATE_DIRECTORY_H
#define PBL_CPP_FS_CREATE_DIRECTORY_H
#include "path.h"
#include <system_error>
namespace cpp17
{
namespace filesystem
{
bool create_directory(const path&, std::error_code&);
bool create_directories(const path&, std::error_code&);
}
}
#endif // PBL_CPP_FS_CREATE_DIRECTORY_H

@ -0,0 +1,81 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "current_path.h"
#include <cerrno>
#include <unistd.h>
namespace cpp17
{
namespace filesystem
{
path current_path()
{
char buf[4096];
if ( ::getcwd( buf, sizeof( buf ) ) )
{
return buf;
}
// Dynamically allocate larger buffers until cwd fits
std::size_t size = 2 * sizeof( buf );
while ( true )
{
char* q = new char[size];
if ( ::getcwd(q, size) )
{
path p = q;
delete[] q;
return p;
}
else
{
if ( errno == ERANGE )
{
delete[] q;
size *= 2;
}
else
{
delete[] q;
break;
}
}
}
return path();
}
}
}

@ -0,0 +1,42 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_FS_CURRENT_PATH_H
#define PBL_CPP_FS_CURRENT_PATH_H
#include "path.h"
namespace cpp17
{
namespace filesystem
{
path current_path();
}
}
#endif // PBL_CPP_FS_CURRENT_PATH_H

@ -0,0 +1,137 @@
/* Copyright (c) 2015, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "direntry.h"
namespace cpp17
{
namespace filesystem
{
directory_entry::directory_entry()
{
}
directory_entry::directory_entry(const directory_entry& e)
: path_(e.path_)
{
}
directory_entry::directory_entry(const ::cpp17::filesystem::path& p)
: path_(p)
{
}
directory_entry& directory_entry::operator=(const directory_entry& e)
{
path_ = e.path_;
return *this;
}
void directory_entry::assign(const ::cpp17::filesystem::path& p)
{
path_ = p;
}
void directory_entry::replace_filename(const ::cpp17::filesystem::path& p)
{
path_ = path_.parent_path() / p;
}
const path& directory_entry::path() const
{
return path_;
}
directory_entry::operator const ::cpp17::filesystem::path&() const
{
return path_;
}
file_status directory_entry::status() const
{
return ::cpp17::filesystem::status(path_);
}
file_status directory_entry::symlink_status() const
{
return ::cpp17::filesystem::symlink_status(path_);
}
bool operator==(
const directory_entry& a,
const directory_entry& b
)
{
return a.path() == b.path();
}
bool operator!=(
const directory_entry& a,
const directory_entry& b
)
{
return a.path() != b.path();
}
bool operator<(
const directory_entry& a,
const directory_entry& b
)
{
return a.path() < b.path();
}
bool operator<=(
const directory_entry& a,
const directory_entry& b
)
{
return a.path() <= b.path();
}
bool operator>(
const directory_entry& a,
const directory_entry& b
)
{
return a.path() > b.path();
}
bool operator>=(
const directory_entry& a,
const directory_entry& b
)
{
return a.path() >= b.path();
}
}
}

@ -0,0 +1,71 @@
/* Copyright (c) 2015, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_FS_DIRENTRY_H
#define PBL_CPP_FS_DIRENTRY_H
#include <iosfwd>
#include "path.h"
#include "filestatus.h"
namespace cpp17
{
namespace filesystem
{
/** Reperesents a file system object
*/
class directory_entry
{
public:
directory_entry();
directory_entry(const directory_entry&);
explicit directory_entry(const path&);
directory_entry& operator=(const directory_entry&);
void assign(const path&);
void replace_filename(const path&);
const ::cpp17::filesystem::path& path() const;
operator const ::cpp17::filesystem::path&() const;
file_status status() const;
file_status symlink_status() const;
private:
::cpp17::filesystem::path path_;
};
bool operator==(const directory_entry&, const directory_entry&);
bool operator!=(const directory_entry&, const directory_entry&);
bool operator<(const directory_entry&, const directory_entry&);
bool operator<=(const directory_entry&, const directory_entry&);
bool operator>(const directory_entry&, const directory_entry&);
bool operator>=(const directory_entry&, const directory_entry&);
}
}
#endif // PBL_FS_DIRENTRY_H

@ -0,0 +1,474 @@
/* Copyright (c) 2014, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "diriter.h"
#include <cstdlib>
#include <cstring>
#include <climits>
#include <dirent.h>
#include "direntry.h"
#include "path.h"
namespace cpp17
{
namespace filesystem
{
/// @todo Could save the malloc/free (of e) if we mark end-of-directory
class directory_iterator::impl
{
public:
impl()
: p(), d(0), e(0), info(), valid_info(false)
{
//printf("directory_iterator::impl::cstr\n");
pos = 0;
}
explicit impl(const path& path_)
: p(path_), d(0), e(0), info(), valid_info(false)
{
//printf("directory_iterator::impl::cstr path[%s]\n", path_.c_str());
this->cPath = path_;
d = ::opendir( path_.c_str() );
if ( d )
{
e = acquire();
next();
}
}
~impl()
{
//printf("directory_iterator::impl::dstr [%s]\n", this->cPath.c_str());
if ( d )
{
release(); // free e
::closedir(d);
d = 0;
}
}
void rewind() {
//printf("directory_iterator::impl::rewind\n");
if ( d )
{
release();
::closedir(d);
}
d = ::opendir( this->cPath.c_str() );
pos = 0;
if ( d )
{
e = acquire();
next();
}
}
void seek(size_t seekPos) {
//printf("directory_iterator::impl::seek\n");
this->rewind();
for(size_t i = 0; i < seekPos; i++) {
this->next();
}
}
/** Test if this is an end iterator
*/
bool is_end() const
{
//printf("directory_iterator::impl::is_end\n");
return !e;
}
bool next()
{
//printf("directory_iterator::impl::next\n");
if ( d )
{
valid_info = false;
do
{
dirent* ptr = 0;
const int res = ::readdir_r(d, e, &ptr);
if ( res != 0 || ptr == 0 )
{
// error, or end of directory
pos = 0;
release();
return false;
}
}
while ( std::strcmp(e->d_name, ".") == 0 || std::strcmp(e->d_name, "..") == 0 );
pos++;
return true;
}
return false;
}
path get_path() const
{
//printf("directory_iterator::impl::get_path\n");
return e ? ( p / e->d_name ) : path();
}
file_type type() const
{
//printf("directory_iterator::impl::type\n");
if ( e )
{
switch ( e->d_type )
{
case DT_FIFO:
return file_type::fifo;
case DT_CHR:
return file_type::character;
case DT_DIR:
return file_type::directory;
case DT_BLK:
return file_type::block;
case DT_REG:
return file_type::regular;
case DT_LNK:
return file_type::symlink;
case DT_SOCK:
return file_type::socket;
default:
break;
} // switch
}
return file_type::unknown;
}
const directory_entry& get_reference()
{
//printf("directory_iterator::impl::get_reference\n");
update();
return info;
}
const directory_entry* get_pointer()
{
//printf("directory_iterator::impl::get_pointer\n");
update();
return &info;
}
/// Position
size_t pos;
// Path to directory
path p;
private:
void update()
{
//printf("directory_iterator::impl::update\n");
if ( !valid_info && e )
{
const path q = p / e->d_name;
info.assign(q);
valid_info = true;
}
}
static dirent* acquire()
{
//printf("directory_iterator::impl::acquire\n");
/* dirent::d_name is required to be at least NAME_MAX + 1 bytes.
* However, some implementations use the struct hack and make d_name
* 1 byte. Watch for this scenario and adjust accordingly.
*/
if ( sizeof( static_cast< dirent* >( 0 )->d_name ) < NAME_MAX + 1 )
{
return static_cast< dirent* >( ::malloc(sizeof( dirent ) + NAME_MAX + 1) );
}
else
{
return static_cast< dirent* >( ::malloc( sizeof( dirent ) ) );
}
}
void release()
{
//printf("directory_iterator::impl::release\n");
::free(e);
e = 0;
}
// constructor path
path cPath;
/// Platform information
DIR* d;
/// Platform information
dirent* e;
directory_entry info;
bool valid_info; // info has been populated
};
directory_iterator::directory_iterator()
: pimpl(new impl)
{
}
directory_iterator::directory_iterator(const path& path_)
: pimpl( new impl(path_) )
{
}
// is this right
directory_iterator::directory_iterator(directory_iterator const &src)
{
//printf("directory_iterator::directory_iterator copy - pimpl[%x] from[%s]\n", pimpl, src->path().c_str());
if (pimpl)
{
//delete pimpl;
}
pimpl = new impl(src.pimpl->p.c_str());
pimpl->seek(src.pimpl->pos);
}
directory_iterator::~directory_iterator()
{
delete pimpl;
}
directory_iterator::directory_iterator(directory_iterator const &src, int pos) {
//printf("directory_iterator::directory_iterator copy at pos - pimpl[%x] from[%s]\n", pimpl, src->path().c_str());
pimpl = new impl(src.pimpl->p.c_str());
pimpl->seek(pos);
}
bool directory_iterator::operator==(const directory_iterator& i) const
{
// only equal if both are end iterators
return pimpl->is_end() && i.pimpl->is_end();
}
bool directory_iterator::operator!=(const directory_iterator& i) const
{
return !( pimpl->is_end() && i.pimpl->is_end() );
}
directory_iterator& directory_iterator::operator++()
{
pimpl->next();
return *this;
}
const directory_entry& directory_iterator::operator*() const
{
return pimpl->get_reference();
}
const directory_entry* directory_iterator::operator->() const
{
return pimpl->get_pointer();
}
file_type directory_iterator::type() const
{
return pimpl->type();
}
void directory_iterator::swap(directory_iterator& d)
{
std::swap(pimpl, d.pimpl);
}
// FIXME: this isn't right
directory_iterator directory_iterator::begin() {
return directory_iterator( *this, 0 );
/*
printf("directory_iterator::directory_iterator::begin - start\n");
size_t cur = pimpl->pos; // backup state
printf("directory_iterator::directory_iterator::begin - was at [%zu][%s]\n", cur, this->pimpl->get_path().c_str());
pimpl->rewind();
directory_iterator *ret = new directory_iterator(*this); // copy ourself
pimpl->seek(cur); // restore state
printf("directory_iterator::directory_iterator::begin - end\n");
return *ret;
*/
}
directory_iterator directory_iterator::end() {
//return *(directory_iterator *)endPtr;
//printf("directory_iterator::directory_iterator::end - start\n");
size_t cur = pimpl->pos; // backup state
//printf("directory_iterator::directory_iterator::end - was at [%zu][%s]\n", cur, this->pimpl->get_path().c_str());
// spool to the end
size_t finalPos = pimpl->pos;
while( !pimpl->is_end() )
{
if (pimpl->next()) {
finalPos = pimpl->pos;
}
}
//directory_iterator *ret = new directory_iterator(*this); // copy ourself
//printf("directory_iterator::directory_iterator::end - now at [%zu][%s]\n", pimpl->pos, this->pimpl->get_path().c_str());
pimpl->seek(cur); // restore state
return directory_iterator( *this, finalPos);
//printf("directory_iterator::directory_iterator::end - end\n");
//return *ret;
}
//
// recursive_directory_iterator
//
recursive_directory_iterator::recursive_directory_iterator()
{
}
recursive_directory_iterator::recursive_directory_iterator(const path& p)
{
descend(p);
}
recursive_directory_iterator::~recursive_directory_iterator()
{
while ( !stack.empty() )
{
ascend();
}
}
bool recursive_directory_iterator::descend(const path& p)
{
directory_iterator it(p), end;
if ( it != end )
{
directory_iterator* jt = new directory_iterator();
jt->swap(it);
stack.push(jt);
return true;
}
return false;
}
void recursive_directory_iterator::ascend()
{
delete stack.top();
stack.pop();
}
const directory_entry& recursive_directory_iterator::operator*() const
{
return *( *stack.top() );
}
const directory_entry* recursive_directory_iterator::operator->() const
{
return stack.top()->operator->();
}
recursive_directory_iterator& recursive_directory_iterator::operator++()
{
if ( stack.top()->type() == file_type::directory )
{
// go to directory's first child (if any)
if ( descend( ( *stack.top() )->path() ) )
{
return *this;
}
}
do
{
// move to sibling
stack.top()->operator++();
directory_iterator end;
if ( *( stack.top() ) != end )
{
return *this;
}
// move to parent
ascend();
}
while ( !stack.empty() );
return *this;
}
bool recursive_directory_iterator::operator==(const recursive_directory_iterator& i) const
{
return stack.empty() && i.stack.empty();
}
bool recursive_directory_iterator::operator!=(const recursive_directory_iterator& i) const
{
return !( stack.empty() && i.stack.empty() );
}
}
}

@ -0,0 +1,151 @@
/* Copyright (c) 2014, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_FS_DIRITER_H
#define PBL_CPP_FS_DIRITER_H
#include <stack>
#include "direntry.h"
namespace cpp17
{
namespace filesystem
{
/** An iterator for traversing directory contents
*
* This class can be used for iterating over the contents of a directory. The
* parameterized constructor will make a "begin" iterator, and the default
* constructor will make an "end" iterator. One can dereference an iterator
* to get a directory_entry describing the file/subdirectory.
*
* @note The "." and ".." 'files' are ignored by this iterator, since they are
* not 'in' the directory.
*
* @note These objects are not copyable
*
* @note Only end iterators are ever considered equal. In particular, two
* directory_iterator-s constructed with the same argument may not point to the
* same file.
*/
class directory_iterator
{
public:
/** Construct an iterator for a directory
*
* After construction, the iterator will point to the first file in the
* directory.
*/
explicit directory_iterator(const path& path_);
/** Construct an end iterator
*/
directory_iterator();
/** Destructor
*/
~directory_iterator();
directory_iterator begin();
directory_iterator end();
/** Test if two iterators are equal
*
* Only two end iterators are equal
*/
bool operator==(const directory_iterator& i) const;
/** Test if two iterators are not equal
*
* Only two end iterators are equal
*/
bool operator!=(const directory_iterator& i) const;
/** Move to the next file/subdirectory
*/
directory_iterator& operator++();
/** Get information for the file system object
*
* @note Causes a stat. If all you need is the type of the file system object,
* use the cheaper type() member
*/
const directory_entry& operator*() const;
/** Get information for the file system object
*
* @note Causes a stat. If all you need is the type of the file system object,
* use the cheaper type() member
*/
const directory_entry* operator->() const;
file_type type() const;
void swap(directory_iterator&);
// non-copyable
// now it is
directory_iterator(const directory_iterator&);
directory_iterator& operator=(const directory_iterator&);
directory_iterator(const directory_iterator&, int pos);
//void *endPtr;
private:
class impl;
impl* pimpl;
};
class recursive_directory_iterator
{
public:
recursive_directory_iterator();
explicit recursive_directory_iterator(const path& p);
~recursive_directory_iterator();
recursive_directory_iterator& operator++();
const directory_entry& operator*() const;
const directory_entry* operator->() const;
bool operator==(const recursive_directory_iterator& i) const;
bool operator!=(const recursive_directory_iterator& i) const;
private:
// non-copyable
recursive_directory_iterator(const recursive_directory_iterator&);
recursive_directory_iterator& operator=(const recursive_directory_iterator&);
bool descend(const path& p);
void ascend();
std::stack< directory_iterator* > stack;
};
}
}
#endif // PBL_FS_DIRITER_H

@ -0,0 +1,60 @@
/* Copyright (c) 2018, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "equivalent.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
namespace cpp17
{
namespace filesystem
{
bool equivalent(
const path& p1,
const path& p2
)
{
struct stat s1;
if ( ::stat(p1.c_str(), &s1) == 0 )
{
struct stat s2;
if ( ::stat(p2.c_str(), &s2) == 0 )
{
return s1.st_ino == s2.st_ino && s1.st_dev == s2.st_dev;
}
}
return false;
}
}
}

@ -0,0 +1,42 @@
/* Copyright (c) 2018, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_FS_EQUIVALENT_H
#define PBL_CPP_FS_EQUIVALENT_H
#include "path.h"
namespace cpp17
{
namespace filesystem
{
bool equivalent(const path&, const path&);
}
}
#endif // PBL_CPP_FS_EQUIVALENT_H

@ -0,0 +1,279 @@
/* Copyright (c) 2015, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "filestatus.h"
#include <iostream>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "path.h"
namespace
{
::cpp17::filesystem::file_status from_mode_t(mode_t m)
{
::cpp17::filesystem::perms p = static_cast< ::cpp17::filesystem::perms >( m & 0xFFF );
::cpp17::filesystem::file_type t = file_type::unknown;
if ( S_ISREG(m) )
{
t = file_type::regular;
}
else if ( S_ISDIR(m) )
{
t = file_type::directory;
}
else if ( S_ISCHR(m) )
{
t = file_type::character;
}
else if ( S_ISBLK(m) )
{
t = file_type::block;
}
else if ( S_ISFIFO(m) )
{
t = file_type::fifo;
}
else if ( S_ISLNK(m) )
{
t = file_type::symlink;
}
else if ( S_ISSOCK(m) )
{
t = file_type::socket;
}
return ::cpp17::filesystem::file_status(t, p);
}
}
namespace cpp17
{
namespace filesystem
{
file_status::file_status(const file_status& s)
: t(s.t), p(s.p)
{
}
file_status::file_status(
file_type t_,
perms p_
)
: t(t_), p(p_)
{
}
file_status& file_status::operator=(const file_status& s)
{
t = s.t;
p = s.p;
return *this;
}
file_type file_status::type() const
{
return t;
}
void file_status::type(file_type t_)
{
t = t_;
}
perms file_status::permissions() const
{
return p;
}
void file_status::permissions(perms p_)
{
p = p_;
}
std::ostream& operator<<(
std::ostream& os,
const file_status& fs
)
{
os << fs.type() << "; " << fs.permissions();
return os;
}
file_status status(const path& path_)
{
if ( !path_.empty() )
{
struct stat st;
if ( ::stat(path_.c_str(), &st) == 0 )
{
return from_mode_t(st.st_mode);
}
}
return file_status();
}
file_status symlink_status(const path& path_)
{
if ( !path_.empty() )
{
struct stat st;
if ( ::lstat(path_.c_str(), &st) == 0 )
{
return from_mode_t(st.st_mode);
}
}
return file_status();
}
bool status_known(file_status s)
{
return s.type() != file_type::none;
}
bool exists(file_status s)
{
return status_known(s) && s.type() != file_type::not_found;
}
bool exists(const path& p, std::error_code& ec)
{
return exists( status(p) );
}
bool is_block_file(file_status s)
{
return s.type() == file_type::block;
}
bool is_block_file(const path& p)
{
return is_block_file( status(p) );
}
bool is_character_file(file_status s)
{
return s.type() == file_type::character;
}
bool is_character_file(const path& p)
{
return is_character_file( status(p) );
}
bool is_fifo(file_status s)
{
return s.type() == file_type::fifo;
}
bool is_fifo(const path& p)
{
return is_fifo( status(p) );
}
bool is_other(file_status s)
{
return exists(s) && !is_regular_file(s) && !is_directory(s) && !is_symlink(s);
}
bool is_other(const path& p)
{
return is_other( status(p) );
}
bool is_regular_file(file_status s)
{
return s.type() == file_type::regular;
}
bool is_regular_file(const path& p)
{
return is_regular_file( status(p) );
}
bool is_socket(file_status s)
{
return s.type() == file_type::socket;
}
bool is_socket(const path& p)
{
return is_socket( status(p) );
}
bool is_symlink(file_status s)
{
return s.type() == file_type::symlink;
}
bool is_symlink(const path& p)
{
return is_symlink( status(p) );
}
bool is_directory(file_status s)
{
return s.type() == file_type::directory;
}
bool is_directory(const path& p)
{
return is_directory( status(p) );
}
std::size_t file_size(const path& p)
{
if ( !p.empty() )
{
struct stat st;
if ( ::stat(p.c_str(), &st) == 0 )
{
return st.st_size;
}
}
return std::size_t(-1);
}
}
}

@ -0,0 +1,92 @@
/* Copyright (c) 2015, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_FS_FILESTATUS_H
#define PBL_CPP_FS_FILESTATUS_H
#include <iosfwd>
#include <system_error>
#include "filetype.h"
#include "perms.h"
namespace cpp17
{
namespace filesystem
{
class path;
/** Information about a file's type and permissions
*
* Due to the nature of the file system, the information may not be exactly
* current.
*/
class file_status
{
public:
file_status(const file_status&);
explicit file_status(file_type = file_type::none, perms = perms::unknown);
file_status& operator=(const file_status&);
file_type type() const;
void type(file_type);
perms permissions() const;
void permissions(perms);
private:
file_type t;
perms p;
};
file_status status(const path&);
file_status symlink_status(const path&);
bool status_known(file_status);
bool exists(file_status);
bool exists(const path&, std::error_code&);
bool is_block_file(file_status);
bool is_block_file(const path&);
bool is_character_file(file_status);
bool is_character_file(const path&);
bool is_fifo(file_status);
bool is_fifo(const path&);
bool is_other(file_status);
bool is_other(const path&);
bool is_regular_file(file_status);
bool is_regular_file(const path&);
bool is_socket(file_status);
bool is_socket(const path&);
bool is_symlink(file_status);
bool is_symlink(const path&);
bool is_directory(file_status);
bool is_directory(const path&);
std::size_t file_size(const path&);
std::ostream& operator<<(std::ostream&, const file_status&);
}
}
#endif // PBL_CPP_FS_FILESTATUS_H

@ -0,0 +1,59 @@
/* Copyright (c) 2015, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "filetype.h"
#include <iostream>
static const char* const friendly[] =
{
"Not found", "None", "Regular File", "Directory", "Symbolic Link",
"Block Device", "Character Device", "FIFO", "Socket"
};
namespace file_type
{
std::ostream& operator<<(
std::ostream& os,
file_type t
)
{
if ( -1 <= t && t < 8 )
{
os << friendly[t + 1];
}
else
{
os << "Unknown";
}
return os;
}
}

@ -0,0 +1,54 @@
/* Copyright (c) 2015, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_FS_FILETYPE_H
#define PBL_CPP_FS_FILETYPE_H
#include <iosfwd>
namespace file_type
{
enum file_type
{
not_found = -1, none = 0, regular, directory, symlink, block, character, fifo,
socket, unknown
};
std::ostream& operator<<(std::ostream&, file_type);
}
namespace cpp17
{
namespace filesystem
{
/** Types of file system objects
*/
typedef ::file_type::file_type file_type;
}
}
#endif // PBL_CPP_FS_FILETYPE_H

@ -0,0 +1,693 @@
/* Copyright (c) 2015, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "path.h"
namespace cpp17
{
namespace filesystem
{
path::path()
{
}
path::path(const string_type& s_)
: s(s_)
{
}
path::path(const char* s_)
: s(s_)
{
}
path::path(const path& p)
: s(p.s)
{
}
path& path::operator=(const path& p)
{
s = p.s;
return *this;
}
void path::clear()
{
s.clear();
}
void path::swap(path& p)
{
s.swap(p.s);
}
std::string path::string() const
{
return s;
}
const char* path::c_str() const
{
return s.c_str();
}
bool path::empty() const
{
return s.empty();
}
path path::extension() const
{
const std::size_t i = s.find_last_of(preferred_separator);
const std::size_t j = ( i == std::string::npos ? 0 : i + 1 );
if ( j < s.length() )
{
if ( s.compare(j, std::string::npos, ".", 1) != 0
&& s.compare(j, std::string::npos, "..", 2) != 0 )
{
const std::size_t k = s.find_last_of('.');
if ( k != std::string::npos && j <= k )
{
return s.substr(k);
}
}
}
return path();
}
path path::filename() const
{
const std::size_t i = s.find_last_of(preferred_separator);
if ( i == std::string::npos )
{
return *this;
}
if ( i + 1 < s.length() )
{
return path( s.substr(i + 1) );
}
else
{
return ".";
}
}
path path::parent_path() const
{
const std::size_t i = s.find_last_of(preferred_separator);
if ( i == std::string::npos )
{
return path();
}
return path( s.substr(0, i) );
}
path& path::remove_filename()
{
const std::size_t i = s.find_last_of(preferred_separator);
if ( i != std::string::npos )
{
s.resize(i);
}
return *this;
}
path& path::replace_filename(const path& p)
{
const std::size_t i = s.find_last_of(preferred_separator);
if ( i != std::string::npos )
{
s.resize(i);
append(p);
}
else
{
assign(p);
}
return *this;
}
path::operator string_type() const
{
return s;
}
path& path::append(const path& p)
{
bool sep = true;
if ( !s.empty() && s[s.length() - 1] == preferred_separator )
{
sep = false;
}
else if ( s.empty() )
{
sep = false;
}
else if ( p.empty() || p.s[0] == preferred_separator )
{
sep = false;
}
if ( sep )
{
s += preferred_separator;
}
s.append( p.native() );
return *this;
}
path& path::operator/=(const path& p)
{
return append(p);
}
const std::string& path::native() const
{
return s;
}
path path::lexically_relative(const path& p) const
{
const_iterator first1 = begin(), last1 = end();
const_iterator first2 = p.begin(), last2 = p.end();
const_iterator it = first1;
const_iterator jt = first2;
while ( it != last1 && jt != last2 && *it == *jt )
{
++it, ++jt;
}
if ( it == first1 || jt == first2 )
{
return path();
}
if ( it == last1 && jt == last2 )
{
return path(".");
}
path r;
for (; jt != last2; ++jt )
{
r /= "..";
}
for (; it != last1; ++it )
{
r /= *it;
}
return r;
}
bool path::is_absolute() const
{
return !s.empty() && s[0] == preferred_separator;
}
path path::lexically_normal() const
{
std::string t;
if ( s.empty() )
{
// error
return t;
}
const std::size_t n = s.length();
for ( std::size_t i = 0; i < n;)
{
if ( s[i] == '/' )
{
// directory separator
t.push_back('/');
i = s.find_first_not_of('/', i);
}
else
{
// path component
const std::size_t j = std::min(s.find('/', i), n);
if ( s.compare(i, j - i, ".", 1) == 0 )
{
// handle dot
if ( j < n )
{
i = s.find_first_not_of('/', j);
}
else
{
i = n;
}
}
else if ( s.compare(i, j - i, "..", 2) == 0 )
{
// handle dot-dot
const std::size_t l = t.length();
if ( l == 0 )
{
// no previous component (ex., "../src")
t.assign("..", 2);
i = j;
}
else
{
// remove previously copied component (unless root)
if ( l >= 2 )
{
const std::size_t k = t.find_last_of('/', l - 2);
if ( k == std::string::npos )
{
t.clear();
}
else
{
t.resize(k + 1);
}
}
if ( j < n )
{
i = s.find_first_not_of('/', j);
}
else
{
i = n;
}
}
}
else
{
// append path component
t.append(s, i, j - i);
i = j;
}
}
}
if ( t.empty() )
{
return ".";
}
// drop trailing slashes
const std::size_t i = t.find_last_not_of('/');
if ( i != std::string::npos )
{
t.resize(i + 1);
}
return t;
}
int path::compare(const path& p) const
{
const_iterator first1 = begin(), last1 = end();
const_iterator first2 = p.begin(), last2 = p.end();
while ( first1 != last1 && first2 != last2 )
{
if ( first1->native() < first2->native() )
{
return -1;
}
if ( first2->native() < first1->native() )
{
return 1;
}
++first1;
++first2;
}
if ( first1 != last1 )
{
return 1;
}
if ( first2 != last2 )
{
return -1;
}
return 0;
}
path::const_iterator path::begin() const
{
begin_iterator_tag tag;
return const_iterator(this, tag);
}
path::const_iterator path::end() const
{
end_iterator_tag tag;
return const_iterator(this, tag);
}
path::const_iterator::const_iterator()
: parent(0), first(std::string::npos), last(std::string::npos), value()
{
}
path::const_iterator::const_iterator(
const path* parent_,
begin_iterator_tag
)
: parent(parent_), first(0)
{
if ( parent->s.empty() )
{
first = std::string::npos;
last = std::string::npos;
}
else
{
const std::size_t k = parent->s.find_first_of(preferred_separator);
if ( k == std::string::npos )
{
last = parent->s.length();
}
else if ( k == 0 )
{
last = 1;
}
else
{
last = k;
}
value = parent->s.substr(0, last);
}
}
path::const_iterator::const_iterator(
const path* p,
end_iterator_tag
)
: parent(p), first(std::string::npos), last(std::string::npos), value()
{
}
path::const_iterator& path::const_iterator::operator++()
{
if ( parent )
{
if ( last < parent->s.length() )
{
// find next component
const std::size_t j = parent->s.find_first_not_of(preferred_separator, last);
if ( j == std::string::npos )
{
if ( parent->s[first] == preferred_separator )
{
// path to root
first = std::string::npos;
last = std::string::npos;
value.clear();
}
else
{
// ends with directory
first = parent->s.length();
last = std::string::npos;
value = ".";
}
}
else
{
first = j;
// next path component
const std::size_t k = parent->s.find_first_of(preferred_separator, j);
if ( k == std::string::npos )
{
last = parent->s.length();
}
else
{
last = k;
}
value = parent->s.substr(first, last - first);
}
}
else
{
// go to end iterator
first = std::string::npos;
last = std::string::npos;
value.clear();
}
}
return *this;
}
path::const_iterator path::const_iterator::operator++(int)
{
const_iterator t = *this;
operator++();
return t;
}
path::const_iterator& path::const_iterator::operator--()
{
if ( parent && first != 0 )
{
if ( first == std::string::npos )
{
// end iterator
if ( !parent->s.empty() )
{
const std::size_t j = parent->s.find_last_of(preferred_separator);
if ( j == std::string::npos )
{
// single path component
first = 0;
last = parent->s.length();
value = parent->s;
}
else
{
if ( j + 1 < parent->s.length() )
{
// trailing filename
first = j + 1;
last = parent->s.length();
value = parent->s.substr(first, last - first);
}
else
{
// trailing directory, or root
const std::size_t k = parent->s.find_last_not_of(preferred_separator, j);
if ( k == std::string::npos )
{
first = 0;
last = 1;
value = parent->s.substr(first, last - first);
}
else
{
first = parent->s.length();
last = std::string::npos;
value = ".";
}
}
}
}
}
else
{
// on an actual path component, or the fake "."
const std::size_t j = parent->s.find_last_not_of(preferred_separator, first - 1);
if ( j == std::string::npos )
{
// beginning of absolute path
first = 0;
last = 1;
}
else
{
last = j + 1;
const std::size_t k = parent->s.find_last_of(preferred_separator, j);
if ( k == std::string::npos )
{
first = 0;
}
else
{
first = k + 1;
}
}
value = parent->s.substr(first, last - first);
}
}
return *this;
}
path::const_iterator path::const_iterator::operator--(int)
{
const_iterator t = *this;
operator--();
return t;
}
bool path::const_iterator::operator==(const const_iterator& o) const
{
return parent == o.parent && first == o.first;
}
bool path::const_iterator::operator!=(const const_iterator& o) const
{
return parent != o.parent || first != o.first;
}
const path& path::const_iterator::operator*() const
{
return value;
}
const path* path::const_iterator::operator->() const
{
return &value;
}
path operator/(
const path& lhs,
const path& rhs
)
{
path res = lhs;
res.append(rhs);
return res;
}
std::ostream& operator<<(
std::ostream& os,
const path& p
)
{
return os << p.string();
}
bool operator==(
const path& l,
const path& r
)
{
return l.compare(r) == 0;
}
bool operator!=(
const path& l,
const path& r
)
{
return l.compare(r) != 0;
}
bool operator<(
const path& l,
const path& r
)
{
return l.compare(r) < 0;
}
bool operator<=(
const path& l,
const path& r
)
{
return l.compare(r) <= 0;
}
bool operator>(
const path& l,
const path& r
)
{
return l.compare(r) > 0;
}
bool operator>=(
const path& l,
const path& r
)
{
return l.compare(r) >= 0;
}
}
}

@ -0,0 +1,190 @@
/* Copyright (c) 2015, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_FS_PATH_H
#define PBL_CPP_FS_PATH_H
#include <string>
#include <iosfwd>
#include <iterator>
namespace cpp17
{
namespace filesystem
{
/** A file path
*
* A partial implementation of std::experimental::filesystem::path
* @todo Construct from the other basic_string types and pointer-to-char16_t, etc.
* @bug Throughout, preferred_separator is used incorrectly
*/
class path
{
public:
typedef char value_type;
typedef std::basic_string< value_type > string_type;
static const value_type preferred_separator = '/';
class const_iterator;
typedef const_iterator iterator;
/// An empty path
path();
/// Construct a path form the given string
path(const string_type&);
path(const char*);
/// Copy constructor
path(const path&);
/// Copy assignment
path& operator=(const path&);
template< typename Source >
path& operator=(const Source& source)
{
return assign(source);
}
template< typename Source >
path& assign(const Source& source)
{
path t(source);
swap(t);
return *this;
}
template< typename Iterator >
path& assign(
Iterator first,
Iterator last
)
{
path t(first, last);
swap(t);
return *this;
}
/// Clear the path
void clear();
/// Swap the two paths
void swap(path&);
std::string string() const;
const char* c_str() const;
path& operator/=(const path&);
path& append(const path&);
/// Is the path empty (i.e., "")
bool empty() const;
const std::string& native() const;
path extension() const;
path filename() const;
path parent_path() const;
path& remove_filename();
path& replace_filename(const path&);
operator string_type() const;
bool is_absolute() const;
path lexically_normal() const;
path lexically_relative(const path&) const;
int compare(const path&) const;
const_iterator begin() const;
const_iterator end() const;
private:
struct begin_iterator_tag {};
struct end_iterator_tag {};
std::string s;
};
class path::const_iterator
{
public:
typedef const path value_type;
typedef const path& reference;
typedef const path* pointer;
typedef std::ptrdiff_t difference_type;
const_iterator();
const_iterator(const path*, begin_iterator_tag);
const_iterator(const path*, end_iterator_tag);
const_iterator& operator++();
const_iterator operator++(int);
const_iterator& operator--();
const_iterator operator--(int);
bool operator==(const const_iterator&) const;
bool operator!=(const const_iterator&) const;
const path& operator*() const;
const path* operator->() const;
private:
const path* parent;
std::size_t first;
std::size_t last;
path value;
};
path operator/(const path& lhs, const path& rhs);
std::ostream& operator<<(std::ostream&, const path&);
bool operator==(const path&, const path&);
bool operator!=(const path&, const path&);
bool operator<(const path&, const path&);
bool operator<=(const path&, const path&);
bool operator>(const path&, const path&);
bool operator>=(const path&, const path&);
}
}
namespace std
{
template< >
struct iterator_traits< ::cpp17::filesystem::path::const_iterator >
{
typedef std::ptrdiff_t difference_type;
typedef const ::cpp17::filesystem::path value_type;
typedef const ::cpp17::filesystem::path* pointer;
typedef const ::cpp17::filesystem::path& reference;
typedef std::bidirectional_iterator_tag iterator_category;
};
}
#endif // PBL_FS_PATH_H

@ -0,0 +1,48 @@
/* Copyright (c) 2015, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "perms.h"
#include <iostream>
#include <iomanip>
namespace perms
{
std::ostream& operator<<(
std::ostream& os,
perms p
)
{
std::ostream t( os.rdbuf() );
t << "mode: " << std::oct << static_cast< int >( p );
return os;
}
}

@ -0,0 +1,101 @@
/* Copyright (c) 2015, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_FS_PERMS_H
#define PBL_CPP_FS_PERMS_H
#include <iosfwd>
namespace perms
{
/** File permissions
*
* See: std::experimental::filesystem::perms
*/
enum perms
{
none = 0,
owner_read = 0400, // S_IRUSR
owner_write = 0200, // S_IWUSR
owner_exec = 0100, // S_IXUSR
owner_all = 0700, // S_IRWXU
group_read = 040, // S_IRGRP
group_write = 020, // S_IWGRP
group_exec = 010, // S_IXGRP
group_all = 070, // S_IRWXG
others_read = 04, // S_IROTH
others_write = 02, // S_IWOTH
others_exec = 01, // S_IXOTH
others_all = 07, // S_IRWXO
all = 0777,
set_uid = 04000,
set_gid = 02000,
sticky_bit = 01000,
mask = 07777,
unknown = 0xffff,
add_perms = 0x10000,
remove_perms = 0x20000,
resolve_symlinks = 0x40000
};
inline perms operator|(
perms a,
perms b
)
{
return static_cast< perms >( static_cast< int >( a ) | static_cast< int >( b ) );
}
inline perms operator&(
perms a,
perms b
)
{
return static_cast< perms >( static_cast< int >( a ) & static_cast< int >( b ) );
}
inline perms operator^(
perms a,
perms b
)
{
return static_cast< perms >( static_cast< int >( a ) ^ static_cast< int >( b ) );
}
std::ostream& operator<<(std::ostream&, perms);
}
namespace cpp17
{
namespace filesystem
{
typedef ::perms::perms perms;
}
}
#endif // PBL_CPP_FS_PERMS_H

@ -0,0 +1,62 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "remove.h"
#include <cstdio>
#include "diriter.h"
namespace cpp17
{
namespace filesystem
{
bool remove(const path& p)
{
return ::remove( p.c_str() ) == 0;
}
unsigned long remove_all(const path& p)
{
unsigned long total = 0;
for ( directory_iterator it(p), last; it != last; ++it )
{
total += remove_all( it->path() );
}
if ( remove(p) )
{
++total;
}
return total;
}
}
}

@ -0,0 +1,43 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_FS_REMOVE_H
#define PBL_CPP_FS_REMOVE_H
#include "path.h"
namespace cpp17
{
namespace filesystem
{
bool remove(const path&);
unsigned long remove_all(const path&);
}
}
#endif // PBL_CPP_FS_REMOVE_H

@ -0,0 +1,51 @@
/* Copyright (c) 2018, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "rename.h"
#include <cstdio>
#include "copyfile.h"
#include "remove.h"
namespace cpp17
{
namespace filesystem
{
/// @bug This is just a quick and dirty implementation
void rename(const path& from, const path& to)
{
if (std::rename(from.c_str(), to.c_str()) != 0)
{
if (copy_file(from, to))
cpp17::filesystem::remove(from);
}
}
}
}

@ -0,0 +1,42 @@
/* Copyright (c) 2018, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_FS_RENAME_H
#define PBL_CPP_FS_RENAME_H
#include "path.h"
namespace cpp17
{
namespace filesystem
{
void rename(const path& from, const path& to);
}
}
#endif // PBL_CPP_FS_RENAME_H

@ -0,0 +1,70 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "tempdir.h"
#include <cstdlib>
namespace cpp17
{
namespace filesystem
{
/* TMPDIR is the POSIX variable for the temporary directory. Other variables
* are sometimes used, however, in non-conforming environments. Those are
* checked as fallback (following Boost's implementation)
*/
path temp_directory_path()
{
const char* p = std::getenv("TMPDIR");
if ( !p )
{
p = std::getenv("TMP");
if ( !p )
{
p = std::getenv("TEMP");
if ( !p )
{
p = std::getenv("TEMPDIR");
if ( !p )
{
p = "/tmp";
}
}
}
}
return path(p);
}
}
}

@ -0,0 +1,42 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_FS_TEMPDIR_H
#define PBL_CPP_FS_TEMPDIR_H
#include "path.h"
namespace cpp17
{
namespace filesystem
{
path temp_directory_path();
}
}
#endif // PBL_CPP_FS_TEMPDIR_H

@ -0,0 +1,28 @@
# Sources are located relative to Makefile
MAKEFILE_DIR := $(shell readlink -f $(dir $(word $(words $(MAKEFILE_LIST)), $(MAKEFILE_LIST))))
# The path of the invoking module
vpath %.cpp $(MAKEFILE_DIR)
default: lib
include $(MAKEFILE_DIR)/../make.inc
CXXFLAGS += -pthread
LDFLAGS += -pthread
INCLUDE += -iquote$(MAKEFILE_DIR)
LIBNAME = cppbackport
LIBFILE = lib$(LIBNAME).a
SRCDIRS = . fs
LIBSRC = $(wildcard $(SRCDIRS:%=$(MAKEFILE_DIR)/%/*.cpp))
LIBOBJS = $(LIBSRC:$(MAKEFILE_DIR)/%.cpp=%.o)
.PHONY: lib clean
$(LIBFILE): $(LIBOBJS)
lib: $(LIBFILE)
clean: clean_objects
@$(RM) $(LIBFILE)

@ -0,0 +1,406 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_ALGORITHM_H
#define PBL_CPP_ALGORITHM_H
#include <algorithm>
#include "version.h"
#ifndef CPP11
#include <functional>
namespace cpp11
{
template< class InputIterator, class Predicate >
InputIterator find_if_not(
InputIterator first,
InputIterator last,
Predicate q
)
{
for (; first != last; ++first )
{
if ( !q(*first) )
{
return first;
}
}
return last;
}
template< class InputIterator, class Predicate >
bool all_of(
InputIterator first,
InputIterator last,
Predicate p
)
{
return ::cpp11::find_if_not(first, last, p) == last;
}
template< class InputIterator, class Predicate >
bool any_of(
InputIterator first,
InputIterator last,
Predicate p
)
{
return std::find_if(first, last, p) != last;
}
template< class InputIterator, class Predicate >
bool none_of(
InputIterator first,
InputIterator last,
Predicate p
)
{
return std::find_if(first, last, p) == last;
}
template< class InputIterator, class OutputIterator, class Predicate >
OutputIterator copy_if(
InputIterator first,
InputIterator last,
OutputIterator d_first,
Predicate pred
)
{
while ( first != last )
{
if ( pred(*first) )
{
*d_first++ = *first;
}
first++;
}
return d_first;
}
template< class InputIterator, class Size, class OutputIterator >
OutputIterator copy_n(
InputIterator first,
Size count,
OutputIterator result
)
{
if ( count > 0 )
{
*result++ = *first;
for ( Size i = 1; i < count; ++i )
{
*result++ = *++first;
}
}
return result;
}
template< class InputIterator, class Predicate >
bool is_partitioned(
InputIterator first,
InputIterator last,
Predicate p
)
{
for (; first != last; ++first )
{
if ( !p(*first) )
{
break;
}
}
for (; first != last; ++first )
{
if ( p(*first) )
{
return false;
}
}
return true;
}
template< class InputIterator, class OutputIt1,
class OutputIt2, class Predicate >
std::pair< OutputIt1, OutputIt2 > partition_copy(
InputIterator first,
InputIterator last,
OutputIt1 d_first_true,
OutputIt2 d_first_false,
Predicate p
)
{
while ( first != last )
{
if ( p(*first) )
{
*d_first_true = *first;
++d_first_true;
}
else
{
*d_first_false = *first;
++d_first_false;
}
++first;
}
return std::pair< OutputIt1, OutputIt2 >(d_first_true, d_first_false);
}
template< class ForwardIterator, class Compare >
ForwardIterator is_sorted_until(
ForwardIterator first,
ForwardIterator last,
Compare comp
)
{
if ( first != last )
{
ForwardIterator next = first;
while ( ++next != last )
{
if ( comp(*next, *first) )
{
return next;
}
first = next;
}
}
return last;
}
template< class ForwardIterator >
ForwardIterator is_sorted_until(
ForwardIterator first,
ForwardIterator last
)
{
return ::cpp11::is_sorted_until( first, last, std::less< typename std::iterator_traits< ForwardIterator >::value_type >() );
}
template< class ForwardIterator >
bool is_sorted(
ForwardIterator first,
ForwardIterator last
)
{
return ::cpp11::is_sorted_until(first, last) == last;
}
template< class ForwardIterator, class Compare >
bool is_sorted(
ForwardIterator first,
ForwardIterator last,
Compare comp
)
{
return ::cpp11::is_sorted_until(first, last, comp) == last;
}
template< class T >
std::pair< const T&, const T& > minmax(
const T& a,
const T& b
)
{
return ( b < a ) ? std::pair< const T&, const T& >(b, a)
: std::pair< const T&, const T& >(a, b);
}
template< class T, class Compare >
std::pair< const T&, const T& > minmax(
const T& a,
const T& b,
Compare comp
)
{
return comp(b, a) ? std::pair< const T&, const T& >(b, a)
: std::pair< const T&, const T& >(a, b);
}
template< class ForwardIterator, class Compare >
std::pair< ForwardIterator, ForwardIterator > minmax_element(
ForwardIterator first,
ForwardIterator last,
Compare comp
)
{
std::pair< ForwardIterator, ForwardIterator > result(first, first);
if ( first == last )
{
return result;
}
if ( ++first == last )
{
return result;
}
if ( comp(*first, *result.first) )
{
result.first = first;
}
else
{
result.second = first;
}
while ( ++first != last )
{
ForwardIterator i = first;
if ( ++first == last )
{
if ( comp(*i, *result.first) )
{
result.first = i;
}
else if ( !( comp(*i, *result.second) ) )
{
result.second = i;
}
break;
}
else
{
if ( comp(*first, *i) )
{
if ( comp(*first, *result.first) )
{
result.first = first;
}
if ( !( comp(*i, *result.second) ) )
{
result.second = i;
}
}
else
{
if ( comp(*i, *result.first) )
{
result.first = i;
}
if ( !( comp(*first, *result.second) ) )
{
result.second = first;
}
}
}
}
return result;
}
template< class ForwardIterator >
std::pair< ForwardIterator, ForwardIterator > minmax_element(
ForwardIterator first,
ForwardIterator last
)
{
return ::cpp11::minmax_element( first, last, std::less< typename std::iterator_traits< ForwardIterator >::value_type >() );
}
template< class ForwardIterator, class T >
void iota(
ForwardIterator first,
ForwardIterator last,
T value
)
{
while ( first != last )
{
*first++ = value;
++value;
}
}
template< class InputIterator, class OutputIterator >
OutputIterator move(
InputIterator first,
InputIterator last,
OutputIterator dest
)
{
while ( first != last )
{
*dest++ = *first++;
}
return dest;
}
}
#endif // ifndef CPP11
#ifndef CPP14
namespace cpp14
{
}
#endif // ifndef CPP14
#ifndef CPP17
namespace cpp17
{
template< typename T, class Compare >
const T& clamp(const T& value, const T& lo, const T& hi, Compare comp)
{
if (comp(value, lo))
return lo;
if (comp(hi, value))
return hi;
return value;
}
template< typename T >
const T& clamp(const T& value, const T& lo, const T& hi)
{
return ::cpp17::clamp(value, lo, hi, std::less<>());
}
}
#endif
#endif // PBL_CPP_ALGORITHM_H

@ -0,0 +1,257 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/// @todo GCC has <experimental/any> which may be preferable
#ifndef PBL_CPP_ANY_H
#define PBL_CPP_ANY_H
#include "version.h"
#ifdef CPP17
#include <any>
#else
#include <typeinfo>
#include <stdexcept>
#include <memory>
namespace cpp17
{
/** Thrown by any_cast if the type of object does not match the indicated type
*
* @todo Get better type name via abi::__cxa_demangle. Might want to add such
* functionality to core
*/
class bad_any_cast
: public std::bad_cast
{
public:
explicit bad_any_cast(const std::type_info& ti)
: info(ti)
{
}
const char* what() const throw ( )
{
return info.name();
}
private:
const std::type_info& info;
};
/** An object that can hold any (CopyConstructible) type
*
* Values are constructed using the constructor, or by copy assignment. They
* are retreived with any_cast<T>
*
* This object stores a pointer to a wrapper around the object. The wrapper
* provides copying, destruction, and RTTI.
*
* @todo safe bool
* @todo small types (no bigger than a pointer) should be stored directly
*/
class any
{
public:
/** An any that does not contain anything
*/
any()
: value(0)
{
}
/** Copy constructor
*/
any(const any& a)
: value(a.value ? a.value->clone() : 0)
{
}
/** Fill an any with a T
*
* T must be CopyConstructible
*/
template< typename T >
any(const T& x)
: value( new actual< T >(x) )
{
}
/** Destroys the stored object
*/
~any()
{
reset();
}
/** Copy assignment
*/
any& operator=(const any& a)
{
any t(a);
t.swap(*this);
return *this;
}
/** Swap stored values
*/
void swap(any& a)
{
base* t = value;
value = a.value;
a.value = t;
}
/** Check if this any currently stores an object
*/
bool has_value() const
{
return value;
}
/** Destroys the stored object
*/
void reset()
{
delete value;
value = 0;
}
/** Get the type info of the stored object
*
* If there is no stored object, the type_info for "void" is returned
*/
const std::type_info& type() const
{
if ( value )
{
return value->type();
}
return typeid( void );
}
private:
struct base
{
virtual ~base()
{
}
virtual base* clone() const = 0;
virtual const std::type_info& type() const = 0;
};
template< typename T >
struct actual
: base
{
explicit actual(const T& y)
: x(y)
{
}
actual* clone() const
{
return new actual(*this);
}
const std::type_info& type() const
{
return typeid( T );
}
T x;
};
template< typename T >
friend T any_cast(const any&);
template< typename T >
friend const T* any_cast(const any*);
template< typename T >
friend T* any_cast(any*);
base* value;
};
/** Get the value out of an any
*/
template< typename T >
T any_cast(const any& a)
{
const std::type_info& ti = typeid( T );
if ( a.type() != ti )
{
throw bad_any_cast(ti);
}
return static_cast< any::actual< T >* >( a.value )->x;
}
template< typename T >
const T* any_cast(const any* a)
{
if ( a )
{
const std::type_info& ti = typeid( T );
if ( a->type() == ti )
{
return &( static_cast< any::actual< T >* >( a->value )->x );
}
}
return 0;
}
template< typename T >
T* any_cast(any* a)
{
if ( a )
{
const std::type_info& ti = typeid( T );
if ( a->type() == ti )
{
return &( static_cast< any::actual< T >* >( a->value )->x );
}
}
return 0;
}
}
#endif // ifdef CPP17
#endif // PBL_CPP_ANY_H

@ -0,0 +1,430 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_ARRAY_H
#define PBL_CPP_ARRAY_H
#include "version.h"
#ifdef CPP11
#include <array>
#else
#include <cstddef>
#include <stdexcept>
#include "algorithm.h"
#include "iterator.h"
namespace cpp11
{
template< class T, std::size_t N >
struct array
{
typedef T& reference;
typedef const T& const_reference;
typedef T* iterator;
typedef const T* const_iterator;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef std::reverse_iterator< iterator > reverse_iterator;
typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
reference at(size_type n)
{
if ( n >= N )
{
throw std::out_of_range("");
}
return elems[n];
}
const_reference at(size_type n) const
{
if ( n >= N )
{
throw std::out_of_range("");
}
return elems[n];
}
reference operator[](size_type n)
{
return elems[n];
}
const_reference operator[](size_type n) const
{
return elems[n];
}
reference front()
{
return elems[0];
}
const_reference front() const
{
return elems[0];
}
reference back()
{
return elems[N - 1];
}
const_reference back() const
{
return elems[N - 1];
}
T* data()
{
return elems;
}
const T* data() const
{
return elems;
}
iterator begin()
{
return elems;
}
const_iterator begin() const
{
return elems;
}
const_iterator cbegin() const
{
return elems;
}
iterator end()
{
return elems + N;
}
const_iterator end() const
{
return elems + N;
}
const_iterator cend() const
{
return elems + N;
}
reverse_iterator rbegin()
{
return reverse_iterator( elems + ( N - 1 ) );
}
const_reverse_iterator rbegin() const
{
return reverse_iterator( elems + ( N - 1 ) );
}
const_reverse_iterator crbegin() const
{
return reverse_iterator( elems + ( N - 1 ) );
}
reverse_iterator rend()
{
return reverse_iterator(elems - 1);
}
const_reverse_iterator rend() const
{
return reverse_iterator(elems - 1);
}
const_reverse_iterator crend() const
{
return reverse_iterator(elems - 1);
}
bool empty() const
{
return false;
}
size_type size() const
{
return N;
}
size_type max_size() const
{
return N;
}
void fill(const T& t)
{
std::fill_n(elems, N, t);
}
void swap(array< T, N >& a)
{
std::swap_ranges(elems, elems + N, a.elems);
}
T elems[N];
};
template< class T >
struct array< T, 0 >
{
typedef T& reference;
typedef const T& const_reference;
typedef T* iterator;
typedef const T* const_iterator;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef std::reverse_iterator< iterator > reverse_iterator;
typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
T elems[1];
void fill(const T& t)
{
}
void swap(array< T, 0 >&)
{
}
iterator begin()
{
return elems;
}
const_iterator begin() const
{
return elems;
}
const_iterator cbegin() const
{
return elems;
}
iterator end()
{
return elems;
}
const_iterator end() const
{
return elems;
}
const_iterator cend() const
{
return elems;
}
reverse_iterator rbegin()
{
return reverse_iterator();
}
const_reverse_iterator rbegin() const
{
return reverse_iterator();
}
const_reverse_iterator crbegin() const
{
return reverse_iterator();
}
reverse_iterator rend()
{
return reverse_iterator();
}
const_reverse_iterator rend() const
{
return reverse_iterator();
}
const_reverse_iterator crend() const
{
return reverse_iterator();
}
size_type size() const
{
return 0;
}
size_type max_size() const
{
return 0;
}
bool empty() const
{
return true;
}
reference operator[](size_type n)
{
return elems[n];
}
const_reference operator[](size_type n) const
{
return elems[n];
}
reference at(size_type n)
{
throw std::out_of_range("");
return elems[n];
}
const_reference at(size_type n) const
{
throw std::out_of_range("");
return elems[n];
}
reference front()
{
return elems[0];
}
const_reference front() const
{
return elems[0];
}
reference back()
{
return elems[0];
}
const_reference back() const
{
return elems[0];
}
T* data()
{
return elems;
}
const T* data() const
{
return elems;
}
};
template< class T, std::size_t N >
void swap(
array< T, N >& a,
array< T, N >& b
)
{
a.swap(b);
}
template< class T, std::size_t N >
bool operator==(
const array< T, N >& a,
const array< T, N >& b
)
{
return std::equal( a.begin(), a.end(), b.begin() );
}
template< class T, std::size_t N >
bool operator!=(
const array< T, N >& a,
const array< T, N >& b
)
{
return !std::equal( a.begin(), a.end(), b.begin() );
}
template< class T, std::size_t N >
bool operator<(
const array< T, N >& a,
const array< T, N >& b
)
{
return std::lexicographical_compare( a.begin(), a.end(), b.begin(), b.end() );
}
template< class T, std::size_t N >
bool operator<=(
const array< T, N >& a,
const array< T, N >& b
)
{
return !std::lexicographical_compare( b.begin(), b.end(), a.begin(), a.end() );
}
template< class T, std::size_t N >
bool operator>(
const array< T, N >& a,
const array< T, N >& b
)
{
return std::lexicographical_compare( b.begin(), b.end(), a.begin(), a.end() );
}
template< class T, std::size_t N >
bool operator>=(
const array< T, N >& a,
const array< T, N >& b
)
{
return !std::lexicographical_compare( a.begin(), a.end(), b.begin(), b.end() );
}
}
#endif // ifdef CPP11
#endif // PBL_CPP_ARRAY_H

@ -0,0 +1,193 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** Just enough std::atomic to get by
*
* Only implementing integral types (for now).
*/
#ifndef PBL_CPP_ATOMIC_H
#define PBL_CPP_ATOMIC_H
#include "version.h"
#ifdef CPP11
#include <atomic>
#else
#include "config/arch.h"
#include "cstdint.h"
#include "traits/enable_if.h"
#include "traits/is_integral.h"
namespace cpp11
{
template< typename T, class Enable = void >
class atomic;
template< typename T >
class atomic< T, typename ::cpp::enable_if< ::cpp::is_integral< T >::value >::type >
{
public:
atomic()
{
}
atomic(T x)
: value(x)
{
}
T operator=(T x)
{
value = x;
return x;
}
operator T() const
{
return value;
}
T operator++()
{
return __sync_add_and_fetch(&value, 1);
}
T operator++(int)
{
return __sync_fetch_and_add(&value, 1);
}
T operator--()
{
return __sync_sub_and_fetch(&value, 1);
}
T operator--(int)
{
return __sync_fetch_and_sub(&value, 1);
}
T operator+=(T arg)
{
return __sync_add_and_fetch(&value, arg);
}
T operator-=(T arg)
{
return __sync_sub_and_fetch(&value, arg);
}
T operator&=(T arg)
{
return __sync_and_and_fetch(&value, arg);
}
T operator|=(T arg)
{
return __sync_or_and_fetch(&value, arg);
}
T operator^=(T arg)
{
return __sync_xor_and_fetch(&value, arg);
}
T fetch_add(T arg)
{
return __sync_fetch_and_add(&value, arg);
}
T fetch_sub(T arg)
{
return __sync_fetch_and_sub(&value, arg);
}
T fetch_and(T arg)
{
return __sync_fetch_and_and(&value, arg);
}
T fetch_or(T arg)
{
return __sync_fetch_and_or(&value, arg);
}
T fetch_xor(T arg)
{
return __sync_fetch_and_xor(&value, arg);
}
private:
atomic(const atomic&); // non-copyable
atomic& operator=(const atomic&); // non-copyable
T value;
};
typedef atomic< bool > atomic_bool;
typedef atomic< char > atomic_char;
typedef atomic< signed char > atomic_schar;
typedef atomic< unsigned char > atomic_uchar;
typedef atomic< short > atomic_short;
typedef atomic< unsigned short > atomic_ushort;
typedef atomic< int > atomic_int;
typedef atomic< unsigned int > atomic_uint;
typedef atomic< long > atomic_long;
typedef atomic< unsigned long > atomic_ulong;
#ifdef HAS_LONG_LONG
typedef atomic< long long > atomic_llong;
typedef atomic< unsigned long long > atomic_ullong;
#endif
typedef atomic< ::cpp::int_least8_t > atomic_int_least8_t;
typedef atomic< ::cpp::uint_least8_t > atomic_uint_least8_t;
typedef atomic< ::cpp::int_least16_t > atomic_int_least16_t;
typedef atomic< ::cpp::uint_least16_t > atomic_uint_least16_t;
typedef atomic< ::cpp::int_least32_t > atomic_int_least32_t;
typedef atomic< ::cpp::uint_least32_t > atomic_uint_least32_t;
typedef atomic< ::cpp::int_least64_t > atomic_int_least64_t;
typedef atomic< ::cpp::uint_least64_t > atomic_uint_least64_t;
typedef atomic< ::cpp::int_fast8_t > atomic_int_fast8_t;
typedef atomic< ::cpp::uint_fast8_t > atomic_uint_fast8_t;
typedef atomic< ::cpp::int_fast16_t > atomic_int_fast16_t;
typedef atomic< ::cpp::uint_fast16_t > atomic_uint_fast16_t;
typedef atomic< ::cpp::int_fast32_t > atomic_int_fast32_t;
typedef atomic< ::cpp::uint_fast32_t > atomic_uint_fast32_t;
typedef atomic< ::cpp::int_fast64_t > atomic_int_fast64_t;
typedef atomic< ::cpp::uint_fast64_t > atomic_uint_fast64_t;
typedef atomic< ::cpp::intptr_t > atomic_intptr_t;
typedef atomic< ::cpp::uintptr_t > atomic_uintptr_t;
typedef atomic< ::std::size_t > atomic_size_t;
typedef atomic< ::std::ptrdiff_t > atomic_ptrdiff_t;
typedef atomic< ::cpp::intmax_t > atomic_intmax_t;
typedef atomic< ::cpp::uintmax_t > atomic_uintmax_t;
}
#endif // ifndef CPP11
#endif // PBL_CPP_ATOMIC_H

@ -0,0 +1,86 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "chrono.h"
#ifndef CPP11
#include <ctime>
#include "cstdint.h"
namespace cpp11
{
namespace chrono
{
time_point< system_clock > system_clock::now()
{
timespec ts;
if ( ::clock_gettime(CLOCK_REALTIME, &ts) == 0 )
{
#if 0
seconds s(ts.tv_sec);
nanoseconds ns(ts.tv_nsec);
return time_point( duration(s + ms) );
#else
return time_point( duration( ts.tv_sec * 1000 + ( ts.tv_nsec / 1000000L ) ) );
#endif
}
return time_point();
}
std::time_t system_clock::to_time_t(const time_point& t)
{
return static_cast< std::time_t >( t.time_since_epoch().count() / 1000 );
}
time_point< system_clock > system_clock::from_time_t(std::time_t t)
{
return time_point( duration(t * 1000) );
}
time_point< steady_clock > steady_clock::now()
{
timespec ts;
if ( ::clock_gettime(CLOCK_MONOTONIC, &ts) == 0 )
{
return time_point( duration(ts.tv_sec * INT32_C(1000000000) + ts.tv_nsec) );
}
return time_point();
}
}
}
#endif // ifndef CPP11

@ -0,0 +1,468 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_CHRONO_H
#define PBL_CPP_CHRONO_H
#include "version.h"
#ifdef CPP11
#include <chrono>
#else
#include <ctime>
#include "numeric.h"
#include "ratio.h"
#include "traits/common_type.h"
namespace cpp11
{
namespace detail
{
template< typename Period1, typename Period2 >
struct duration_cast_helper
{
static const cpp::intmax_t d1 = cpp11::detail::gcd< Period1::num, Period2::num >::value;
static const cpp::intmax_t d2 = cpp11::detail::gcd< Period1::den, Period2::den >::value;
static const cpp::intmax_t p = ( Period1::num / d1 ) * ( Period2::den / d2 );
static const cpp::intmax_t q = ( Period2::num / d1 ) * ( Period1::den / d2 );
};
template< typename, typename >
struct period_common;
template< cpp::intmax_t N1, cpp::intmax_t D1, cpp::intmax_t N2, cpp::intmax_t D2 >
struct period_common< cpp::ratio< N1, D1 >, cpp::ratio< N2, D2 > >
{
static const cpp::intmax_t na = N1 / cpp11::detail::gcd< N1, N2 >::value;
static const cpp::intmax_t nb = N2 / cpp11::detail::gcd< N1, N2 >::value;
static const cpp::intmax_t da = D1 / cpp11::detail::gcd< D1, D2 >::value;
static const cpp::intmax_t db = D2 / cpp11::detail::gcd< D1, D2 >::value;
};
// larget intmax_t that can fit into T
template< typename T >
struct max_int
{
static const cpp::intmax_t value = (std::numeric_limits< T >::digits >= std::numeric_limits< cpp::intmax_t >::digits)
? INTMAX_MAX
: ((INTMAX_C(1) << std::numeric_limits< T >::digits) - 1);
};
template< typename Rep, cpp::intmax_t X, cpp::intmax_t Y >
struct can_fit
{
typedef max_int< Rep > max_type;
static const bool value = (max_type::value >= X && max_type::value >= Y);
};
}
namespace chrono
{
template< class Rep, class Period = cpp11::ratio< 1 > >
class duration
{
public:
typedef Rep rep;
typedef typename Period::type period;
duration()
: r(0)
{
}
template< typename Rep2 >
explicit duration(const Rep2& r_)
: r(r_)
{
}
template< typename Rep2, typename Period2 >
explicit duration(const duration< Rep2, Period2 >& d)
{
typedef detail::duration_cast_helper< Period, Period2 > Helper;
r = d.count() * Helper::q / Helper::p;
}
static duration zero()
{
return duration(0);
}
rep count() const
{
return r;
}
duration operator+() const
{
return duration(*this);
}
duration operator-() const
{
return duration(-r);
}
duration& operator++()
{
++r;
return *this;
}
duration operator++(int)
{
return duration(r++);
}
duration& operator--()
{
--r;
return *this;
}
duration operator--(int)
{
return duration(r--);
}
duration& operator+=(const duration& d)
{
r += d.r;
return *this;
}
duration& operator-=(const duration& d)
{
r -= d.r;
return *this;
}
duration& operator*=(const rep& rhs)
{
r *= rhs;
return *this;
}
duration& operator/=(const rep& rhs)
{
r /= rhs;
return *this;
}
duration& operator%=(const rep& rhs)
{
r %= rhs;
return *this;
}
duration& operator%=(const duration& rhs)
{
r %= rhs.r;
return *this;
}
private:
rep r;
};
}
// Specialization of common_type for durations
template< typename Rep1, typename Period1, typename Rep2, typename Period2 >
struct common_type< chrono::duration< Rep1, Period1 >, chrono::duration< Rep2, Period2 > >
{
typedef chrono::duration< typename common_type< Rep1, Rep2 >::type,
ratio< detail::gcd< Period1::num, Period2::num >::value, detail::lcm< Period1::den, Period2::den >::value > > type;
};
template< typename Rep, typename Period >
struct common_type< chrono::duration< Rep, Period >, chrono::duration< Rep, Period > >
{
typedef chrono::duration< Rep, Period > type;
};
namespace chrono
{
template< class Rep1, class Period1, class Rep2, class Period2 >
typename common_type< duration< Rep1, Period1 >, duration< Rep2, Period2 > >::type operator+(
const duration< Rep1, Period1 >& a,
const duration< Rep2, Period2 >& b
)
{
typedef typename common_type< duration< Rep1, Period1 >, duration< Rep2, Period2 > >::type Duration3;
return Duration3( Duration3(a).count() + Duration3(b).count() );
}
template< class Rep1, class Period1, class Rep2, class Period2 >
typename common_type< duration< Rep1, Period1 >, duration< Rep2, Period2 > >::type operator-(
const duration< Rep1, Period1 >& a,
const duration< Rep2, Period2 >& b
)
{
typedef typename common_type< duration< Rep1, Period1 >, duration< Rep2, Period2 > >::type Duration3;
return Duration3( Duration3(a).count() - Duration3(b).count() );
}
/** Compare durations
*
* Essentially tests test a.count() * Period1::num / Period1::den == b.count() * Period2::num / Period2::den
*
* Because of overflow concerns, we can't do the multiplication straight. So
* we'll use a variation to show that all factors of the right are the same as
* all the factors on the left.
*
* @note Assumes Period1 and Period2 are std::ratio-s
*/
template< class Rep1, class Period1, class Rep2, class Period2 >
bool operator==(
const duration< Rep1, Period1 >& a,
const duration< Rep2, Period2 >& b
)
{
// Helper type removes common factors between periods at compile time
typedef detail::period_common< Period1, Period2 > common;
// If one side is zero, the other must be, too
if (common::na == 0 && common::nb == 0)
return true;
const Rep1 ca = a.count();
const Rep2 cb = b.count();
if (ca == 0)
return cb == 0 || common::nb == 0;
if (cb == 0)
return common::na == 0;
// Full check, ca * na * db == cb * nb * da
if (detail::can_fit< Rep1, common::nb, common::da >::value && detail::can_fit< Rep2, common::na, common::db >::value)
{
const Rep1 nb = static_cast< Rep1 >(common::nb);
const Rep1 da = static_cast< Rep1 >(common::da);
const Rep2 na = static_cast< Rep2 >(common::na);
const Rep2 db = static_cast< Rep2 >(common::db);
if (ca >= nb && (ca / nb) >= da && cb >= na && (cb / na) >= db)
{
return (ca / nb) / da == (cb / na) / db;
}
}
return false;
}
template< class Rep1, class Period1, class Rep2, class Period2 >
bool operator!=(
const duration< Rep1, Period1 >& a,
const duration< Rep2, Period2 >& b
)
{
return !(a == b);
}
/// @bug Don't use the intermediate type
template< class Rep1, class Period1, class Rep2, class Period2 >
bool operator<(
const duration< Rep1, Period1 >& a,
const duration< Rep2, Period2 >& b
)
{
typedef typename common_type< duration< Rep1, Period1 >, duration< Rep2, Period2 > >::type Duration3;
return Duration3(a).count() < Duration3(b).count();
}
template< class Rep1, class Period1, class Rep2, class Period2 >
bool operator>(
const duration< Rep1, Period1 >& a,
const duration< Rep2, Period2 >& b
)
{
return b < a;
}
template< class Rep1, class Period1, class Rep2, class Period2 >
bool operator<=(
const duration< Rep1, Period1 >& a,
const duration< Rep2, Period2 >& b
)
{
return !( b < a );
}
template< class Rep1, class Period1, class Rep2, class Period2 >
bool operator>=(
const duration< Rep1, Period1 >& a,
const duration< Rep2, Period2 >& b
)
{
return !( a < b );
}
typedef duration< long long, cpp11::nano > nanoseconds;
typedef duration< long long, cpp11::micro > microseconds;
typedef duration< long long, cpp11::milli > milliseconds;
typedef duration< long long > seconds;
typedef duration< long, cpp11::ratio< 60 > > minutes;
typedef duration< long, cpp11::ratio< 3600 > > hours;
template< typename To, class Rep, class Period >
To duration_cast(const duration< Rep, Period >& d)
{
typedef detail::duration_cast_helper< typename To::period, Period > Helper;
return To(d.count() * Helper::q / Helper::p);
}
template< typename Clock, typename Duration = typename Clock::duration >
class time_point
{
public:
typedef Clock clock;
typedef Duration duration;
typedef typename Duration::rep rep;
typedef typename Duration::period period;
time_point()
: d()
{
}
explicit time_point(const duration& d_)
: d(d_)
{
}
duration time_since_epoch() const
{
return d;
}
friend duration operator-(
const time_point& t1,
const time_point& t2
)
{
return t1.d - t2.d;
}
private:
duration d;
};
template< class Clock, class Dur1, class Dur2 >
bool operator==(
const time_point< Clock, Dur1 >& l,
const time_point< Clock, Dur2 >& r
)
{
return l.time_since_epoch() == r.time_since_epoch();
}
template< class Clock, class Dur1, class Dur2 >
bool operator!=(
const time_point< Clock, Dur1 >& l,
const time_point< Clock, Dur2 >& r
)
{
return l.time_since_epoch() != r.time_since_epoch();
}
template< class Clock, class Dur1, class Dur2 >
bool operator<(
const time_point< Clock, Dur1 >& l,
const time_point< Clock, Dur2 >& r
)
{
return l.time_since_epoch() < r.time_since_epoch();
}
template< class Clock, class Dur1, class Dur2 >
bool operator<=(
const time_point< Clock, Dur1 >& l,
const time_point< Clock, Dur2 >& r
)
{
return l.time_since_epoch() <= r.time_since_epoch();
}
template< class Clock, class Dur1, class Dur2 >
bool operator>(
const time_point< Clock, Dur1 >& l,
const time_point< Clock, Dur2 >& r
)
{
return l.time_since_epoch() > r.time_since_epoch();
}
template< class Clock, class Dur1, class Dur2 >
bool operator>=(
const time_point< Clock, Dur1 >& l,
const time_point< Clock, Dur2 >& r
)
{
return l.time_since_epoch() >= r.time_since_epoch();
}
// wall time, millisecond resolution
class system_clock
{
public:
typedef milliseconds duration;
typedef duration::rep rep;
typedef duration::period period;
typedef cpp11::chrono::time_point< system_clock > time_point;
static time_point now();
static std::time_t to_time_t(const time_point&);
static time_point from_time_t(std::time_t);
private:
};
// monotonic, nanosecond resolution
class steady_clock
{
public:
typedef nanoseconds duration;
typedef duration::rep rep;
typedef duration::period period;
typedef cpp::chrono::time_point< steady_clock > time_point;
static time_point now();
};
typedef steady_clock high_resolution_clock;
}
}
#endif // ifndef CPP11
#endif // PBL_CPP_CHRONO_H

@ -0,0 +1,95 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "cmath.h"
#ifdef PBL_CPP_CMATH_LGAMMA
namespace cpp11
{
namespace detail
{
/* Fallback implementation for lgamma, if it isn't available from environment
*
* See "Numerical Recipes 3e", Press et al., p 257
*/
long double lgamma_implementation(long double z)
{
static const long double cof[14] =
{
57.1562356658629235l,
-59.5979603554754912l,
14.1360979747417471l,
-0.491913816097620199l,
0.339946499848118887e-4l,
0.465236289270485756e-4l,
-0.983744753048795646e-4l,
0.158088703224912494e-3l,
-0.210264441724104883e-3l,
0.217439618115212643e-3l,
-0.164318106536763890e-3l,
0.844182239838527433e-4l,
-0.261908384015814087e-4l,
0.368991826595316234e-5l
};
long double x = z;
long double y = z;
long double tmp = x + ( 671.0L / 128 );
tmp = ( x + 0.5 ) * std::log(tmp) - tmp;
long double ser = 0.999999999999997092L;
for ( std::size_t j = 0; j < 14; ++j )
{
y += 1;
ser += cof[j] / y;
}
return tmp + std::log(2.5066282746310005L * ser / x);
}
}
}
#endif // ifdef PBL_CPP_CMATH_LGAMMA
#ifdef PBL_CPP_CMATH_BETA
namespace cpp17
{
namespace detail
{
long double beta_implementation(
long double z,
long double w
)
{
return std::exp( cpp::lgamma(z) + cpp::lgamma(w) - cpp::lgamma(z + w) );
}
}
}
#endif

@ -0,0 +1,980 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** Implementation of C++11 cmath header
*
* Pretty much borrows everything from C99/POSIX.
*
* @todo Use the appropriate feature test macros for each function
*/
#ifndef PBL_CPP_CMATH_H
#define PBL_CPP_CMATH_H
#include <cmath>
#include "version.h"
#ifndef CPP11
#include "config/os.h"
#endif
#ifndef CPP17
#include "type_traits.h"
namespace cpp11
{
namespace detail
{
// Used to promote arithmetic arguments to double or long double
template< typename Arithmetic1, typename Arithmetic2 = void, typename Arithmetic3 = void, bool has_long_double = ( cpp::is_same< long double, Arithmetic1 >::value || cpp::is_same< long double, Arithmetic2 >::value || cpp::is_same< long double, Arithmetic3 >::value ) >
struct promoted
{
typedef double type;
};
template< typename Arithmetic1, typename Arithmetic2, typename Arithmetic3 >
struct promoted< Arithmetic1, Arithmetic2, Arithmetic3, true >
{
typedef long double type;
};
}
}
#endif // ifndef CPP17
#ifndef CPP11
namespace cpp11
{
#ifdef POSIX_ISSUE_6
inline float remainder(
float x,
float y
)
{
return ::remainderf(x, y);
}
inline double remainder(
double x,
double y
)
{
return ::remainder(x, y);
}
inline long double remainder(
long double x,
long double y
)
{
return ::remainderl(x, y);
}
template< typename Arithmetic1, typename Arithmetic2 >
typename detail::promoted< Arithmetic1, Arithmetic2 >::type remainder(
Arithmetic1 x,
Arithmetic2 y
)
{
typedef typename detail::promoted< Arithmetic1, Arithmetic2 >::type real;
return ::cpp11::remainder( static_cast< real >( x ), static_cast< real >( y ) );
}
inline float remquo(
float x,
float y,
int* quo
)
{
return ::remquof(x, y, quo);
}
inline double remquo(
double x,
double y,
int* quo
)
{
return ::remquo(x, y, quo);
}
inline long double remquo(
long double x,
long double y,
int* quo
)
{
return ::remquol(x, y, quo);
}
template< typename Arithmetic1, typename Arithmetic2 >
typename detail::promoted< Arithmetic1, Arithmetic2 >::type remquo(
Arithmetic1 x,
Arithmetic2 y,
int* quo
)
{
typedef typename detail::promoted< Arithmetic1, Arithmetic2 >::type real;
return ::cpp11::remquo(static_cast< real >( x ), static_cast< real >( y ), quo);
}
inline float fma(
float x,
float y,
float z
)
{
return ::fmaf(x, y, z);
}
inline double fma(
double x,
double y,
double z
)
{
return ::fma(x, y, z);
}
inline long double fma(
long double x,
long double y,
long double z
)
{
return ::fmal(x, y, z);
}
template< typename Arithmetic1, typename Arithmetic2, typename Arithmetic3 >
typename detail::promoted< Arithmetic1, Arithmetic2, Arithmetic3 >::type fma(
Arithmetic1 x,
Arithmetic2 y,
Arithmetic3 z
)
{
typedef typename detail::promoted< Arithmetic1, Arithmetic2, Arithmetic3 >::type real;
return ::cpp11::fma( static_cast< real >( x ), static_cast< real >( y ), static_cast< real >( z ) );
}
inline float fmax(
float x,
float y
)
{
return ::fmaxf(x, y);
}
inline double fmax(
double x,
double y
)
{
return ::fmax(x, y);
}
inline long double fmax(
long double x,
long double y
)
{
return ::fmaxl(x, y);
}
template< typename Arithmetic1, typename Arithmetic2 >
typename detail::promoted< Arithmetic1, Arithmetic2 >::type fmax(
Arithmetic1 x,
Arithmetic2 y
)
{
typedef typename detail::promoted< Arithmetic1, Arithmetic2 >::type real;
return ::cpp11::fmax( static_cast< real >( x ), static_cast< real >( y ) );
}
inline float fmin(
float x,
float y
)
{
return ::fminf(x, y);
}
inline double fmin(
double x,
double y
)
{
return ::fmin(x, y);
}
inline long double fmin(
long double x,
long double y
)
{
return ::fminl(x, y);
}
template< typename Arithmetic1, typename Arithmetic2 >
typename detail::promoted< Arithmetic1, Arithmetic2 >::type fmin(
Arithmetic1 x,
Arithmetic2 y
)
{
typedef typename detail::promoted< Arithmetic1, Arithmetic2 >::type real;
return ::cpp11::fmin( static_cast< real >( x ), static_cast< real >( y ) );
}
inline float fdim(
float x,
float y
)
{
return ::fdimf(x, y);
}
inline double fdim(
double x,
double y
)
{
return ::fdim(x, y);
}
inline long double fdim(
long double x,
long double y
)
{
return ::fdiml(x, y);
}
template< typename Arithmetic1, typename Arithmetic2 >
typename detail::promoted< Arithmetic1, Arithmetic2 >::type fdim(
Arithmetic1 x,
Arithmetic2 y
)
{
typedef typename detail::promoted< Arithmetic1, Arithmetic2 >::type real;
return ::cpp11::fdim( static_cast< real >( x ), static_cast< real >( y ) );
}
inline float exp2(float n)
{
return ::exp2f(n);
}
inline double exp2(double n)
{
return ::exp2(n);
}
inline long double exp2(long double n)
{
return ::exp2l(n);
}
template< typename Arithmetic1 >
typename detail::promoted< Arithmetic1 >::type exp2(Arithmetic1 x)
{
typedef typename detail::promoted< Arithmetic1 >::type real;
return ::cpp11::exp2( static_cast< real >( x ) );
}
inline float expm1(float n)
{
return ::expm1f(n);
}
inline double expm1(double n)
{
return ::expm1(n);
}
inline long double expm1(long double n)
{
return ::expm1l(n);
}
template< typename Arithmetic1 >
typename detail::promoted< Arithmetic1 >::type expm1(Arithmetic1 x)
{
typedef typename detail::promoted< Arithmetic1 >::type real;
return ::cpp11::expm1( static_cast< real >( x ) );
}
inline float log2(float n)
{
return ::log2f(n);
}
inline double log2(double n)
{
return ::log2(n);
}
inline long double log2(long double n)
{
return ::log2l(n);
}
template< typename Arithmetic1 >
typename detail::promoted< Arithmetic1 >::type log2(Arithmetic1 x)
{
typedef typename detail::promoted< Arithmetic1 >::type real;
return ::cpp11::log2( static_cast< real >( x ) );
}
inline float log1p(float n)
{
return ::log1pf(n);
}
inline double log1p(double n)
{
return ::log1p(n);
}
inline long double log1p(long double n)
{
return ::log1pl(n);
}
template< typename Arithmetic1 >
typename detail::promoted< Arithmetic1 >::type log1p(Arithmetic1 x)
{
typedef typename detail::promoted< Arithmetic1 >::type real;
return ::cpp11::log1p( static_cast< real >( x ) );
}
inline float cbrt(float n)
{
return ::cbrtf(n);
}
inline double cbrt(double n)
{
return ::cbrt(n);
}
inline long double cbrt(long double n)
{
return ::cbrtl(n);
}
template< typename Arithmetic1 >
typename detail::promoted< Arithmetic1 >::type cbrt(Arithmetic1 x)
{
typedef typename detail::promoted< Arithmetic1 >::type real;
return ::cpp11::cbrt( static_cast< real >( x ) );
}
inline float hypot(
float x,
float y
)
{
return ::hypotf(x, y);
}
inline double hypot(
double x,
double y
)
{
return ::hypot(x, y);
}
inline long double hypot(
long double x,
long double y
)
{
return ::hypotl(x, y);
}
template< typename Arithmetic1, typename Arithmetic2 >
typename detail::promoted< Arithmetic1, Arithmetic2 >::type hypot(
Arithmetic1 x,
Arithmetic2 y
)
{
typedef typename detail::promoted< Arithmetic1, Arithmetic2 >::type real;
return ::cpp11::hypot( static_cast< real >( x ), static_cast< real >( y ) );
}
inline float asinh(float n)
{
return ::asinhf(n);
}
inline double asinh(double n)
{
return ::asinh(n);
}
inline long double asinh(long double n)
{
return ::asinhl(n);
}
template< typename Arithmetic1 >
typename detail::promoted< Arithmetic1 >::type asinh(Arithmetic1 x)
{
typedef typename detail::promoted< Arithmetic1 >::type real;
return ::cpp11::asinh( static_cast< real >( x ) );
}
inline float acosh(float n)
{
return ::acoshf(n);
}
inline double acosh(double n)
{
return ::acosh(n);
}
inline long double acosh(long double n)
{
return ::acoshl(n);
}
template< typename Arithmetic1 >
typename detail::promoted< Arithmetic1 >::type acosh(Arithmetic1 x)
{
typedef typename detail::promoted< Arithmetic1 >::type real;
return ::cpp11::acosh( static_cast< real >( x ) );
}
inline float atanh(float n)
{
return ::atanhf(n);
}
inline double atanh(double n)
{
return ::atanh(n);
}
inline long double atanh(long double n)
{
return ::atanhl(n);
}
template< typename Arithmetic1 >
typename detail::promoted< Arithmetic1 >::type atanh(Arithmetic1 x)
{
typedef typename detail::promoted< Arithmetic1 >::type real;
return ::cpp11::atanh( static_cast< real >( x ) );
}
inline float erf(float n)
{
return ::erff(n);
}
inline double erf(double n)
{
return ::erf(n);
}
inline long double erf(long double n)
{
return ::erfl(n);
}
template< typename Arithmetic1 >
typename detail::promoted< Arithmetic1 >::type erf(Arithmetic1 x)
{
typedef typename detail::promoted< Arithmetic1 >::type real;
return ::cpp11::erf( static_cast< real >( x ) );
}
inline float erfc(float n)
{
return ::erfcf(n);
}
inline double erfc(double n)
{
return ::erfc(n);
}
inline long double erfc(long double n)
{
return ::erfcl(n);
}
template< typename Arithmetic1 >
typename detail::promoted< Arithmetic1 >::type erfc(Arithmetic1 x)
{
typedef typename detail::promoted< Arithmetic1 >::type real;
return ::cpp11::erfc( static_cast< real >( x ) );
}
inline float tgamma(float n)
{
return ::tgammaf(n);
}
inline double tgamma(double n)
{
return ::tgamma(n);
}
inline long double tgamma(long double n)
{
return ::tgammal(n);
}
template< typename Arithmetic1 >
typename detail::promoted< Arithmetic1 >::type tgamma(Arithmetic1 x)
{
typedef typename detail::promoted< Arithmetic1 >::type real;
return ::cpp11::tgamma( static_cast< real >( x ) );
}
// We can reuse a lot of the functions defined by POSIX
inline float round(float arg)
{
return ::roundf(arg);
}
inline double round(double arg)
{
return ::round(arg);
}
inline long double round(long double arg)
{
return ::roundl(arg);
}
template< typename Arithmetic1 >
typename detail::promoted< Arithmetic1 >::type round(Arithmetic1 x)
{
typedef typename detail::promoted< Arithmetic1 >::type real;
return ::cpp11::round( static_cast< real >( x ) );
}
inline long lround(float arg)
{
return ::lroundf(arg);
}
inline long lround(double arg)
{
return ::lround(arg);
}
inline long lround(long double arg)
{
return ::lroundl(arg);
}
template< typename Arithmetic1 >
typename detail::promoted< Arithmetic1 >::type lround(Arithmetic1 x)
{
typedef typename detail::promoted< Arithmetic1 >::type real;
return ::cpp11::lround( static_cast< real >( x ) );
}
inline float trunc(float arg)
{
return ::truncf(arg);
}
inline double trunc(double arg)
{
return ::trunc(arg);
}
inline long double trunc(long double arg)
{
return ::truncl(arg);
}
template< typename Arithmetic1 >
typename detail::promoted< Arithmetic1 >::type trunc(Arithmetic1 x)
{
typedef typename detail::promoted< Arithmetic1 >::type real;
return ::cpp11::trunc( static_cast< real >( x ) );
}
inline float rint(float arg)
{
return ::rintf(arg);
}
inline double rint(double arg)
{
return ::rint(arg);
}
inline long double rint(long double arg)
{
return ::rintl(arg);
}
template< typename Arithmetic1 >
typename detail::promoted< Arithmetic1 >::type rint(Arithmetic1 x)
{
typedef typename detail::promoted< Arithmetic1 >::type real;
return ::cpp11::rint( static_cast< real >( x ) );
}
inline long lrint(float arg)
{
return ::lrintf(arg);
}
inline long lrint(double arg)
{
return ::lrint(arg);
}
inline long lrint(long double arg)
{
return ::lrintl(arg);
}
template< typename Arithmetic1 >
typename detail::promoted< Arithmetic1 >::type lrint(Arithmetic1 x)
{
typedef typename detail::promoted< Arithmetic1 >::type real;
return ::cpp11::lrint( static_cast< real >( x ) );
}
inline float scalbn(
float x,
int exp
)
{
return ::scalbnf(x, exp);
}
inline double scalbn(
double x,
int exp
)
{
return ::scalbn(x, exp);
}
inline long double scalbn(
long double x,
int exp
)
{
return ::scalbnl(x, exp);
}
inline float scalbln(
float x,
long exp
)
{
return ::scalblnf(x, exp);
}
inline double scalbln(
double x,
long exp
)
{
return ::scalbln(x, exp);
}
inline long double scalbln(
long double x,
long exp
)
{
return ::scalblnl(x, exp);
}
inline int ilogb(float arg)
{
return ::ilogbf(arg);
}
inline int ilogb(double arg)
{
return ::ilogb(arg);
}
inline int ilogb(long double arg)
{
return ::ilogbl(arg);
}
template< typename Arithmetic1 >
typename detail::promoted< Arithmetic1 >::type ilogb(Arithmetic1 x)
{
typedef typename detail::promoted< Arithmetic1 >::type real;
return ::cpp11::ilogb( static_cast< real >( x ) );
}
inline float logb(float arg)
{
return ::logbf(arg);
}
inline double logb(double arg)
{
return ::logb(arg);
}
inline long double logb(long double arg)
{
return ::logbl(arg);
}
template< typename Arithmetic1 >
typename detail::promoted< Arithmetic1 >::type logb(Arithmetic1 x)
{
typedef typename detail::promoted< Arithmetic1 >::type real;
return ::cpp11::logb( static_cast< real >( x ) );
}
inline float nextafter(
float x,
float y
)
{
return ::nextafterf(x, y);
}
inline double nextafter(
double x,
double y
)
{
return ::nextafter(x, y);
}
inline long double nextafter(
long double x,
long double y
)
{
return ::nextafterl(x, y);
}
template< typename Arithmetic >
typename detail::promoted< Arithmetic >::type nextafter(
Arithmetic x,
Arithmetic y
)
{
typedef typename detail::promoted< Arithmetic >::type real;
return ::cpp11::nextafter( static_cast< real >( x ), static_cast< real >( y ) );
}
inline float nexttoward(
float x,
float y
)
{
return ::nexttowardf(x, y);
}
inline double nexttoward(
double x,
double y
)
{
return ::nexttoward(x, y);
}
inline long double nexttoward(
long double x,
long double y
)
{
return ::nexttowardl(x, y);
}
inline float copysign(
float x,
float y
)
{
return ::copysignf(x, y);
}
inline double copysign(
double x,
double y
)
{
return ::copysign(x, y);
}
inline long double copysign(
long double x,
long double y
)
{
return ::copysignl(x, y);
}
template< typename Arithmetic1, typename Arithmetic2 >
typename detail::promoted< Arithmetic1, Arithmetic2 >::type copysign(
Arithmetic1 x,
Arithmetic2 y
)
{
typedef typename detail::promoted< Arithmetic1, Arithmetic2 >::type real;
return ::cpp11::copysign( static_cast< real >( x ), static_cast< real >( y ) );
}
#endif // ifdef POSIX_ISSUE_6
#if ( defined( _BSD_SOURCE ) || defined( _SVID_SOURCE ) \
|| defined( _XOPEN_SOURCE ) || defined( _ISOC99_SOURCE ) || \
( defined( _POSIX_C_SOURCE ) || _POSIX_C_SOURCE >= 200112L ) )
inline float lgamma(float n)
{
return ::lgammaf(n);
}
inline double lgamma(double n)
{
return ::lgamma(n);
}
inline long double lgamma(long double n)
{
return ::lgammal(n);
}
#else
#define PBL_CPP_CMATH_LGAMMA
namespace detail
{
long double lgamma_implementation(long double);
}
inline float lgamma(float z)
{
return static_cast< float >( detail::lgamma_implementation(z) );
}
inline double lgamma(double z)
{
return static_cast< double >( detail::lgamma_implementation(z) );
}
inline long double lgamma(long double z)
{
return detail::lgamma_implementation(z);
}
#endif // if ( defined( _BSD_SOURCE ) || defined( _SVID_SOURCE ) || defined( _XOPEN_SOURCE ) || defined( _ISOC99_SOURCE ) || ( defined( _POSIX_C_SOURCE ) || _POSIX_C_SOURCE >= 200112L ) )
template< typename Arithmetic1 >
double lgamma(Arithmetic1 x)
{
return ::cpp11::lgamma( static_cast< double >( x ) );
}
}
#endif // ifndef CPP11
#ifndef CPP17
#define PBL_CPP_CMATH_BETA
namespace cpp17
{
namespace detail
{
long double beta_implementation(long double, long double);
}
inline double beta(
double x,
double y
)
{
return static_cast< double >( detail::beta_implementation(x, y) );
}
inline float betaf(
float x,
float y
)
{
return static_cast< float >( detail::beta_implementation(x, y) );
}
inline long double betal(
long double x,
long double y
)
{
return detail::beta_implementation(x, y);
}
template< typename Arithmetic1, typename Arithmetic2 >
typename ::cpp11::detail::promoted< Arithmetic1, Arithmetic2 >::type beta(
Arithmetic1 x,
Arithmetic2 y
)
{
typedef typename ::cpp11::detail::promoted< Arithmetic1, Arithmetic2 >::type real;
return static_cast< real >( detail::beta_implementation( static_cast< real >( x ), static_cast< real >( y ) ) );
}
}
#endif // ifndef CPP17
#endif // PBL_CPP_CMATH_H

@ -0,0 +1,89 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "condition_variable.h"
#ifndef CPP11
namespace cpp11
{
condition_variable::condition_variable()
{
pthread_cond_init(&cond, 0);
}
condition_variable::~condition_variable()
{
pthread_cond_destroy(&cond);
}
void condition_variable::notify_one()
{
pthread_cond_signal(&cond);
}
void condition_variable::notify_all()
{
pthread_cond_broadcast(&cond);
}
void condition_variable::wait(unique_lock< mutex >& lock)
{
pthread_cond_wait( &cond, lock.mutex()->native_handle() );
}
condition_variable::native_handle_type condition_variable::native_handle()
{
return &cond;
}
cv_status::cv_status condition_variable::wait_until(
unique_lock< mutex >& lock,
const chrono::system_clock::time_point& tp
)
{
timespec ts;
chrono::nanoseconds d = chrono::duration_cast< chrono::nanoseconds >( tp.time_since_epoch() );
chrono::nanoseconds::rep r = d.count();
long scale = 1000000000L;
ts.tv_sec = r / scale;
ts.tv_nsec = r % scale;
if ( pthread_cond_timedwait(&cond, lock.mutex()->native_handle(), &ts) == 0 )
{
return cv_status::no_timeout;
}
return cv_status::timeout;
}
}
#endif // ifndef CPP11

@ -0,0 +1,84 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_CONDITION_VARIABLE_H
#define PBL_CPP_CONDITION_VARIABLE_H
#include "version.h"
#ifdef CPP11
#include <condition_variable>
#else
#include "chrono.h"
#include "config/os.h"
#include "mutex.h"
namespace cpp11
{
namespace cv_status
{
enum cv_status {no_timeout, timeout};
}
class condition_variable
{
public:
typedef ::pbl::os::condition_variable_type* native_handle_type;
condition_variable();
~condition_variable();
void notify_one();
void notify_all();
void wait(unique_lock< mutex >&);
native_handle_type native_handle();
template< class Duration >
cv_status::cv_status wait_for(
unique_lock< mutex >& l,
const Duration& dt
)
{
chrono::system_clock::time_point t = chrono::system_clock::now();
t += chrono::duration_cast< chrono::system_clock::duration >(dt);
return wait_until(l, t);
}
cv_status::cv_status wait_until(unique_lock< mutex >&, const chrono::system_clock::time_point&);
private:
condition_variable(const condition_variable&);
condition_variable& operator=(const condition_variable&);
::pbl::os::condition_variable_type cond;
};
}
#endif // ifdef CPP11
#endif // PBL_CPP_CONDITION_VARIABLE_H

@ -0,0 +1,50 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_CSTDARG_H
#define PBL_CPP_CSTDARG_H
#include <cstdarg>
#include "version.h"
#ifndef CPP11
#ifndef va_copy
#ifdef __va_copy
/** @brief Workaround for va_copy macro
*
* va_copy was not standardized until C++11, but is usually available
* as the non-standard __va_copy. In this case, a define is appropriate
* because va_copy is *supposed* to be a macro
*/
#define va_copy(dest, src) __va_copy(dest, src)
#endif
#endif
#endif
#endif // PBL_CPP_CSTDARG_H

@ -0,0 +1,53 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_CSTDDEF_H
#define PBL_CPP_CSTDDEF_H
#include <cstddef>
#include "version.h"
#ifndef CPP11
namespace cpp11
{
#if defined(__GNUG__)
struct max_align_t
{
long double x;
} __attribute__((aligned));
#elif defined(_MSC_VER)
/// @todo Using 16-bytes rather arbitrarily. Can't find any MSVC documentation that gives the appropriate value "automatically".
struct __declspec(align(16)) max_align_t
{
long double x;
};
#endif
}
#endif
#endif // PBL_CPP_CSTDDEF_H

@ -0,0 +1,463 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @file cstdint.h
* @brief Implementation of C++11 cstdint header
*/
#ifndef PBL_CPP_CSTDINT_H
#define PBL_CPP_CSTDINT_H
#include "version.h"
#ifdef CPP11
// Provided by C++11
#include <cstdint>
#else
#include <climits>
// Steal some types from the implementation, if we can
#if !defined( _WIN32 ) && ( defined( __unix__ ) || defined( __unix ) || ( defined( __APPLE__ ) && defined( __MACH__ )))
#include <unistd.h>
#if ( _POSIX_C_SOURCE >= 200112L )
// Provided by POSIX
#include <stdint.h>
namespace cpp11
{
using ::intptr_t;
using ::uintptr_t;
}
#endif // POSIX
#endif // UNIX-LIKE
namespace cpp11
{
#define AT_LEAST_16_BITS_S(x) ((x) >= 32767)
#define AT_LEAST_32_BITS_S(x) ((x) >= 2147483647)
#define AT_LEAST_64_BITS_S(x) ((((((x) >> 15) >> 15) >> 15) >> 15) >= 7)
#define AT_LEAST_16_BITS_U(x) ((x) >= 65535)
#define AT_LEAST_32_BITS_U(x) (((x) >> 1) >= 2147483647)
#define AT_LEAST_64_BITS_U(x) ((((((x) >> 15) >> 15) >> 15) >> 15) >= 15)
#define EXACTLY_8_BITS_S(x) ((x) == 127)
#define EXACTLY_16_BITS_S(x) ((x) == 32767)
#define EXACTLY_32_BITS_S(x) ((x) == 2147483647)
#define EXACTLY_64_BITS_S(x) ((((((x) >> 15) >> 15) >> 15) >> 15) == 7)
#define EXACTLY_8_BITS_U(x) ((x) == 255)
#define EXACTLY_16_BITS_U(x) ((x) == 65535)
#define EXACTLY_32_BITS_U(x) (((x) >> 1) == 2147483647)
#define EXACTLY_64_BITS_U(x) ((((((x) >> 15) >> 15) >> 15) >> 15) == 15)
// int_least8_t
typedef signed char int_least8_t;
#ifndef INT8_C
#define INT8_C(x) x
#endif
#ifndef INT_LEAST8_MIN
#define INT_LEAST8_MIN SCHAR_MIN
#endif
#ifndef INT_LEAST8_MAX
#define INT_LEAST8_MAX SCHAR_MAX
#endif
// int8_t
#if EXACTLY_8_BITS_S(INT_LEAST8_MAX)
#ifndef INT8_MIN
#define INT8_MIN INT_LEAST8_MIN
#endif
#ifndef INT8_MAX
#define INT8_MAX INT_LEAST8_MAX
#endif
typedef int_least8_t int8_t;
#endif
// int_least16_t
#if AT_LEAST_16_BITS_S(SCHAR_MAX)
typedef signed char int_least16_t;
#ifndef INT_LEAST16_MIN
#define INT_LEAST16_MIN SCHAR_MIN
#endif
#ifndef INT_LEAST16_MAX
#define INT_LEAST16_MAX SCHAR_MAX
#endif
#else
typedef short int int_least16_t;
#ifndef INT_LEAST16_MIN
#define INT_LEAST16_MIN SHRT_MIN
#endif
#ifndef INT_LEAST16_MAX
#define INT_LEAST16_MAX SHRT_MAX
#endif
#endif
#ifndef INT16_C
#define INT16_C(x) x
#endif
// int16_t
#if EXACTLY_16_BITS_S(INT_LEAST8_MAX)
#ifndef INT16_MIN
#define INT16_MIN INT_LEAST16_MIN
#endif
#ifndef INT16_MAX
#define INT16_MAX INT_LEAST16_MAX
#endif
typedef int_least16_t int16_t;
#endif
// int_least32_t
#if AT_LEAST_32_BITS_S(SCHAR_MAX)
typedef signed char int_least32_t
#ifndef INT_LEAST32_MIN
#define INT_LEAST32_MIN SCHAR_MIN
#endif
#ifndef INT_LEAST32_MAX
#define INT_LEAST32_MAX SCHAR_MAX
#endif
#ifndef INT32_C
#define INT32_C(x) x
#endif
#elif AT_LEAST_32_BITS_S(SHRT_MAX)
typedef short int int_least32_t
#ifndef INT_LEAST32_MIN
#define INT_LEAST32_MIN SHRT_MIN
#endif
#ifndef INT_LEAST32_MAX
#define INT_LEAST32_MAX SHRT_MAX
#endif
#ifndef INT32_C
#define INT32_C(x) x
#endif
#elif AT_LEAST_32_BITS_S(INT_MAX)
typedef int int_least32_t;
#ifndef INT_LEAST32_MIN
#define INT_LEAST32_MIN INT_MIN
#endif
#ifndef INT_LEAST32_MAX
#define INT_LEAST32_MAX INT_MAX
#endif
#ifndef INT32_C
#define INT32_C(x) x
#endif
#else
typedef long int_least32_t;
#ifndef INT_LEAST32_MIN
#define INT_LEAST32_MIN LONG_MIN
#endif
#ifndef INT_LEAST32_MAX
#define INT_LEAST32_MAX LONG_MAX
#endif
#ifndef INT32_C
#define INT32_C(x) x##l
#endif
#endif // if AT_LEAST_32_BITS_S(SCHAR_MAX)
// int32_t
#if EXACTLY_32_BITS_S(INT_LEAST32_MAX)
#ifndef INT32_MIN
#define INT32_MIN INT_LEAST32_MIN
#endif
#ifndef INT32_MAX
#define INT32_MAX INT_LEAST32_MAX
#endif
typedef int_least32_t int32_t;
#endif
// int_least64_t
#if AT_LEAST_64_BITS_S(SCHAR_MAX)
typedef signed char int_least64_t
#ifndef INT_LEAST64_MIN
#define INT_LEAST64_MIN SCHAR_MIN
#endif
#ifndef INT_LEAST64_MAX
#define INT_LEAST64_MAX SCHAR_MAX
#endif
#ifndef INT64_C
#define INT64_C(x) x
#endif
#elif AT_LEAST_64_BITS_S(SHRT_MAX)
typedef short int_least64_t
#ifndef INT_LEAST64_MIN
#define INT_LEAST64_MIN SHRT_MIN
#endif
#ifndef INT_LEAST64_MAX
#define INT_LEAST64_MAX SHRT_MAX
#endif
#ifndef INT64_C
#define INT64_C(x) x
#endif
#elif AT_LEAST_64_BITS_S(INT_MAX)
typedef int int_least64_t;
#ifndef INT_LEAST64_MIN
#define INT_LEAST64_MIN INT_MIN
#endif
#ifndef INT_LEAST64_MAX
#define INT_LEAST64_MAX INT_MAX
#endif
#ifndef INT64_C
#define INT64_C(x) x
#endif
#elif AT_LEAST_64_BITS_S(LONG_MAX)
typedef long int_least64_t;
#ifndef INT_LEAST64_MIN
#define INT_LEAST64_MIN LONG_MIN
#endif
#ifndef INT_LEAST64_MAX
#define INT_LEAST64_MAX LONG_MAX
#endif
#ifndef INT64_C
#define INT64_C(x) x##l
#endif
#else
#ifdef LLONG_MAX
typedef long long int_least64_t;
#ifndef INT_LEAST64_MIN
#define INT_LEAST64_MIN LLONG_MIN
#endif
#ifndef INT_LEAST64_MAX
#define INT_LEAST64_MAX LLONG_MAX
#endif
#ifndef INT64_C
#define INT64_C(x) x##ll
#endif
#endif
#endif // if AT_LEAST_64_BITS_S(SCHAR_MAX)
// int64_t
#if EXACTLY_64_BITS_S(INT_LEAST64_MAX)
#ifndef INT64_MIN
#define INT64_MIN INT_LEAST64_MIN
#endif
#ifndef INT64_MAX
#define INT64_MAX INT_LEAST64_MAX
#endif
typedef int_least64_t int64_t;
#endif
// uint_least8_t
typedef unsigned char uint_least8_t;
#ifndef UINT8_C
#define UINT8_C(x) x
#endif
#ifndef UINT_LEAST8_MAX
#define UINT_LEAST8_MAX UCHAR_MAX
#endif
// uint8_t
#if EXACTLY_8_BITS_U(UINT_LEAST8_MAX)
#ifndef UINT8_MAX
#define UINT8_MAX UINT_LEAST8_MAX
#endif
typedef uint_least8_t uint8_t;
#endif
// uint_least16_t
#if AT_LEAST_16_BITS_U(UCHAR_MAX)
typedef unsigned char uint_least16_t;
#ifndef UINT_LEAST16_MAX
#define UINT_LEAST16_MAX UCHAR_MAX
#endif
#else
typedef unsigned short uint_least16_t;
#ifndef UINT_LEAST16_MAX
#define UINT_LEAST16_MAX USHRT_MAX
#endif
#endif
#ifndef UINT16_C
#define UINT16_C(x) x
#endif
// uint16_t
#if EXACTLY_16_BITS_U(UINT_LEAST16_MAX)
#ifndef UINT16_MAX
#define UINT16_MAX UINT_LEAST16_MAX
#endif
typedef uint_least16_t uint16_t;
#endif
// uint_least32_t
#if AT_LEAST_32_BITS_U(UCHAR_MAX)
typedef unsigned char uint_least32_t
#ifndef UINT_LEAST32_MAX
#define UINT_LEAST32_MAX UCHAR_MAX
#endif
#ifndef UINT32_C
#define UINT32_C(x) x
#endif
#elif AT_LEAST_32_BITS_U(USHRT_MAX)
typedef unsigned short uint_least32_t
#ifndef UINT_LEAST32_MAX
#define UINT_LEAST32_MAX USHRT_MAX
#endif
#ifndef UINT32_C
#define UINT32_C(x) x
#endif
#elif AT_LEAST_32_BITS_U(UINT_MAX)
typedef unsigned uint_least32_t;
#ifndef UINT_LEAST32_MAX
#define UINT_LEAST32_MAX UINT_MAX
#endif
#ifndef UINT32_C
#define UINT32_C(x) x
#endif
#else
typedef unsigned long uint_least32_t;
#ifndef UINT_LEAST32_MAX
#define UINT_LEAST32_MAX ULONG_MAX
#endif
#ifndef UINT32_C
#define UINT32_C(x) x##ul
#endif
#endif // if AT_LEAST_32_BITS_U(UCHAR_MAX)
// uint32_t
#if EXACTLY_32_BITS_U(UINT_LEAST32_MAX)
#ifndef UINT32_MAX
#define UINT32_MAX UINT_LEAST32_MAX
#endif
typedef uint_least32_t uint32_t;
#endif
// uint_least64_t
#if AT_LEAST_64_BITS_U(UCHAR_MAX)
typedef unsigned char uint_least64_t
#ifndef UINT64_C
#define UINT64_C(x) x
#endif
#ifndef UINT_LEAST64_MAX
#define UINT_LEAST64_MAX UCHAR_MAX
#endif
#elif AT_LEAST_64_BITS_U(USHRT_MAX)
typedef unsigned short uint_least64_t
#ifndef UINT64_C
#define UINT64_C(x) x
#endif
#ifndef UINT_LEAST64_MAX
#define UINT_LEAST64_MAX USHRT_MAX
#endif
#elif AT_LEAST_64_BITS_U(UINT_MAX)
typedef unsigned uint_least64_t;
#ifndef UINT64_C
#define UINT64_C(x) x
#endif
#ifndef UINT_LEAST64_MAX
#define UINT_LEAST64_MAX UINT_MAX
#endif
#elif AT_LEAST_64_BITS_U(LONG_MAX)
typedef unsigned long uint_least64_t;
#ifndef UINT64_C
#define UINT64_C(x) x##ul
#endif
#ifndef UINT_LEAST64_MAX
#define UINT_LEAST64_MAX ULONG_MAX
#endif
#else
#ifdef ULLONG_MAX
typedef unsigned long long uint_least64_t;
#ifndef UINT64_C
#define UINT64_C(x) x##ull
#endif
#ifndef UINT_LEAST64_MAX
#define UINT_LEAST64_MAX ULLONG_MAX
#endif
#endif
#endif // if AT_LEAST_64_BITS_U(UCHAR_MAX)
// uint64_t
#if EXACTLY_64_BITS_U(UINT_LEAST64_MAX)
#ifndef UINT64_MAX
#define UINT64_MAX UINT_LEAST64_MAX
#endif
typedef uint_least64_t uint64_t;
#endif
typedef signed char int_fast8_t;
typedef int int_fast16_t;
typedef long int_fast32_t;
typedef int_least64_t int_fast64_t;
typedef unsigned char uint_fast8_t;
typedef unsigned uint_fast16_t;
typedef unsigned long uint_fast32_t;
typedef uint_least64_t uint_fast64_t;
#ifdef LLONG_MAX
typedef long long intmax_t;
#ifndef INTMAX_C
#define INTMAX_C(x) x##ll
#endif
#ifndef INTMAX_MAX
#define INTMAX_MAX LLONG_MAX
#endif
#else
typedef long intmax_t;
#ifndef INTMAX_C
#define INTMAX_C(x) x##l
#endif
#ifndef INTMAX_MAX
#define INTMAX_MAX LONG_MAX
#endif
#endif
#ifdef ULLONG_MAX
typedef unsigned long long uintmax_t;
#ifndef UINTMAX_C
#define UINTMAX_C(x) x##ull
#endif
#ifndef UINTMAX_MAX
#define UINTMAX_MAX ULLONG_MAX
#endif
#else
typedef unsigned long uintmax_t;
#ifndef UINTMAX_C
#define UINTMAX_C(x) x##ul
#endif
#ifndef UINTMAX_MAX
#define UINTMAX_MAX ULONG_MAX
#endif
#endif
#undef EXACTLY_8_BITS_S
#undef EXACTLY_16_BITS_S
#undef EXACTLY_32_BITS_S
#undef EXACTLY_64_BITS_S
#undef EXACTLY_8_BITS_U
#undef EXACTLY_16_BITS_U
#undef EXACTLY_32_BITS_U
#undef EXACTLY_64_BITS_U
#undef AT_LEAST_16_BITS_S
#undef AT_LEAST_32_BITS_S
#undef AT_LEAST_64_BITS_S
#undef AT_LEAST_16_BITS_U
#undef AT_LEAST_32_BITS_U
#undef AT_LEAST_64_BITS_U
}
#endif // CPP11
#endif // PBL_CPP_CSTDINT_H

@ -0,0 +1,50 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_CSTDLIB_H
#define PBL_CPP_CSTDLIB_H
#include <cstdlib>
#include "version.h"
#ifndef CPP11
namespace cpp11
{
#if _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE || _POSIX_C_SOURCE >= 200112L
void _Exit(int code) __attribute__(( noreturn ));
inline void _Exit(int code)
{
::_Exit(code);
}
#endif
}
#endif
#endif // PBL_CPP_CSTDLIB_H

@ -0,0 +1,837 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_FORWARD_LIST_H
#define PBL_CPP_FORWARD_LIST_H
#include "version.h"
#ifdef CPP11
#include <forward_list>
#else
#include <cstddef>
#include <limits>
namespace cpp11
{
/** Implementation of std::forward_list
*
* @todo Some of these functions duplicate logic (or nearly so)
*/
template< typename T >
class forward_list
{
struct node
{
node* next;
};
struct value_node
: node
{
value_node()
: value()
{
}
explicit value_node(const T& value_)
: value(value_)
{
}
T value;
};
public:
typedef T value_type;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef T* pointer;
typedef const T* const_pointer;
class iterator
{
public:
iterator()
: p(0)
{
}
explicit iterator(node* p_)
: p(p_)
{
}
iterator& operator++()
{
p = p->next;
return *this;
}
iterator operator++(int)
{
iterator t(*this);
p = p->next;
return t;
}
pointer operator->()
{
return &( static_cast< value_node* >( p )->value );
}
const_pointer operator->() const
{
return &( static_cast< const value_node* >( p )->value );
}
reference operator*()
{
return static_cast< value_node* >( p )->value;
}
const_reference operator*() const
{
return static_cast< const value_node* >( p )->value;
}
bool operator==(const iterator& jt) const
{
return p == jt.p;
}
bool operator!=(const iterator& jt) const
{
return p != jt.p;
}
private:
friend class forward_list;
friend class const_iterator;
node* p;
};
class const_iterator
{
public:
const_iterator()
: p(0)
{
}
const_iterator(const iterator& it)
: p(it.p)
{
}
explicit const_iterator(node* p_)
: p(p_)
{
}
const_iterator& operator++()
{
p = p->next;
return *this;
}
const_iterator operator++(int)
{
const_iterator t(*this);
p = p->next;
return t;
}
const_pointer operator->() const
{
return &( static_cast< const value_node* >( p )->value );
}
const_reference operator*() const
{
return static_cast< const value_node* >( p )->value;
}
bool operator==(const const_iterator& jt) const
{
return p == jt.p;
}
bool operator!=(const const_iterator& jt) const
{
return p != jt.p;
}
private:
friend class forward_list;
node* p;
};
forward_list()
{
p.next = 0;
}
forward_list(
size_type count,
const T& value
)
{
node* q = &p;
for (; count != 0; --count )
{
q->next = new value_node(value);
q = q->next;
}
q->next = 0;
}
forward_list(size_type count)
{
node* q = &p;
for (; count != 0; --count )
{
q->next = new value_node;
q = q->next;
}
q->next = 0;
}
template< typename InputIt >
forward_list(
InputIt first,
InputIt last
)
{
node* q = &p;
for (; first != last; ++first )
{
q->next = new value_node(*first);
q = q->next;
}
q->next = 0;
}
forward_list(const forward_list& l)
{
node* q = &p;
for ( const node* first = l.p.next; first; first = first->next )
{
q->next = new node(first->value);
q = q->next;
}
q->next = 0;
}
~forward_list()
{
clear();
}
forward_list& operator=(const forward_list& l)
{
forward_list t(l);
swap(t);
return *this;
}
void assign(
size_type count,
const T& value
)
{
forward_list t(count, value);
swap(t);
}
template< typename InputIt >
void assign(
InputIt first,
InputIt last
)
{
forward_list t(first, last);
swap(t);
}
reference front()
{
return p.next->value;
}
const_reference front() const
{
return p.next->value;
}
bool empty() const
{
return p.next == 0;
}
size_type max_size() const
{
return std::numeric_limits< size_type >::max();
}
void clear()
{
node* q = p.next;
while ( q )
{
node* t = q;
q = q->next;
delete t;
}
p.next = 0;
}
iterator before_begin()
{
return iterator(&p);
}
const_iterator before_begin() const
{
return const_iterator(&p);
}
const_iterator cbefore_begin() const
{
return const_iterator(&p);
}
iterator begin()
{
return iterator(p.next);
}
const_iterator begin() const
{
return const_iterator(p.next);
}
const_iterator cbegin() const
{
return const_iterator(p.next);
}
iterator end()
{
return iterator(0);
}
const_iterator end() const
{
return const_iterator(0);
}
const_iterator cend() const
{
return const_iterator(0);
}
iterator insert_after(
const_iterator pos,
const T& value
)
{
if ( node* q = pos.p )
{
node* t = new value_node(value);
t->next = q->next;
q->next = t;
return iterator(t);
}
return iterator(0);
}
iterator insert_after(
const_iterator pos,
size_type count,
const T& value
)
{
if ( count != 0 )
{
return iterator( insert_after_private(pos.p, count, value) );
}
return iterator(pos.p);
}
template< typename InputIt >
iterator insert_after(
const_iterator pos,
InputIt first,
InputIt last
)
{
node* q = pos.p;
if ( q )
{
for (; first != last; ++first )
{
node* t = new value_node(*first);
t->next = q->next;
q->next = t;
q = t;
}
}
return iterator(q);
}
iterator erase_after(const_iterator pos)
{
if ( node* q = pos.p )
{
if ( node* t = q->next )
{
q->next = t->next;
delete t;
return iterator(q->next);
}
}
return iterator(0);
}
void push_front(const T& value)
{
node* t = new value_node(value);
t->next = p.next;
p.next = t;
}
void pop_front()
{
if ( p.next )
{
node* t = p.next;
p.next = t->next;
delete t;
}
}
void resize(size_type count)
{
std::pair< node*, size_type > rem = resize_private(count);
if ( rem.second != 0 )
{
insert_after_private(rem.first, rem.second);
}
}
void resize(
size_type count,
const T& value
)
{
std::pair< node*, size_type > rem = resize_private(count);
if ( rem.second != 0 )
{
insert_after_private(rem.first, rem.second, value);
}
}
void swap(forward_list& l)
{
std::swap(p.next, l.p.next);
}
void splice_after(
const_iterator pos,
forward_list& other
)
{
splice_after( pos, other, other.before_begin() );
}
void splice_after(
const_iterator pos,
forward_list& other,
const_iterator it
)
{
if ( node* q = pos.p )
{
if ( node* r = it.p )
{
if ( node* u = r->next )
{
r->next = 0;
node* t = q->next;
q->next = u;
if ( t )
{
while ( u->next )
{
u = u->next;
}
u->next = t;
}
}
}
}
}
void splice_after(
const_iterator pos,
forward_list& other,
const_iterator first,
const_iterator last
)
{
if ( node* q = pos.p )
{
if ( node* r = first.p )
{
if ( node* u = r->next )
{
r->next = last.p;
node* t = q->next;
q->next = u;
while ( u->next != last.p )
{
u = u->next;
}
u->next = t;
}
}
}
}
void remove(const T& value)
{
node* q = &p;
while ( q->next )
{
if ( static_cast< value_node* >( q->next )->value == value )
{
node* t = q->next;
q->next = t->next;
delete t;
}
else
{
q = q->next;
}
}
}
template< typename Pred >
void remove_if(Pred pred)
{
node* q = &p;
while ( q->next )
{
if ( pred(static_cast< value_node* >( q->next )->value) )
{
node* t = q->next;
q->next = t->next;
delete t;
}
else
{
q = q->next;
}
}
}
void reverse()
{
node* q = p.next;
node* r = 0;
while ( q )
{
node* t = q->next;
q->next = r;
r = q;
q = t;
}
p.next = r;
}
void unique()
{
unique(equal_to);
}
template< typename Predicate >
void unique(Predicate pred)
{
node* q = p.next;
while ( q )
{
if ( node* t = q->next )
{
if ( pred(static_cast< value_node* >( q )->value, static_cast< value_node* >( t )->value) )
{
q->next = t->next;
delete t;
}
else
{
q = t;
}
}
else
{
break;
}
}
}
void merge(forward_list& other)
{
merge(other, less_than);
}
template< typename Compare >
void merge(
forward_list& other,
Compare comp
)
{
p.next = merge_inner(p.next, other.p.next, comp);
other.p.next = 0;
}
void sort()
{
sort(less_than);
}
template< typename Compare >
void sort(Compare comp)
{
p.next = sort_inner(p.next, comp);
}
private:
static bool equal_to(
const T& a,
const T& b
)
{
return a == b;
}
static bool less_than(
const T& a,
const T& b
)
{
return a < b;
}
/** Split list in two, sort each half, merge, return the first node
*
* @todo Can probably be done without recursion. Sort 2 items, 2, 4, 2, 2,
* 4, 8
* @todo Probably don't need to traverse the list multiple times
*/
template< typename Compare >
static node* sort_inner(
node* q,
Compare comp
)
{
if ( q && q->next )
{
node* turtle = q;
node* hare = q;
while ( hare->next && hare->next->next )
{
turtle = turtle->next;
hare = hare->next->next;
}
hare = turtle->next;
turtle->next = 0;
return merge_inner(sort_inner(q, comp), sort_inner(hare, comp), comp);
}
return q;
}
/** Build a third list by repeatedly taking the least of the two given lists
*
* @todo Could probably save some rewriting of each s->next by following
* an algorithm like set_union
*/
template< typename Compare >
static node* merge_inner(
node* q,
node* r,
Compare comp
)
{
node t = { 0 };
node* s = &t;
while ( q && r )
{
if ( comp(static_cast< value_node* >( r )->value, static_cast< value_node* >( q )->value) )
{
s->next = r;
r = r->next;
}
else
{
s->next = q;
q = q->next;
}
s = s->next;
}
s->next = q ? q : r;
return t.next;
}
// count must not be zero
node* insert_after_private(
node* q,
size_type count
)
{
if ( q )
{
node* t = q->next;
for (; count != 0; --count )
{
node* u = new value_node;
u->next = t;
t = u;
}
q->next = t;
}
return q;
}
node* insert_after_private(
node* q,
size_type count,
const T& value
)
{
if ( q )
{
node* t = q->next;
for (; count != 0; --count )
{
node* u = new value_node(value);
u->next = t;
t = u;
}
q->next = t;
}
return q;
}
std::pair< node*, size_type > resize_private(size_type count)
{
node* q = &p;
while ( q->next )
{
q = q->next;
if ( --count == 0 )
{
node* t = q->next;
q->next = 0;
while ( t )
{
q = t->next;
delete t;
t = q;
}
return std::pair< node*, size_type >(0, 0);
}
}
return std::pair< node*, size_type >(q, count);
}
node p;
};
}
#endif // ifdef CPP11
#endif // FORWARD_LIST_H

@ -0,0 +1,645 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_FUNCTIONAL_H
#define PBL_CPP_FUNCTIONAL_H
#include "version.h"
#include <functional>
#ifndef CPP11
#include <exception>
#include "cstdint.h"
#include "rvalueref.h"
#include "traits/enable_if.h"
#include "traits/remove_reference.h"
#include "traits/is_unsigned.h"
#include "traits/is_signed.h"
#include "traits/make_unsigned.h"
#include "memory.h"
namespace cpp11
{
namespace detail
{
template< typename R >
class callable
{
public:
virtual ~callable()
{
}
virtual callable* clone() const = 0;
virtual R operator()() const = 0;
};
template< typename F >
class binder;
template< typename R, typename A1 >
class binder< R(A1) >
: public callable< R >
{
public:
typedef R result_type;
typedef R (* fn)(A1);
template< typename B1 >
binder(
fn f_,
B1 b1
)
: f(f_), a1(b1)
{
}
binder* clone() const
{
return new binder(*this);
}
R operator()() const
{
return f(a1);
}
private:
fn f;
typename cpp::remove_reference< A1 >::type a1;
};
template< typename R, typename A1, typename A2 >
class binder< R(A1, A2) >
: public callable< R >
{
public:
typedef R result_type;
typedef R (* fn)(A1, A2);
template< typename B1, typename B2 >
binder(
fn f_,
B1 b1,
B2 b2
)
: f(f_), a1(b1), a2(b2)
{
}
binder* clone() const
{
return new binder(*this);
}
R operator()() const
{
return f(a1, a2);
}
private:
fn f;
typename cpp::remove_reference< A1 >::type a1;
typename cpp::remove_reference< A2 >::type a2;
};
template< typename R, typename A1, typename A2, typename A3 >
class binder< R(A1, A2, A3) >
: public callable< R >
{
public:
typedef R result_type;
typedef R (* fn)(A1, A2, A3);
template< typename B1, typename B2, typename B3 >
binder(
fn f_,
B1 b1,
B2 b2,
B3 b3
)
: f(f_), a1(b1), a2(b2), a3(b3)
{
}
binder* clone() const
{
return new binder(*this);
}
R operator()() const
{
return f(a1, a2, a3);
}
private:
fn f;
typename cpp::remove_reference< A1 >::type a1;
typename cpp::remove_reference< A2 >::type a2;
typename cpp::remove_reference< A3 >::type a3;
};
template< typename R, typename A1, typename A2, typename A3, typename A4 >
class binder< R(A1, A2, A3, A4) >
: public callable< R >
{
public:
typedef R result_type;
typedef R (* fn)(A1, A2, A3, A4);
template< typename B1, typename B2, typename B3, typename B4 >
binder(
fn f_,
B1 b1,
B2 b2,
B3 b3,
B4 b4
)
: f(f_), a1(b1), a2(b2), a3(b3), a4(b4)
{
}
binder* clone() const
{
return new binder(*this);
}
R operator()() const
{
return f(a1, a2, a3, a4);
}
private:
fn f;
typename cpp::remove_reference< A1 >::type a1;
typename cpp::remove_reference< A2 >::type a2;
typename cpp::remove_reference< A3 >::type a3;
typename cpp::remove_reference< A4 >::type a4;
};
template< typename R, typename A1, typename A2, typename A3, typename A4, typename A5 >
class binder< R(A1, A2, A3, A4, A5) >
: public callable< R >
{
public:
typedef R result_type;
typedef R (* fn)(A1, A2, A3, A4, A5);
template< typename B1, typename B2, typename B3, typename B4, typename B5 >
binder(
fn f_,
B1 b1,
B2 b2,
B3 b3,
B4 b4,
B5 b5
)
: f(f_), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5)
{
}
binder* clone() const
{
return new binder(*this);
}
R operator()() const
{
return f(a1, a2, a3, a4, a5);
}
private:
fn f;
typename cpp::remove_reference< A1 >::type a1;
typename cpp::remove_reference< A2 >::type a2;
typename cpp::remove_reference< A3 >::type a3;
typename cpp::remove_reference< A4 >::type a4;
typename cpp::remove_reference< A5 >::type a5;
};
template< typename R, typename T >
class binder< R ( T::* )() >
: public callable< R >
{
public:
typedef R result_type;
typedef R (T::* fn)();
binder(
fn f_,
T* p_
)
: f(f_), p(p_)
{
}
binder* clone() const
{
return new binder(*this);
}
R operator()() const
{
return ( p->*f )();
}
private:
fn f;
T* p;
};
template< typename R, typename T >
class binder< R ( T::* )() const >
: public callable< R >
{
public:
typedef R result_type;
typedef R ( T::* fn )() const;
binder(
fn f_,
T* p_
)
: f(f_), p(p_)
{
}
binder* clone() const
{
return new binder(*this);
}
R operator()() const
{
return ( p->*f )();
}
private:
fn f;
T* p;
};
template< typename T >
struct to_function_type
{
typedef T type;
};
template< typename T >
struct to_function_type< T* >
{
typedef T type;
};
}
template< typename F, typename T1 >
detail::binder< typename detail::to_function_type< F >::type > bind(
F f,
T1 t1
)
{
return detail::binder< typename detail::to_function_type< F >::type >(f, t1);
}
template< typename F, typename T1, typename T2 >
detail::binder< typename detail::to_function_type< F >::type > bind(
F f,
T1 t1,
T2 t2
)
{
return detail::binder< typename detail::to_function_type< F >::type >(f, t1, t2);
}
template< typename F, typename T1, typename T2, typename T3 >
detail::binder< typename detail::to_function_type< F >::type > bind(
F f,
T1 t1,
T2 t2,
T3 t3
)
{
return detail::binder< typename detail::to_function_type< F >::type >(f, t1, t2, t3);
}
template< typename F, typename T1, typename T2, typename T3, typename T4 >
detail::binder< typename detail::to_function_type< F >::type > bind(
F f,
T1 t1,
T2 t2,
T3 t3,
T4 t4
)
{
return detail::binder< typename detail::to_function_type< F >::type >(f, t1, t2, t3, t4);
}
template< typename F, typename T1, typename T2, typename T3, typename T4, typename T5 >
detail::binder< typename detail::to_function_type< F >::type > bind(
F f,
T1 t1,
T2 t2,
T3 t3,
T4 t4,
T5 t5
)
{
return detail::binder< typename detail::to_function_type< F >::type >(f, t1, t2, t3, t4, t5);
}
class bad_function_call
: public std::exception
{
public:
bad_function_call()
: exception()
{
}
};
template< typename F >
class function;
template< typename R >
class function< R() >
{
typedef R (* function_pointer)();
public:
function()
: type(EMPTY)
{
}
function(function_pointer f)
: type(FUNCTION)
{
s.f = f;
}
function(const detail::callable< R >& c)
: type(BINDER)
{
s.callable = c.clone();
}
function(rvalue_reference< function > r)
: type(r.ref.type), s(r.ref.s)
{
r.ref.type = EMPTY;
}
function(const function& other)
: type(other.type)
{
switch ( other.type )
{
case EMPTY:
break;
case FUNCTION:
s.f = other.s.f;
break;
case BINDER:
s.callable = other.s.callable->clone();
break;
}
}
~function()
{
if ( type == BINDER )
{
delete s.callable;
}
}
function& operator=(const function& other)
{
function x(other);
swap(x);
return *this;
}
R operator()() const
{
switch ( type )
{
case EMPTY:
throw bad_function_call();
case FUNCTION:
return s.f();
case BINDER:
return ( *s.callable )();
}
}
void swap(function& other)
{
{
callable_type t = other.type;
other.type = type;
type = t;
}
{
function_storage t = other.s;
other.s = s;
s = t;
}
}
typedef void ( function::* safe_bool )() const;
operator safe_bool() const
{
return type != EMPTY ? &function::safe_bool_function : 0;
}
private:
void safe_bool_function() const
{
}
union function_storage
{
function_pointer f;
detail::callable< R >* callable;
};
enum callable_type {EMPTY, FUNCTION, BINDER};
callable_type type;
function_storage s;
};
template< typename T >
class reference_wrapper
{
public:
typedef T type;
reference_wrapper(T& x)
: p( addressof(x) )
{
}
reference_wrapper(const reference_wrapper& o)
: p(o.p)
{
}
reference_wrapper& operator=(const reference_wrapper& o)
{
p = o.p;
return *this;
}
operator T&() const { return *p; }
T& get() const
{
return *p;
}
private:
T* p;
};
template< typename T >
reference_wrapper< T > ref(T& t)
{
return reference_wrapper< T >(t);
}
template< typename T >
reference_wrapper< T > ref(reference_wrapper< T > t)
{
return ref( t.get() );
}
template< typename T >
reference_wrapper< const T > cref(const T& t)
{
return reference_wrapper< const T >(t);
}
template< typename T >
reference_wrapper< const T > cref(reference_wrapper< T > t)
{
return cref( t.get() );
}
namespace details
{
template< std::size_t >
struct uinthash;
template< >
struct uinthash< 32 >
{
std::size_t operator()(uint32_t x) const
{
x = ( x + 0x7ed55d16 ) + ( x << 12 );
x = ( x ^ 0xc761c23c ) ^ ( x >> 19 );
x = ( x + 0x165667b1 ) + ( x << 5 );
x = ( x + 0xd3a2646c ) ^ ( x << 9 );
x = ( x + 0xfd7046c5 ) + ( x << 3 );
x = ( x ^ 0xb55a4f09 ) ^ ( x >> 16 );
return x;
}
};
template< >
struct uinthash< 64 >
{
std::size_t operator()(uint64_t x) const
{
x = ( ~x ) + ( x << 21 );
x = x ^ ( x >> 24 );
x = ( x + ( x << 3 ) ) + ( x << 8 );
x = x ^ ( x >> 14 );
x = ( x + ( x << 2 ) ) + ( x << 4 );
x = x ^ ( x >> 28 );
x = x + ( x << 31 );
return x;
}
};
}
template< class T, class Enable = void >
struct hash;
// partial specialization for pointers
template< typename T >
struct hash< T*, void >
{
std::size_t operator()(T* p) const
{
details::uinthash< sizeof( uintptr_t ) * CHAR_BIT > h;
return h( reinterpret_cast< uintptr_t >( p ) );
}
};
template< typename T >
struct hash< T, typename enable_if< is_unsigned< T >::value >::type >
{
std::size_t operator()(T x) const
{
details::uinthash< sizeof( T ) * CHAR_BIT > h;
return h(x);
}
};
template< typename T >
struct hash< T, typename enable_if< is_signed< T >::value >::type >
{
std::size_t operator()(T x) const
{
details::uinthash< sizeof( T ) * CHAR_BIT > h;
return h( static_cast< typename make_unsigned< T >::type >( x ) );
}
};
}
#endif // ifndef CPP11
#endif // PBL_CPP_FUNCTIONAL_H

@ -0,0 +1,908 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_FUTURE_H
#define PBL_CPP_FUTURE_H
#include "version.h"
#ifdef CPP11
#include <future>
#else
#include <stdexcept>
#include "thread.h"
#include "mutex.h"
#include "condition_variable.h"
#include "system_error.h"
#include "utility.h"
#include "functional.h"
namespace cpp11
{
namespace future_errc
{
enum future_errc
{
no_error = 0,
broken_promise = 1,
future_already_retrieved = 2,
promise_already_satisfied = 3,
no_state = 4
};
}
namespace future_status
{
enum future_status
{
ready,
timeout,
deferred
};
}
namespace launch
{
enum launch_type
{
async = 1,
deferred = 2,
async_or_deferred = 3
};
}
namespace details
{
template< typename T >
struct future_shared_state
{
future_shared_state()
: result(0), owners(0), error(future_errc::no_error)
{
}
/** All access to this object should be done with mutual exclusion
*/
::cpp11::mutex lock;
/** For waiting for the promise
*/
::cpp11::condition_variable cond;
/** pointer to result. If 0, the promise is still going to provide
* the calculation
*/
T* result;
unsigned owners;
future_errc::future_errc error;
};
template< >
struct future_shared_state< void >
{
future_shared_state()
: result(false), owners(0), error(future_errc::no_error)
{
}
::cpp11::mutex lock;
::cpp11::condition_variable cond;
bool result;
unsigned owners;
future_errc::future_errc error;
};
}
class future_error
: public std::logic_error
{
public:
future_error(error_code ec)
: logic_error("future error"), code_(ec)
{
}
const error_code& code() const
{
return code_;
}
private:
error_code code_;
};
template< class T >
class promise;
template< class T >
class future;
template< typename T >
void swap(future< T >& f, future< T >& g);
/// @bug future does not have a swap member
template< class T >
class future
{
friend class promise< T >;
typedef details::future_shared_state< T > shared_state;
friend void::cpp11::swap< >(future< T >&, future< T >&);
public:
future()
: state(0)
{
}
future(rvalue_reference< future > other)
: state(0)
{
swap(other.ref);
}
~future()
{
if ( state )
{
unique_lock< mutex > lk(state->lock);
if ( state->owners == 1 )
{
// ownership has transferred to future
delete state->result;
lk.unlock();
delete state;
}
else
{
--( state->owners );
}
}
}
future& operator=(rvalue_reference< future > other)
{
swap(other.ref);
return *this;
}
bool valid() const
{
return state != 0;
}
T get()
{
if ( !state )
{
throw future_error(future_errc::no_state);
}
unique_lock< mutex > lk(state->lock);
if ( state->error != future_errc::no_error )
{
throw future_error(state->error);
}
if ( !state->result )
{
state->cond.wait(lk);
}
// Take the result so we can return it
T* y = state->result;
// release the state
shared_state* t = state;
state = 0;
if ( t->owners == 1 )
{
lk.unlock();
delete t;
}
else
{
--( t->owners );
lk.unlock();
}
T x(*y);
delete y;
return x;
}
void wait()
{
if ( !state )
{
throw future_error(future_errc::no_state);
}
::cpp11::unique_lock< ::cpp11::mutex > l(state->lock);
if ( !state->result )
{
state->cond.wait(l);
}
}
bool is_ready() const
{
bool ready = false;
if ( state )
{
unique_lock< mutex > lk(state->lock);
ready = ( state->result != 0 );
}
return ready;
}
future(const future&);
private:
future& operator=(const future&);
future(shared_state* p)
: state(p)
{
unique_lock< mutex > lk(state->lock);
state->owners += 1;
}
void swap(future& f)
{
/// @todo Should we lock in case one of the objects is destroyed?
shared_state* t = f.state;
f.state = state;
state = t;
}
shared_state* state;
};
template< >
class future< void >
{
friend class promise< void >;
typedef details::future_shared_state< void > shared_state;
friend void::cpp11::swap< >(future< void >&, future< void >&);
public:
future()
: state(0)
{
}
future(rvalue_reference< future > other)
: state(0)
{
swap(other.ref);
}
~future()
{
if ( state )
{
unique_lock< mutex > lk(state->lock);
if ( state->owners == 1 )
{
// ownership has transferred to future
lk.unlock();
delete state;
}
else
{
--( state->owners );
}
}
}
future& operator=(rvalue_reference< future > other)
{
swap(other.ref);
return *this;
}
bool valid() const
{
return state != 0;
}
void get()
{
if ( !state )
{
throw future_error(future_errc::no_state);
}
unique_lock< mutex > lk(state->lock);
if ( state->error != future_errc::no_error )
{
throw future_error(state->error);
}
if ( !state->result )
{
state->cond.wait(lk);
}
// release the state
shared_state* t = state;
state = 0;
if ( t->owners == 1 )
{
lk.unlock();
delete t;
}
else
{
--( t->owners );
lk.unlock();
}
}
void wait() const
{
if ( !state )
{
throw future_error(future_errc::no_state);
}
::cpp11::unique_lock< ::cpp11::mutex > l(state->lock);
if ( !state->result )
{
state->cond.wait(l);
}
}
template< class Duration >
future_status::future_status wait_for(const Duration& dt) const
{
if ( !state )
{
throw future_error(future_errc::no_state);
}
::cpp11::unique_lock< ::cpp11::mutex > l(state->lock);
if ( state->result )
{
return future_status::ready;
}
if ( state->cond.wait_for(l, dt) == cv_status::timeout )
{
return future_status::timeout;
}
return future_status::ready;
}
template< class Clock, class Duration >
future_status::future_status wait_until(const chrono::time_point< Clock, Duration >& timeout_time) const
{
if ( !state )
{
throw future_error(future_errc::no_state);
}
::cpp11::unique_lock< ::cpp11::mutex > l(state->lock);
if ( state->result )
{
return future_status::ready;
}
if ( state->cond.wait_until(l, timeout_time) == cv_status::timeout )
{
return future_status::timeout;
}
return future_status::ready;
}
bool is_ready() const
{
bool ready = false;
if ( state )
{
unique_lock< mutex > lk(state->lock);
ready = state->result;
}
return ready;
}
future(const future&);
private:
future& operator=(const future&);
future(shared_state* p)
: state(p)
{
unique_lock< mutex > pk(state->lock);
state->owners += 1;
}
void swap(future& f)
{
/// @todo Should we lock in case one of the objects is destroyed?
shared_state* t = f.state;
f.state = state;
state = t;
}
shared_state* state;
};
template< typename T >
void swap(
future< T >& f,
future< T >& g
)
{
f.swap(g);
}
template< class T >
class promise
{
typedef details::future_shared_state< T > shared_state;
public:
promise()
: state( new shared_state() )
{
state->owners = 1;
}
promise(rvalue_reference< promise > other)
: state(0)
{
swap(other.ref);
}
~promise()
{
if ( state )
{
unique_lock< mutex > lk(state->lock);
if ( state->owners == 1 )
{
// last owner
delete state->result;
lk.unlock();
delete state;
}
else
{
--( state->owners );
if ( !state->result )
{
state->error = future_errc::broken_promise;
}
}
}
}
promise& operator=(rvalue_reference< promise > other)
{
swap(other.ref);
return *this;
}
void swap(promise& other)
{
shared_state* t = state;
state = other.state;
other.state = t;
}
void set_value(const T& value)
{
if ( !state )
{
throw future_error(future_errc::no_state);
}
unique_lock< mutex > lk(state->lock);
if ( state->result || state->error != future_errc::no_error )
{
throw future_error(future_errc::promise_already_satisfied);
}
state->result = new T(value);
lk.unlock();
state->cond.notify_all();
}
future< T > get_future()
{
if ( !state )
{
throw future_error(future_errc::no_state);
}
unique_lock< mutex > lk(state->lock);
if ( state->owners != 1 )
{
throw future_error(future_errc::future_already_retrieved);
}
lk.unlock();
return future< T >(state);
}
promise(const promise&);
private:
promise& operator=(promise&);
shared_state* state;
};
template< >
class promise< void >
{
typedef details::future_shared_state< void > shared_state;
public:
promise()
: state( new shared_state() )
{
state->owners = 1;
}
promise(rvalue_reference< promise > other)
: state(0)
{
swap(other.ref);
}
~promise()
{
if ( state )
{
unique_lock< mutex > lk(state->lock);
if ( state->owners == 1 )
{
// last owner
lk.unlock();
delete state;
}
else
{
--( state->owners );
if ( !state->result )
{
state->error = future_errc::broken_promise;
}
}
}
}
promise& operator=(rvalue_reference< promise > other)
{
swap(other.ref);
return *this;
}
void swap(promise& other)
{
shared_state* t = state;
state = other.state;
other.state = t;
}
void set_value()
{
if ( !state )
{
throw future_error(future_errc::no_state);
}
unique_lock< mutex > lk(state->lock);
if ( state->result || state->error != future_errc::no_error )
{
throw future_error(future_errc::promise_already_satisfied);
}
state->result = true;
lk.unlock();
state->cond.notify_all();
}
future< void > get_future()
{
if ( !state )
{
throw future_error(future_errc::no_state);
}
unique_lock< mutex > lk(state->lock);
if ( state->owners != 1 )
{
throw future_error(future_errc::future_already_retrieved);
}
lk.unlock();
return future< void >(state);
}
promise(const promise&);
private:
promise& operator=(promise&);
shared_state* state;
};
template< typename T >
class packaged_task;
template< typename R >
class packaged_task< R() >
{
public:
typedef R result_type;
template< typename F >
explicit packaged_task(F f_)
: f(f_)
{
}
packaged_task(rvalue_reference< packaged_task > w)
: f( move(w.ref.f) ), p( move(w.ref.p) )
{
}
void operator()()
{
p.set_value( f() );
}
future< result_type > get_future()
{
return p.get_future();
}
private:
packaged_task(const packaged_task& w);
packaged_task& operator=(packaged_task&);
function< R() > f;
promise< result_type > p;
};
// Only difference between this and T() is how operator() is executed
template< >
class packaged_task< void() >
{
public:
typedef void result_type;
template< typename F >
explicit packaged_task(F f_)
: f(f_)
{
}
packaged_task(rvalue_reference< packaged_task > w)
: f( move(w.ref.f) ), p( move(w.ref.p) )
{
}
void operator()()
{
f();
p.set_value();
}
future< result_type > get_future()
{
return p.get_future();
}
private:
packaged_task(const packaged_task& w);
packaged_task& operator=(packaged_task&);
function< void() > f;
promise< result_type > p;
};
namespace detail
{
template< typename B >
future< typename B::result_type > async_inner(
launch::launch_type policy,
const B& bound_function
)
{
if ( (policy& launch::async) == 0 )
{
throw std::runtime_error("Deferred execution is not supported yet");
}
typedef typename B::result_type R;
packaged_task< R() > w(bound_function);
future< R > fu = w.get_future();
thread t( move(w) );
t.detach();
return move(fu);
}
}
template< typename F, typename Arg1 >
future< typename result_of< F(const Arg1&) >::type > async(
F f,
const Arg1& a1
)
{
return detail::async_inner( launch::async_or_deferred, bind(f, a1) );
}
template< typename F, typename Arg1, typename Arg2 >
future< typename result_of< F(const Arg1&, const Arg2&) >::type > async(
F f,
const Arg1& a1,
const Arg2& a2
)
{
return detail::async_inner( launch::async_or_deferred, bind(f, a1, a2) );
}
template< typename F, typename Arg1, typename Arg2, typename Arg3 >
future< typename result_of< F(const Arg1&, const Arg2&, const Arg3&) >::type > async(
F f,
const Arg1& a1,
const Arg2& a2,
const Arg3& a3
)
{
return detail::async_inner( launch::async_or_deferred, bind(f, a1, a2, a3) );
}
template< typename F, typename Arg1, typename Arg2, typename Arg3, typename Arg4 >
future< typename result_of< F(const Arg1&, const Arg2&, const Arg3&, const Arg4&) >::type > async(
F f,
const Arg1& a1,
const Arg2& a2,
const Arg3& a3,
const Arg4& a4
)
{
return detail::async_inner( launch::async_or_deferred, bind(f, a1, a2, a3, a4) );
}
template< typename F, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5 >
future< typename result_of< F(const Arg1&, const Arg2&, const Arg3&, const Arg4&, const Arg5&) >::type > async(
F f,
const Arg1& a1,
const Arg2& a2,
const Arg3& a3,
const Arg4& a4,
const Arg5& a5
)
{
return detail::async_inner( launch::async_or_deferred, bind(f, a1, a2, a3, a4, a5) );
}
template< typename F, typename Arg1 >
future< typename result_of< F(const Arg1&) >::type > async(
launch::launch_type policy,
F f,
const Arg1& a1
)
{
return detail::async_inner( policy, bind(f, a1) );
}
template< typename F, typename Arg1, typename Arg2 >
future< typename result_of< F(const Arg1&, const Arg2&) >::type > async(
launch::launch_type policy,
F f,
const Arg1& a1,
const Arg2& a2
)
{
return detail::async_inner( policy, bind(f, a1, a2) );
}
template< typename F, typename Arg1, typename Arg2, typename Arg3 >
future< typename result_of< F(const Arg1&, const Arg2&, const Arg3&) >::type > async(
launch::launch_type policy,
F f,
const Arg1& a1,
const Arg2& a2,
const Arg3& a3
)
{
return detail::async_inner( policy, bind(f, a1, a2, a3) );
}
template< typename F, typename Arg1, typename Arg2, typename Arg3, typename Arg4 >
future< typename result_of< F(const Arg1&, const Arg2&, const Arg3&, const Arg4&) >::type > async(
launch::launch_type policy,
F f,
const Arg1& a1,
const Arg2& a2,
const Arg3& a3,
const Arg4& a4
)
{
return detail::async_inner( policy, bind(f, a1, a2, a3, a4) );
}
template< typename F, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5 >
future< typename result_of< F(const Arg1&, const Arg2&, const Arg3&, const Arg4&, const Arg5&) >::type > async(
launch::launch_type policy,
F f,
const Arg1& a1,
const Arg2& a2,
const Arg3& a3,
const Arg4& a4,
const Arg5& a5
)
{
return detail::async_inner( policy, bind(f, a1, a2, a3, a4, a5) );
}
}
#endif // ifdef CPP11
#endif // PBL_CPP_FUTURE_H

@ -0,0 +1,192 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @file iterator.h
* @brief Implementation of C++11 iterator header
*/
#ifndef PBL_CPP_ITERATOR_H
#define PBL_CPP_ITERATOR_H
#include "version.h"
#include <iterator>
#ifndef CPP11
namespace cpp11
{
template< typename T >
typename T::iterator begin(T& c)
{
return c.begin();
}
/** @brief Get a beginning iterator to a container
* @param c A container
* @returns c.begin()
*/
template< typename T >
typename T::const_iterator begin(const T& c)
{
return c.begin();
}
template< typename T >
typename T::iterator end(T& c)
{
return c.end();
}
/** @brief Get an end iterator to a container
* @param c A container
* @returns c.end()
*/
template< typename T >
typename T::const_iterator end(const T& c)
{
return c.end();
}
template< typename T, std::size_t N >
T* begin(T(&a)[N])
{
return a;
}
/** @brief Get a beginning iterator to an array
* @param a An array
* @returns Pointer to the first element of a
*/
template< typename T, std::size_t N >
const T* begin(const T(&a)[N])
{
return a;
}
template< typename T, std::size_t N >
T* end(T(&a)[N])
{
return a + N;
}
/** @brief Get an end iterator to an array
* @param a An array
* @returns Pointer to the past-the-last elemnt of a
*/
template< typename T, std::size_t N >
const T* end(const T(&a)[N])
{
return a + N;
}
template< typename InputIterator >
InputIterator next(
InputIterator it,
typename std::iterator_traits< InputIterator >::difference_type n = 1
)
{
std::advance(it, n);
return it;
}
template< typename BidirectionalIterator >
BidirectionalIterator prev(
BidirectionalIterator it,
typename std::iterator_traits< BidirectionalIterator >::difference_type n = 1
)
{
std::advance(it, -n);
return it;
}
}
#endif // ifndef CPP11
#ifndef CPP14
namespace cpp14
{
template< typename T >
typename T::const_iterator cbegin(const T& c)
{
return c.begin();
}
template< typename T, std::size_t N >
const T* cbegin(const T(&a)[N])
{
return a;
}
template< typename T >
typename T::const_iterator cend(const T& c)
{
return c.end();
}
template< typename T, std::size_t N >
const T* cend(const T(&a)[N])
{
return a + N;
}
}
#endif // ifndef CPP14
#ifndef CPP17
namespace cpp17
{
template< typename T >
typename T::size_type size(const T& c)
{
return c.size();
}
template< typename T, std::size_t N >
std::size_t size(const T(&)[N])
{
return N;
}
template< typename T >
bool empty(const T& c)
{
return c.empty();
}
template< typename T, std::size_t N >
bool empty(const T(&)[N])
{
return false;
}
}
#endif // ifndef CPP17
#endif // PBL_CPP__ITERATOR_H

@ -0,0 +1,67 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_LOCALE_H
#define PBL_CPP_LOCALE_H
#include <locale>
#include "version.h"
#if !(__cplusplus >= 201103L) || (!defined(__clang__) && defined(__GNUC__) && __GNUC__ < 5)
#include <cctype>
namespace cpp11
{
template< typename Char >
bool isblank(Char, const std::locale & l);
template< >
inline bool isblank< char >(
char c,
const std::locale&
)
{
return ::isblank(c);
}
template< >
inline bool isblank< wchar_t >(
wchar_t c,
const std::locale&
)
{
return ::iswblank(c);
}
}
#endif // ifndef CPP11
#endif // PBL_CPP_LOCALE_H

@ -0,0 +1,715 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_MEMORY_H
#define PBL_CPP_MEMORY_H
#include "version.h"
#include <memory>
#ifndef CPP11
#include "atomic.h"
namespace cpp11
{
namespace detail
{
struct deleter_base
{
explicit deleter_base(void* p)
: refcount(1), value(p)
{
}
virtual ~deleter_base()
{
}
deleter_base(const deleter_base&); // non-copyable
deleter_base& operator=(const deleter_base&); // non-copyable
cpp::atomic_long refcount;
void* value;
};
template< typename U, typename D = void >
class deleter
: public deleter_base
{
public:
deleter(
U* value_,
const D& del_
)
: deleter_base(value_), orig(value_), del(del_)
{
}
~deleter()
{
del(orig);
}
private:
U* orig;
D del;
};
template< typename U >
class deleter< U, void >
: public deleter_base
{
public:
explicit deleter(U* value_)
: deleter_base(value_), orig(value_)
{
}
~deleter()
{
delete orig;
}
private:
U* orig;
};
}
/// @todo There seems to be some overlap with threadsafe reference counting and
/// semaphores
template< typename T >
class shared_ptr
{
void safe_bool_function() const
{
}
typedef void ( shared_ptr::* safe_bool )() const;
public:
shared_ptr()
: share(0)
{
}
shared_ptr(const shared_ptr& p)
: share(p.share)
{
if ( share )
{
++share->refcount;
}
}
// U must be convertible to T
template< typename U >
explicit shared_ptr(U* p)
: share(p ? new detail::deleter< U >(p) : 0)
{
}
template< typename U, typename Deleter >
shared_ptr(
U* p,
Deleter d
)
: share(p ? new detail::deleter< U, Deleter >(p, d) : 0)
{
}
~shared_ptr()
{
if ( share )
{
if ( --share->refcount == 0 )
{
delete share;
}
}
}
shared_ptr& operator=(const shared_ptr& p)
{
shared_ptr q(p);
swap(q);
return *this;
}
void swap(shared_ptr& p)
{
detail::deleter_base* t = p.share;
p.share = share;
share = t;
}
void reset()
{
shared_ptr().swap(*this);
}
template< typename U >
void reset(U* p)
{
shared_ptr(p).swap(*this);
}
T* get() const
{
return share ? static_cast< T* >( share->value ) : 0;
}
T& operator*() const
{
return *( static_cast< T* >( share->value ) );
}
T* operator->() const
{
return static_cast< T* >( share->value );
}
long use_count()
{
return share ? static_cast< long >( share->refcount ) : 0l;
}
bool unique()
{
return use_count() == 1;
}
operator safe_bool() const
{
return share ? &shared_ptr::safe_bool_function : 0;
}
private:
detail::deleter_base* share;
};
template< typename T, typename Arg1 >
shared_ptr< T > make_shared(const Arg1& a)
{
return shared_ptr< T >( new T(a) );
}
template< typename T, typename Arg1, typename Arg2 >
shared_ptr< T > make_shared(
const Arg1& a1,
const Arg2& a2
)
{
return shared_ptr< T >( new T(a1, a2) );
}
template< typename T >
class default_delete
{
public:
void operator()(T* ptr) const
{
delete ptr;
}
};
template< typename T >
class default_delete< T[] >
{
public:
void operator()(T* ptr) const
{
delete[] ptr;
}
};
template< typename T, typename Deleter = default_delete< T > >
class unique_ptr
{
public:
typedef void ( unique_ptr::* bool_type )() const;
unique_ptr()
: p(0), lock(0)
{
}
unique_ptr(const unique_ptr& o)
: p(0), lock(0)
{
take(o);
}
explicit unique_ptr(T* q)
: p(0), lock(0)
{
if ( q )
{
lock = new lock_t(this);
p = q;
}
}
~unique_ptr()
{
reset();
}
unique_ptr& operator=(const unique_ptr& o)
{
reset();
take(o);
return *this;
}
void reset()
{
if ( lock )
{
if ( lock->owner == this )
{
// Free the resource we've been managing
deleter(p);
// now nobody owns it
lock->owner = 0;
}
// Free the share object
if ( --lock->refcount == 0 )
{
delete lock;
}
lock = 0;
p = 0;
}
}
operator bool_type() const
{
return owner() ? &unique_ptr::safe_bool() : 0;
}
T& operator*() const
{
return *p;
}
T* operator->() const
{
return p;
}
T* get() const
{
return owner() ? p : 0;
}
T* release()
{
T* q = get();
p = 0;
reset();
return q;
}
void swap(unique_ptr& o)
{
if ( owner() )
{
if ( o.owner() )
{
// both owners
T* t1 = p;
p = o.p;
o.p = t1;
lock_t* t2 = lock;
lock = o.lock;
o.lock = t2;
unique_ptr* t3 = lock->owner;
lock->owner = o.lock->owner;
o.lock->owner = t3;
}
else
{
give(o);
}
}
else
{
take(o);
}
}
private:
struct lock_t
{
explicit lock_t(unique_ptr* o)
: owner(o), refcount(1)
{
}
unique_ptr* owner;
unsigned long refcount;
};
void safe_bool() const
{
}
bool owner() const
{
return lock && ( lock->owner == this );
}
// we own, and o does not
void give(unique_ptr& o)
{
// transfer ownership to o
o.p = p;
lock_t* t = o.lock;
o.lock = lock;
lock->owner = &o;
// maintain refcount
lock = t;
}
// prerequisite: owner() == false
void take(const unique_ptr& o)
{
if ( o.owner() )
{
p = o.p;
lock = o.lock;
lock->owner = this;
++lock->refcount;
}
}
T* p;
lock_t* lock;
/// @todo EBCO
Deleter deleter;
};
/// @todo Combine common functionality with unique_ptr<T>
template< typename T, typename Deleter >
class unique_ptr< T[], Deleter >
{
public:
typedef void ( unique_ptr::* bool_type )() const;
unique_ptr()
: p(0), lock(0)
{
}
unique_ptr(const unique_ptr& o)
: p(0), lock(0)
{
take(o);
}
explicit unique_ptr(T* q)
: p(0), lock(0)
{
if ( q )
{
lock = new lock_t(this);
p = q;
}
}
~unique_ptr()
{
reset();
}
unique_ptr& operator=(const unique_ptr& o)
{
reset();
take(o);
return *this;
}
void reset()
{
if ( lock )
{
if ( lock->owner == this )
{
// Free the resource we've been managing
deleter(p);
// now nobody owns it
lock->owner = 0;
}
// Free the share object
if ( --lock->refcount == 0 )
{
delete lock;
}
lock = 0;
p = 0;
}
}
operator bool_type() const
{
return owner() ? &unique_ptr::safe_bool() : 0;
}
T& operator[](std::size_t i) const
{
return p[i];
}
T* get() const
{
return owner() ? p : 0;
}
T* release()
{
T* q = get();
p = 0;
reset();
return q;
}
void swap(unique_ptr& o)
{
if ( owner() )
{
if ( o.owner() )
{
// both owners
T* t1 = p;
p = o.p;
o.p = t1;
lock_t* t2 = lock;
lock = o.lock;
o.lock = t2;
unique_ptr* t3 = lock->owner;
lock->owner = o.lock->owner;
o.lock->owner = t3;
}
else
{
give(o);
}
}
else
{
take(o);
}
}
private:
struct lock_t
{
explicit lock_t(unique_ptr* o)
: owner(o), refcount(1)
{
}
unique_ptr* owner;
unsigned long refcount;
};
void safe_bool() const
{
}
bool owner() const
{
return lock && ( lock->owner == this );
}
// we own, and o does not
void give(unique_ptr& o)
{
// transfer ownership to o
o.p = p;
lock_t* t = o.lock;
o.lock = lock;
lock->owner = &o;
// maintain refcount
lock = t;
}
// prerequisite: owner() == false
void take(const unique_ptr& o)
{
if ( o.owner() )
{
p = o.p;
lock = o.lock;
lock->owner = this;
++lock->refcount;
}
}
T* p;
lock_t* lock;
/// @todo EBCO
Deleter deleter;
};
namespace detail
{
template< class T >
struct addr_impl_ref
{
T& v_;
inline addr_impl_ref(T& v)
: v_(v)
{
}
inline operator T&() const
{
return v_;
}
private:
addr_impl_ref& operator=(const addr_impl_ref&);
};
template< class T >
struct addressof_impl
{
static inline T* f(
T& v,
long
)
{
return reinterpret_cast< T* >(
&const_cast< char& >( reinterpret_cast< const volatile char& >( v ) ) );
}
static inline T* f(
T* v,
int
)
{
return v;
}
};
}
template< class T >
T* addressof(T& v)
{
return detail::addressof_impl< T >::f(detail::addr_impl_ref< T >(v), 0);
}
template< class InputIt, class Size, class ForwardIt >
ForwardIt uninitialized_copy_n(
InputIt first,
Size count,
ForwardIt d_first
)
{
typedef typename std::iterator_traits< ForwardIt >::value_type Value;
ForwardIt current = d_first;
try
{
for (; count > 0; ++first, ++current, --count )
{
::new( static_cast< void* >( addressof(*current) ) )Value(*first);
}
}
catch ( ... )
{
for (; d_first != current; ++d_first )
{
d_first->~Value();
}
throw;
}
return current;
}
}
#endif // ifndef CPP11
#ifndef CPP14
namespace cpp14
{
#ifdef CPP11
template< typename T, typename... Ts >
std::unique_ptr< T > make_unique(Ts&& ... params)
{
return std::unique_ptr< T >( new T(std::forward< Ts >(params) ...) );
}
#else
template< typename T, typename Arg1, typename Arg2 >
cpp::unique_ptr< T > make_unique(
const Arg1& a1,
const Arg2& a2
)
{
return cpp::unique_ptr< T >( new T(a1, a2) );
}
#endif
}
#endif // ifndef CPP14
#endif // PBL_CPP_MEMORY_H

@ -0,0 +1,109 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "mutex.h"
#ifndef CPP11
#include <stdexcept>
namespace cpp11
{
#ifdef POSIX_THREADS
mutex::mutex()
{
int r = pthread_mutex_init(&mut, 0);
if ( r != 0 )
{
throw std::runtime_error("Could not construct POSIX mutex.");
}
}
mutex::~mutex()
{
pthread_mutex_destroy(&mut);
}
void mutex::lock()
{
pthread_mutex_lock(&mut);
}
void mutex::unlock()
{
pthread_mutex_unlock(&mut);
}
bool mutex::trylock()
{
return pthread_mutex_trylock(&mut) == 0;
}
mutex::native_handle_type mutex::native_handle()
{
return &mut;
}
#elif defined( OS_WINDOWS )
mutex::mutex()
{
InitializeCriticalSection(&mut);
}
mutex::~mutex()
{
DeleteCriticalSection(&mut);
}
void mutex::lock()
{
EnterCriticalSection(&mut);
}
void mutex::unlock()
{
LeaveCriticalSection(&mut);
}
bool mutex::trylock()
{
return TryEnterCriticalSection(&mut);
}
mutex::native_handle_type mutex::native_handle()
{
return &mut;
}
#endif // ifdef POSIX_THREADS
}
#endif // ifndef CPP11

@ -0,0 +1,218 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_MUTEX_H
#define PBL_CPP_MUTEX_H
#include "version.h"
#ifdef CPP11
#include <mutex>
#else
#include "config/os.h"
namespace cpp11
{
struct defer_lock_t {};
struct try_to_lock_t {};
struct adopt_lock_t {};
extern const defer_lock_t defer_lock;
extern const try_to_lock_t try_to_lock;
extern const adopt_lock_t adopt_lock;
class mutex
{
public:
typedef ::pbl::os::mutex_type* native_handle_type;
mutex();
~mutex();
void lock();
void unlock();
bool trylock();
native_handle_type native_handle();
private:
mutex(const mutex&); // non-copyable
mutex& operator=(const mutex&); // non-copyable
::pbl::os::mutex_type mut;
};
template< class Mutex >
class lock_guard
{
public:
typedef Mutex mutex_type;
explicit lock_guard(mutex_type& m)
: pm(m)
{
m.lock();
}
lock_guard(
mutex_type& m,
adopt_lock_t
)
: pm(m)
{
}
~lock_guard()
{
pm.unlock();
}
private:
mutex_type& pm;
lock_guard(const lock_guard&);
lock_guard& operator=(const lock_guard&);
};
template< class Mutex >
class unique_lock
{
public:
typedef Mutex mutex_type;
unique_lock()
: pm(0), owns(false)
{
}
explicit unique_lock(mutex_type& m)
: pm(&m), owns(true)
{
m.lock();
}
unique_lock(
mutex_type& m,
defer_lock_t
)
: pm(&m), owns(false)
{
}
unique_lock(
mutex_type& m,
try_to_lock_t
)
: pm(&m), owns( m.try_lock() )
{
}
unique_lock(
mutex_type& m,
adopt_lock_t
)
: pm(&m), owns(true)
{
}
~unique_lock()
{
if ( owns )
{
pm->unlock();
}
}
void lock()
{
if ( pm )
{
pm->lock();
owns = true;
}
}
bool try_lock()
{
if ( pm )
{
owns = pm->try_lock();
}
return owns;
}
void unlock()
{
if ( pm )
{
pm->unlock();
}
owns = false;
}
void swap(unique_lock& m)
{
bool t1 = owns;
owns = m.owns;
m.owns = t1;
mutex_type* t2 = pm;
pm = m.pm;
m.pm = t2;
}
mutex_type* release()
{
mutex_type* p = pm;
pm = 0;
owns = false;
return p;
}
bool owns_lock() const
{
return owns;
}
mutex_type* mutex() const
{
return pm;
}
private:
unique_lock(const unique_lock&); // non-copyable
unique_lock& operator=(const unique_lock&); // non-copyable
mutex_type* pm;
bool owns;
};
}
#endif // ifdef CPP11
#endif // ifndef PBL_CPP_MUTEX_H

@ -0,0 +1,128 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_NUMERIC_H
#define PBL_CPP_NUMERIC_H
#include <numeric>
#include "version.h"
#ifndef CPP11
namespace cpp11
{
template< class ForwardIterator, class T >
void iota(
ForwardIterator first,
ForwardIterator last,
T value
)
{
while ( first != last )
{
*first++ = value;
++value;
}
}
}
#endif
#ifndef CPP17
#include "type_traits.h"
#include "cmath.h"
namespace cpp17
{
namespace detail
{
template< class T >
typename ::cpp::make_unsigned< T >::type uabs(T x)
{
typedef typename ::cpp::make_unsigned< T >::type U;
return x >= 0 ? static_cast< U >( x ) : -static_cast< U >( x );
}
template< class T, class U >
typename ::cpp::common_type< T, U >::type ugcd(
T a_,
U b_
)
{
typedef typename ::cpp::common_type< T, U >::type V;
V a = a_, b = b_;
while ( b != 0 )
{
V t = b;
b = a % b;
a = t;
}
return a;
}
template< class T, class U >
typename ::cpp::common_type< T, U >::type ulcm(
T a,
U b
)
{
typedef typename ::cpp::common_type< T, U >::type V;
const V d = ugcd(a, b);
return d == 0 ? 0 : a* ( b / d );
}
}
template< class T, class U >
typename ::cpp::common_type< T, U >::type gcd(
T a,
U b
)
{
return detail::ugcd( detail::uabs(a), detail::uabs(b) );
}
template< class T, class U >
typename ::cpp::common_type< T, U >::type lcm(
T a,
U b
)
{
return detail::ulcm( detail::uabs(a), detail::uabs(b) );
}
}
#endif // ifndef CPP17
#endif // PBL_CPP_NUMERIC_H

@ -0,0 +1,326 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_OPTIONAL_H
#define PBL_CPP_OPTIONAL_H
#include "version.h"
#ifdef CPP17
#include <optional>
#else
#include <stdexcept>
#include <new>
#include "type_traits.h"
namespace cpp17
{
struct none_t
{
};
const none_t none = {};
/** @brief A class that represents an uninitialized value
*
* This is a simple wrapper for a (T, bool) pair where the bool
* indicates whether or not the T value contains anything
* meaningful (i.e., whether it has been "set"). For example,
*
* @code
* optional<int> num_near_wins;
*
* // num_near_wins = 6;
*
* if (num_near_wins)
* generate_near_wins(num_near_wins.get());
* @endcode
*
* Equivalent to get() is the use of the dereference or pointer
* operator. This is sometimes more useful for classes.
*
* @code
* optional< Symbol > multiplier_sym;
*
* ... // somewhere multiplier_sym gets set
*
* const int id = multiplier_sym->getId()
* @endcode
*
* @todo Partial specialization for POD since we don't have to bother with
* placement new and all that.
*/
template< typename T >
class optional
{
typedef void ( optional::* bool_type )() const;
public:
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
typedef T* pointer;
typedef const T* const_pointer;
/// @brief An uninitialized T
optional()
: init(false)
{
}
optional(none_t)
: init(false)
{
}
/** @brief Copy constructor
* @param x The optional to copy
*/
optional(const optional& x)
: init(false)
{
if ( x.init )
{
acquire( x.get() );
}
}
/** @brief Construct an initialized T, copied from x
* @param x The value to set *this to
*/
optional(const T& x)
: init(false)
{
acquire(x);
}
template< typename U >
explicit optional(const optional< U >& x)
: init(false)
{
if ( x )
{
acquire( x.get() );
}
}
~optional()
{
release();
}
optional& operator=(none_t)
{
release();
return *this;
}
/** @brief Copy assignment
* @param x The optional to copy
*/
optional& operator=(const optional& x)
{
release();
if ( x.init )
{
acquire( x.get() );
}
return *this;
}
/** @brief Set the value of this to x
* @param x The value to set *this to
*
* @note This is considered initilized after this function returns
*/
optional& operator=(const T& x)
{
release();
acquire(x);
return *this;
}
template< typename U >
optional& operator=(const optional< U >& x)
{
release();
if ( x )
{
acquire( x.get() );
}
return *this;
}
const_reference value() const
{
if ( !init )
{
throw std::runtime_error("Attempting to get from an uninitialized optional<T>");
}
return *data();
}
reference value()
{
if ( !init )
{
throw std::runtime_error("Attempting to get from an uninitialized optional<T>");
}
return *data();
}
template< typename U >
value_type value_or(const U& u) const
{
if ( init )
{
return get();
}
return u;
}
/** @brief Get a reference to the (initialized) value. Const version.
* @throws std::runtime_error if this is not initialized
*/
const_reference get() const
{
return *data();
}
/** @brief Get a reference to the (initialized) value
* @throws std::runtime_error if this is not initialized
*/
reference get()
{
return *data();
}
/// @brief Dereference notation. Same as get()
const_reference operator*() const
{
return get();
}
/// @brief Dereference notation. Same as get()
reference operator*()
{
return get();
}
const_pointer get_ptr() const
{
return init ? data() : 0;
}
pointer get_ptr()
{
return init ? data() : 0;
}
/// @brief Pointer notation. Like get(), but returns a pointer
const_pointer operator->() const
{
return data();
}
/// @brief Pointer notation. Like get(), but returns a pointer
pointer operator->()
{
return data();
}
/** @brief Conversion to bool
* @returns true iff object is initialized
*/
operator bool_type() const
{
return init ? &optional::safe_bool_fn : NULL;
}
/** @brief Conversion to bool (negation)
* @returns true iff the object is @em not initialized
*/
bool operator!() const
{
return !init;
}
private:
// Safe bool idiom
void safe_bool_fn() const
{
}
T* data()
{
return static_cast< T* >( static_cast< void* >( &value_ ) );
}
const T* data() const
{
return static_cast< const T* >( static_cast< const void* >( &value_ ) );
}
// Should only ever be called when init == false
void acquire(const T& x)
{
new( static_cast< void* >( &value_ ) )T(x);
init = true;
}
// Calls the destructor for an allocated value
void release()
{
if ( init )
{
get().~T();
init = false;
}
}
bool init; ///< True iff object has been initialized with a value
/** Reserved space to hold an instance of T
*
* value is managed with placement new/delete. It is cast wherever it's used.
*/
typename ::cpp::aligned_union< 0, T >::type value_;
};
}
#endif // ifdef CPP17
#endif // ifndef PBL_CPP_OPTIONAL_H

@ -0,0 +1,71 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "random.h"
#ifndef CPP11
#include <stdexcept>
#include <climits>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
namespace cpp11
{
random_device::random_device()
: fd(-1)
{
fd = ::open("/dev/urandom", O_RDONLY);
}
random_device::result_type random_device::operator()()
{
if ( fd != -1 )
{
char buf[sizeof( result_type )];
if ( ::read( fd, buf, sizeof( buf ) ) == sizeof( result_type ) )
{
result_type x = 0;
for ( std::size_t i = 0; i < sizeof( result_type ); ++i )
{
x += static_cast< result_type >( static_cast< unsigned char >( buf[i] ) ) << ( i * CHAR_BIT );
}
return x;
}
}
throw std::runtime_error("Random device not available");
}
}
#endif // ifndef CPP11

@ -0,0 +1,265 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @file random.h
* @brief Implementation of C++11 random header
*/
#ifndef PBL_CPP_RANDOM_H
#define PBL_CPP_RANDOM_H
#include "version.h"
#ifdef CPP11
#include <random>
#else
#include <stdexcept>
#include <limits>
#include <cstddef>
namespace cpp11
{
class random_device
{
public:
typedef unsigned int result_type;
random_device();
result_type operator()();
private:
random_device(const random_device&); /* noncopyable */
random_device& operator=(const random_device&); /* noncopyable */
int fd;
};
template< class UIntType, std::size_t W, std::size_t N, std::size_t M, std::size_t R, UIntType A, std::size_t U, UIntType D, std::size_t S, UIntType B, std::size_t T, UIntType C, std::size_t L, UIntType F >
class mersenne_twister_engine
{
public:
typedef UIntType result_type;
static const UIntType default_seed = 5489u;
/** \brief Construct a pseudo-random number generator
* \param value The seed to initialize the PRNG with
*/
explicit mersenne_twister_engine(result_type value = default_seed)
: state(), k(0)
{
seed(value);
}
/** \brief Seed the object with a 32-bit value
* @param value The seed to use
*/
void seed(result_type value = default_seed)
{
const result_type x = max_;
state[0] = static_cast< result_type >( value ) & x;
// Expand the state
for ( k = 1; k < N; k++ )
{
state[k] = ( ( state[k - 1] ^ ( state[k - 1] >> ( W - 2 ) ) ) * F + k ) & x;
}
}
/// \brief Generate a random value
result_type operator()()
{
return get();
}
/// \brief Move ahead by z calls
void discard(unsigned long z)
{
while ( z-- )
{
get();
}
}
/// \brief Return the minimum value that this rng can produce
static result_type min()
{
return 0;
}
/// \brief Return the maximum value that this rng can produce
static result_type max()
{
return max_;
}
/// \brief Get a random value, increment the internal counter
result_type get()
{
if ( k >= N )
{
generate_state();
}
// Temper and mix the result
UIntType y = state[k++];
y ^= ( y >> U ) & D;
y ^= ( y << S ) & B;
y ^= ( y << T ) & C;
y ^= ( y >> L );
return y;
}
private:
/// \brief Regenerate the state of the mersenne twister
void generate_state()
{
k = 0;
const UIntType x = ( ~UIntType(0) ) << R;
for ( unsigned j = 0; j < N; j++ )
{
UIntType y = state[( j + 1 ) % N] ^ ( ( state[j] ^ state[( j + 1 ) % N] ) & x );
y = ( y >> 1 ) ^ ( -( y % 2 ) & A );
state[j] = state[( j + M ) % N] ^ y;
}
}
static const result_type max_ = ~( ( ( ~UIntType(0) ) << 1 ) << ( W - 1 ) );
// mersenne twister state
UIntType state[N];
unsigned k;
};
typedef mersenne_twister_engine< unsigned long, 32, 624, 397, 31, 0x9908b0dful, 11, 0xfffffffful, 7, 0x9d2c5680ul, 15, 0xefc60000ul, 18, 1812433253ul > mt19937;
typedef mt19937 default_random_engine;
template< typename T >
class uniform_int_distribution
{
public:
typedef T result_type;
explicit uniform_int_distribution(
T a = 0,
T b = std::numeric_limits< T >::max()
)
: min(a), max(b)
{
}
template< typename Generator >
result_type operator()(Generator& g)
{
typedef typename Generator::result_type gtype;
const gtype max_ = g.max();
const gtype n = max - min;
if ( n > max_ )
{
throw std::logic_error("Not implemented");
}
gtype x = g();
if ( n < max_ )
{
gtype rem = max_ % ( n + 1 );
if ( rem != n )
{
while ( x >= max_ - rem )
{
x = g();
}
x %= ( n + 1 );
}
else if ( n != 0 )
{
x /= ( ( max_ / ( n + 1 ) ) + 1 );
}
else
{
x = 0;
}
}
return min + static_cast< T >( x );
}
private:
T min;
T max;
};
template< typename R >
class uniform_real_distribution
{
public:
typedef R result_type;
explicit uniform_real_distribution(
R a = 0,
R b = 1
)
: min(a), max(b)
{
}
/** @todo If Generator::max() is 2**n-1 then we should get u by simply
* shifting bits into R(0)
* @todo Alternatively, determine the number of uniformly distributed
* points between min and max. Treat this as n int, and (effectively)
* call uniform_int_distribution.
*/
template< typename Generator >
result_type operator()(Generator& g)
{
/// @bug Can be 1, but should never be 1
const R u = static_cast< R >( g() ) / static_cast< R >( g.max() );
/// @bug Rounding can cause "max" to be returned
return ( max - min ) * u + min;
}
private:
R min;
R max;
};
}
#endif
#endif // PBL_CPP_RANDOM_H

@ -0,0 +1,120 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_RATIO_H
#define PBL_CPP_RATIO_H
#include "version.h"
#ifdef CPP11
#include <ratio>
#else
#include "cstdint.h"
#include "traits/integral_constant.h"
namespace cpp11
{
namespace detail
{
template< cpp::intmax_t X >
struct sign
{
static const cpp::intmax_t value = ( X >= 0 ? 1 : -1 );
};
template< cpp::intmax_t X >
struct abs
{
static const cpp::intmax_t value = ( X >= 0 ? X : -X );
};
template< cpp::intmax_t P, cpp::intmax_t Q >
struct gcd
{
static const cpp::intmax_t value = gcd< abs< Q >::value, abs< P >::value % abs< Q >::value >::value;
};
template< cpp::intmax_t P >
struct gcd< P, 0 >
{
static const cpp::intmax_t value = abs< P >::value;
};
template< cpp::intmax_t Q >
struct gcd< 0, Q >
{
static const cpp::intmax_t value = abs< Q >::value;
};
template< cpp::intmax_t P, cpp::intmax_t Q >
struct lcm
{
static const cpp::intmax_t value = P * ( Q / gcd< P, Q >::value );
};
}
template< cpp::intmax_t Num, cpp::intmax_t Denom = 1 >
class ratio
{
public:
static const intmax_t num = detail::sign< Num >::value * detail::sign< Denom >::value
* detail::abs< Num >::value / detail::gcd< Num, Denom >::value;
static const intmax_t den = detail::abs< Denom >::value / detail::gcd< Num, Denom >::value;
typedef ratio< num, den > type;
};
typedef ratio< 1000000000L, 1 > giga;
typedef ratio< 1000000L, 1 > mega;
typedef ratio< 1000, 1 > kilo;
typedef ratio< 100, 1 > hecto;
typedef ratio< 10, 1 > deca;
typedef ratio< 1, 10 > deci;
typedef ratio< 1, 100 > centi;
typedef ratio< 1, 1000 > milli;
typedef ratio< 1, 1000000L > micro;
typedef ratio< 1, 1000000000L > nano;
template< class R1, class R2 >
struct ratio_equal
: public integral_constant< bool, R1::num == R2::num&& R1::den == R2::den >
{
};
template< class R1, class R2 >
struct ratio_not_equal
: public integral_constant< bool, R1::num != R2::num || R1::den != R2::den >
{
};
}
#endif // ifndef CPP11
#endif // PBL_CPP_RATIO_H

@ -0,0 +1,56 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Fake rvalue references
*
* Objects that we can take a reference for, we do. Otherwise we copy the
* object.
*/
#ifndef PBL_CPP_RVALUEREF_H
#define PBL_CPP_RVALUEREF_H
#include "version.h"
#ifndef CPP11
namespace cpp11
{
// A class to fake rvalue references
template< typename T >
struct rvalue_reference
{
explicit rvalue_reference(T& value)
: ref(value)
{
}
T& ref;
};
}
#endif // ifndef CPP11
#endif // PBL_CPP_RVALUEREF_H

@ -0,0 +1,82 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "shared_mutex.h"
#ifndef CPP17
#include <pthread.h>
namespace cpp17
{
shared_mutex::shared_mutex()
{
::pthread_rwlock_init(&mut, NULL);
}
shared_mutex::~shared_mutex()
{
::pthread_rwlock_destroy(&mut);
}
void shared_mutex::lock()
{
::pthread_rwlock_wrlock(&mut);
}
bool shared_mutex::try_lock()
{
return ::pthread_rwlock_trywrlock(&mut) == 0;
}
void shared_mutex::unlock()
{
::pthread_rwlock_unlock(&mut);
}
void shared_mutex::lock_shared()
{
::pthread_rwlock_rdlock(&mut);
}
bool shared_mutex::try_lock_shared()
{
return ::pthread_rwlock_tryrdlock(&mut) == 0;
}
void shared_mutex::unlock_shared()
{
::pthread_rwlock_unlock(&mut);
}
shared_mutex::native_handle_type shared_mutex::native_handle()
{
return &mut;
}
}
#endif

@ -0,0 +1,180 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_SHARED_MUTEX_H
#define PBL_CPP_SHARED_MUTEX_H
#include "version.h"
#ifdef CPP17
#include <shared_mutex>
#else
#include "config/os.h"
#include "mutex.h"
namespace cpp17
{
/** @todo See N3569 re: upgrade_mutex. Also https://github.com/HowardHinnant/upgrade_mutex
* has a public domain implementation
*/
class shared_mutex
{
public:
typedef ::pbl::os::shared_mutex_type* native_handle_type;
shared_mutex();
~shared_mutex();
void lock();
bool try_lock();
void unlock();
void lock_shared();
bool try_lock_shared();
void unlock_shared();
native_handle_type native_handle();
private:
shared_mutex(const shared_mutex&);
shared_mutex& operator=(const shared_mutex&);
::pbl::os::shared_mutex_type mut;
};
template< class Mutex >
class shared_lock
{
public:
typedef Mutex mutex_type;
shared_lock()
: pm(0), owns(false)
{
}
explicit shared_lock(mutex_type& m)
: pm(&m), owns(true)
{
m.lock_shared();
}
shared_lock(
mutex_type& m,
cpp::defer_lock_t
)
: pm(&m), owns(false)
{
}
shared_lock(
mutex_type& m,
cpp::try_to_lock_t
)
: pm(&m), owns( m.try_lock_shared() )
{
}
shared_lock(
mutex_type& m,
cpp::adopt_lock_t
)
: pm(&m), owns(true)
{
}
~shared_lock()
{
if ( owns )
{
pm->unlock_shared();
}
}
void lock()
{
if ( pm )
{
pm->lock_shared();
owns = true;
}
}
bool try_lock()
{
if ( pm )
{
owns = pm->try_lock_shared();
}
return owns;
}
void unlock()
{
if ( pm && owns )
{
pm->unlock_shared();
}
owns = false;
}
void swap(shared_lock& m)
{
bool t1 = owns;
owns = m.owns;
m.owns = t1;
mutex_type* t2 = pm;
pm = m.pm;
m.pm = t2;
}
bool owns_lock() const
{
return owns;
}
mutex_type* mutex() const
{
return pm;
}
private:
shared_lock(const shared_lock&); // non-copyable
shared_lock& operator=(const shared_lock&); // non-copyable
mutex_type* pm;
bool owns;
};
}
#endif // ifdef CPP17
#endif // PBL_CPP_SHARED_MUTEX_H

@ -0,0 +1,216 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @file string.h
* @brief Implementation of C++11 string header
* @todo Might be able to use std::num_put
*/
#ifndef PBL_CPP_STRING_H
#define PBL_CPP_STRING_H
#include <string>
#include "version.h"
#ifndef CPP11
#include <cstdlib>
#include <iostream>
#include <sstream>
#include "config/arch.h"
namespace cpp11
{
namespace detail
{
template< typename I >
std::string arithmetic_to_string(I x)
{
std::ostringstream ss;
ss << x;
return ss.str();
}
template< typename I >
std::wstring arithmetic_to_wstring(I x)
{
std::wostringstream ss;
ss << x;
return ss.str();
}
}
inline unsigned long stoul(
const std::string& s,
std::size_t* pos = 0,
int base = 10
)
{
char* ptr;
const char* s_ = s.c_str();
const long res = std::strtoul(s_, &ptr, base);
if ( pos )
{
*pos = ptr - s_;
}
return res;
}
/// @todo Should throw if not convertible, or result is too large
inline long stol(
const std::string& s,
std::size_t* pos = 0,
int base = 10
)
{
char* ptr;
const char* s_ = s.c_str();
const long res = std::strtol(s_, &ptr, base);
if ( pos )
{
*pos = ptr - s_;
}
return res;
}
/// @todo Should throw if not convertible, or result is too large
inline int stoi(
const std::string& s,
std::size_t* pos = 0,
int base = 10
)
{
return static_cast< int >( stol(s, pos, base) );
}
/** @brief Get the string representation of an int
* @param n An integer
* @returns lexical_cast<std::string>(n)
*/
inline std::string to_string(int n)
{
return detail::arithmetic_to_string(n);
}
inline std::string to_string(long n)
{
return detail::arithmetic_to_string(n);
}
inline std::string to_string(unsigned n)
{
return detail::arithmetic_to_string(n);
}
inline std::string to_string(unsigned long n)
{
return detail::arithmetic_to_string(n);
}
inline std::string to_string(float n)
{
return detail::arithmetic_to_string(n);
}
inline std::string to_string(double n)
{
return detail::arithmetic_to_string(n);
}
inline std::string to_string(long double n)
{
return detail::arithmetic_to_string(n);
}
#ifdef HAS_LONG_LONG
inline std::string to_string(long long n)
{
return detail::arithmetic_to_string(n);
}
inline std::string to_string(unsigned long long n)
{
return detail::arithmetic_to_string(n);
}
#endif
inline std::wstring to_wstring(int n)
{
return detail::arithmetic_to_wstring(n);
}
inline std::wstring to_wstring(unsigned n)
{
return detail::arithmetic_to_wstring(n);
}
inline std::wstring to_wstring(long n)
{
return detail::arithmetic_to_wstring(n);
}
inline std::wstring to_wstring(unsigned long n)
{
return detail::arithmetic_to_wstring(n);
}
#ifdef HAS_LONG_LONG
inline std::wstring to_wstring(long long n)
{
return detail::arithmetic_to_wstring(n);
}
inline std::wstring to_wstring(unsigned long long n)
{
return detail::arithmetic_to_wstring(n);
}
#endif
inline std::wstring to_wstring(float n)
{
return detail::arithmetic_to_wstring(n);
}
inline std::wstring to_wstring(double n)
{
return detail::arithmetic_to_wstring(n);
}
inline std::wstring to_wstring(long double n)
{
return detail::arithmetic_to_wstring(n);
}
}
#endif // ifndef CPP11
#endif // PBL_CPP_STRING_H

@ -0,0 +1,222 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_STRING_VIEW_H
#define PBL_CPP_STRING_VIEW_H
#include "version.h"
#ifdef CPP17
#include <string_view>
#else
#include <stdexcept>
#include <string>
#include <limits>
namespace cpp17
{
template< typename CharT, typename Traits = std::char_traits< CharT > >
class basic_string_view
{
public:
typedef Traits traits_type;
typedef CharT value_type;
typedef CharT* pointer;
typedef const CharT* const_pointer;
typedef CharT& reference;
typedef const CharT& const_reference;
typedef const CharT* const_iterator;
typedef const_iterator iterator;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
static const size_type npos = size_type(-1);
basic_string_view()
: first(0), len(0)
{
}
basic_string_view(const basic_string_view&) = default;
basic_string_view(
const CharT* s,
size_type count
)
: first(s), len(count)
{
}
basic_string_view(const CharT* s)
: first(s), len( Traits::length(s) )
{
}
basic_string_view& operator=(const basic_string_view&) = default;
const_iterator begin() const
{
return first;
}
const_iterator cbegin() const
{
return first;
}
const_iterator end() const
{
return first + len;
}
const_iterator cend() const
{
return first + len;
}
const_reference operator[](size_type i) const
{
return first[i];
}
const_reference at(size_type i) const
{
if ( i >= len )
{
throw std::out_of_range("Index is out of range for string view");
}
return first[i];
}
const_reference front() const
{
return first[0];
}
const_reference back() const
{
return first + ( len - 1 );
}
const_pointer data() const
{
return first;
}
size_type size() const
{
return len;
}
size_type length() const
{
return size();
}
size_type max_size() const
{
return static_cast< size_type >( std::numeric_limits< difference_type >::max() );
}
bool empty() const
{
return len == 0;
}
void remove_prefix(size_type n)
{
first += n;
}
void remove_suffix(size_type n)
{
len -= n;
}
void swap(basic_string_view& v)
{
const CharT* t = first;
first = v.first;
v.first = t;
size_type n = len;
len = v.len;
v.len = n;
}
size_type copy(
CharT* dest,
size_type count,
size_type pos = 0
) const
{
if ( pos < len )
{
const char* p = first + pos;
const size_type m = len - pos;
const size_type n = count < m ? count : m;
for ( size_t i = 0; i < n; ++i )
{
dest[i] = p[i];
}
return n;
}
return 0;
}
basic_string_view substr(
size_type pos = 0,
size_type count = npos
) const
{
const size_type n = ( pos < len )
? ( count <= len - pos ? count : len - pos )
: 0;
return basic_string_view(first + pos, n);
}
private:
const CharT* first;
size_type len;
};
typedef basic_string_view< char > string_view;
typedef basic_string_view< wchar_t > wstring_view;
#ifdef CPP11
typedef basic_string_view< char16_t > u16string_view;
typedef basic_string_view< char32_t > u32string_view;
#endif
}
#endif // ifdef CPP17
#endif // STRING_VIEW_H

@ -0,0 +1,43 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_SYSTEM_ERROR_H
#define PBL_CPP_SYSTEM_ERROR_H
#include "version.h"
#ifdef CPP11
#include <system_error>
#else
namespace cpp11
{
typedef int error_code;
}
#endif
#endif // PBL_CPP_SYSTEM_ERROR_H

@ -0,0 +1,235 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "thread.h"
#ifndef CPP11
#include <stdexcept>
#include <algorithm>
#include <unistd.h>
#if ( !defined( POSIX_THREADS ) && !defined( OS_WINDOWS ) )
#error "Threads are not supported on this platform"
#endif
namespace
{
#ifdef POSIX_THREADS
static void* start(void* arg)
#elif defined( OS_WINDOWS )
static DWORD start(void* arg) // to match LPTHREAD_START_ROUTINE
#endif
{
cpp11::details::runnable* func = static_cast< cpp11::details::runnable* >( arg );
func->operator()();
delete func;
return 0;
}
}
namespace cpp11
{
thread::thread()
: tid()
{
}
thread::~thread()
{
if ( joinable() )
{
std::terminate();
}
}
thread::id thread::get_id() const
{
return tid;
}
void thread::swap(thread& t)
{
std::swap(tid, t.tid);
}
void thread::run(details::runnable* c)
{
#ifdef POSIX_THREADS
native_handle_type tid_;
int res = pthread_create( &tid_, 0, start, static_cast< void* >( c ) );
if ( res != 0 )
{
throw std::runtime_error("Could not create thread");
}
tid = id(tid_);
#elif defined( OS_WINDOWS )
native_handle_type res = CreateThread(NULL, 0, reinterpret_cast< LPTHREAD_START_ROUTINE >( start ), static_cast< void* >( c ), 0, 0);
if ( res == NULL )
{
throw std::runtime_error("Could not create thread");
}
tid = id(res);
#endif
}
bool thread::joinable() const
{
return tid != id();
}
void thread::join()
{
if ( joinable() )
{
#ifdef POSIX_THREADS
void* arg;
int res = pthread_join(tid.tid, &arg);
if ( res != 0 )
{
throw std::runtime_error("Thread could not be joined.");
}
#elif defined( OS_WINDOWS )
DWORD res = WaitForSingleObject(tid, INFINITE);
#endif
tid = id();
}
}
void thread::detach()
{
if ( joinable() )
{
#ifdef POSIX_THREADS
pthread_detach(tid.tid);
#elif defined( OS_WINDOWS )
/// @todo Anything to be done here? Doesn't seem so.
#endif
tid = id();
}
}
unsigned thread::hardware_concurrancy()
{
return 0;
}
// =============================================================================
thread::id::id()
: valid(false), tid()
{
}
thread::id::id(const id& x)
: valid(x.valid), tid(x.tid)
{
}
thread::id::id(thread::native_handle_type t)
: valid(true), tid(t)
{
}
thread::id& thread::id::operator=(const id& x)
{
valid = x.valid;
tid = x.tid;
return *this;
}
bool thread::id::operator==(const id& y) const
{
return ( valid && y.valid && tid == y.tid ) || ( !valid && !y.valid );
}
bool thread::id::operator!=(const id& y) const
{
return ( valid && y.valid && tid != y.tid ) || ( valid != y.valid );
}
bool thread::id::operator<(const id& y) const
{
return ( valid && y.valid && tid < y.tid ) || ( !valid && y.valid );
}
bool thread::id::operator<=(const id& y) const
{
return ( valid && y.valid && tid <= y.tid ) || ( !valid );
}
bool thread::id::operator>(const id& y) const
{
return ( valid && y.valid && tid > y.tid ) || ( valid && !y.valid );
}
bool thread::id::operator>=(const id& y) const
{
return ( valid && y.valid && tid >= y.tid ) || ( !y.valid );
}
template< class charT, class traits >
std::basic_ostream< charT, traits >& operator<<(
std::basic_ostream< charT, traits >& os,
thread::id i
)
{
if ( i.valid )
{
os << i.tid;
}
else
{
os << "(null)";
}
return os;
}
namespace details
{
void microsleep(const ::cpp11::chrono::microseconds& dt)
{
::usleep( static_cast< useconds_t >( dt.count() ) );
}
}
} // end namespace cpp11
#endif // ifndef CPP11

@ -0,0 +1,271 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_THREAD_H
#define PBL_CPP_THREAD_H
#include "version.h"
#ifdef CPP11
#include <thread>
#else
#include <iosfwd>
#include "rvalueref.h"
#include "chrono.h"
#include "config/os.h"
namespace cpp11
{
namespace details
{
class runnable
{
public:
virtual ~runnable()
{
}
virtual void operator()() = 0;
};
}
/// @todo Use C++17 invoke on the backend
class thread
{
template< typename F, typename Arg1 = void, typename Arg2 = void, typename Arg3 = void >
class runnable_wrapper
: public details::runnable
{
public:
runnable_wrapper(
F f_,
const Arg1& a1_,
const Arg2& a2_,
const Arg3& a3_
)
: f(f_), a1(a1_), a2(a2_), a3(a3_)
{
}
void operator()()
{
f(a1, a2, a3);
}
private:
F f;
Arg1 a1;
Arg2 a2;
Arg3 a3;
};
template< typename F, typename Arg1 >
class runnable_wrapper< F, Arg1, void, void >
: public details::runnable
{
public:
runnable_wrapper(
F f_,
const Arg1& a1_
)
: f(f_), a1(a1_)
{
}
void operator()()
{
f(a1);
}
private:
F f;
Arg1 a1;
};
template< typename R, typename C >
class runnable_wrapper< R ( C::* )(), C*, void, void >
: public details::runnable
{
public:
typedef R (C::* F)();
runnable_wrapper(
F f_,
C* a1_
)
: f(f_), a1(a1_)
{
}
void operator()()
{
( a1->*f )();
}
private:
F f;
C* a1;
};
template< typename F >
class runnable_wrapper< F, void, void, void >
: public details::runnable
{
public:
explicit runnable_wrapper(F f_)
: f(f_)
{
}
runnable_wrapper(rvalue_reference< F > f_)
: f(f_)
{
}
void operator()()
{
f();
}
private:
F f;
};
public:
typedef ::pbl::os::thread_type native_handle_type;
class id
{
friend class thread;
bool valid;
native_handle_type tid;
explicit id(native_handle_type);
public:
id();
id(const id&);
id& operator=(const id&);
bool operator==(const id&) const;
bool operator!=(const id&) const;
bool operator<(const id&) const;
bool operator<=(const id&) const;
bool operator>(const id&) const;
bool operator>=(const id&) const;
template< class charT, class traits >
friend std::basic_ostream< charT, traits >& operator<<(std::basic_ostream< charT, traits >&, id);
};
thread();
/// @note func must be copyable. thread::start<F> takes ownership of the copy
/// @todo Move the platform specific code to thread.cpp
template< class F >
explicit thread(F func)
: tid()
{
run( new runnable_wrapper< F >(func) );
}
/// @bug Should be copying decayed value
template< class F, class Arg1 >
thread(
F func,
const Arg1& arg1
)
: tid()
{
run( new runnable_wrapper< F, Arg1 >(func, arg1) );
}
template< class F >
explicit thread(rvalue_reference< F > func)
: tid()
{
run( new runnable_wrapper< F >(func) );
}
template< class F, class Arg1, class Arg2, class Arg3 >
thread(
F func,
const Arg1& a1,
const Arg2& a2,
const Arg3& a3
)
: tid()
{
run( new runnable_wrapper< F, Arg1, Arg2, Arg3 >(func, a1, a2, a3) );
}
~thread();
void swap(thread&);
bool joinable() const;
void join();
void detach();
id get_id() const;
native_handle_type native_handle();
static unsigned hardware_concurrancy();
private:
thread(const thread&); // non-copyable
thread& operator=(const thread&); // non-copyable
void run(details::runnable* c);
id tid;
};
template< class charT, class traits >
std::basic_ostream< charT, traits >& operator<<(std::basic_ostream< charT, traits >&, thread::id);
namespace details
{
void microsleep(const ::cpp11::chrono::microseconds& dt);
}
namespace this_thread
{
template< class Rep, class Period >
void sleep_for(const ::cpp11::chrono::duration< Rep, Period >& dt)
{
details::microsleep( ::cpp11::chrono::duration_cast< ::cpp11::chrono::microseconds >(dt) );
}
}
}
#endif // ifdef CPP11
#endif // ifndef PBL_CPP_THREAD_H

@ -0,0 +1,64 @@
/* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBL_CPP_TRAITS_ADD_CV_H
#define PBL_CPP_TRAITS_ADD_CV_H
#ifndef CPP11
namespace cpp11
{
template< class T >
struct add_const {typedef const T type;};
template< class T >
struct add_volatile {typedef volatile T type;};
template< class T >
struct add_cv
{
typedef typename add_volatile< typename add_const< T >::type >::type type;
};
}
#else
#ifndef CPP14
namespace cpp14
{
template< class T >
using add_const_t = typename std::add_const< T >::type;
template< class T >
using add_volatile_t = typename std::add_volatile< T >::type;
template< class T >
using add_cv_t = typename std::add_cv< T >::type;
}
#endif
#endif // ifndef CPP11
#endif // PBL_CPP_TRAITS_ADD_CV_H

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

Loading…
Cancel
Save