mirror of https://github.com/oxen-io/lokinet
vendor c++17 backport with my changes to make it compile in xcode
parent
72bc32dcf4
commit
9d5a79ab18
@ -0,0 +1 @@
|
||||
*.user
|
@ -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 @@
|
||||
[General]
|
@ -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,3 @@
|
||||
lib
|
||||
examples
|
||||
.
|
@ -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…
Reference in New Issue