From a15cf65c44d5c224169c32ef5495b68c758134b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sun, 18 May 2014 16:08:14 +0200 Subject: Imported Upstream version 3.3.0.2 --- libcult/cult/cli/arguments.cxx | 22 + libcult/cult/cli/arguments.hxx | 85 +++ libcult/cult/cli/arguments.ixx | 21 + libcult/cult/cli/exceptions.hxx | 136 ++++ libcult/cult/cli/file-arguments.cxx | 118 ++++ libcult/cult/cli/file-arguments.hxx | 59 ++ libcult/cult/cli/mapper.hxx.m4 | 65 ++ libcult/cult/cli/options-parser.cxx | 40 ++ libcult/cult/cli/options-parser.hxx | 570 ++++++++++++++++ libcult/cult/cli/options-parser.ixx | 12 + libcult/cult/cli/options-parser.txx | 34 + libcult/cult/cli/options-spec.cxx | 14 + libcult/cult/cli/options-spec.hxx | 723 +++++++++++++++++++++ libcult/cult/cli/options-spec.ixx | 12 + libcult/cult/cli/options-spec.txx | 320 +++++++++ libcult/cult/cli/options.cxx | 17 + libcult/cult/cli/options.hxx | 502 ++++++++++++++ libcult/cult/cli/options.ixx | 12 + libcult/cult/cli/options.txx | 320 +++++++++ libcult/cult/cli/scanner.cxx | 17 + libcult/cult/cli/scanner.hxx | 132 ++++ libcult/cult/cli/scanner.ixx | 12 + libcult/cult/containers/any.hxx | 192 ++++++ libcult/cult/containers/any.txx | 11 + libcult/cult/containers/deque.hxx | 166 +++++ libcult/cult/containers/graph.hxx | 193 ++++++ libcult/cult/containers/graph.txx | 313 +++++++++ libcult/cult/containers/iterator.hxx | 227 +++++++ libcult/cult/containers/list.hxx | 193 ++++++ libcult/cult/containers/map.hxx | 175 +++++ libcult/cult/containers/pair.hxx | 58 ++ libcult/cult/containers/set.hxx | 175 +++++ libcult/cult/containers/stack.hxx | 95 +++ libcult/cult/containers/vector.hxx | 164 +++++ libcult/cult/dr/xdr/input-stream.cxx | 152 +++++ libcult/cult/dr/xdr/input-stream.hxx | 78 +++ libcult/cult/dr/xdr/output-stream.cxx | 222 +++++++ libcult/cult/dr/xdr/output-stream.hxx | 89 +++ libcult/cult/eh/exception.cxx | 27 + libcult/cult/eh/exception.hxx | 25 + libcult/cult/makefile | 160 +++++ libcult/cult/meta/answer.hxx | 27 + libcult/cult/meta/class-p.hxx | 33 + libcult/cult/meta/polymorphic-p.hxx | 56 ++ libcult/cult/meta/remove-c.hxx | 27 + libcult/cult/meta/remove-cv.hxx | 24 + libcult/cult/meta/remove-v.hxx | 27 + libcult/cult/mm/arch/generic/counter.hxx | 45 ++ libcult/cult/mm/arch/generic/counter.ixx | 47 ++ libcult/cult/mm/arch/i386/counter.hxx | 43 ++ libcult/cult/mm/arch/i386/counter.ixx | 46 ++ .../mm/arch/i386/i486/i586/i686/x86_64/counter.hxx | 43 ++ .../mm/arch/i386/i486/i586/i686/x86_64/counter.ixx | 46 ++ libcult/cult/mm/bits/evptr.hxx | 379 +++++++++++ libcult/cult/mm/bits/shptr.hxx | 85 +++ libcult/cult/mm/buffer.cxx | 140 ++++ libcult/cult/mm/buffer.hxx | 80 +++ libcult/cult/mm/counter.cxx | 14 + libcult/cult/mm/counter.hxx | 79 +++ libcult/cult/mm/counter.ixx | 38 ++ libcult/cult/mm/evptr.hxx | 221 +++++++ libcult/cult/mm/exception.hxx | 31 + libcult/cult/mm/new.cxx | 192 ++++++ libcult/cult/mm/new.hxx | 297 +++++++++ libcult/cult/mm/new.ixx | 36 + libcult/cult/mm/shptr.hxx | 139 ++++ libcult/cult/mm/static-ptr.hxx | 75 +++ libcult/cult/os/exception.cxx | 13 + libcult/cult/os/exception.hxx | 46 ++ libcult/cult/os/net/address.cxx | 37 ++ libcult/cult/os/net/address.hxx | 60 ++ libcult/cult/os/net/datagram-socket.cxx | 26 + libcult/cult/os/net/datagram-socket.hxx | 57 ++ libcult/cult/os/net/ipv4/address.cxx | 37 ++ libcult/cult/os/net/ipv4/address.hxx | 143 ++++ libcult/cult/os/net/ipv4/datagram-socket.cxx | 20 + libcult/cult/os/net/ipv4/datagram-socket.hxx | 282 ++++++++ libcult/cult/os/net/ipv4/multicast-socket.cxx | 19 + libcult/cult/os/net/ipv4/multicast-socket.hxx | 133 ++++ libcult/cult/os/net/multicast-socket.cxx | 26 + libcult/cult/os/net/multicast-socket.hxx | 40 ++ libcult/cult/os/net/socket.cxx | 26 + libcult/cult/os/net/socket.hxx | 54 ++ libcult/cult/rtti/type-id.hxx | 52 ++ libcult/cult/rtti/type-id.ixx | 45 ++ libcult/cult/rtti/type-id.txx | 18 + libcult/cult/rtti/type-info.cxx | 42 ++ libcult/cult/rtti/type-info.hxx | 147 +++++ libcult/cult/rtti/type-info.ixx | 87 +++ libcult/cult/sched/condition.cxx | 49 ++ libcult/cult/sched/condition.hxx | 42 ++ libcult/cult/sched/exception.hxx | 30 + libcult/cult/sched/lock.cxx | 13 + libcult/cult/sched/lock.hxx | 58 ++ libcult/cult/sched/mutex.cxx | 54 ++ libcult/cult/sched/mutex.hxx | 41 ++ libcult/cult/sched/spin.cxx | 28 + libcult/cult/sched/spin.hxx | 41 ++ libcult/cult/sched/spin.ixx | 43 ++ libcult/cult/sched/thread.cxx | 211 ++++++ libcult/cult/sched/thread.hxx | 86 +++ libcult/cult/trace/log.cxx | 49 ++ libcult/cult/trace/log.hxx | 51 ++ libcult/cult/trace/log.ixx | 20 + libcult/cult/trace/null/record.ixx | 45 ++ libcult/cult/trace/null/record.txx | 18 + libcult/cult/trace/null/stream.ixx | 67 ++ libcult/cult/trace/null/stream.txx | 18 + libcult/cult/trace/record.hxx | 86 +++ libcult/cult/trace/record.ixx | 45 ++ libcult/cult/trace/record.txx | 19 + libcult/cult/trace/stream.hxx | 74 +++ libcult/cult/trace/stream.ixx | 76 +++ libcult/cult/trace/stream.txx | 19 + libcult/cult/types.hxx | 14 + libcult/cult/types/evptr.hxx | 21 + libcult/cult/types/fundamental.hxx | 175 +++++ libcult/cult/types/shptr.hxx | 21 + libcult/cult/types/string.hxx | 397 +++++++++++ 119 files changed, 11549 insertions(+) create mode 100644 libcult/cult/cli/arguments.cxx create mode 100644 libcult/cult/cli/arguments.hxx create mode 100644 libcult/cult/cli/arguments.ixx create mode 100644 libcult/cult/cli/exceptions.hxx create mode 100644 libcult/cult/cli/file-arguments.cxx create mode 100644 libcult/cult/cli/file-arguments.hxx create mode 100644 libcult/cult/cli/mapper.hxx.m4 create mode 100644 libcult/cult/cli/options-parser.cxx create mode 100644 libcult/cult/cli/options-parser.hxx create mode 100644 libcult/cult/cli/options-parser.ixx create mode 100644 libcult/cult/cli/options-parser.txx create mode 100644 libcult/cult/cli/options-spec.cxx create mode 100644 libcult/cult/cli/options-spec.hxx create mode 100644 libcult/cult/cli/options-spec.ixx create mode 100644 libcult/cult/cli/options-spec.txx create mode 100644 libcult/cult/cli/options.cxx create mode 100644 libcult/cult/cli/options.hxx create mode 100644 libcult/cult/cli/options.ixx create mode 100644 libcult/cult/cli/options.txx create mode 100644 libcult/cult/cli/scanner.cxx create mode 100644 libcult/cult/cli/scanner.hxx create mode 100644 libcult/cult/cli/scanner.ixx create mode 100644 libcult/cult/containers/any.hxx create mode 100644 libcult/cult/containers/any.txx create mode 100644 libcult/cult/containers/deque.hxx create mode 100644 libcult/cult/containers/graph.hxx create mode 100644 libcult/cult/containers/graph.txx create mode 100644 libcult/cult/containers/iterator.hxx create mode 100644 libcult/cult/containers/list.hxx create mode 100644 libcult/cult/containers/map.hxx create mode 100644 libcult/cult/containers/pair.hxx create mode 100644 libcult/cult/containers/set.hxx create mode 100644 libcult/cult/containers/stack.hxx create mode 100644 libcult/cult/containers/vector.hxx create mode 100644 libcult/cult/dr/xdr/input-stream.cxx create mode 100644 libcult/cult/dr/xdr/input-stream.hxx create mode 100644 libcult/cult/dr/xdr/output-stream.cxx create mode 100644 libcult/cult/dr/xdr/output-stream.hxx create mode 100644 libcult/cult/eh/exception.cxx create mode 100644 libcult/cult/eh/exception.hxx create mode 100644 libcult/cult/makefile create mode 100644 libcult/cult/meta/answer.hxx create mode 100644 libcult/cult/meta/class-p.hxx create mode 100644 libcult/cult/meta/polymorphic-p.hxx create mode 100644 libcult/cult/meta/remove-c.hxx create mode 100644 libcult/cult/meta/remove-cv.hxx create mode 100644 libcult/cult/meta/remove-v.hxx create mode 100644 libcult/cult/mm/arch/generic/counter.hxx create mode 100644 libcult/cult/mm/arch/generic/counter.ixx create mode 100644 libcult/cult/mm/arch/i386/counter.hxx create mode 100644 libcult/cult/mm/arch/i386/counter.ixx create mode 100644 libcult/cult/mm/arch/i386/i486/i586/i686/x86_64/counter.hxx create mode 100644 libcult/cult/mm/arch/i386/i486/i586/i686/x86_64/counter.ixx create mode 100644 libcult/cult/mm/bits/evptr.hxx create mode 100644 libcult/cult/mm/bits/shptr.hxx create mode 100644 libcult/cult/mm/buffer.cxx create mode 100644 libcult/cult/mm/buffer.hxx create mode 100644 libcult/cult/mm/counter.cxx create mode 100644 libcult/cult/mm/counter.hxx create mode 100644 libcult/cult/mm/counter.ixx create mode 100644 libcult/cult/mm/evptr.hxx create mode 100644 libcult/cult/mm/exception.hxx create mode 100644 libcult/cult/mm/new.cxx create mode 100644 libcult/cult/mm/new.hxx create mode 100644 libcult/cult/mm/new.ixx create mode 100644 libcult/cult/mm/shptr.hxx create mode 100644 libcult/cult/mm/static-ptr.hxx create mode 100644 libcult/cult/os/exception.cxx create mode 100644 libcult/cult/os/exception.hxx create mode 100644 libcult/cult/os/net/address.cxx create mode 100644 libcult/cult/os/net/address.hxx create mode 100644 libcult/cult/os/net/datagram-socket.cxx create mode 100644 libcult/cult/os/net/datagram-socket.hxx create mode 100644 libcult/cult/os/net/ipv4/address.cxx create mode 100644 libcult/cult/os/net/ipv4/address.hxx create mode 100644 libcult/cult/os/net/ipv4/datagram-socket.cxx create mode 100644 libcult/cult/os/net/ipv4/datagram-socket.hxx create mode 100644 libcult/cult/os/net/ipv4/multicast-socket.cxx create mode 100644 libcult/cult/os/net/ipv4/multicast-socket.hxx create mode 100644 libcult/cult/os/net/multicast-socket.cxx create mode 100644 libcult/cult/os/net/multicast-socket.hxx create mode 100644 libcult/cult/os/net/socket.cxx create mode 100644 libcult/cult/os/net/socket.hxx create mode 100644 libcult/cult/rtti/type-id.hxx create mode 100644 libcult/cult/rtti/type-id.ixx create mode 100644 libcult/cult/rtti/type-id.txx create mode 100644 libcult/cult/rtti/type-info.cxx create mode 100644 libcult/cult/rtti/type-info.hxx create mode 100644 libcult/cult/rtti/type-info.ixx create mode 100644 libcult/cult/sched/condition.cxx create mode 100644 libcult/cult/sched/condition.hxx create mode 100644 libcult/cult/sched/exception.hxx create mode 100644 libcult/cult/sched/lock.cxx create mode 100644 libcult/cult/sched/lock.hxx create mode 100644 libcult/cult/sched/mutex.cxx create mode 100644 libcult/cult/sched/mutex.hxx create mode 100644 libcult/cult/sched/spin.cxx create mode 100644 libcult/cult/sched/spin.hxx create mode 100644 libcult/cult/sched/spin.ixx create mode 100644 libcult/cult/sched/thread.cxx create mode 100644 libcult/cult/sched/thread.hxx create mode 100644 libcult/cult/trace/log.cxx create mode 100644 libcult/cult/trace/log.hxx create mode 100644 libcult/cult/trace/log.ixx create mode 100644 libcult/cult/trace/null/record.ixx create mode 100644 libcult/cult/trace/null/record.txx create mode 100644 libcult/cult/trace/null/stream.ixx create mode 100644 libcult/cult/trace/null/stream.txx create mode 100644 libcult/cult/trace/record.hxx create mode 100644 libcult/cult/trace/record.ixx create mode 100644 libcult/cult/trace/record.txx create mode 100644 libcult/cult/trace/stream.hxx create mode 100644 libcult/cult/trace/stream.ixx create mode 100644 libcult/cult/trace/stream.txx create mode 100644 libcult/cult/types.hxx create mode 100644 libcult/cult/types/evptr.hxx create mode 100644 libcult/cult/types/fundamental.hxx create mode 100644 libcult/cult/types/shptr.hxx create mode 100644 libcult/cult/types/string.hxx (limited to 'libcult/cult') diff --git a/libcult/cult/cli/arguments.cxx b/libcult/cult/cli/arguments.cxx new file mode 100644 index 0000000..28805d0 --- /dev/null +++ b/libcult/cult/cli/arguments.cxx @@ -0,0 +1,22 @@ +// file : cult/cli/arguments.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace CLI + { + Arguments:: + ~Arguments () + { + } + + BasicArguments:: + ~BasicArguments () + { + } + } +} diff --git a/libcult/cult/cli/arguments.hxx b/libcult/cult/cli/arguments.hxx new file mode 100644 index 0000000..5381172 --- /dev/null +++ b/libcult/cult/cli/arguments.hxx @@ -0,0 +1,85 @@ +// file : cult/cli/arguments.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_CLI_ARGUMENTS_HXX +#define CULT_CLI_ARGUMENTS_HXX + +#include + +#include + +namespace Cult +{ + namespace CLI + { + class Arguments: public NonCopyable + { + public: + virtual + ~Arguments (); + + public: + class Bounds: public virtual Exception {}; + + virtual Size + size () const = 0; + + virtual Char const* + operator[] (Index) const = 0; + + virtual Void + erase (Index) = 0; + }; + + class BasicArguments: public Arguments + { + public: + virtual + ~BasicArguments (); + + BasicArguments (Int& argc, Char** argv); + + public: + virtual Size + size () const + { + return static_cast (argc_); + } + + virtual Char const* + operator[] (Index i) const + { + if (i >= size ()) + throw Bounds (); + + return argv_[i]; + } + + virtual Void + erase (Index i) + { + if (i >= size ()) + throw Bounds (); + + for (++i; i < size (); ++i) + { + argv_[i - 1] = argv_[i]; + } + + --argc_; + + argv_[argc_] = 0; + } + + private: + Int& argc_; + Char** argv_; + }; + } +} + +#include + +#endif // CULT_CLI_ARGUMENTS_HXX diff --git a/libcult/cult/cli/arguments.ixx b/libcult/cult/cli/arguments.ixx new file mode 100644 index 0000000..b05295d --- /dev/null +++ b/libcult/cult/cli/arguments.ixx @@ -0,0 +1,21 @@ +// file : cult/cli/arguments.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace CLI + { + inline + BasicArguments:: + BasicArguments (Int& argc, Char** argv) + : argc_ (argc), argv_ (argv) + { + assert (argc > 0); + } + } +} + diff --git a/libcult/cult/cli/exceptions.hxx b/libcult/cult/cli/exceptions.hxx new file mode 100644 index 0000000..886e008 --- /dev/null +++ b/libcult/cult/cli/exceptions.hxx @@ -0,0 +1,136 @@ +// file : cult/cli/exceptions.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_CLI_EXCEPTIONS_HXX +#define CULT_CLI_EXCEPTIONS_HXX + +#include + +#include + +namespace Cult +{ + namespace CLI + { + // + // + class Exception: public virtual EH::Exception + { + }; + + // Exception for FileArguments class. + // + class OptionFile: public virtual Exception + { + public: + ~OptionFile () throw () + { + } + + OptionFile (String const& description) + : description_ (description) + { + } + + OptionFile (String const& value, + String const& description) + : value_ (value), description_ (description) + { + } + + String const& + value () const + { + return value_; + } + + String const& + description () const + { + return description_; + } + + private: + String value_; + String description_; + }; + + // + // + class UnexpectedOption: public virtual Exception + { + public: + ~UnexpectedOption () throw () + { + } + + UnexpectedOption (String const& option) + : option_ (option) + { + } + + String const& + option () const + { + return option_; + } + + private: + String option_; + }; + + + // + // + class UnexpectedArgument: public virtual Exception + { + public: + ~UnexpectedArgument () throw () + { + } + + UnexpectedArgument (String const& argument) + : argument_ (argument) + { + } + + String const& + argument () const + { + return argument_; + } + + private: + String argument_; + }; + + + // + // + class OptionFormat: public virtual Exception + { + public: + ~OptionFormat () throw () + { + } + + OptionFormat (String const& option) + : option_ (option) + { + } + + String const& + option () const + { + return option_; + } + + private: + String option_; + }; + } +} + +#endif // CULT_CLI_EXCEPTIONS_HXX diff --git a/libcult/cult/cli/file-arguments.cxx b/libcult/cult/cli/file-arguments.cxx new file mode 100644 index 0000000..4f082dc --- /dev/null +++ b/libcult/cult/cli/file-arguments.cxx @@ -0,0 +1,118 @@ +// file : cult/cli/file-arguments.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strcmp +#include + +#include + +namespace Cult +{ + namespace CLI + { + FileArguments:: + ~FileArguments () + { + } + + FileArguments:: + FileArguments (Int argc, Char const* const* argv, Char const* op) + { + using namespace std; + + if (argc == 0) + return; + + args_.push_back (argv[0]); + + Boolean skip (false); + + for (Int i (1); i < argc; ++i) + { + if (!skip) + { + if (strcmp (argv[i], "--") == 0) + { + skip = true; + } + else if (strcmp (argv[i], op) == 0) + { + ++i; + + if (i >= argc) + throw OptionFile ("missing file name"); + + ifstream is (argv[i]); + + if (!is.is_open ()) + throw OptionFile (argv[i], "unable to open in read mode"); + + while (!is.eof ()) + { + String line; + getline (is, line); + + if (is.fail () && !is.eof ()) + throw OptionFile (argv[i], "read failure"); + + Size size (line.size ()); + + // Trim the line from leading and trailing whitespaces. + // + if (size != 0) + { + const Char* f (line.data ()); + const Char* l (f + size); + + const Char* of (f); + while (f < l && (*f == ' ' || *f == '\t' || *f == '\r')) + ++f; + + --l; + + const Char* ol (l); + while (l > f && (*l == ' ' || *l == '\t' || *l == '\r')) + --l; + + if (f != of || l != ol) + line = f <= l ? String (f, l - f + 1) : String (); + } + + if (line.empty () || line[0] == '#') + continue; // Ignore empty lines, those that start with # + + Size pos (line.find (' ')); + + if (pos == String::npos) + args_.push_back (line); + else + { + Size size (line.size ()); + + args_.push_back (String (line, 0, pos)); + + // Skip leading whitespaces in the argument. + // + for (pos++; pos < size; pos++) + { + Char c (line[pos]); + + if (c != ' ' && c != '\t' && c != '\r') + break; + } + + args_.push_back (String (line, pos)); + } + } + + continue; + } + } + + args_.push_back (argv[i]); + } + } + } +} diff --git a/libcult/cult/cli/file-arguments.hxx b/libcult/cult/cli/file-arguments.hxx new file mode 100644 index 0000000..e14f53c --- /dev/null +++ b/libcult/cult/cli/file-arguments.hxx @@ -0,0 +1,59 @@ +// file : cult/cli/file-arguments.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_CLI_FILE_ARGUMENTS_HXX +#define CULT_CLI_FILE_ARGUMENTS_HXX + +#include +#include + +#include +#include + +namespace Cult +{ + namespace CLI + { + class FileArguments: public Arguments + { + public: + virtual + ~FileArguments (); + + FileArguments (Int argc, + Char const* const* argv, + Char const* file_option); + public: + virtual Size + size () const + { + return args_.size (); + } + + virtual Char const* + operator[] (Index i) const + { + if (i >= size ()) + throw Bounds (); + + return args_[i].c_str (); + } + + virtual Void + erase (Index i) + { + if (i >= size ()) + throw Bounds (); + + args_.erase (args_.begin () + i); + } + + private: + Containers::Vector args_; + }; + } +} + +#endif // CULT_CLI_FILE_ARGUMENTS_HXX diff --git a/libcult/cult/cli/mapper.hxx.m4 b/libcult/cult/cli/mapper.hxx.m4 new file mode 100644 index 0000000..7ac6760 --- /dev/null +++ b/libcult/cult/cli/mapper.hxx.m4 @@ -0,0 +1,65 @@ +divert(-1) + +# file : cult/cli/mapper.hxx.m4 +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +define(`N', 100) + +define(`forloop', + `pushdef(`$1', `$2')_forloop(`$1', `$2', `$3', `$4')popdef(`$1')') + +define(`_forloop', + `$4`'ifelse($1, `$3', , + `define(`$1', incr($1))_forloop(`$1', `$2', `$3', `$4')')') + +define(`specialization',` +template +< +forloop(`i', 1, $1, ` char const* x`'i, typename Y`'i`'ifelse(i, $1, ,`,') +')dnl +> +struct Mapper +< +forloop(`i', 1, $1, ` x`'i, Y`'i, +')dnl +forloop(`i', $1, N, ` null, Null`'ifelse(i, N, ,`,') +')dnl +> +{ +`#ifdef __GNUC__' +forloop(`i', 1, $1, ` static Y`'i f (Tag*); +')dnl + + template + struct Selector + { + typedef typeof (Mapper::f ((Tag*) (0))) Type; + }; +`#else' + template + struct Selector + { + typedef typename if_::r, Y1,ifelse($1, 1, ` Void', ` + typename Mapper + < +forloop(`i', 2, $1, ` x`'i, Y`'i`'ifelse(i, $1, ,`,') +') >::template Selector::Type')>::Type Type; + }; +`#endif' +}; +') + +divert(0)dnl + +template +< +forloop(`i', 1, incr(N), + ` char const* x`'i`'ifelse(i, 1, ,`= null'), dnl +typename Y`'i`'ifelse(i, 1, ,`= Null')`'ifelse(i, incr(N), ,`,') +')dnl +> +struct Mapper; + +forloop(`n', 1, N, `specialization(n)') diff --git a/libcult/cult/cli/options-parser.cxx b/libcult/cult/cli/options-parser.cxx new file mode 100644 index 0000000..4a2b6b3 --- /dev/null +++ b/libcult/cult/cli/options-parser.cxx @@ -0,0 +1,40 @@ +// file : cult/cli/options-parser.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace CLI + { + Trace::Stream OptionsParserBase::tout ("Cult::CLI::OptionsParser", 7); + + + // OptionParserBooleanBase + // + Boolean OptionParserBooleanBase:: + parse (Char const*, Scanner&) + { + return true; + } + + // OptionParserStringBase + // + String OptionParserStringBase:: + parse (Char const* o, Scanner& s) + { + Char const* v (s.next ()); + + if (v == Scanner::eos) + { + //@@ "expected string literal after --option"? + // + throw OptionFormat (o); + } + + return v; + } + } +} diff --git a/libcult/cult/cli/options-parser.hxx b/libcult/cult/cli/options-parser.hxx new file mode 100644 index 0000000..4068fa6 --- /dev/null +++ b/libcult/cult/cli/options-parser.hxx @@ -0,0 +1,570 @@ +// file : cult/cli/options-parser.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_CLI_OPTIONS_PARSER_HXX +#define CULT_CLI_OPTIONS_PARSER_HXX + +#include + +#include +#include + +#include + +#include +#include +#include + +#include + +//@! which types should be NonCopyable + +namespace Cult +{ + namespace CLI + { + struct UnknownMode + { + enum Value + { + skip, + stop, + fail + }; + }; + + template + struct OptionParserBase + { + T + parse (Char const* o, Scanner& s); + }; + + template + struct OptionParser: OptionParserBase + { + OptionParser (Spec const&) + { + } + }; + + template + class OptionParser > > + { + public: + OptionParser (OptionSpec > const&) + : impl_ (OptionSpec ()) + { + } + + T + parse (Char const* k, Scanner& s) + { + return impl_.parse (k, s); + } + + private: + OptionParser > impl_; + }; + + struct OptionParserBooleanBase + { + Boolean + parse (Char const*, Scanner& s); + }; + + template + struct OptionParser >: OptionParserBooleanBase + { + OptionParser (OptionSpec const&) + { + } + }; + + struct OptionParserStringBase + { + String + parse (Char const*, Scanner& s); + }; + + template + struct OptionParser >: OptionParserStringBase + { + OptionParser (OptionSpec const&) + { + } + }; + + // + // + // + + class OptionsParserBase + { + protected: + struct GlueBase + { + // I am using Void* here to (significantly) reduce the length + // on the object file symbols. + // + virtual Void + operator() (Char const*, Scanner&, Void* options) = 0; + }; + + static Trace::Stream tout; + }; + + template + class OptionsParser : OptionsParserBase + { + typedef + Containers::Map > + Map; + + template + struct Glue; + + template + struct Glue > : GlueBase + { + Glue (OptionSpec const& spec) + : parser_ (spec) + { + } + + virtual Void + operator() (Char const* o, Scanner& scan, Void* options) + { + typedef typename Spec::Options Options; + + Options& ops (*reinterpret_cast (options)); + + ops.template value () = parser_.parse (o, scan); + } + + private: + OptionParser > parser_; + }; + + //@@ It's bad that I also have to specialize Glue. Need to redesign + // this. + // + template + struct Glue > > : GlueBase + { + Glue (OptionSpec > const& spec) + : parser_ (spec) + { + } + + virtual Void + operator() (Char const* o, Scanner& scan, Void* options) + { + typedef typename Spec::Options Options; + + Options& ops (*reinterpret_cast (options)); + + ops.template value ().push_back (parser_.parse (o, scan)); + } + + private: + OptionParser > > parser_; + }; + + + // Option-specific specializations of some functions. + // + template + struct S_ + { + // This is a "specialization" for when type is Bits::Null. + // + static Void + add_parser (Spec const&, Map&) + { + } + + static Void + set_default (typename Spec::Options&, Spec const&) + { + } + }; + + template + struct S_ > + { + static Void + add_parser (Spec const& spec, Map& map) + { + if (k[0] != '\0') + { + OptionSpec const& os (spec.template option ()); + map[os.name ()] = new Glue > (os); + } + } + + static Void + set_default (typename Spec::Options& o, Spec const& s) + { + o.template value () = s.template option ().default_value (); + } + }; + + public: + + OptionsParser (Spec const& spec) + : spec_ (spec) + { + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + } + + + typename Spec::Options + parse (Scanner& scan, + UnknownMode::Value option_mode = UnknownMode::fail, + UnknownMode::Value argument_mode = UnknownMode::stop) + { + typename Spec::Options ops; + + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + + for (Char const* s (scan.peek ()); s != Scanner::eos; s = scan.peek ()) + { + tout << "looking at \"" << s << "\""; + + //@@ Std:: + // + if (strcmp (s, "--") == 0) + { + // We don't want to remove '--' if our option mode is skip. + // + if (option_mode == UnknownMode::skip) + scan.skip (); + else + scan.next (); + + break; + } + + typename Map::ConstIterator it (map_.find (s)); + + if (it != map_.end ()) + { + tout << "found parser for \"" << s << "\""; + + s = scan.next (); + (*(it->second)) (s, scan, &ops); + } + else if (s[0] == '-') + { + // Unknown option. + // + switch (option_mode) + { + case UnknownMode::skip: + { + scan.skip (); + continue; + } + case UnknownMode::stop: + { + break; + } + case UnknownMode::fail: + { + throw UnexpectedOption (s); + } + } + + break; // stop case + } + else + { + // Something else. + // + switch (argument_mode) + { + case UnknownMode::skip: + { + scan.skip (); + continue; + } + case UnknownMode::stop: + { + break; + } + case UnknownMode::fail: + { + throw UnexpectedArgument (s); + } + } + + break; // stop case + } + } + + return ops; + } + + private: + Map map_; + Spec spec_; + }; + + // + // + // + + template + typename Spec::Options + parse (Spec const& s, + Arguments& args, + UnknownMode::Value option_mode = UnknownMode::fail, + UnknownMode::Value argument_mode = UnknownMode::stop) + { + Scanner scan (args, Scanner::Action::erase); + OptionsParser parser (s); + + return parser.parse (scan, option_mode, argument_mode); + } + + template + Options + parse (Arguments& args, + UnknownMode::Value option_mode = UnknownMode::fail, + UnknownMode::Value argument_mode = UnknownMode::stop) + { + OptionsSpec spec; + return parse (spec, args, option_mode, argument_mode); + } + + template + typename Spec::Options + parse (Spec const& s, + Int& argc, + Char** argv, + UnknownMode::Value option_mode = UnknownMode::fail, + UnknownMode::Value argument_mode = UnknownMode::stop) + { + BasicArguments args (argc, argv); + return parse (s, args, option_mode, argument_mode); + } + + template + Options + parse (Int& argc, + Char** argv, + UnknownMode::Value option_mode = UnknownMode::fail, + UnknownMode::Value argument_mode = UnknownMode::stop) + { + OptionsSpec spec; + + return parse (spec, argc, argv, option_mode, argument_mode); + } + } +} + +#include +#include + +#endif // CULT_CLI_OPTIONS_PARSER_HXX diff --git a/libcult/cult/cli/options-parser.ixx b/libcult/cult/cli/options-parser.ixx new file mode 100644 index 0000000..80427f2 --- /dev/null +++ b/libcult/cult/cli/options-parser.ixx @@ -0,0 +1,12 @@ +// file : cult/cli/options-parser.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace CLI + { + } +} + diff --git a/libcult/cult/cli/options-parser.txx b/libcult/cult/cli/options-parser.txx new file mode 100644 index 0000000..bd8172a --- /dev/null +++ b/libcult/cult/cli/options-parser.txx @@ -0,0 +1,34 @@ +// file : cult/cli/options-parser.txx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace CLI + { + // OptionParserBase + // + template + T OptionParserBase:: + parse (Char const* o, Scanner& s) + { + Char const* v (s.next ()); + + //@@ "expected something after --option"? + // + if (v == Scanner::eos) + throw OptionFormat (o); + + T r; + std::istringstream is (v); + is >> r; + + if (is.fail () || !is.eof ()) + throw OptionFormat (o); + + return r; + } + } +} + diff --git a/libcult/cult/cli/options-spec.cxx b/libcult/cult/cli/options-spec.cxx new file mode 100644 index 0000000..9f1e43b --- /dev/null +++ b/libcult/cult/cli/options-spec.cxx @@ -0,0 +1,14 @@ +// file : cult/cli/options-spec.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace CLI + { + } +} + diff --git a/libcult/cult/cli/options-spec.hxx b/libcult/cult/cli/options-spec.hxx new file mode 100644 index 0000000..aff4541 --- /dev/null +++ b/libcult/cult/cli/options-spec.hxx @@ -0,0 +1,723 @@ +// file : cult/cli/options-spec.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_CLI_OPTIONS_SPEC_HXX +#define CULT_CLI_OPTIONS_SPEC_HXX + +#include + +#include + +namespace Cult +{ + namespace CLI + { + template + class OptionSpec + { + public: + static Char const* const key; + typedef T Type; + + public: + ~OptionSpec () + { + } + + OptionSpec () + : default_value_ (), + name_ ("--") + { + name_ += k; + } + + T const& + default_value () const + { + return default_value_; + } + + Void + default_value (T const& value) + { + default_value_ = value; + } + + //@@ bad name + // + Char const* + name () const + { + return name_.c_str (); + } + + private: + T default_value_; + String name_; + }; + + template + struct OptionSpecType + { + typedef OptionSpec Type; + }; + + template <> + struct OptionSpecType + { + typedef Bits::Null Type; + }; + + + template + Char const* const OptionSpec::key = k; + + template + class OptionsSpec; + + template + + class OptionsSpec > + { + public: + typedef CLI::Options Options; + + typedef typename OptionSpecType::Type o01; + typedef typename OptionSpecType::Type o02; + typedef typename OptionSpecType::Type o03; + typedef typename OptionSpecType::Type o04; + typedef typename OptionSpecType::Type o05; + typedef typename OptionSpecType::Type o06; + typedef typename OptionSpecType::Type o07; + typedef typename OptionSpecType::Type o08; + typedef typename OptionSpecType::Type o09; + typedef typename OptionSpecType::Type o10; + typedef typename OptionSpecType::Type o11; + typedef typename OptionSpecType::Type o12; + typedef typename OptionSpecType::Type o13; + typedef typename OptionSpecType::Type o14; + typedef typename OptionSpecType::Type o15; + typedef typename OptionSpecType::Type o16; + typedef typename OptionSpecType::Type o17; + typedef typename OptionSpecType::Type o18; + typedef typename OptionSpecType::Type o19; + typedef typename OptionSpecType::Type o20; + typedef typename OptionSpecType::Type o21; + typedef typename OptionSpecType::Type o22; + typedef typename OptionSpecType::Type o23; + typedef typename OptionSpecType::Type o24; + typedef typename OptionSpecType::Type o25; + typedef typename OptionSpecType::Type o26; + typedef typename OptionSpecType::Type o27; + typedef typename OptionSpecType::Type o28; + typedef typename OptionSpecType::Type o29; + typedef typename OptionSpecType::Type o30; + typedef typename OptionSpecType::Type o31; + typedef typename OptionSpecType::Type o32; + typedef typename OptionSpecType::Type o33; + typedef typename OptionSpecType::Type o34; + typedef typename OptionSpecType::Type o35; + typedef typename OptionSpecType::Type o36; + typedef typename OptionSpecType::Type o37; + typedef typename OptionSpecType::Type o38; + typedef typename OptionSpecType::Type o39; + typedef typename OptionSpecType::Type o40; + typedef typename OptionSpecType::Type o41; + typedef typename OptionSpecType::Type o42; + typedef typename OptionSpecType::Type o43; + typedef typename OptionSpecType::Type o44; + typedef typename OptionSpecType::Type o45; + typedef typename OptionSpecType::Type o46; + typedef typename OptionSpecType::Type o47; + typedef typename OptionSpecType::Type o48; + typedef typename OptionSpecType::Type o49; + typedef typename OptionSpecType::Type o50; + typedef typename OptionSpecType::Type o51; + typedef typename OptionSpecType::Type o52; + typedef typename OptionSpecType::Type o53; + typedef typename OptionSpecType::Type o54; + typedef typename OptionSpecType::Type o55; + typedef typename OptionSpecType::Type o56; + typedef typename OptionSpecType::Type o57; + typedef typename OptionSpecType::Type o58; + typedef typename OptionSpecType::Type o59; + typedef typename OptionSpecType::Type o60; + typedef typename OptionSpecType::Type o61; + typedef typename OptionSpecType::Type o62; + typedef typename OptionSpecType::Type o63; + typedef typename OptionSpecType::Type o64; + typedef typename OptionSpecType::Type o65; + typedef typename OptionSpecType::Type o66; + typedef typename OptionSpecType::Type o67; + typedef typename OptionSpecType::Type o68; + typedef typename OptionSpecType::Type o69; + typedef typename OptionSpecType::Type o70; + typedef typename OptionSpecType::Type o71; + typedef typename OptionSpecType::Type o72; + typedef typename OptionSpecType::Type o73; + typedef typename OptionSpecType::Type o74; + typedef typename OptionSpecType::Type o75; + typedef typename OptionSpecType::Type o76; + typedef typename OptionSpecType::Type o77; + typedef typename OptionSpecType::Type o78; + typedef typename OptionSpecType::Type o79; + typedef typename OptionSpecType::Type o80; + typedef typename OptionSpecType::Type o81; + typedef typename OptionSpecType::Type o82; + typedef typename OptionSpecType::Type o83; + typedef typename OptionSpecType::Type o84; + typedef typename OptionSpecType::Type o85; + typedef typename OptionSpecType::Type o86; + typedef typename OptionSpecType::Type o87; + typedef typename OptionSpecType::Type o88; + typedef typename OptionSpecType::Type o89; + typedef typename OptionSpecType::Type o90; + typedef typename OptionSpecType::Type o91; + typedef typename OptionSpecType::Type o92; + typedef typename OptionSpecType::Type o93; + typedef typename OptionSpecType::Type o94; + typedef typename OptionSpecType::Type o95; + typedef typename OptionSpecType::Type o96; + typedef typename OptionSpecType::Type o97; + typedef typename OptionSpecType::Type o98; + typedef typename OptionSpecType::Type o99; + typedef typename OptionSpecType::Type o100; + + + private: + typedef Bits::Mapper Mapper; + + public: + template + typename Mapper::template Selector::Type& + option () + { + typedef + typename Mapper::template Selector::Type + Type; + + return *reinterpret_cast (option (k)); + } + + template + typename Mapper::template Selector::Type const& + option () const + { + typedef + typename Mapper::template Selector::Type + Type; + + return *reinterpret_cast (option (k)); + } + + private: + Void* + option (Char const*) const; + + private: + o01 o01_; + o02 o02_; + o03 o03_; + o04 o04_; + o05 o05_; + o06 o06_; + o07 o07_; + o08 o08_; + o09 o09_; + o10 o10_; + o11 o11_; + o12 o12_; + o13 o13_; + o14 o14_; + o15 o15_; + o16 o16_; + o17 o17_; + o18 o18_; + o19 o19_; + o20 o20_; + o21 o21_; + o22 o22_; + o23 o23_; + o24 o24_; + o25 o25_; + o26 o26_; + o27 o27_; + o28 o28_; + o29 o29_; + o30 o30_; + o31 o31_; + o32 o32_; + o33 o33_; + o34 o34_; + o35 o35_; + o36 o36_; + o37 o37_; + o38 o38_; + o39 o39_; + o40 o40_; + o41 o41_; + o42 o42_; + o43 o43_; + o44 o44_; + o45 o45_; + o46 o46_; + o47 o47_; + o48 o48_; + o49 o49_; + o50 o50_; + o51 o51_; + o52 o52_; + o53 o53_; + o54 o54_; + o55 o55_; + o56 o56_; + o57 o57_; + o58 o58_; + o59 o59_; + o60 o60_; + o61 o61_; + o62 o62_; + o63 o63_; + o64 o64_; + o65 o65_; + o66 o66_; + o67 o67_; + o68 o68_; + o69 o69_; + o70 o70_; + o71 o71_; + o72 o72_; + o73 o73_; + o74 o74_; + o75 o75_; + o76 o76_; + o77 o77_; + o78 o78_; + o79 o79_; + o80 o80_; + o81 o81_; + o82 o82_; + o83 o83_; + o84 o84_; + o85 o85_; + o86 o86_; + o87 o87_; + o88 o88_; + o89 o89_; + o90 o90_; + o91 o91_; + o92 o92_; + o93 o93_; + o94 o94_; + o95 o95_; + o96 o96_; + o97 o97_; + o98 o98_; + o99 o99_; + o100 o100_; + }; + } +} + +#include +#include + +#endif // CULT_CLI_OPTIONS_SPEC_HXX diff --git a/libcult/cult/cli/options-spec.ixx b/libcult/cult/cli/options-spec.ixx new file mode 100644 index 0000000..1c47da1 --- /dev/null +++ b/libcult/cult/cli/options-spec.ixx @@ -0,0 +1,12 @@ +// file : cult/cli/options-spec.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace CLI + { + } +} + diff --git a/libcult/cult/cli/options-spec.txx b/libcult/cult/cli/options-spec.txx new file mode 100644 index 0000000..f5d59a0 --- /dev/null +++ b/libcult/cult/cli/options-spec.txx @@ -0,0 +1,320 @@ +// file : cult/cli/options-spec.txx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace CLI + { + template + Void* + OptionsSpec >:: + option (Char const* k) const + { + Void* r (0); + + if (k == k01) r = (Void*) (&o01_); else + if (k == k02) r = (Void*) (&o02_); else + if (k == k03) r = (Void*) (&o03_); else + if (k == k04) r = (Void*) (&o04_); else + if (k == k05) r = (Void*) (&o05_); else + if (k == k06) r = (Void*) (&o06_); else + if (k == k07) r = (Void*) (&o07_); else + if (k == k08) r = (Void*) (&o08_); else + if (k == k09) r = (Void*) (&o09_); else + if (k == k10) r = (Void*) (&o10_); else + if (k == k11) r = (Void*) (&o11_); else + if (k == k12) r = (Void*) (&o12_); else + if (k == k13) r = (Void*) (&o13_); else + if (k == k14) r = (Void*) (&o14_); else + if (k == k15) r = (Void*) (&o15_); else + if (k == k16) r = (Void*) (&o16_); else + if (k == k17) r = (Void*) (&o17_); else + if (k == k18) r = (Void*) (&o18_); else + if (k == k19) r = (Void*) (&o19_); else + if (k == k20) r = (Void*) (&o20_); else + if (k == k21) r = (Void*) (&o21_); else + if (k == k22) r = (Void*) (&o22_); else + if (k == k23) r = (Void*) (&o23_); else + if (k == k24) r = (Void*) (&o24_); else + if (k == k25) r = (Void*) (&o25_); else + if (k == k26) r = (Void*) (&o26_); else + if (k == k27) r = (Void*) (&o27_); else + if (k == k28) r = (Void*) (&o28_); else + if (k == k29) r = (Void*) (&o29_); else + if (k == k30) r = (Void*) (&o30_); else + if (k == k31) r = (Void*) (&o31_); else + if (k == k32) r = (Void*) (&o32_); else + if (k == k33) r = (Void*) (&o33_); else + if (k == k34) r = (Void*) (&o34_); else + if (k == k35) r = (Void*) (&o35_); else + if (k == k36) r = (Void*) (&o36_); else + if (k == k37) r = (Void*) (&o37_); else + if (k == k38) r = (Void*) (&o38_); else + if (k == k39) r = (Void*) (&o39_); else + if (k == k40) r = (Void*) (&o40_); else + if (k == k41) r = (Void*) (&o41_); else + if (k == k42) r = (Void*) (&o42_); else + if (k == k43) r = (Void*) (&o43_); else + if (k == k44) r = (Void*) (&o44_); else + if (k == k45) r = (Void*) (&o45_); else + if (k == k46) r = (Void*) (&o46_); else + if (k == k47) r = (Void*) (&o47_); else + if (k == k48) r = (Void*) (&o48_); else + if (k == k49) r = (Void*) (&o49_); else + if (k == k50) r = (Void*) (&o50_); else + if (k == k51) r = (Void*) (&o51_); else + if (k == k52) r = (Void*) (&o52_); else + if (k == k53) r = (Void*) (&o53_); else + if (k == k54) r = (Void*) (&o54_); else + if (k == k55) r = (Void*) (&o55_); else + if (k == k56) r = (Void*) (&o56_); else + if (k == k57) r = (Void*) (&o57_); else + if (k == k58) r = (Void*) (&o58_); else + if (k == k59) r = (Void*) (&o59_); else + if (k == k60) r = (Void*) (&o60_); else + if (k == k61) r = (Void*) (&o61_); else + if (k == k62) r = (Void*) (&o62_); else + if (k == k63) r = (Void*) (&o63_); else + if (k == k64) r = (Void*) (&o64_); else + if (k == k65) r = (Void*) (&o65_); else + if (k == k66) r = (Void*) (&o66_); else + if (k == k67) r = (Void*) (&o67_); else + if (k == k68) r = (Void*) (&o68_); else + if (k == k69) r = (Void*) (&o69_); else + if (k == k70) r = (Void*) (&o70_); else + if (k == k71) r = (Void*) (&o71_); else + if (k == k72) r = (Void*) (&o72_); else + if (k == k73) r = (Void*) (&o73_); else + if (k == k74) r = (Void*) (&o74_); else + if (k == k75) r = (Void*) (&o75_); else + if (k == k76) r = (Void*) (&o76_); else + if (k == k77) r = (Void*) (&o77_); else + if (k == k78) r = (Void*) (&o78_); else + if (k == k79) r = (Void*) (&o79_); else + if (k == k80) r = (Void*) (&o80_); else + if (k == k81) r = (Void*) (&o81_); else + if (k == k82) r = (Void*) (&o82_); else + if (k == k83) r = (Void*) (&o83_); else + if (k == k84) r = (Void*) (&o84_); else + if (k == k85) r = (Void*) (&o85_); else + if (k == k86) r = (Void*) (&o86_); else + if (k == k87) r = (Void*) (&o87_); else + if (k == k88) r = (Void*) (&o88_); else + if (k == k89) r = (Void*) (&o89_); else + if (k == k90) r = (Void*) (&o90_); else + if (k == k91) r = (Void*) (&o91_); else + if (k == k92) r = (Void*) (&o92_); else + if (k == k93) r = (Void*) (&o93_); else + if (k == k94) r = (Void*) (&o94_); else + if (k == k95) r = (Void*) (&o95_); else + if (k == k96) r = (Void*) (&o96_); else + if (k == k97) r = (Void*) (&o97_); else + if (k == k98) r = (Void*) (&o98_); else + if (k == k99) r = (Void*) (&o99_); else + if (k == k100) r = (Void*) (&o100_); else + assert (false); + + return r; + } + } +} diff --git a/libcult/cult/cli/options.cxx b/libcult/cult/cli/options.cxx new file mode 100644 index 0000000..6b6e996 --- /dev/null +++ b/libcult/cult/cli/options.cxx @@ -0,0 +1,17 @@ +// file : cult/cli/options.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace CLI + { + namespace Bits + { + extern Char const null[] = ""; + } + } +} diff --git a/libcult/cult/cli/options.hxx b/libcult/cult/cli/options.hxx new file mode 100644 index 0000000..2a780e1 --- /dev/null +++ b/libcult/cult/cli/options.hxx @@ -0,0 +1,502 @@ +// file : cult/cli/options.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_CLI_OPTIONS_HXX +#define CULT_CLI_OPTIONS_HXX + +#include + +#include + +namespace Cult +{ + namespace CLI + { + namespace Bits + { + template + struct if_; + + template + struct if_ + { + typedef X Type; + }; + + template + struct if_ + { + typedef Y Type; + }; + + template + struct same + { + static Boolean const r = false; + }; + + template + struct same + { + static Boolean const r = true; + }; + + template + struct Tag + { + }; + + //@@ should end up in Cult::Meta + // + struct Null {}; + extern Char const null[]; + +#include + + } + + template + class Options + { + typedef Bits::Mapper Mapper; + + public: + Options () + : i01_ (), + i02_ (), + i03_ (), + i04_ (), + i05_ (), + i06_ (), + i07_ (), + i08_ (), + i09_ (), + i10_ (), + i11_ (), + i12_ (), + i13_ (), + i14_ (), + i15_ (), + i16_ (), + i17_ (), + i18_ (), + i19_ (), + i20_ (), + i21_ (), + i22_ (), + i23_ (), + i24_ (), + i25_ (), + i26_ (), + i27_ (), + i28_ (), + i29_ (), + i30_ (), + i31_ (), + i32_ (), + i33_ (), + i34_ (), + i35_ (), + i36_ (), + i37_ (), + i38_ (), + i39_ (), + i40_ (), + i41_ (), + i42_ (), + i43_ (), + i44_ (), + i45_ (), + i46_ (), + i47_ (), + i48_ (), + i49_ (), + i50_ (), + i51_ (), + i52_ (), + i53_ (), + i54_ (), + i55_ (), + i56_ (), + i57_ (), + i58_ (), + i59_ (), + i60_ (), + i61_ (), + i62_ (), + i63_ (), + i64_ (), + i65_ (), + i66_ (), + i67_ (), + i68_ (), + i69_ (), + i70_ (), + i71_ (), + i72_ (), + i73_ (), + i74_ (), + i75_ (), + i76_ (), + i77_ (), + i78_ (), + i79_ (), + i80_ (), + i81_ (), + i82_ (), + i83_ (), + i84_ (), + i85_ (), + i86_ (), + i87_ (), + i88_ (), + i89_ (), + i90_ (), + i91_ (), + i92_ (), + i93_ (), + i94_ (), + i95_ (), + i96_ (), + i97_ (), + i98_ (), + i99_ (), + i100_ () + { + } + + template + typename Mapper::template Selector::Type& + value () + { + typedef + typename Mapper::template Selector::Type + Type; + + return *reinterpret_cast (value (k)); + } + + template + typename Mapper::template Selector::Type const& + value () const + { + typedef + typename Mapper::template Selector::Type + Type; + + return *reinterpret_cast (value (k)); + } + + private: + Void* + value (Char const*) const; + + private: + T01 i01_; + T02 i02_; + T03 i03_; + T04 i04_; + T05 i05_; + T06 i06_; + T07 i07_; + T08 i08_; + T09 i09_; + T10 i10_; + T11 i11_; + T12 i12_; + T13 i13_; + T14 i14_; + T15 i15_; + T16 i16_; + T17 i17_; + T18 i18_; + T19 i19_; + T20 i20_; + T21 i21_; + T22 i22_; + T23 i23_; + T24 i24_; + T25 i25_; + T26 i26_; + T27 i27_; + T28 i28_; + T29 i29_; + T30 i30_; + T31 i31_; + T32 i32_; + T33 i33_; + T34 i34_; + T35 i35_; + T36 i36_; + T37 i37_; + T38 i38_; + T39 i39_; + T40 i40_; + T41 i41_; + T42 i42_; + T43 i43_; + T44 i44_; + T45 i45_; + T46 i46_; + T47 i47_; + T48 i48_; + T49 i49_; + T50 i50_; + T51 i51_; + T52 i52_; + T53 i53_; + T54 i54_; + T55 i55_; + T56 i56_; + T57 i57_; + T58 i58_; + T59 i59_; + T60 i60_; + T61 i61_; + T62 i62_; + T63 i63_; + T64 i64_; + T65 i65_; + T66 i66_; + T67 i67_; + T68 i68_; + T69 i69_; + T70 i70_; + T71 i71_; + T72 i72_; + T73 i73_; + T74 i74_; + T75 i75_; + T76 i76_; + T77 i77_; + T78 i78_; + T79 i79_; + T80 i80_; + T81 i81_; + T82 i82_; + T83 i83_; + T84 i84_; + T85 i85_; + T86 i86_; + T87 i87_; + T88 i88_; + T89 i89_; + T90 i90_; + T91 i91_; + T92 i92_; + T93 i93_; + T94 i94_; + T95 i95_; + T96 i96_; + T97 i97_; + T98 i98_; + T99 i99_; + T100 i100_; + }; + } +} + +#include +#include + +#endif // CULT_CLI_OPTIONS_HXX diff --git a/libcult/cult/cli/options.ixx b/libcult/cult/cli/options.ixx new file mode 100644 index 0000000..c25b833 --- /dev/null +++ b/libcult/cult/cli/options.ixx @@ -0,0 +1,12 @@ +// file : cult/cli/options.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace CLI + { + } +} + diff --git a/libcult/cult/cli/options.txx b/libcult/cult/cli/options.txx new file mode 100644 index 0000000..b26666d --- /dev/null +++ b/libcult/cult/cli/options.txx @@ -0,0 +1,320 @@ +// file : cult/cli/options.txx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace CLI + { + template + Void* + Options:: + value (Char const* k) const + { + Void* r (0); + + if (k == k01) r = (Void*) (&i01_); else + if (k == k02) r = (Void*) (&i02_); else + if (k == k03) r = (Void*) (&i03_); else + if (k == k04) r = (Void*) (&i04_); else + if (k == k05) r = (Void*) (&i05_); else + if (k == k06) r = (Void*) (&i06_); else + if (k == k07) r = (Void*) (&i07_); else + if (k == k08) r = (Void*) (&i08_); else + if (k == k09) r = (Void*) (&i09_); else + if (k == k10) r = (Void*) (&i10_); else + if (k == k11) r = (Void*) (&i11_); else + if (k == k12) r = (Void*) (&i12_); else + if (k == k13) r = (Void*) (&i13_); else + if (k == k14) r = (Void*) (&i14_); else + if (k == k15) r = (Void*) (&i15_); else + if (k == k16) r = (Void*) (&i16_); else + if (k == k17) r = (Void*) (&i17_); else + if (k == k18) r = (Void*) (&i18_); else + if (k == k19) r = (Void*) (&i19_); else + if (k == k20) r = (Void*) (&i20_); else + if (k == k21) r = (Void*) (&i21_); else + if (k == k22) r = (Void*) (&i22_); else + if (k == k23) r = (Void*) (&i23_); else + if (k == k24) r = (Void*) (&i24_); else + if (k == k25) r = (Void*) (&i25_); else + if (k == k26) r = (Void*) (&i26_); else + if (k == k27) r = (Void*) (&i27_); else + if (k == k28) r = (Void*) (&i28_); else + if (k == k29) r = (Void*) (&i29_); else + if (k == k30) r = (Void*) (&i30_); else + if (k == k31) r = (Void*) (&i31_); else + if (k == k32) r = (Void*) (&i32_); else + if (k == k33) r = (Void*) (&i33_); else + if (k == k34) r = (Void*) (&i34_); else + if (k == k35) r = (Void*) (&i35_); else + if (k == k36) r = (Void*) (&i36_); else + if (k == k37) r = (Void*) (&i37_); else + if (k == k38) r = (Void*) (&i38_); else + if (k == k39) r = (Void*) (&i39_); else + if (k == k40) r = (Void*) (&i40_); else + if (k == k41) r = (Void*) (&i41_); else + if (k == k42) r = (Void*) (&i42_); else + if (k == k43) r = (Void*) (&i43_); else + if (k == k44) r = (Void*) (&i44_); else + if (k == k45) r = (Void*) (&i45_); else + if (k == k46) r = (Void*) (&i46_); else + if (k == k47) r = (Void*) (&i47_); else + if (k == k48) r = (Void*) (&i48_); else + if (k == k49) r = (Void*) (&i49_); else + if (k == k50) r = (Void*) (&i50_); else + if (k == k51) r = (Void*) (&i51_); else + if (k == k52) r = (Void*) (&i52_); else + if (k == k53) r = (Void*) (&i53_); else + if (k == k54) r = (Void*) (&i54_); else + if (k == k55) r = (Void*) (&i55_); else + if (k == k56) r = (Void*) (&i56_); else + if (k == k57) r = (Void*) (&i57_); else + if (k == k58) r = (Void*) (&i58_); else + if (k == k59) r = (Void*) (&i59_); else + if (k == k60) r = (Void*) (&i60_); else + if (k == k61) r = (Void*) (&i61_); else + if (k == k62) r = (Void*) (&i62_); else + if (k == k63) r = (Void*) (&i63_); else + if (k == k64) r = (Void*) (&i64_); else + if (k == k65) r = (Void*) (&i65_); else + if (k == k66) r = (Void*) (&i66_); else + if (k == k67) r = (Void*) (&i67_); else + if (k == k68) r = (Void*) (&i68_); else + if (k == k69) r = (Void*) (&i69_); else + if (k == k70) r = (Void*) (&i70_); else + if (k == k71) r = (Void*) (&i71_); else + if (k == k72) r = (Void*) (&i72_); else + if (k == k73) r = (Void*) (&i73_); else + if (k == k74) r = (Void*) (&i74_); else + if (k == k75) r = (Void*) (&i75_); else + if (k == k76) r = (Void*) (&i76_); else + if (k == k77) r = (Void*) (&i77_); else + if (k == k78) r = (Void*) (&i78_); else + if (k == k79) r = (Void*) (&i79_); else + if (k == k80) r = (Void*) (&i80_); else + if (k == k81) r = (Void*) (&i81_); else + if (k == k82) r = (Void*) (&i82_); else + if (k == k83) r = (Void*) (&i83_); else + if (k == k84) r = (Void*) (&i84_); else + if (k == k85) r = (Void*) (&i85_); else + if (k == k86) r = (Void*) (&i86_); else + if (k == k87) r = (Void*) (&i87_); else + if (k == k88) r = (Void*) (&i88_); else + if (k == k89) r = (Void*) (&i89_); else + if (k == k90) r = (Void*) (&i90_); else + if (k == k91) r = (Void*) (&i91_); else + if (k == k92) r = (Void*) (&i92_); else + if (k == k93) r = (Void*) (&i93_); else + if (k == k94) r = (Void*) (&i94_); else + if (k == k95) r = (Void*) (&i95_); else + if (k == k96) r = (Void*) (&i96_); else + if (k == k97) r = (Void*) (&i97_); else + if (k == k98) r = (Void*) (&i98_); else + if (k == k99) r = (Void*) (&i99_); else + if (k == k100) r = (Void*) (&i100_); else + assert (false); + + return r; + } + } +} diff --git a/libcult/cult/cli/scanner.cxx b/libcult/cult/cli/scanner.cxx new file mode 100644 index 0000000..af51bfa --- /dev/null +++ b/libcult/cult/cli/scanner.cxx @@ -0,0 +1,17 @@ +// file : cult/cli/scanner.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace CLI + { + Scanner::Action const Scanner::Action::keep (Scanner::Action::keep_); + Scanner::Action const Scanner::Action::erase (Scanner::Action::erase_); + + Char const* const Scanner::eos = 0; + } +} diff --git a/libcult/cult/cli/scanner.hxx b/libcult/cult/cli/scanner.hxx new file mode 100644 index 0000000..13fa804 --- /dev/null +++ b/libcult/cult/cli/scanner.hxx @@ -0,0 +1,132 @@ +// file : cult/cli/scanner.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_CLI_SCANNER_HXX +#define CULT_CLI_SCANNER_HXX + +#include + +#include +#include + +namespace Cult +{ + namespace CLI + { + class Scanner: public NonCopyable + { + public: + class Action + { + public: + static Action const keep, erase; + + friend Boolean + operator== (Action const& a, Action const& b) + { + return a.v_ == b.v_; + } + + friend Boolean + operator!= (Action const& a, Action const& b) + { + return a.v_ != b.v_; + } + + private: + enum Value { keep_, erase_ } v_; + + Action (Value v) + : v_ (v) + { + } + }; + + public: + Scanner (Arguments& args, Action a = Action::keep, Index start = 1) + : cargs_ (args), + args_ (a == Action::erase ? &args : 0), + next_ (start) + { + } + + Scanner (Arguments const& args, Index start = 1) + : cargs_ (args), args_ (0), next_ (start) + { + } + + public: + static Char const* const eos; + + class PastEOS: public virtual Exception {}; + + Char const* + next () + { + if (next_ > cargs_.size ()) + { + throw PastEOS (); + } + else if (next_ == cargs_.size ()) + { + ++next_; + return eos; + } + else + { + Char const* r (cargs_[next_]); + + if (args_ != 0) + { + hold_ = r; + args_->erase (next_); + return hold_.c_str (); + } + else + { + ++next_; + return r; + } + } + } + + Char const* + peek () + { + if (next_ > cargs_.size ()) + { + throw PastEOS (); + } + else if (next_ == cargs_.size ()) + { + return eos; + } + else + { + return cargs_[next_]; + } + } + + Void + skip () + { + if (next_ > cargs_.size ()) + throw PastEOS (); + else + ++next_; + } + + private: + Arguments const& cargs_; + Arguments* args_; + Index next_; + String hold_; + }; + } +} + +#include + +#endif // CULT_CLI_SCANNER_HXX diff --git a/libcult/cult/cli/scanner.ixx b/libcult/cult/cli/scanner.ixx new file mode 100644 index 0000000..5e84451 --- /dev/null +++ b/libcult/cult/cli/scanner.ixx @@ -0,0 +1,12 @@ +// file : cult/cli/scanner.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace CLI + { + } +} + diff --git a/libcult/cult/containers/any.hxx b/libcult/cult/containers/any.hxx new file mode 100644 index 0000000..10f771f --- /dev/null +++ b/libcult/cult/containers/any.hxx @@ -0,0 +1,192 @@ +// file : cult/containers/any.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_CONTAINERS_ANY_HXX +#define CULT_CONTAINERS_ANY_HXX + +#include + +#include + +namespace Cult +{ + namespace Containers + { + //@@ eager clonning: do I need it? + // + // + class Any + { + public: + struct Typing {}; + + public: + template + Any (X const& x) + : holder_ (new HolderTemplate (x)) + { + } + + Any (Any const& any) + : holder_ (any.holder_->clone ()) + { + } + + public: + template + Any& + operator= (X const& x) + { + holder_ = Evptr (new HolderTemplate (x)); + return *this; + } + + Any& + operator= (Any const& any) + { + holder_ = any.holder_->clone (); + return *this; + } + + public: + /* + template + operator X& () + { + return value (); + } + + template + operator X const& () const + { + return value (); + } + */ + + public: + template + X& + value () + { + //@@ too strict + // + if (holder_->type_id () == typeid (X)) + { + return dynamic_cast*>(holder_.get ())->value (); + } + else + { + throw Typing (); + } + } + + template + X const& + value () const + { + if (holder_->type_id () == typeid (X)) + { + return dynamic_cast*>(holder_.get ())->value (); + } + else + { + throw Typing (); + } + } + + public: + RTTI::TypeId + type_id () const + { + return holder_->type_id (); + } + + public: + /* + template + friend x + operator+ (any const& a, x const& b) + { + return a.value () + b; + } + + template + friend x + operator+ (x const& a, any const& b) + { + return a + b.value (); + } + */ + + private: + class Holder + { + public: + virtual + ~Holder () + { + } + + Evptr + clone () const + { + return clone_ (); + } + + virtual RTTI::TypeId + type_id () const = 0; + + protected: + virtual Evptr + clone_ () const = 0; + }; + + template + class HolderTemplate : public Holder + { + public: + HolderTemplate (X const& value) + : value_ (value) + { + } + + virtual RTTI::TypeId + type_id () const + { + return RTTI::TypeId (typeid (value_)); + } + + X const& + value () const + { + return value_; + } + + X& + value () + { + return value_; + } + + protected: + virtual Evptr + clone_ () const + { + return new HolderTemplate (value_); + } + + private: + X value_; + }; + + private: + Evptr holder_; + }; + } +} + +#include + +#endif // CULT_CONTAINERS_ANY_HXX diff --git a/libcult/cult/containers/any.txx b/libcult/cult/containers/any.txx new file mode 100644 index 0000000..8e97345 --- /dev/null +++ b/libcult/cult/containers/any.txx @@ -0,0 +1,11 @@ +// file : cult/containers/any.txx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace Containers + { + } +} diff --git a/libcult/cult/containers/deque.hxx b/libcult/cult/containers/deque.hxx new file mode 100644 index 0000000..ed17a0c --- /dev/null +++ b/libcult/cult/containers/deque.hxx @@ -0,0 +1,166 @@ +// file : cult/containers/deque.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_CONTAINERS_DEQUE_HXX +#define CULT_CONTAINERS_DEQUE_HXX + +#include + +#include + +#include + +namespace Cult +{ + namespace Containers + { + template + class Deque: public std::deque + { + typedef std::deque Base; + + Base& + base () + { + return *this; + } + + Base const& + base () const + { + return *this; + } + + public: + typedef typename Base::value_type Value; + + + typedef typename Base::reference Reference; + typedef typename Base::const_reference ConstReference; + + + typedef typename Base::pointer Pointer; + typedef typename Base::const_pointer ConstPointer; + + + typedef + IteratorAdapter + Iterator; + + typedef + IteratorAdapter + ConstIterator; + + + typedef + IteratorAdapter + ReverseIterator; + + typedef + IteratorAdapter + ConstReverseIterator; + + + // Use Cult::Size and Cult::PtrDifference. + // + // typedef Base::size_type; + // typedef Base::difference_type; + + public: + explicit + Deque () + : Base () + { + } + + explicit + Deque (Size size, Value const& value = Value ()) + : Base (size, value) + { + } + + template + Deque (InputIterator first, InputIterator last) + : Base (first, last) + { + } + + Deque (Deque const& other) + : Base (other) + { + } + + Deque& + operator= (Deque const& other) + { + base () = other; + return *this; + } + + public: + Iterator + begin () + { + return Iterator (base ().begin ()); + } + + Iterator + end () + { + return Iterator (base ().end ()); + } + + + ConstIterator + begin () const + { + return ConstIterator (base ().begin ()); + } + + ConstIterator + end () const + { + return ConstIterator (base ().end ()); + } + + // + // + + ReverseIterator + rbegin () + { + return ReverseIterator (base ().rbegin ()); + } + + ReverseIterator + rend () + { + return ReverseIterator (base ().rend ()); + } + + + ConstReverseIterator + rbegin () const + { + return ConstReverseIterator (base ().rbegin ()); + } + + ConstReverseIterator + rend () const + { + return ConstReverseIterator (base ().rend ()); + } + + public: + Void + swap (Deque& other) + { + base ().swap (other); + } + }; + } +} + +#endif // CULT_CONTAINERS_DEQUE_HXX diff --git a/libcult/cult/containers/graph.hxx b/libcult/cult/containers/graph.hxx new file mode 100644 index 0000000..d61cd53 --- /dev/null +++ b/libcult/cult/containers/graph.hxx @@ -0,0 +1,193 @@ +// file : cult/containers/graph.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_CONTAINERS_GRAPH_HXX +#define CULT_CONTAINERS_GRAPH_HXX + +#include +#include +#include + +namespace Cult +{ + namespace Containers + { + template + class Graph + { + public: + typedef N Node; + typedef E Edge; + + struct NoEdge: virtual EH::Exception {}; + struct NoNode: virtual EH::Exception {}; + + public: + template + T& + new_node (); + + template + T& + new_node (A0 const&); + + template + T& + new_node (A0 const&, A1 const&); + + template + T& + new_node (A0 const&, A1 const&, A2 const&); + + template + T& + new_node (A0 const&, A1 const&, A2 const&, A3 const&); + + template + T& + new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&); + + template + T& + new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&, + A5 const&); + + template + T& + new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&, + A5 const&, A6 const&); + + template + T& + new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&, + A5 const&, A6 const&, A7 const&); + + template + T& + new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&, + A5 const&, A6 const&, A7 const&, A8 const&); + + template + T& + new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&, + A5 const&, A6 const&, A7 const&, A8 const&, A9 const&); + + public: + template + T& + new_edge (Left&, Right&); + + template + T& + new_edge (Left&, Right&, A0 const&); + + template + T& + new_edge (Left&, Right&, A0 const&, A1 const&); + + template + T& + new_edge (Left&, Right&, A0 const&, A1 const&, A2 const&); + + template + T& + new_edge (Left&, Right&, A0 const&, A1 const&, A2 const&, A3 const&); + + template + T& + new_edge (Left&, Right&, A0 const&, A1 const&, A2 const&, A3 const&, + A4 const&); + + template + T& + new_edge (Left&, Right&, A0 const&, A1 const&, A2 const&, A3 const&, + A4 const&, A5 const&); + + // Functions to reset edge's nodes. + // + public: + template + Void + reset_left_node (TE& edge, TN& node) + { + edge.set_left_node (node); + } + + template + Void + reset_right_node (TE& edge, TN& node) + { + edge.set_right_node (node); + } + + // Functions to add edges to a node. + // + public: + template + Void + add_edge_left (TN& node, TE& edge) + { + node.add_edge_left (edge); + } + + template + Void + add_edge_right (TN& node, TE& edge) + { + node.add_edge_right (edge); + } + + // Functions to delete edges and nodes. In order to delete a + // a node without leaving any dangling edges you need to make + // sure that each edge pointing to it is either deleted or reset + // to some other node. + // + public: + template + Void + delete_edge (Left& left_node, Right& right_node, T& edge); + + Void + delete_node (Node& node) + { + if (nodes_.erase (&node) == 0) + throw NoNode (); + } + + protected: + typedef Shptr NodePtr; + typedef Shptr EdgePtr; + + typedef Map Nodes; + typedef Map Edges; + + Nodes nodes_; + Edges edges_; + }; + } +} + + +#include + +#endif // CULT_CONTAINERS_GRAPH_HXX diff --git a/libcult/cult/containers/graph.txx b/libcult/cult/containers/graph.txx new file mode 100644 index 0000000..a9c9979 --- /dev/null +++ b/libcult/cult/containers/graph.txx @@ -0,0 +1,313 @@ +// file : cult/containers/graph.txx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace Containers + { + + // Nodes. + // + + template + template + T& Graph:: + new_node () + { + Shptr node (new T); + nodes_[node.get ()] = node; + + return *node; + } + + + template + template + T& Graph:: + new_node (A0 const& a0) + { + Shptr node (new T (a0)); + nodes_[node.get ()] = node; + + return *node; + } + + + template + template + T& Graph:: + new_node (A0 const& a0, A1 const& a1) + { + Shptr node (new T (a0, a1)); + nodes_[node.get ()] = node; + + return *node; + } + + template + template + T& Graph:: + new_node (A0 const& a0, A1 const& a1, A2 const& a2) + { + Shptr node (new T (a0, a1, a2)); + nodes_[node.get ()] = node; + + return *node; + } + + template + template + T& Graph:: + new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3) + { + Shptr node (new T (a0, a1, a2, a3)); + nodes_[node.get ()] = node; + + return *node; + } + + template + template + T& Graph:: + new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, + A4 const& a4) + { + Shptr node (new T (a0, a1, a2, a3, a4)); + nodes_[node.get ()] = node; + + return *node; + } + + template + template + T& Graph:: + new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, + A4 const& a4, A5 const& a5) + { + Shptr node (new T (a0, a1, a2, a3, a4, a5)); + nodes_[node.get ()] = node; + + return *node; + } + + template + template + T& Graph:: + new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, + A4 const& a4, A5 const& a5, A6 const& a6) + { + Shptr node (new T (a0, a1, a2, a3, a4, a5, a6)); + nodes_[node.get ()] = node; + + return *node; + } + + template + template + T& Graph:: + new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, + A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7) + { + Shptr node (new T (a0, a1, a2, a3, a4, a5, a6, a7)); + nodes_[node.get ()] = node; + + return *node; + } + + + template + template + T& Graph:: + new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, + A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7, + A8 const& a8) + { + Shptr node (new T (a0, a1, a2, a3, a4, a5, a6, a7, a8)); + nodes_[node.get ()] = node; + + return *node; + } + + + template + template + T& Graph:: + new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, + A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7, + A8 const& a8, A9 const& a9) + { + Shptr node (new T (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); + nodes_[node.get ()] = node; + + return *node; + } + + + // Edges. + // + + template + template + T& Graph:: + new_edge (Left& l, Right& r) + { + Shptr edge (new T); + edges_[edge.get ()] = edge; + + edge->set_left_node (l); + edge->set_right_node (r); + + l.add_edge_left (*edge); + r.add_edge_right (*edge); + + return *edge; + } + + template + template + T& Graph:: + new_edge (Left& l, Right& r, A0 const& a0) + { + Shptr edge (new T (a0)); + edges_[edge.get ()] = edge; + + edge->set_left_node (l); + edge->set_right_node (r); + + l.add_edge_left (*edge); + r.add_edge_right (*edge); + + return *edge; + } + + template + template + T& Graph:: + new_edge (Left& l, Right& r, A0 const& a0, A1 const& a1) + { + Shptr edge (new T (a0, a1)); + edges_[edge.get ()] = edge; + + edge->set_left_node (l); + edge->set_right_node (r); + + l.add_edge_left (*edge); + r.add_edge_right (*edge); + + return *edge; + } + + template + template + T& Graph:: + new_edge (Left& l, Right& r, A0 const& a0, A1 const& a1, A2 const& a2) + { + Shptr edge (new T (a0, a1, a2)); + edges_[edge.get ()] = edge; + + edge->set_left_node (l); + edge->set_right_node (r); + + l.add_edge_left (*edge); + r.add_edge_right (*edge); + + return *edge; + } + + template + template + T& Graph:: + new_edge (Left& l, Right& r, A0 const& a0, A1 const& a1, A2 const& a2, + A3 const& a3) + { + Shptr edge (new T (a0, a1, a2, a3)); + edges_[edge.get ()] = edge; + + edge->set_left_node (l); + edge->set_right_node (r); + + l.add_edge_left (*edge); + r.add_edge_right (*edge); + + return *edge; + } + + template + template + T& Graph:: + new_edge (Left& l, Right& r, A0 const& a0, A1 const& a1, A2 const& a2, + A3 const& a3, A4 const& a4) + { + Shptr edge (new T (a0, a1, a2, a3, a4)); + edges_[edge.get ()] = edge; + + edge->set_left_node (l); + edge->set_right_node (r); + + l.add_edge_left (*edge); + r.add_edge_right (*edge); + + return *edge; + } + + template + template + T& Graph:: + new_edge (Left& l, Right& r, A0 const& a0, A1 const& a1, A2 const& a2, + A3 const& a3, A4 const& a4, A5 const& a5) + { + Shptr edge (new T (a0, a1, a2, a3, a4, a5)); + edges_[edge.get ()] = edge; + + edge->set_left_node (l); + edge->set_right_node (r); + + l.add_edge_left (*edge); + r.add_edge_right (*edge); + + return *edge; + } + + + template + template + Void Graph:: + delete_edge (Left& l, Right& r, T& edge) + { + typename Edges::Iterator i (edges_.find (&edge)); + + if (i == edges_.end () || + nodes_.find (&l) == nodes_.end () || + nodes_.find (&r) == nodes_.end ()) + throw NoEdge (); + + r.remove_edge_right (edge); + l.remove_edge_left (edge); + + edge.clear_right_node (r); + edge.clear_left_node (l); + + edges_.erase (i); + } + } +} diff --git a/libcult/cult/containers/iterator.hxx b/libcult/cult/containers/iterator.hxx new file mode 100644 index 0000000..132043b --- /dev/null +++ b/libcult/cult/containers/iterator.hxx @@ -0,0 +1,227 @@ +// file : cult/containers/iterator.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_CONTAINERS_ITERATOR_HXX +#define CULT_CONTAINERS_ITERATOR_HXX + +#include + +#include + +namespace Cult +{ + namespace Containers + { + template + class IteratorAdapter + { + public: + typedef typename std::iterator_traits::value_type Value; + typedef typename std::iterator_traits::difference_type Difference; + typedef typename std::iterator_traits::pointer Pointer; + typedef typename std::iterator_traits::reference Reference; + typedef typename std::iterator_traits::iterator_category Category; + + // For compatibility with std::iterator_traits + // + public: + typedef Value value_type; + typedef Reference reference; + typedef Pointer pointer; + typedef Category iterator_category; + typedef Difference difference_type; + + public: + IteratorAdapter () + : i_ () // i_ can be of a pointer type. + { + } + + explicit + IteratorAdapter (I const& i) + : i_ (i) + { + } + + template + IteratorAdapter (IteratorAdapter const& j) + : i_ (j.i_) + { + } + public: + // Forward iterator requirements. + // + Reference + operator* () const + { + return *i_; + } + + Pointer + operator-> () const + { + return &(*i_); + } + + IteratorAdapter& + operator++ () + { + ++i_; + return *this; + } + + IteratorAdapter + operator++ (Int) + { + return IteratorAdapter (i_++); + } + + public: + // Bidirectional iterator requirements. + // + IteratorAdapter& + operator-- () + { + --i_; + return *this; + } + + IteratorAdapter + operator-- (Int) + { + return IteratorAdapter (i_--); + } + + public: + // Random access iterator requirements. + // + Reference + operator[] (Difference n) const + { + return i_[n]; + } + + IteratorAdapter + operator+ (Difference n) const + { + return IteratorAdapter (i_ + n); + } + + IteratorAdapter& + operator+= (Difference n) + { + i_ += n; + return *this; + } + + IteratorAdapter + operator- (Difference n) const + { + return IteratorAdapter (i_ - n); + } + + IteratorAdapter& + operator-= (Difference n) + { + i_ += n; + return *this; + } + + public: + I const& + base () const + { + return i_; + } + + // @@ This is needed so that call to functions such as erase() + // be possible without writing a wrapper. This should be a temporary + // measure. + + operator I& () + { + return i_; + } + + operator I const& () const + { + return i_; + } + + private: + template + friend class IteratorAdapter; + + I i_; + }; + + // Note: We use different types for left- and right-hand-side + // arguments to allow comparison between iterator and const_iterator. + // + + // Forward iterator requirements. + // + template + inline Boolean + operator== (IteratorAdapter const& i, IteratorAdapter const& j) + { + return i.base () == j.base (); + } + + template + inline Boolean + operator!= (IteratorAdapter const& i, IteratorAdapter const& j) + { + return i.base () != j.base (); + } + + // Random access iterator requirements + // + template + inline Boolean + operator< (IteratorAdapter const& i, IteratorAdapter const& j) + { + return i.base() < j.base(); + } + + template + inline Boolean + operator> (IteratorAdapter const& i, IteratorAdapter const& j) + { + return i.base() > j.base(); + } + + template + inline Boolean + operator<= (IteratorAdapter const& i, IteratorAdapter const& j) + { + return i.base() <= j.base(); + } + + template + inline Boolean + operator>= (IteratorAdapter const& i, IteratorAdapter const& j) + { + return i.base() >= j.base(); + } + + template + inline typename IteratorAdapter::Difference + operator- (IteratorAdapter const& i, IteratorAdapter const& j) + { + return i.base () - j.base (); + } + + template + IteratorAdapter + operator+ (typename IteratorAdapter::Difference n, + IteratorAdapter const& x) + { + return x + n; + } + } +} + +#endif // CULT_CONTAINERS_ITERATOR_HXX diff --git a/libcult/cult/containers/list.hxx b/libcult/cult/containers/list.hxx new file mode 100644 index 0000000..161052e --- /dev/null +++ b/libcult/cult/containers/list.hxx @@ -0,0 +1,193 @@ +// file : cult/containers/list.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_CONTAINERS_LIST_HXX +#define CULT_CONTAINERS_LIST_HXX + +#include + +#include + +#include + +namespace Cult +{ + namespace Containers + { + template + class List: public std::list + { + typedef std::list Base; + + Base& + base () + { + return *this; + } + + Base const& + base () const + { + return *this; + } + + public: + typedef typename Base::value_type Value; + + typedef typename Base::reference Reference; + typedef typename Base::const_reference ConstReference; + + typedef typename Base::pointer Pointer; + typedef typename Base::const_pointer ConstPointer; + + + typedef + IteratorAdapter + Iterator; + + typedef + IteratorAdapter + ConstIterator; + + + typedef + IteratorAdapter + ReverseIterator; + + typedef + IteratorAdapter + ConstReverseIterator; + + + // Use Cult::Size and Cult::PtrDifference. + // + // typedef Base::size_type; + // typedef Base::difference_type; + + public: + explicit + List () + : Base () + { + } + + explicit + List (Size size, Value const& value = Value ()) + : Base (size, value) + { + } + + template + List (InputIterator first, InputIterator last) + : Base (first, last) + { + } + + List (List const& other) + : Base (other) + { + } + + List& + operator= (List const& other) + { + base () = other; + return *this; + } + + public: + Void + swap (List& other) + { + base ().swap (other); + } + + public: + Iterator + begin () + { + return Iterator (base ().begin ()); + } + + Iterator + end () + { + return Iterator (base ().end ()); + } + + + ConstIterator + begin () const + { + return ConstIterator (base ().begin ()); + } + + ConstIterator + end () const + { + return ConstIterator (base ().end ()); + } + + // + // + + ReverseIterator + rbegin () + { + return ReverseIterator (base ().rbegin ()); + } + + ReverseIterator + rend () + { + return ReverseIterator (base ().rend ()); + } + + + ConstReverseIterator + rbegin () const + { + return ConstReverseIterator (base ().rbegin ()); + } + + ConstReverseIterator + rend () const + { + return ConstReverseIterator (base ().rend ()); + } + + public: + Iterator + insert (Iterator const& p, Value const& x) + { + return Iterator (base ().insert (p.base (), x)); + } + + template + Void + insert (Iterator const& p, I const& first, I const& last) + { + base ().insert (p.base (), first, last); + } + + template + Void + insert (Iterator const& p, + IteratorAdapter const& first, + IteratorAdapter const& last) + { + base ().insert (p.base (), first.base (), last.base ()); + } + + Iterator + erase (Iterator const& i) + { + return Iterator (base ().erase (i.base ())); + } + }; + } +} + +#endif // CULT_CONTAINERS_LIST_HXX diff --git a/libcult/cult/containers/map.hxx b/libcult/cult/containers/map.hxx new file mode 100644 index 0000000..8a3fbdb --- /dev/null +++ b/libcult/cult/containers/map.hxx @@ -0,0 +1,175 @@ +// file : cult/containers/map.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_CONTAINERS_MAP_HXX +#define CULT_CONTAINERS_MAP_HXX + +#include + +#include + +#include + +namespace Cult +{ + namespace Containers + { + template > + class Map: public std::map + { + typedef std::map Base; + + Base& + base () + { + return *this; + } + + Base const& + base () const + { + return *this; + } + + public: + typedef typename Base::key_type Key; + typedef typename Base::mapped_type Value; + typedef typename Base::value_type Pair; + typedef typename Base::key_compare Compare; + + typedef typename Base::reference Reference; + typedef typename Base::const_reference ConstReference; + + typedef typename Base::pointer Pointer; + typedef typename Base::const_pointer ConstPointer; + + + typedef + IteratorAdapter + Iterator; + + typedef + IteratorAdapter + ConstIterator; + + + typedef + IteratorAdapter + ReverseIterator; + + typedef + IteratorAdapter + ConstReverseIterator; + + // Use Cult::Size and Cult::PtrDifference. + // + // typedef Base::size_type; + // typedef Base::difference_type; + + public: + explicit + Map (Compare const& comp = Compare ()) + : Base (comp) + { + } + + template + Map (InputIterator first, + InputIterator last, + Compare const& comp = Compare ()) + : Base (first, last, comp) + { + } + + Map (Map const& other) + : Base (other) + { + } + + Map& + operator= (Map const& other) + { + base () = other; + return *this; + } + + public: + Iterator + begin () + { + return Iterator (base ().begin ()); + } + + Iterator + end () + { + return Iterator (base ().end ()); + } + + + ConstIterator + begin () const + { + return ConstIterator (base ().begin ()); + } + + ConstIterator + end () const + { + return ConstIterator (base ().end ()); + } + + // + // + + ReverseIterator + rbegin () + { + return ReverseIterator (base ().rbegin ()); + } + + ReverseIterator + rend () + { + return ReverseIterator (base ().rend ()); + } + + + ConstReverseIterator + rbegin () const + { + return ConstReverseIterator (base ().rbegin ()); + } + + ConstReverseIterator + rend () const + { + return ConstReverseIterator (base ().rend ()); + } + + public: + Iterator + find (Key const& k) + { + return Iterator (base ().find (k)); + } + + ConstIterator + find (Key const& k) const + { + return ConstIterator (base ().find (k)); + } + + public: + Void + swap (Map& other) + { + base ().swap (other); + } + }; + } +} + +#endif // CULT_CONTAINERS_MAP_HXX diff --git a/libcult/cult/containers/pair.hxx b/libcult/cult/containers/pair.hxx new file mode 100644 index 0000000..b8b7506 --- /dev/null +++ b/libcult/cult/containers/pair.hxx @@ -0,0 +1,58 @@ +// file : cult/containers/pair.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_CONTAINERS_PAIR_HXX +#define CULT_CONTAINERS_PAIR_HXX + +#include + +namespace Cult +{ + namespace Containers + { + template + class Pair: public std::pair + { + typedef std::pair Base; + + Base& + base () + { + return *this; + } + + public: + typedef T1 First; + typedef T2 Second; + + public: + Pair () + : Base () + { + } + + Pair (First const& first, Second const& second) + : Base (first, second) + { + } + + template + Pair (std::pair const& pair) + : Base (pair) + { + } + + template + Pair& + operator= (std::pair const& pair) + { + base () = pair; + return *this; + } + }; + } +} + +#endif // CULT_CONTAINERS_PAIR_HXX diff --git a/libcult/cult/containers/set.hxx b/libcult/cult/containers/set.hxx new file mode 100644 index 0000000..a911c19 --- /dev/null +++ b/libcult/cult/containers/set.hxx @@ -0,0 +1,175 @@ +// file : cult/containers/set.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_CONTAINERS_SET_HXX +#define CULT_CONTAINERS_SET_HXX + +#include + +#include + +#include + +namespace Cult +{ + namespace Containers + { + template > + class Set: public std::set + { + typedef std::set Base; + + Base& + base () + { + return *this; + } + + Base const& + base () const + { + return *this; + } + + public: + typedef typename Base::key_type Key; + typedef typename Base::value_type Value; // Same as Key. + typedef typename Base::key_compare Compare; + + typedef typename Base::reference Reference; + typedef typename Base::const_reference ConstReference; + + typedef typename Base::pointer Pointer; + typedef typename Base::const_pointer ConstPointer; + + + typedef + IteratorAdapter + Iterator; + + typedef + IteratorAdapter + ConstIterator; + + + typedef + IteratorAdapter + ReverseIterator; + + typedef + IteratorAdapter + ConstReverseIterator; + + + // Use Cult::Size and Cult::PtrDifference. + // + // typedef Base::size_type; + // typedef Base::difference_type; + + public: + explicit + Set (Compare const& comp = Compare ()) + : Base (comp) + { + } + + template + Set (InputIterator first, + InputIterator last, + Compare const& comp = Compare ()) + : Base (first, last, comp) + { + } + + Set (Set const& other) + : Base (other) + { + } + + Set& + operator= (Set const& other) + { + base () = other; + return *this; + } + + public: + Iterator + begin () + { + return Iterator (base ().begin ()); + } + + Iterator + end () + { + return Iterator (base ().end ()); + } + + + ConstIterator + begin () const + { + return ConstIterator (base ().begin ()); + } + + ConstIterator + end () const + { + return ConstIterator (base ().end ()); + } + + // + // + + ReverseIterator + rbegin () + { + return ReverseIterator (base ().rbegin ()); + } + + ReverseIterator + rend () + { + return ReverseIterator (base ().rend ()); + } + + + ConstReverseIterator + rbegin () const + { + return ConstReverseIterator (base ().rbegin ()); + } + + ConstReverseIterator + rend () const + { + return ConstReverseIterator (base ().rend ()); + } + + public: + Iterator + find (Key const& k) + { + return Iterator (base ().find (k)); + } + + ConstIterator + find (Key const& k) const + { + return ConstIterator (base ().find (k)); + } + + public: + Void + swap (Set& other) + { + base ().swap (other); + } + }; + } +} + +#endif // CULT_CONTAINERS_SET_HXX diff --git a/libcult/cult/containers/stack.hxx b/libcult/cult/containers/stack.hxx new file mode 100644 index 0000000..930bfe8 --- /dev/null +++ b/libcult/cult/containers/stack.hxx @@ -0,0 +1,95 @@ +// file : cult/containers/stack.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_CONTAINERS_STACK_HXX +#define CULT_CONTAINERS_STACK_HXX + +#include + +#include + +namespace Cult +{ + namespace Containers + { + template > + class Stack + { + public: + typedef C Container; + typedef typename Container::Value Value; + + + public: + explicit + Stack (Container const& c = Container()) + : c_ (c) + { + } + + Boolean + empty () const + { + return c_.empty(); + } + + Size + size () const + { + return c_.size(); + } + + Value& + top () + { + return c_.back(); + } + + Value const& + top () const + { + return c_.back(); + } + + Void + push (const Value& x) + { + c_.push_back(x); + } + + Void + pop() + { + c_.pop_back(); + } + + protected: + Container c_; + }; + + /* + template + bool operator==(const stack& x, + const stack& y); + template + bool operator< (const stack& x, + const stack& y); + template + bool operator!=(const stack& x, + const stack& y); + template + bool operator> (const stack& x, + const stack& y); + template + bool operator>=(const stack& x, + const stack& y); + template + bool operator<=(const stack& x, + const stack& y); + */ + } +} + +#endif // CULT_CONTAINERS_STACK_HXX diff --git a/libcult/cult/containers/vector.hxx b/libcult/cult/containers/vector.hxx new file mode 100644 index 0000000..3a3b32f --- /dev/null +++ b/libcult/cult/containers/vector.hxx @@ -0,0 +1,164 @@ +// file : cult/containers/vector.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_CONTAINERS_VECTOR_HXX +#define CULT_CONTAINERS_VECTOR_HXX + +#include + +#include + +#include + +namespace Cult +{ + namespace Containers + { + template + class Vector: public std::vector + { + typedef std::vector Base; + + Base& + base () + { + return *this; + } + + Base const& + base () const + { + return *this; + } + + public: + typedef typename Base::value_type Value; + + typedef typename Base::reference Reference; + typedef typename Base::const_reference ConstReference; + + typedef typename Base::pointer Pointer; + typedef typename Base::const_pointer ConstPointer; + + + typedef + IteratorAdapter + Iterator; + + typedef + IteratorAdapter + ConstIterator; + + + typedef + IteratorAdapter + ReverseIterator; + + typedef + IteratorAdapter + ConstReverseIterator; + + + // Use Cult::Size and Cult::PtrDifference. + // + // typedef Base::size_type; + // typedef Base::difference_type; + + public: + explicit + Vector () + : Base () + { + } + + explicit + Vector (Size size, Value const& value = Value ()) + : Base (size, value) + { + } + + template + Vector (InputIterator first, InputIterator last) + : Base (first, last) + { + } + + Vector (Vector const& other) + : Base (other) + { + } + + Vector& + operator= (Vector const& other) + { + base () = other; + return *this; + } + + public: + Iterator + begin () + { + return Iterator (base ().begin ()); + } + + Iterator + end () + { + return Iterator (base ().end ()); + } + + + ConstIterator + begin () const + { + return ConstIterator (base ().begin ()); + } + + ConstIterator + end () const + { + return ConstIterator (base ().end ()); + } + + // + // + + ReverseIterator + rbegin () + { + return ReverseIterator (base ().rbegin ()); + } + + ReverseIterator + rend () + { + return ReverseIterator (base ().rend ()); + } + + + ConstReverseIterator + rbegin () const + { + return ConstReverseIterator (base ().rbegin ()); + } + + ConstReverseIterator + rend () const + { + return ConstReverseIterator (base ().rend ()); + } + + public: + Void + swap (Vector& other) + { + base ().swap (other); + } + }; + } +} + +#endif // CULT_CONTAINERS_VECTOR_HXX diff --git a/libcult/cult/dr/xdr/input-stream.cxx b/libcult/cult/dr/xdr/input-stream.cxx new file mode 100644 index 0000000..1730763 --- /dev/null +++ b/libcult/cult/dr/xdr/input-stream.cxx @@ -0,0 +1,152 @@ +// file : cult/dr/xdr/input-stream.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace DR + { + namespace XDR + { + InputStream:: + InputStream (Shptr buffer) + : buffer_ (buffer) + { + xdrmem_create (&xdr_, buffer_->data (), buffer_->size (), XDR_DECODE); + } + + InputStream:: + ~InputStream () + { + xdr_destroy (&xdr_); + } + + InputStream& InputStream:: + operator>> (Boolean& v) + { + bool_t b; + + if (!xdr_bool (&xdr_, &b)) + throw Extraction (); + + v = b; + + return *this; + } + + InputStream& InputStream:: + operator>> (Int8& v) + { + if (!xdr_int8_t (&xdr_, &v)) + throw Extraction (); + + return *this; + } + + InputStream& InputStream:: + operator>> (UnsignedInt8& v) + { + if (!xdr_uint8_t (&xdr_, &v)) + throw Extraction (); + + return *this; + } + + InputStream& InputStream:: + operator>> (Int16& v) + { + if (!xdr_int16_t (&xdr_, &v)) + throw Extraction (); + + return *this; + } + + InputStream& InputStream:: + operator>> (UnsignedInt16& v) + { + if (!xdr_uint16_t (&xdr_, &v)) + throw Extraction (); + + return *this; + } + + InputStream& InputStream:: + operator>> (Int32& v) + { + if (!xdr_int32_t (&xdr_, &v)) + throw Extraction (); + + return *this; + } + + InputStream& InputStream:: + operator>> (UnsignedInt32& v) + { + if (!xdr_uint32_t (&xdr_, &v)) + throw Extraction (); + + return *this; + } + + InputStream& InputStream:: + operator>> (Int64& v) + { + if (!xdr_int64_t (&xdr_, (int64_t*)&v)) + throw Extraction (); + + return *this; + } + + InputStream& InputStream:: + operator>> (UnsignedInt64& v) + { + if (!xdr_uint64_t (&xdr_, (uint64_t*)&v)) + throw Extraction (); + + return *this; + } + + InputStream& InputStream:: + operator>> (String& v) + { + UnsignedInt32 size; + + if (!xdr_uint32_t (&xdr_, &size)) + throw Extraction (); + + // I dare to change the guts! + // + v.resize (size); + + Char* p (const_cast (v.data ())); + + if (!xdr_opaque (&xdr_, p, size)) + throw Extraction (); + + return *this; + } + + Void InputStream:: + read (Buffer& buffer, Size size) + { + Size new_size (buffer.position () + size); + + buffer.capacity (new_size); + + if (!xdr_opaque (&xdr_, buffer.data () + buffer.position (), size)) + throw Extraction (); + + buffer.size (new_size); + } + + Boolean InputStream:: + eos () const + { + return xdr_getpos (&xdr_) >= buffer_->size (); + } + } + } +} diff --git a/libcult/cult/dr/xdr/input-stream.hxx b/libcult/cult/dr/xdr/input-stream.hxx new file mode 100644 index 0000000..653b228 --- /dev/null +++ b/libcult/cult/dr/xdr/input-stream.hxx @@ -0,0 +1,78 @@ +// file : cult/dr/xdr/input-stream.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_DR_XDR_INPUT_STREAM_HXX +#define CULT_DR_XDR_INPUT_STREAM_HXX + +#include + +#include + +#include + +#include + +namespace Cult +{ + namespace DR + { + namespace XDR + { + struct Extraction: virtual EH::Exception {}; + + class InputStream: public NonCopyable + { + public: + InputStream (Shptr buffer); + + ~InputStream (); + + public: + InputStream& + operator>> (Boolean&); + + InputStream& + operator>> (Int8&); + + InputStream& + operator>> (UnsignedInt8&); + + InputStream& + operator>> (Int16&); + + InputStream& + operator>> (UnsignedInt16&); + + InputStream& + operator>> (Int32&); + + InputStream& + operator>> (UnsignedInt32&); + + InputStream& + operator>> (Int64&); + + InputStream& + operator>> (UnsignedInt64&); + + InputStream& + operator>> (String&); + + public: + Void + read (Buffer& buffer, Size size); + + Boolean + eos () const; + + private: + ::XDR xdr_; + Shptr buffer_; + }; + } + } +} + +#endif // CULT_DR_XDR_INPUT_STREAM_HXX diff --git a/libcult/cult/dr/xdr/output-stream.cxx b/libcult/cult/dr/xdr/output-stream.cxx new file mode 100644 index 0000000..acda64c --- /dev/null +++ b/libcult/cult/dr/xdr/output-stream.cxx @@ -0,0 +1,222 @@ +// file : cult/dr/xdr/output-stream.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace DR + { + namespace XDR + { + OutputStream:: + OutputStream (Size hint) + : buffer_ (new Buffer (hint ? hint : 256)) + { + xdrmem_create (&xdr_, buffer_->data (), ~(u_int (0)), XDR_ENCODE); + } + + + OutputStream:: + ~OutputStream () + { + xdr_destroy (&xdr_); + } + + Shptr OutputStream:: + buffer () + { + return buffer_; + } + + Void OutputStream:: + ensure_space (Size size) + { + size += size % 4 ? 4 - size % 4 : 0; + + Size needed (size + xdr_getpos (&xdr_)); + + if (needed > buffer_->capacity ()) + { + Size new_size (buffer_->capacity () * 2); + + if (needed > new_size) + new_size = needed % 8 ? 8 - new_size % 8 : 0; + + if (buffer_->capacity (new_size)) + { + xdr_destroy (&xdr_); + + xdrmem_create (&xdr_, + buffer_->data () + buffer_->size (), + ~(u_int (0)), + XDR_ENCODE); + } + } + } + + Void OutputStream:: + update_position (Size position) + { + // Align to 4-boundary. + // + position += position % 4 ? 4 - position % 4 : 0; + + buffer_->size (buffer_->size () + position); + } + + OutputStream& OutputStream:: + operator<< (Boolean v) + { + ensure_space (4); + + bool_t b (v); + + if (!xdr_bool (&xdr_, &b)) + throw Insertion (); + + update_position (4); + return *this; + } + + OutputStream& OutputStream:: + operator<< (Int8 v) + { + ensure_space (4); + + if (!xdr_int8_t (&xdr_, &v)) + throw Insertion (); + + update_position (4); + + return *this; + } + + OutputStream& OutputStream:: + operator<< (UnsignedInt8 v) + { + ensure_space (4); + + if (!xdr_uint8_t (&xdr_, &v)) + throw Insertion (); + + update_position (4); + + return *this; + } + + OutputStream& OutputStream:: + operator<< (Int16 v) + { + ensure_space (4); + + if (!xdr_int16_t (&xdr_, &v)) + throw Insertion (); + + update_position (4); + + return *this; + } + + OutputStream& OutputStream:: + operator<< (UnsignedInt16 v) + { + ensure_space (4); + + if (!xdr_uint16_t (&xdr_, &v)) + throw Insertion (); + + update_position (4); + + return *this; + } + + OutputStream& OutputStream:: + operator<< (Int32 v) + { + ensure_space (4); + + if (!xdr_int32_t (&xdr_, &v)) + throw Insertion (); + + update_position (4); + + return *this; + } + + OutputStream& OutputStream:: + operator<< (UnsignedInt32 v) + { + ensure_space (4); + + if (!xdr_uint32_t (&xdr_, &v)) + throw Insertion (); + + update_position (4); + + return *this; + } + + OutputStream& OutputStream:: + operator<< (Int64 v) + { + ensure_space (8); + + if (!xdr_int64_t (&xdr_, (int64_t*)&v)) + throw Insertion (); + + update_position (8); + + return *this; + } + + OutputStream& OutputStream:: + operator<< (UnsignedInt64 v) + { + ensure_space (8); + + if (!xdr_uint64_t (&xdr_, (uint64_t*)&v)) + throw Insertion (); + + update_position (8); + + return *this; + } + + OutputStream& OutputStream:: + operator<< (String const& v) + { + UnsignedInt32 size (v.size ()); + + ensure_space (4 + size); + + Char* p (const_cast(v.c_str ())); + + if (!xdr_string (&xdr_, &p, size)) + throw Insertion (); + + update_position (4 + size); + + return *this; + } + + Void OutputStream:: + write (Buffer const& buffer) + { + Size size (buffer.size () - buffer.position ()); + + ensure_space (size); + + if (!xdr_opaque ( + &xdr_, + const_cast (buffer.data ()) + buffer.position (), + size)) + throw Insertion (); + + update_position (size); + } + } + } +} diff --git a/libcult/cult/dr/xdr/output-stream.hxx b/libcult/cult/dr/xdr/output-stream.hxx new file mode 100644 index 0000000..72e0c19 --- /dev/null +++ b/libcult/cult/dr/xdr/output-stream.hxx @@ -0,0 +1,89 @@ +// file : cult/dr/xdr/output-stream.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_DR_XDR_OUTPUT_STREAM_HXX +#define CULT_DR_XDR_OUTPUT_STREAM_HXX + +#include + +#include + +#include + +#include + +namespace Cult +{ + namespace DR + { + namespace XDR + { + struct Insertion: virtual EH::Exception {}; + + //@@ I think I should use refernce to buffer instead of Shptr. + // To keep it simple, so to speak. + // + class OutputStream: public NonCopyable + { + public: + OutputStream (Size hint = 0); + + ~OutputStream (); + + public: + Shptr + buffer (); + + public: + OutputStream& + operator<< (Boolean); + + OutputStream& + operator<< (Int8); + + OutputStream& + operator<< (UnsignedInt8); + + OutputStream& + operator<< (Int16); + + OutputStream& + operator<< (UnsignedInt16); + + OutputStream& + operator<< (Int32); + + OutputStream& + operator<< (UnsignedInt32); + + OutputStream& + operator<< (Int64); + + OutputStream& + operator<< (UnsignedInt64); + + OutputStream& + operator<< (String const&); + + public: + Void + write (Buffer const& buffer); + + private: + Void + ensure_space (Size size); + + Void + update_position (Size position); + + private: + ::XDR xdr_; + Shptr buffer_; + }; + } + } +} + +#endif // CULT_DR_XDR_OUTPUT_STREAM_HXX diff --git a/libcult/cult/eh/exception.cxx b/libcult/cult/eh/exception.cxx new file mode 100644 index 0000000..21494cd --- /dev/null +++ b/libcult/cult/eh/exception.cxx @@ -0,0 +1,27 @@ +// file : cult/eh/exception.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace Cult +{ + namespace EH + { + Char const* Exception:: + what () const throw () + { + try + { + return typeid (*this).name (); + } + catch (...) + { + return ""; + } + } + } +} diff --git a/libcult/cult/eh/exception.hxx b/libcult/cult/eh/exception.hxx new file mode 100644 index 0000000..266c591 --- /dev/null +++ b/libcult/cult/eh/exception.hxx @@ -0,0 +1,25 @@ +// file : cult/eh/exception.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_EH_EXCEPTION_HXX +#define CULT_EH_EXCEPTION_HXX + +#include + +#include // std::exception + +namespace Cult +{ + namespace EH + { + struct Exception : std::exception + { + virtual Char const* + what () const throw (); + }; + } +} + +#endif // CULT_EH_EXCEPTION_HXX diff --git a/libcult/cult/makefile b/libcult/cult/makefile new file mode 100644 index 0000000..e4ce5ea --- /dev/null +++ b/libcult/cult/makefile @@ -0,0 +1,160 @@ +# file : cult/makefile +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make + +$(call include,$(bld_root)/system.make) +$(call include,$(scf_root)/configuration.make) + +cxx_tun := eh/exception.cxx + +cxx_tun += mm/new.cxx \ + mm/counter.cxx \ + mm/buffer.cxx + +cxx_tun += rtti/type-info.cxx + +cxx_tun += trace/log.cxx + +cxx_tun += cli/arguments.cxx \ + cli/file-arguments.cxx \ + cli/scanner.cxx \ + cli/options.cxx \ + cli/options-parser.cxx \ + cli/options-spec.cxx + +ifeq ($(cult_threads),y) +cxx_tun += sched/condition.cxx \ + sched/mutex.cxx \ + sched/spin.cxx \ + sched/thread.cxx +endif + + +ifeq ($(cult_network),y) +cxx_tun += os/net/address.cxx \ + os/net/socket.cxx \ + os/net/datagram-socket.cxx \ + os/net/multicast-socket.cxx \ + os/net/ipv4/address.cxx \ + os/net/ipv4/datagram-socket.cxx \ + os/net/ipv4/multicast-socket.cxx +endif + + +ifeq ($(cult_dr),y) +cxx_tun += dr/xdr/input-stream.cxx \ + dr/xdr/output-stream.cxx +endif + + +cxx_o := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o)) +cxx_d := $(cxx_o:.o=.o.d) + +cult.l := $(out_base)/cult.l +cult.l.cpp-options := $(out_base)/cult.l.cpp-options + +clean := $(out_base)/.clean + + +# Architectures. +# +# +#@@ arch can collide if src_root == out_root +# + +# List of known architectures. +# +architectures := i386 \ + i386/i486 \ + i386/i486/i586 \ + i386/i486/i586/i686 \ + i386/i486/i586/i686/x86_64 + +# Directories with architecture-specific code. +# +arch_dirs := mm +arch := $(filter %$(host_cpu),$(architectures)) + +r := +r := generic $(foreach a,$(subst /, ,$(arch)),$(eval r := $(if $r,$r/)$a)$r) + +sub_archs := +$(foreach a,$r,$(eval sub_archs := $a $(sub_archs))) + +#$(warning $(sub_archs)) + +# $1 - sub-architecture dir (e.g. i386/i486) +# +define arch-rule + +arch_targets += $(foreach d,$(arch_dirs),$(out_base)/arch/$1/cult/$d/arch) + +$(out_base)/arch/$1/cult/%/arch: $(src_base)/%/arch/$1 | $(out_base)/arch/$1/cult/%/. + $(call message,using $1,ln -s $$$$< $$$$@) +endef + +arch_targets := +$(foreach a,$(sub_archs),$(eval $(call arch-rule,$a))) + + +# Build. +# +$(cult.l): $(cxx_o) + +ifeq ($(cult_threads),y) +$(cult.l): -lpthread +endif + +$(cxx_o) $(cxx_d): $(cult.l.cpp-options) + +$(cult.l.cpp-options): prefix := cult/ $(out_root)/ +$(cult.l.cpp-options): value := $(addprefix -I$(out_base)/arch/,$(sub_archs))\ + -I$(out_root)\ + -I$(src_root) + +$(cult.l.cpp-options): | $(arch_targets) + +$(call include-dep,$(cxx_d)) + + +# config.hxx +# +ifdef cult_dr +$(out_base)/config.hxx: cult_threads := $(cult_threads) +$(out_base)/config.hxx: + @echo '// file : cult/config.hxx' >$@ + @echo '// author : automatically generated' >>$@ + @echo '// copyright : Copyright (c) 2006-2010 Boris Kolpackov' >>$@ + @echo '// license : GNU GPL v2; see accompanying LICENSE file' >>$@ + @echo '#ifndef CULT_CONFIG_HXX' >>$@ + @echo '#define CULT_CONFIG_HXX' >>$@ +ifeq ($(cult_threads),y) + @echo '#define CULT_THREADS' >>$@ +endif + @echo '#endif // CULT_CONFIG_HXX' >>$@ +endif + +# Convenience alias for default target. +# +$(out_base)/: $(cult.l) + + +# Clean. +# +$(clean): $(cult.l).o.clean \ + $(cult.l.cpp-options).clean \ + $(out_base)/cli/mapper.hxx.m4.clean \ + $(addsuffix .cxx.clean,$(cxx_o)) \ + $(addsuffix .cxx.clean,$(cxx_d)) + $(call message,rm $$1,rm -f -r $$1,$(out_base)/arch) + $(call message,rm $$1,rm -f $$1,$(out_base)/config.hxx) + +# How to. +# +$(call include,$(bld_root)/cxx/o-l.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) +$(call include,$(bld_root)/m4/m4.make) diff --git a/libcult/cult/meta/answer.hxx b/libcult/cult/meta/answer.hxx new file mode 100644 index 0000000..402d152 --- /dev/null +++ b/libcult/cult/meta/answer.hxx @@ -0,0 +1,27 @@ +// file : cult/meta/answer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_META_ANSWER_HXX +#define CULT_META_ANSWER_HXX + +#include + +namespace Cult +{ + namespace Meta + { + struct Yes + { + Char filling; + }; + + struct No + { + Char filling[2]; + }; + } +} + +#endif // CULT_META_ANSWER_HXX diff --git a/libcult/cult/meta/class-p.hxx b/libcult/cult/meta/class-p.hxx new file mode 100644 index 0000000..6ac056d --- /dev/null +++ b/libcult/cult/meta/class-p.hxx @@ -0,0 +1,33 @@ +// file : cult/meta/class-p.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_META_CLASS_HXX +#define CULT_META_CLASS_HXX + +#include + +#include + +namespace Cult +{ + namespace Meta + { + template + class class_p + { + //@@ g++ bug 14881 + public: + template static No test (...); + template static Yes test (Void* Y::*); + + public: + //@@ Qualification bug fixed for g++ 3.4.0. + static Boolean const r = + sizeof (class_p::template test (0)) == sizeof (Yes); + }; + } +} + +#endif // CULT_META_CLASS_HXX diff --git a/libcult/cult/meta/polymorphic-p.hxx b/libcult/cult/meta/polymorphic-p.hxx new file mode 100644 index 0000000..0743de3 --- /dev/null +++ b/libcult/cult/meta/polymorphic-p.hxx @@ -0,0 +1,56 @@ +// file : cult/meta/polymorphic-p.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_META_POLYMORPHIC_HXX +#define CULT_META_POLYMORPHIC_HXX + +#include + +#include +#include + +namespace Cult +{ + namespace Meta + { + template + class polymorphic_p + { + typedef typename remove_cv::R X; + + template + struct impl + { + static const Boolean r = false; + }; + + template + struct impl + { + //@@ private + + struct S1 : Y + { + S1 (); + }; + + struct S2 : Y + { + S2 (); + + virtual + ~S2 () throw (); + }; + + static const Boolean r = sizeof (S1) == sizeof (S2); + }; + + public: + static const Boolean r = impl::r>::r; + }; + } +} + +#endif // CULT_META_POLYMORPHIC_HXX diff --git a/libcult/cult/meta/remove-c.hxx b/libcult/cult/meta/remove-c.hxx new file mode 100644 index 0000000..a25382c --- /dev/null +++ b/libcult/cult/meta/remove-c.hxx @@ -0,0 +1,27 @@ +// file : cult/meta/remove-c.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_META_REMOVE_C_HXX +#define CULT_META_REMOVE_C_HXX + +namespace Cult +{ + namespace Meta + { + template + struct remove_c + { + typedef X R; + }; + + template + struct remove_c + { + typedef X R; + }; + } +} + +#endif // CULT_META_REMOVE_C_HXX diff --git a/libcult/cult/meta/remove-cv.hxx b/libcult/cult/meta/remove-cv.hxx new file mode 100644 index 0000000..190e393 --- /dev/null +++ b/libcult/cult/meta/remove-cv.hxx @@ -0,0 +1,24 @@ +// file : cult/meta/remove-cv.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_META_REMOVE_CV_HXX +#define CULT_META_REMOVE_CV_HXX + +#include +#include + +namespace Cult +{ + namespace Meta + { + template + struct remove_cv + { + typedef typename remove_v::R>::R R; + }; + } +} + +#endif // CULT_META_REMOVE_CV_HXX diff --git a/libcult/cult/meta/remove-v.hxx b/libcult/cult/meta/remove-v.hxx new file mode 100644 index 0000000..eb6e4ee --- /dev/null +++ b/libcult/cult/meta/remove-v.hxx @@ -0,0 +1,27 @@ +// file : cult/meta/remove-v.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_META_REMOVE_V_HXX +#define CULT_META_REMOVE_V_HXX + +namespace Cult +{ + namespace Meta + { + template + struct remove_v + { + typedef X R; + }; + + template + struct remove_v + { + typedef X R; + }; + } +} + +#endif // CULT_META_REMOVE_V_HXX diff --git a/libcult/cult/mm/arch/generic/counter.hxx b/libcult/cult/mm/arch/generic/counter.hxx new file mode 100644 index 0000000..6a26759 --- /dev/null +++ b/libcult/cult/mm/arch/generic/counter.hxx @@ -0,0 +1,45 @@ +// file : cult/mm/arch/generic/counter.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_MM_ARCH_GENERIC_COUNTER_HXX +#define CULT_MM_ARCH_GENERIC_COUNTER_HXX + +#include +#include + +namespace Cult +{ + namespace MM + { + class Counter: public NonCopyable + { + public: + Counter (); + + // After failure assume the counter has its old value. + // + Void + inc_ref (); + + + // After failure assume the counter has its new value. + // + Boolean + dec_ref (); + + + Size + count () const; + + private: + Size value_; + mutable Sched::Spin spin_; + }; + } +} + +#include + +#endif // CULT_MM_ARCH_GENERIC_COUNTER_HXX diff --git a/libcult/cult/mm/arch/generic/counter.ixx b/libcult/cult/mm/arch/generic/counter.ixx new file mode 100644 index 0000000..648d28a --- /dev/null +++ b/libcult/cult/mm/arch/generic/counter.ixx @@ -0,0 +1,47 @@ +// file : cult/mm/arch/generic/counter.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace MM + { + inline + Counter:: + Counter () + : value_ (1) + { + } + + inline + Void Counter:: + inc_ref () + { + Sched::Lock l (spin_); + + ++value_; + } + + inline + Boolean Counter:: + dec_ref () + { + Sched::Lock l (spin_); + + return --value_ == 0; + + } + + inline + Size Counter:: + count () const + { + Sched::Lock l (spin_); + + return value_; + } + } +} diff --git a/libcult/cult/mm/arch/i386/counter.hxx b/libcult/cult/mm/arch/i386/counter.hxx new file mode 100644 index 0000000..21f5f63 --- /dev/null +++ b/libcult/cult/mm/arch/i386/counter.hxx @@ -0,0 +1,43 @@ +// file : cult/mm/arch/i386/counter.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_MM_ARCH_I386_COUNTER_HXX +#define CULT_MM_ARCH_I386_COUNTER_HXX + +#include + +namespace Cult +{ + namespace MM + { + class Counter: public NonCopyable + { + public: + Counter (); + + // After failure assume the counter has its old value. + // + Void + inc_ref (); + + + // After failure assume the counter has its new value. + // + Boolean + dec_ref (); + + + Size + count () const; + + private: + Size value_; + }; + } +} + +#include + +#endif // CULT_MM_ARCH_I386_COUNTER_HXX diff --git a/libcult/cult/mm/arch/i386/counter.ixx b/libcult/cult/mm/arch/i386/counter.ixx new file mode 100644 index 0000000..8279394 --- /dev/null +++ b/libcult/cult/mm/arch/i386/counter.ixx @@ -0,0 +1,46 @@ +// file : cult/mm/arch/i386/counter.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace MM + { + inline + Counter:: + Counter () + : value_ (1) + { + } + + inline + Void Counter:: + inc_ref () + { + asm volatile ("lock; incl %0" + :"=m" (value_) + :"m" (value_)); + } + + inline + Boolean Counter:: + dec_ref () + { + register unsigned char r; + + asm volatile("lock; decl %0; setz %1" + :"=m" (value_), "=rm" (r) + :"m" (value_)); + + return r != 0; + } + + inline + Size Counter:: + count () const + { + return value_; + } + } +} diff --git a/libcult/cult/mm/arch/i386/i486/i586/i686/x86_64/counter.hxx b/libcult/cult/mm/arch/i386/i486/i586/i686/x86_64/counter.hxx new file mode 100644 index 0000000..5869b09 --- /dev/null +++ b/libcult/cult/mm/arch/i386/i486/i586/i686/x86_64/counter.hxx @@ -0,0 +1,43 @@ +// file : cult/mm/arch/i386/i486/i586/i686/x86_64/counter.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_MM_ARCH_I386_I486_I586_I686_X86_64_COUNTER_HXX +#define CULT_MM_ARCH_I386_I486_I586_I686_X86_64_COUNTER_HXX + +#include + +namespace Cult +{ + namespace MM + { + class Counter: public NonCopyable + { + public: + Counter (); + + // After failure assume the counter has its old value. + // + Void + inc_ref (); + + + // After failure assume the counter has its new value. + // + Boolean + dec_ref (); + + + Size + count () const; + + private: + Size value_; + }; + } +} + +#include + +#endif // CULT_MM_ARCH_I386_I486_I586_I686_X86_64_COUNTER_HXX diff --git a/libcult/cult/mm/arch/i386/i486/i586/i686/x86_64/counter.ixx b/libcult/cult/mm/arch/i386/i486/i586/i686/x86_64/counter.ixx new file mode 100644 index 0000000..9e9e7f4 --- /dev/null +++ b/libcult/cult/mm/arch/i386/i486/i586/i686/x86_64/counter.ixx @@ -0,0 +1,46 @@ +// file : cult/mm/arch/i386/i486/i586/i686/x86_64/counter.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace MM + { + inline + Counter:: + Counter () + : value_ (1) + { + } + + inline + Void Counter:: + inc_ref () + { + asm volatile ("lock; incq %0" + :"=m" (value_) + :"m" (value_)); + } + + inline + Boolean Counter:: + dec_ref () + { + register unsigned char r; + + asm volatile("lock; decq %0; setz %1" + :"=m" (value_), "=rm" (r) + :"m" (value_)); + + return r != 0; + } + + inline + Size Counter:: + count () const + { + return value_; + } + } +} diff --git a/libcult/cult/mm/bits/evptr.hxx b/libcult/cult/mm/bits/evptr.hxx new file mode 100644 index 0000000..02f0b48 --- /dev/null +++ b/libcult/cult/mm/bits/evptr.hxx @@ -0,0 +1,379 @@ +// file : cult/mm/bits/evptr.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_MM_BITS_EVPTR_HXX +#define CULT_MM_BITS_EVPTR_HXX + +#include + +#include + +#include +#include + +#include // assert + +namespace Cult +{ + namespace MM + { + + //@@ Should be in mm/evptr.hxx + // + struct Clone: virtual Exception {}; + + template + class Evptr; + + namespace Bits + { + template (x::*f) () const = &x::clone> + struct Helper; + + //@@ Should be generalized and moved to Cult::meta + // + template + struct has_clone + { + template + static Meta::Yes + test (Helper*); + + template + static Meta::No + test (...); + + static Boolean const r = sizeof (test (0)) == sizeof (Meta::Yes); + }; + + //@@ Need to incorporate tests for polymorpism and NonCopyable. + // + + template ::r> + struct Cloner; + + template + struct Cloner + { + static X* + clone (X const* cp) + { + return cp->clone ().release (); + } + }; + + template + struct Cloner + { + static X* + clone (X const*) + { + throw MM::Clone (); + } + }; + } + + namespace Bits + { + template + class Transfer; + } + + namespace Bits + { + template + class EvptrBase + { + protected: + ~EvptrBase () + { + free (p_ ? p_ : cp_, c_); + } + + EvptrBase (X* p, X const* cp, Counter* c, Boolean inc = true) + : p_ (p), cp_ (cp), c_ (c) + { + assert (!(p_ != 0 && cp_ != 0)); + + if (cp_ != 0 && c_ && inc) c_->inc_ref (); + } + + public: + X* + get () const + { + return get_ (); + } + + X* + release () + { + X* p (get_ ()); + + c_ = 0; + p_ = 0; + cp_ = 0; + + return p; + } + + Size + count () const + { + if (c_ == 0) throw NullPointer (); + return c_->count (); + } + + public: + // Conversion to Boolean. + // + typedef X* (EvptrBase::*BooleanConvertible)() const; + + operator BooleanConvertible () const + { + return c_ ? &EvptrBase::get : 0; + } + + protected: + Void + assign (X const* cp, Counter* c) + { + if (c_ && c_ == c) throw SelfAssignment (); + + free (p_ ? p_ : cp_, c_); + + if (c) c->inc_ref (); + + c_ = c; + p_ = 0; + cp_ = cp; + } + + Void + transfer (X* p, X const* cp, Counter* c) + { + free (p_ ? p_ : cp_, c_); + + c_ = c; + p_ = p; + cp_ = cp; + } + + protected: + X* + get_ () const + { + if (c_ == 0) return 0; + + assert (p_ != 0 || cp_ != 0); + + if (p_ != 0) + { + if (c_->count () == 1) return p_; + else + { + // Convert to shared case. + // + cp_ = p_; + p_ = 0; + } + } + + // Shared case with cloning. + // + + // Check if we are the sole owner. + // + if (c_->count () == 1) + { + // Convert to exclusive case. + // + p_ = const_cast (cp_); + cp_ = 0; + } + else + { + assert (cp_ != 0); + + //p_ = cp_->clone ().release (); + + p_ = Cloner::clone (cp_); + + free (cp_, c_); + + cp_ = 0; + c_ = locate (p_, *counted); + } + + return p_; + } + + static Void + free (X const* p, Counter* c) + { + if (c && c->dec_ref ()) + { + assert (p != 0); + delete p; + } + } + + private: + template + friend class Evptr; + + template + friend class Transfer; + + mutable X* p_; + mutable X const* cp_; + mutable Counter* c_; + }; + + + template + class EvptrBase + { + protected: + ~EvptrBase () + { + free (p_ ? p_ : cp_, c_); + } + + EvptrBase (X const* p, X const* cp, Counter* c, Boolean inc = true) + : p_ (p), cp_ (cp), c_ (c) + { + assert (!(p_ != 0 && cp_ != 0)); + + if (cp_ != 0 && c_ && inc) c_->inc_ref (); + } + + public: + X const* + get () + { + return get_ (); + } + + //@@ Should clone if shared? + // + X const* + release () + { + X const* p (get_ ()); + + c_ = 0; + p_ = 0; + cp_ = 0; + + return p; + } + + Size + count () const + { + if (c_ == 0) throw NullPointer (); + return c_->count (); + } + + public: + // Conversion to Boolean. + // + typedef X const* (EvptrBase::*BooleanConvertible)() const; + + operator BooleanConvertible () const + { + return c_ ? &EvptrBase::get : 0; + } + + protected: + Void + assign (X const* cp, Counter* c) + { + if (c_ && c_ == c) throw SelfAssignment (); + + free (p_ ? p_ : cp_, c_); + + if (c) c->inc_ref (); + + c_ = c; + p_ = 0; + cp_ = cp; + } + + Void + transfer (X const* p, X const* cp, Counter* c) + { + free (p_ ? p_ : cp_, c_); + + c_ = c; + p_ = p; + cp_ = cp; + } + + protected: + X const* + get_ () const + { + return p_ ? p_ : cp_; + } + + static Void + free (X const* p, Counter* c) + { + if (c && c->dec_ref ()) + { + assert (p != 0); + delete p; + } + } + + private: + template + friend class Evptr; + + template + friend class Transfer; + + mutable X const* p_; + mutable X const* cp_; + mutable Counter* c_; + }; + } + + namespace Bits + { + template + class Transfer : protected EvptrBase + { + public: + Transfer (Transfer const& ct) + : EvptrBase (ct.p_, ct.cp_, ct.c_, false) + { + Transfer& t (const_cast&> (ct)); + + t.c_ = 0; + t.p_ = 0; + t.cp_ = 0; + } + + private: + Transfer (X* p, X const* cp, Counter* c) + : EvptrBase (p, cp, c, false) + { + } + + template + friend class Evptr; + + private: + Transfer& + operator= (Transfer const&); + }; + } + } +} + +#endif // CULT_MM_BITS_EVPTR_HXX diff --git a/libcult/cult/mm/bits/shptr.hxx b/libcult/cult/mm/bits/shptr.hxx new file mode 100644 index 0000000..7089c53 --- /dev/null +++ b/libcult/cult/mm/bits/shptr.hxx @@ -0,0 +1,85 @@ +// file : cult/mm/bits/shptr.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_MM_BITS_SHPTR_HXX +#define CULT_MM_BITS_SHPTR_HXX + +#include + +#include +#include + +namespace Cult +{ + namespace MM + { + namespace Bits + { + template + class Shptr + { + protected: + ~Shptr () + { + if (c_ && c_->dec_ref ()) delete p_; + } + + Shptr (X* p, Counter* c, Boolean inc = true) + : p_ (p), c_ (c) + { + if (c_ && inc) c_->inc_ref (); + } + + protected: + X* + release_ () throw () + { + X* tmp (p_); + + c_ = 0; + p_ = 0; + + return tmp; + } + + protected: + template + Void + assign (Shptr const& bp, Boolean inc = true) + { + assign (bp.p_, bp.c_, inc); + } + + Void + assign (X* p, Counter* c, Boolean inc) + { + if (c_ && c_ == c) throw SelfAssignment (); + + if (c_) + { + Counter* t (c_); + c_ = 0; + p_ = 0; + t->dec_ref (); + } + + if (c && inc) c->inc_ref (); + + p_ = p; + c_ = c; + } + + protected: + template + friend class Shptr; + + X* p_; + Counter* c_; + }; + } + } +} + +#endif // CULT_MM_BITS_SHPTR_HXX diff --git a/libcult/cult/mm/buffer.cxx b/libcult/cult/mm/buffer.cxx new file mode 100644 index 0000000..c3a28ff --- /dev/null +++ b/libcult/cult/mm/buffer.cxx @@ -0,0 +1,140 @@ +// file : cult/mm/buffer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include // malloc, realloc, free +#include // memcpy + +namespace Cult +{ + namespace MM + { + Buffer:: + ~Buffer () + { + std::free (b_); + } + + Buffer:: + Buffer (Size capacity, Size size) throw (ZeroCapacity, Bounds, BadAlloc) + : c_ (capacity), s_ (size), p_ (0) + { + if (c_ == 0) throw ZeroCapacity (); + if (s_ > c_) throw Bounds (); + + b_ = std::malloc (c_); + + if (b_ == 0) throw BadAlloc (); + } + + Buffer:: + Buffer (void const* p, size_t s) + : c_ (s), s_ (s), p_ (0) + { + if (c_ == 0) throw ZeroCapacity (); + + b_ = std::malloc (c_); + + if (b_ == 0) throw BadAlloc (); + + std::memcpy (b_, p, s); + } + + + Buffer:: + Buffer (Buffer const& b) + : c_ (b.c_), s_ (b.s_), p_ (b.p_) + { + b_ = std::malloc (c_); + + if (b_ == 0) throw BadAlloc (); + + std::memcpy (b_, b.b_, s_); + } +/* + Buffer& + operator= (Buffer const&) + { + return *this; + } +*/ + + // capacity + // + + Size Buffer:: + capacity () const throw () + { + return c_; + } + + Boolean Buffer:: + capacity (Size c) throw (ZeroCapacity, Bounds, BadAlloc) + { + if (c == 0) throw ZeroCapacity (); + if (s_ > c) throw Bounds (); + + Void* b (std::realloc (b_, c)); + + if (b == 0) throw BadAlloc (); + + c_ = c; + + if (b == b_) return false; + + b_ = b; + + return true; + } + + // size + // + + Size Buffer:: + size () const throw () + { + return s_; + } + + void Buffer:: + size (Size s) throw (Bounds) + { + if (s > c_ || p_ > s) throw Bounds (); + + s_ = s; + } + + // position + // + + Index Buffer:: + position () const throw () + { + return p_; + } + + Void Buffer:: + position (Index p) throw (Bounds) + { + if (p > s_) throw Bounds (); + + p_ = p; + } + + + Char const* Buffer:: + data () const + { + return reinterpret_cast (b_); + } + + Char* Buffer:: + data () + { + return reinterpret_cast (b_); + } + } +} diff --git a/libcult/cult/mm/buffer.hxx b/libcult/cult/mm/buffer.hxx new file mode 100644 index 0000000..d50c824 --- /dev/null +++ b/libcult/cult/mm/buffer.hxx @@ -0,0 +1,80 @@ +// file : cult/mm/buffer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_MM_BUFFER_HXX +#define CULT_MM_BUFFER_HXX + +#include + +#include + +namespace Cult +{ + namespace MM + { + //@@ why can't capacity be zero? + // + + class Buffer + { + public: + struct Bounds: virtual Exception {}; + struct ZeroCapacity: virtual Exception {}; + + public: + virtual + ~Buffer (); + + Buffer (Size capacity, Size size = 0) + throw (ZeroCapacity, Bounds, BadAlloc); + + Buffer (Void const*, Size size); + + Buffer (Buffer const& other); + + private: + Buffer& + operator= (Buffer const&); + + public: + Size + capacity () const throw (); + + // Returns true if the underlying buffer has been moved. + // + Boolean + capacity (Size capacity) throw (ZeroCapacity, Bounds, BadAlloc); + + public: + Size + size () const throw (); + + Void + size (Size size) throw (Bounds); + + public: + Index + position () const throw (); + + Void + position (Index) throw (Bounds); + + public: + Char const* + data () const; + + Char* + data (); + + private: + Void* b_; + Size c_, s_, p_; + }; + } + + using MM::Buffer; +} + +#endif // CULT_MM_BUFFER_HXX diff --git a/libcult/cult/mm/counter.cxx b/libcult/cult/mm/counter.cxx new file mode 100644 index 0000000..7d43e3c --- /dev/null +++ b/libcult/cult/mm/counter.cxx @@ -0,0 +1,14 @@ +// file : cult/mm/counter.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace MM + { + StaticPtr > counted; + } +} diff --git a/libcult/cult/mm/counter.hxx b/libcult/cult/mm/counter.hxx new file mode 100644 index 0000000..12e1e70 --- /dev/null +++ b/libcult/cult/mm/counter.hxx @@ -0,0 +1,79 @@ +// file : cult/mm/counter.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_MM_COUNTER_HXX +#define CULT_MM_COUNTER_HXX + +#ifdef CULT_THREADS + +// Multi-threaded version is architecture-specific. +// +#include + +#else + +// Single-threaded version. +// + +#include + +namespace Cult +{ + namespace MM + { + class Counter: public NonCopyable + { + public: + Counter (); + + // After failure assume the counter has its old value. + // + Void + inc_ref (); + + + // After failure assume the counter has its new value. + // + Boolean + dec_ref (); + + + Size + count () const; + + private: + Size value_; + }; + } +} + +#include + +#endif // CULT_THREADS + + +#include +#include + +namespace Cult +{ + namespace MM + { + extern StaticPtr > counted; + + + // Non-member inc_ref. Especially useful for messing with `this'. + // + template + X* + inc_ref (X* p) + { + locate (p, *counted)->inc_ref (); + return p; + } + } +} + +#endif // CULT_MM_COUNTER_HXX diff --git a/libcult/cult/mm/counter.ixx b/libcult/cult/mm/counter.ixx new file mode 100644 index 0000000..f807552 --- /dev/null +++ b/libcult/cult/mm/counter.ixx @@ -0,0 +1,38 @@ +// file : cult/mm/counter.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace MM + { + inline + Counter:: + Counter () + : value_ (1) + { + } + + inline + Void Counter:: + inc_ref () + { + ++value_; + } + + inline + Boolean Counter:: + dec_ref () + { + return --value_ == 0; + } + + inline + Size Counter:: + count () const + { + return value_; + } + } +} diff --git a/libcult/cult/mm/evptr.hxx b/libcult/cult/mm/evptr.hxx new file mode 100644 index 0000000..ed0bd93 --- /dev/null +++ b/libcult/cult/mm/evptr.hxx @@ -0,0 +1,221 @@ +// file : cult/mm/evptr.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_MM_EVPTR_HXX +#define CULT_MM_EVPTR_HXX + +#include + +#include +#include + +#include //@@ tmp + +namespace Cult +{ + namespace MM + { + // Leaks resource should dec_ref fail. + // + template + class Evptr: public Bits::EvptrBase + { + typedef Bits::EvptrBase Base; + + public: + Evptr (X* p = 0) + : Base (p, 0, locate (p, *counted)) + { + } + + Evptr (Evptr const& ep) + : Base (0, ep.cp_ ? ep.cp_ : ep.p_, ep.c_) + { + } + + template + Evptr (Bits::Transfer const& ct) + : Base (ct.p_, ct.cp_, ct.c_, false) + { + Bits::Transfer& t (const_cast&> (ct)); + + t.c_ = 0; + t.p_ = 0; + t.cp_ = 0; + } + + template + Evptr (Evptr const& ep) + : Base (0, ep.cp_ ? ep.cp_ : ep.p_, ep.c_) + { + //@@ + //printf ("X : %s\n", typeid (X).name ()); + //printf ("Y : %s\n", typeid (Y).name ()); + } + + template + Evptr (Evptr const& ep) + : Base (0, ep.cp_ ? ep.cp_ : ep.p_, ep.c_) + { + //@@ + //printf ("X : %s\n", typeid (X).name ()); + //printf ("Y : %s const\n", typeid (Y).name ()); + } + + public: + // After failure leaves object in destructable state. + // + Evptr& + operator= (Evptr const& ep) + { + this->assign (ep.cp_ ? ep.cp_ : ep.p_, ep.c_); + + return *this; + } + + template + Evptr& + operator= (Evptr const& ep) + { + this->assign (ep.cp_ ? ep.cp_ : ep.p_, ep.c_); + + return *this; + } + + template + Evptr& + operator= (Bits::Transfer const& ct) + { + Bits::Transfer& t (const_cast&> (ct)); + + transfer (t.p_, t.cp_, t.c_); + + t.c_ = 0; + t.p_ = 0; + t.cp_ = 0; + + return *this; + } + + protected: + using Base::get_; + + public: + X* + operator-> () const + { + if (X* p = get_ ()) return p; + + throw NullPointer (); + } + + X& + operator* () const + { + if (X* p = get_ ()) return *p; + + throw NullPointer (); + } + + Bits::Transfer + operator~ () + { + Counter* c (c_); + X* p (p_); + X const* cp (cp_); + + c_ = 0; + p_ = 0; + cp_ = 0; + + return Bits::Transfer (p, cp, c); + } + + public: + using Base::p_; + using Base::cp_; + using Base::c_; + + // Object pointed to by this becomes null. + // + template + Evptr + s_cast () + { + if (p_) + { + Counter* c (c_); + Y* p (static_cast (p_)); + + + c_ = 0; + p_ = 0; + cp_ = 0; + + return Evptr (p, 0, c); + } + else + { + Counter* c (c_); + Y const* cp (static_cast (cp_)); + + c_ = 0; + p_ = 0; + cp_ = 0; + + return Evptr (0, cp, c); + } + } + + // Object pointed to by this becomes null if dynamic_cast succeeds. + // + template + Evptr + d_cast () + { + if (p_) + { + if (Y* p = dynamic_cast (p_)) + { + Counter* c (c_); + + c_ = 0; + p_ = 0; + cp_ = 0; + + return Evptr (p, 0, c); + } + } + else if (Y const* cp = dynamic_cast (cp_)) + { + Counter* c (c_); + + c_ = 0; + p_ = 0; + cp_ = 0; + + return Evptr (0, cp, c); + } + + return Evptr (0); + } + + + private: + Evptr (X* p, X const* cp, Counter* c) // for *_cast + : Base (p, cp, c, false) + { + } + + private: + template + friend class Evptr; + }; + } + + using MM::Evptr; +} + +#endif // CULT_MM_EVPTR_HXX diff --git a/libcult/cult/mm/exception.hxx b/libcult/cult/mm/exception.hxx new file mode 100644 index 0000000..38b3412 --- /dev/null +++ b/libcult/cult/mm/exception.hxx @@ -0,0 +1,31 @@ +// file : cult/mm/exceptions.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_MM_EXCEPTIONS_HXX +#define CULT_MM_EXCEPTIONS_HXX + +#include + +#include // std::bad_alloc + +namespace Cult +{ + namespace MM + { + typedef std::bad_alloc StdBadAlloc; + + struct Exception: virtual EH::Exception {}; + + struct BadAlloc: virtual Exception, StdBadAlloc {}; + + //@@ who uses this? + // + struct SelfAssignment: virtual Exception {}; + + struct NullPointer : virtual Exception {}; + } +} + +#endif // CULT_MM_EXCEPTIONS_HXX diff --git a/libcult/cult/mm/new.cxx b/libcult/cult/mm/new.cxx new file mode 100644 index 0000000..2443f1f --- /dev/null +++ b/libcult/cult/mm/new.cxx @@ -0,0 +1,192 @@ +// file : cult/mm/new.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +#include // std::malloc, std::free + +#include + +namespace +{ + Cult::Trace::Stream& + tout () + { + static Cult::Trace::Stream o ("Cult::MM", 7); + return o; + } +} + +namespace Cult +{ + namespace MM + { + using Bits::Offset; + + + namespace + { + Void* + allocate (Size size, KeyList const& l) throw (StdBadAlloc) + { + Size zone_size (0); + + for (KeyList::Iterator i (l.begin ()); i != l.end (); ++i) + { + zone_size += (*i)->size (); + } + + Size map_size ((l.size () + 1) * sizeof (Offset)); + + //tout () << "allocate: size: " << size + // << " map size: " << map_size + // << " zone size: " << zone_size; + + Char* block (reinterpret_cast ( + std::malloc (size + zone_size + map_size))); + + Char* base (block + zone_size + map_size); + + Offset* map (reinterpret_cast (base) - 1); // map bottom + Char* zone (block + zone_size); // zone bottom + + //tout () << 9 << "allocate:" << '\n' + // << " block : " << (Void*) block << '\n' + // << " base : " << (Void*) base << '\n' + // << " map : " << (Void*) zone << '\n' + // << " zone : " << (Void*) block; + + + // Initialize zone map and construct services. + // + for (KeyList::Iterator i (l.begin ()); i != l.end (); ++i) + { + KeyBase const& k (**i); + + zone -= k.size (); // now at the beginning of the block + + try + { + k.construct (zone); + } + catch (...) + { + std::free (block); + throw StdBadAlloc (); + } + + map->key = &k; + map->offset = base - zone; + + --map; + } + + // Last element. + // + map->key = 0; + map->offset = 0; + + return base; + } + + Void + free (Void* p) throw () + { + Char* base (reinterpret_cast (p)); + + Offset* map (reinterpret_cast (base) - 1); // Map bottom. + + Char* block (reinterpret_cast (map)); + + while (map->key != 0) + { + Char* zone (base - map->offset); + + block = zone; // Last zone is the begining of the block. + + map->key->destroy (zone); + + --map; + } + + //tout () << 9 << "free:" << '\n' + // << " block : " << (Void*) block; + + std::free (block); + } + } + } +} + +namespace Cult +{ + namespace MM + { + namespace Bits + { +#ifdef CULT_THREADS + __thread + Block* first_ __attribute__ ((tls_model ("initial-exec"))) = 0; +#else + Block* first_ = 0; +#endif + } + } +} + +using namespace Cult; + +Void* +operator new (Size s) throw (MM::StdBadAlloc) +{ + return MM::allocate (s, *MM::counted); +} + +Void* +operator new (Size size, MM::KeyList const& list, MM::Bits::Block const& b) + throw (MM::StdBadAlloc) +{ + Void* p (MM::allocate (size, list)); + + const_cast (b).set (p, size); + + return p; +} + +Void +operator delete (Void* p) throw () +{ + if (p) MM::free (p); +} + +Void +operator delete (Void* p, Size) throw () +{ + if (p) MM::free (p); +} + +namespace Cult +{ + namespace MM + { + + Void* ServiceAwareObject:: + operator new (Size size, Bits::Block const& block) + { + Void* p (allocate (size, *MM::counted)); + + const_cast (block).set (p, size); + + return p; + } + + Void ServiceAwareObject:: + operator delete (Void* p, Size) + { + if (p) MM::free (p); + } + } +} diff --git a/libcult/cult/mm/new.hxx b/libcult/cult/mm/new.hxx new file mode 100644 index 0000000..2b815b4 --- /dev/null +++ b/libcult/cult/mm/new.hxx @@ -0,0 +1,297 @@ +// file : cult/mm/new.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_MM_NEW_HXX +#define CULT_MM_NEW_HXX + +#include + +#include + +#include + +#include + +namespace Cult +{ + namespace MM + { + class KeyBase + { + public: + // Returned size should be a multiple of a "perfect" size, + // sizeof (size_t) * 2. + // + virtual Size + size () const = 0; + + virtual Void + construct (Void* p) const = 0; + + virtual Void + destroy (Void* p) const = 0; + + virtual + ~KeyBase () + { + } + }; + + + template + class Key: public KeyBase, public NonCopyable + { + public: + Key () + { + } + + virtual Size + size () const + { + //@@ I can do this transparently in allocate(). + // + Size align (sizeof (Size) * 2); + Size size (sizeof (X)); + + return align * (size / align + ((size % align) ? 1 : 0)); + } + + virtual Void + construct (Void* p) const + { + new (p) X; + } + + virtual Void + destroy (Void* p) const + { + reinterpret_cast (p)->~X (); + } + }; + + + struct Absent : virtual Exception {}; + + + namespace Bits + { + Void* + locate (Void const* p, KeyBase const& k) throw (Absent); + + template ::r> + struct Locator; + + template + struct Locator + { + static Void* + locate (X* p, KeyBase const& k) throw (Absent) + { + return Bits::locate (p, k); + } + }; + + template + struct Locator + { + static Void* + locate (X* p, KeyBase const& k) throw (Absent) + { + return Bits::locate (dynamic_cast (p), k); + } + }; + + // Note that this structure has a "perfect" size: sizeof (size_t) * 2. + // If its size is added to the properly-aligned pointer the result will + // still be a properly-aligned pointer. + // + struct Offset //@@ better name would be OffsetMap + { + KeyBase const* key; + Size offset; + }; + } + + + template + inline + Y* + locate (X* p, Key const& k) throw (Absent) + { + return p ? reinterpret_cast (Bits::Locator::locate (p, k)) : 0; + } + + class KeyList + { + public: + KeyList () + : size_ (0) + { + } + + KeyList (KeyBase const& k) + : size_ (1) + { + keys_[0] = &k; + } + + friend KeyList + operator| (KeyList const& list, KeyBase const& key); + + public: + typedef KeyBase const* const* Iterator; + + Iterator + begin () const + { + return keys_; + } + + Iterator + end () const + { + return &(keys_[size_]); + } + + Size + size () const + { + return size_; + } + + private: + KeyBase const* keys_[8]; + Size size_; + }; + + inline KeyList + operator| (KeyList const& list, KeyBase const& key) + { + //@@ Need to throw on overflow. + // + KeyList r (list); + r.keys_[r.size_++] = &key; + return r; + } + + inline KeyList + operator| (KeyBase const& a, KeyBase const& b) + { + return KeyList (a) | b; + } + } +} + +namespace Cult +{ + namespace MM + { + namespace Bits + { + class Block; + +#ifdef CULT_THREADS + extern __thread + Block* first_ __attribute__ ((tls_model ("initial-exec"))); +#else + extern + Block* first_; +#endif + + class Block + { + public: + Block () + { + } + + ~Block () + { + //@@ assert (first_ == this); + first_ = next_; + } + + Void + set (Void* p, Size size) + { + p_ = reinterpret_cast (p); + size_ = size; + + next_ = first_; + first_ = this; + } + + public: + static Void* + locate (Void const* p) + { + return locate (p, first_); + } + + private: + static Void* + locate (Void const* p, Block* b) + { + if (b) + { + if (p >= b->p_ && p < b->p_ + b->size_) return b->p_; + else return locate (p, b->next_); + } + + return 0; + } + + private: + Char* p_; + Size size_; + + Block* next_; + }; + } + } +} + +Cult::Void* +operator new (Cult::Size) throw (Cult::MM::StdBadAlloc); + +Cult::Void* +operator new (Cult::Size, + Cult::MM::KeyList const&, + Cult::MM::Bits::Block const& = Cult::MM::Bits::Block ()) + throw (Cult::MM::StdBadAlloc); + +//@@ Need a special operator new that just allocates memory (to use in +// static_ptr for instance). +// + +Cult::Void +operator delete (Cult::Void*) throw (); + +Cult::Void +operator delete (Cult::Void*, Cult::Size) throw (); + + +namespace Cult +{ + namespace MM + { + // Inherit from this class if you plan to access service objects + // from a ctor. + // + struct ServiceAwareObject + { + static Void* + operator new (Size s, Bits::Block const& b = Bits::Block ()); + + static Void + operator delete (Void* p, Size s); + }; + } +} + +#include + +#endif // CULT_MM_NEW_HXX diff --git a/libcult/cult/mm/new.ixx b/libcult/cult/mm/new.ixx new file mode 100644 index 0000000..c3287fb --- /dev/null +++ b/libcult/cult/mm/new.ixx @@ -0,0 +1,36 @@ +// file : cult/mm/new.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace MM + { + namespace Bits + { + inline + Void* + locate (Void const* p, KeyBase const& k) throw (Absent) + { + if (Void* bp = Block::locate (p)) p = bp; + + Char* base (reinterpret_cast (const_cast (p))); + + Offset* map (reinterpret_cast (base) - 1); // Map bottom. + + while (map->key != 0) + { + if (map->key == &k) + { + return base - map->offset; + } + + --map; + } + + throw Absent (); + } + } + } +} diff --git a/libcult/cult/mm/shptr.hxx b/libcult/cult/mm/shptr.hxx new file mode 100644 index 0000000..6630b1c --- /dev/null +++ b/libcult/cult/mm/shptr.hxx @@ -0,0 +1,139 @@ +// file : cult/mm/Shptr.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_MM_SHPTR_HXX +#define CULT_MM_SHPTR_HXX + +#include + +#include +#include + +namespace Cult +{ + namespace MM + { + // Leaks resource should dec_ref fail. + // + template + class Shptr : public Bits::Shptr + { + typedef Bits::Shptr Base; + + public: + Shptr (X* p = 0) + : Base (p, locate (p, *counted), false) + { + } + + Shptr (Shptr const& ap) + : Base (ap.p_, ap.c_) + { + } + + template + Shptr (Shptr const& ap) + : Base (ap.p_, ap.c_) + { + } + + public: + // After failure leaves object in destructable state. + // + Shptr& + operator= (Shptr const& ap) + { + this->assign (ap); + return *this; + } + + template + Shptr& + operator= (Shptr const& ap) + { + this->assign (ap); + return *this; + } + + public: + X* + operator-> () const + { + if (p_ == 0) + throw NullPointer (); + + return p_; + } + + X& + operator* () const + { + if (p_ == 0) + throw NullPointer (); + + return *p_; + } + + // conversion to bool + // + typedef X* (Shptr::*BooleanConvertible)() const; + + operator BooleanConvertible () const throw () + { + return p_ ? &Shptr::operator-> : 0; + } + + public: + X* + get () const throw () + { + return p_; + } + + X* + release () throw () + { + return release_ (); + } + + Size + count () const + { + if (p_ == 0) + throw NullPointer (); + + return c_->count (); + } + + public: + template + Shptr + d_cast () const + { + Y* p (dynamic_cast (p_)); + return Shptr (p, p ? c_ : 0); + } + + private: + Shptr (X* p, Counter* c) + : Base (p, c) + { + } + + template + friend class Shptr; + + protected: + using Base::release_; + + using Base::p_; + using Base::c_; + }; + } + + using MM::Shptr; +} + +#endif // CULT_MM_SHPTR_HXX diff --git a/libcult/cult/mm/static-ptr.hxx b/libcult/cult/mm/static-ptr.hxx new file mode 100644 index 0000000..d3dffbd --- /dev/null +++ b/libcult/cult/mm/static-ptr.hxx @@ -0,0 +1,75 @@ +// file : cult/mm/static-ptr.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_MM_STATIC_PTR_HXX +#define CULT_MM_STATIC_PTR_HXX + +#include + +#include // operator new + +namespace Cult +{ + namespace MM + { + namespace Bits + { + struct Default {}; + } + + template + class StaticPtr: public NonCopyable + { + public: + X& + operator* () const + { + return instance (); + } + + X* + operator-> () const + { + return &instance (); + } + + public: + StaticPtr () + { + if (i_ == 0) i_ = instance_ (); + } + + ~StaticPtr () + { + // Note that we don't delete the object in order to avoid + // destruction order problem. + // + } + + private: + static X& + instance () + { + if (i_ == 0) i_ = instance_ (); + + return *i_; + } + + static X* + instance_ () + { + static X* i = new (KeyList ()) X; + return i; + } + + static X* i_; + }; + + template + X* StaticPtr::i_ = 0; + } +} + +#endif // CULT_MM_STATIC_PTR_HXX diff --git a/libcult/cult/os/exception.cxx b/libcult/cult/os/exception.cxx new file mode 100644 index 0000000..1fd7e3b --- /dev/null +++ b/libcult/cult/os/exception.cxx @@ -0,0 +1,13 @@ +// file : cult/os/exception.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace OS + { + } +} diff --git a/libcult/cult/os/exception.hxx b/libcult/cult/os/exception.hxx new file mode 100644 index 0000000..3c4164e --- /dev/null +++ b/libcult/cult/os/exception.hxx @@ -0,0 +1,46 @@ +// file : cult/os/exception.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_OS_EXCEPTION_HXX +#define CULT_OS_EXCEPTION_HXX + +#include + +#include + +#include + +namespace Cult +{ + namespace OS + { + class Exception : public virtual EH::Exception + { + public: + Exception (Int code = error_code ()) throw () + : code_ (code) + { + } + + Int + code () const throw () + { + return code_; + } + + private: + static Int + error_code () throw () + { + return errno; + } + + private: + Int code_; + }; + } +} + +#endif // CULT_OS_EXCEPTION_HXX diff --git a/libcult/cult/os/net/address.cxx b/libcult/cult/os/net/address.cxx new file mode 100644 index 0000000..7860b29 --- /dev/null +++ b/libcult/cult/os/net/address.cxx @@ -0,0 +1,37 @@ +// file : cult/os/net/address.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace OS + { + namespace Net + { + Address:: + Address () + { + } + + Address:: + ~Address () + { + } + + Address:: + Address (Address const&) + { + } + + Address& Address:: + operator= (Address const&) + { + return *this; + } + } + } +} + diff --git a/libcult/cult/os/net/address.hxx b/libcult/cult/os/net/address.hxx new file mode 100644 index 0000000..2923ec6 --- /dev/null +++ b/libcult/cult/os/net/address.hxx @@ -0,0 +1,60 @@ +// file : cult/os/net/address.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_OS_NET_ADDRESS_HXX +#define CULT_OS_NET_ADDRESS_HXX + +#include + +#include + +#include // sa_family_t, sockaddr + +namespace Cult +{ + namespace OS + { + namespace Net + { + class Address + { + public: + struct Exception: virtual OS::Exception {}; + + struct Invalid : virtual Exception {}; + + public: + Address (); + + virtual + ~Address (); + + public: + //@@ need to wrap family + // + virtual sa_family_t + familiy () const = 0; + + virtual sockaddr const* + raw_addr () const = 0; + + virtual Size + raw_size () const = 0; + + + //@@ Should it be Clonable rather? + // + protected: + Address (Address const&); + + Address& + operator= (Address const&); + }; + } + } +} + + +#endif // CULT_OS_NET_ADDRESS_HXX diff --git a/libcult/cult/os/net/datagram-socket.cxx b/libcult/cult/os/net/datagram-socket.cxx new file mode 100644 index 0000000..b023b46 --- /dev/null +++ b/libcult/cult/os/net/datagram-socket.cxx @@ -0,0 +1,26 @@ +// file : cult/os/net/datagram-socket.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace OS + { + namespace Net + { + DatagramSocket:: + DatagramSocket () + { + } + + DatagramSocket:: + ~DatagramSocket () + { + } + } + } +} + diff --git a/libcult/cult/os/net/datagram-socket.hxx b/libcult/cult/os/net/datagram-socket.hxx new file mode 100644 index 0000000..62d1a07 --- /dev/null +++ b/libcult/cult/os/net/datagram-socket.hxx @@ -0,0 +1,57 @@ +// file : cult/os/net/datagram-socket.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_OS_NET_DATAGRAM_SOCKET_HXX +#define CULT_OS_NET_DATAGRAM_SOCKET_HXX + +#include + +#include +#include + +#include // SOCK_DGRAM + +namespace Cult +{ + namespace OS + { + namespace Net + { + class DatagramSocket: public virtual Socket + { + protected: + DatagramSocket (); + + virtual + ~DatagramSocket (); + + public: + virtual Int + type () const + { + return SOCK_DGRAM; + } + + public: + virtual Size + send (Void const* buf, Size size, Address const& addr) = 0; + + virtual Size + recv (Void* buf, Size size) = 0; + + /* + virtual Boolean + recv (Void* buf, + Size size, + Size& received, + OS::Time const& timeout) = 0; + */ + }; + } + } +} + + +#endif // CULT_OS_NET_DATAGRAM_SOCKET_HXX diff --git a/libcult/cult/os/net/ipv4/address.cxx b/libcult/cult/os/net/ipv4/address.cxx new file mode 100644 index 0000000..2507ed6 --- /dev/null +++ b/libcult/cult/os/net/ipv4/address.cxx @@ -0,0 +1,37 @@ +// file : cult/os/net/ipv4/address.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace Cult +{ + namespace OS + { + namespace Net + { + namespace IPv4 + { + std::ostream& + operator<< (std::ostream& os, Address const& addr) + { + char str[INET_ADDRSTRLEN]; + + if (inet_ntop (AF_INET, + &addr.addr_.sin_addr, + str, + INET_ADDRSTRLEN) == 0) + { + throw Address::Invalid (); + } + + return os << str << ":" << addr.port (); + } + } + } + } +} + diff --git a/libcult/cult/os/net/ipv4/address.hxx b/libcult/cult/os/net/ipv4/address.hxx new file mode 100644 index 0000000..9168507 --- /dev/null +++ b/libcult/cult/os/net/ipv4/address.hxx @@ -0,0 +1,143 @@ +// file : cult/os/net/ipv4/address.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_OS_NET_IPV4_ADDRESS_HXX +#define CULT_OS_NET_IPV4_ADDRESS_HXX + +#include + +#include + +#include // IPv4 types (sockaddr_in, etc) +#include // hto{n,h}{s,l}, iNet_pton + +#include +#include // memset + +namespace Cult +{ + namespace OS + { + namespace Net + { + namespace IPv4 + { + class Address: public Net::Address + { + public: + Address () + { + std::memset (&addr_, 0, sizeof (addr_)); + } + + Address (sockaddr_in const& addr) + { + if (addr.sin_family != AF_INET) + throw Invalid (); + + std::memset (&addr_, 0, sizeof (addr_)); + + addr_.sin_family = AF_INET; + addr_.sin_addr.s_addr = addr.sin_addr.s_addr; + addr_.sin_port = addr.sin_port; + } + + Address (in_addr_t host_addr, in_port_t host_port) + { + std::memset (&addr_, 0, sizeof (addr_)); + + addr_.sin_family = AF_INET; + addr_.sin_addr.s_addr = htonl (host_addr); + addr_.sin_port = htons (host_port); + } + + Address (String const& host_addr, in_port_t host_port) + { + std::memset (&addr_, 0, sizeof (addr_)); + + addr_.sin_family = AF_INET; + addr_.sin_port = htons (host_port); + + if (inet_pton (AF_INET, host_addr.c_str (), &addr_.sin_addr) <= 0) + throw Invalid (); + } + + public: + virtual sa_family_t + familiy () const + { + return AF_INET; + } + + virtual sockaddr const* + raw_addr () const + { + return reinterpret_cast (&addr_); + } + + virtual Size + raw_size () const + { + return sizeof (addr_); + } + + public: + sockaddr_in const& + addr () const + { + return addr_; + } + + in_addr_t + ip () const + { + return ntohl (addr_.sin_addr.s_addr); + } + + in_port_t + port () const + { + return ntohs (addr_.sin_port); + } + + public: + friend + Boolean + operator< (Address const& x, Address const& y) + { + return (x.addr_.sin_addr.s_addr < y.addr_.sin_addr.s_addr) || + ((x.addr_.sin_addr.s_addr == y.addr_.sin_addr.s_addr) && + (x.addr_.sin_port < y.addr_.sin_port)); + } + + friend + Boolean + operator== (Address const& x, Address const& y) + { + return (x.addr_.sin_addr.s_addr == y.addr_.sin_addr.s_addr) && + (x.addr_.sin_port == y.addr_.sin_port); + } + + friend + Boolean + operator!= (Address const& x, Address const& y) + { + return !(x == y); + } + + friend + std::ostream& + operator<< (std::ostream&, Address const&); + + private: + sockaddr_in addr_; + }; + } + } + } +} + + +#endif // CULT_OS_NET_IPV4_ADDRESS_HXX diff --git a/libcult/cult/os/net/ipv4/datagram-socket.cxx b/libcult/cult/os/net/ipv4/datagram-socket.cxx new file mode 100644 index 0000000..ce470cc --- /dev/null +++ b/libcult/cult/os/net/ipv4/datagram-socket.cxx @@ -0,0 +1,20 @@ +// file : cult/os/net/ipv4/datagram-socket.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace OS + { + namespace Net + { + namespace IPv4 + { + } + } + } +} + diff --git a/libcult/cult/os/net/ipv4/datagram-socket.hxx b/libcult/cult/os/net/ipv4/datagram-socket.hxx new file mode 100644 index 0000000..2aad43f --- /dev/null +++ b/libcult/cult/os/net/ipv4/datagram-socket.hxx @@ -0,0 +1,282 @@ +// file : cult/os/net/ipv4/datagram-socket.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_OS_NET_IPV4_DATAGRAM_SOCKET_HXX +#define CULT_OS_NET_IPV4_DATAGRAM_SOCKET_HXX + +#include + +#include +#include +#include + +#include // close +#include // socket, bind, sendto, revcfrom + +namespace Cult +{ + namespace OS + { + namespace Net + { + namespace IPv4 + { + class DatagramSocket: public virtual Net::DatagramSocket + { + public: + virtual + ~DatagramSocket () + { + ::close (sock_); + } + + DatagramSocket () + { + sock_ = ::socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); + + if (sock_ == -1) + throw Exception (); //@@ + } + + DatagramSocket (Address const& addr) + { + sock_ = ::socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); + + if (sock_ == -1) + throw Exception (); //@@ + + if (::bind (sock_, addr.raw_addr (), addr.raw_size ()) == -1) + throw Exception (); //@@ + } + + public: + virtual sa_family_t + familiy () const + { + return AF_INET; + } + + virtual Int + protocol () const + { + return IPPROTO_UDP; + } + + // Options. + // + public: + Size + recv_buffer_size () const + { + Int r; + socklen_t s (sizeof (r)); + + if (::getsockopt (sock_, + SOL_SOCKET, + SO_RCVBUF, + &r, + &s) == -1) + { + throw Exception (); //@@ + } + + return static_cast (r); + } + + Void + recv_buffer_size (Size size) + { + Int r (static_cast (size)); + + if (::setsockopt (sock_, + SOL_SOCKET, + SO_RCVBUF, + &r, + sizeof (r)) == -1) + { + throw Exception (); + } + } + + Size + send_buffer_size () const + { + Int r; + socklen_t s (sizeof (r)); + + if (::getsockopt (sock_, + SOL_SOCKET, + SO_SNDBUF, + &r, + &s) == -1) + { + throw Exception (); + } + + return static_cast (r); + } + + void + send_buffer_size (Size size) + { + Int r (static_cast (size)); + + if (::setsockopt (sock_, + SOL_SOCKET, + SO_SNDBUF, + &r, + sizeof (r)) == -1) + { + throw Exception (); + } + } + + public: + Void + connect (Address const& addr) + { + if (::connect (sock_, addr.raw_addr (), addr.raw_size ()) == -1) + throw Exception (); + } + + Address + address () const + { + sockaddr_in raw_addr; + socklen_t raw_size (sizeof (raw_addr)); + + if (::getsockname (sock_, + reinterpret_cast (&raw_addr), + &raw_size) == -1) + { + throw Exception (); + } + + return Address (raw_addr); + } + + + public: + virtual Size + send (Void const* buf, Size size, Net::Address const& addr) + { + if (addr.familiy () != familiy ()) + throw InvalidAddress (); + + return send (buf, size, dynamic_cast
(addr)); + } + + virtual Size + send (Void const* buf, Size size, Address const& addr) + { + ssize_t n (::sendto (sock_, + buf, + size, + 0, + addr.raw_addr (), + addr.raw_size ())); + + if (n == -1) + throw Exception (); + + return static_cast (n); + } + + virtual Size + recv (Void* buf, Size size) + { + ssize_t n (::recvfrom (sock_, buf, size, 0, 0, 0)); + + if (n == -1) + throw Exception (); + + return static_cast (n); + } + + virtual Size + recv (Void* buf, Size size, Address& addr) + { + sockaddr_in raw_addr; + socklen_t raw_size (sizeof (raw_addr)); + + ssize_t n (::recvfrom (sock_, + buf, + size, + 0, + reinterpret_cast (&raw_addr), + &raw_size)); + + if (n == -1) + throw Exception (); + + addr = Address (raw_addr); + + return static_cast (n); + } + + virtual Size + peek (Void* buf, Size size, Address& addr) + { + sockaddr_in raw_addr; + socklen_t raw_size (sizeof (raw_addr)); + + ssize_t n (::recvfrom (sock_, + buf, + size, + MSG_PEEK, + reinterpret_cast (&raw_addr), + &raw_size)); + + if (n == -1) + throw Exception (); + + addr = Address (raw_addr); + + return static_cast (n); + } + + /* + virtual Boolean + recv (Void* buf, + Size size, + Size& received, + OS::Time const& timeout) + { + fd_set r,e; + + FD_ZERO (&r); + FD_ZERO (&e); + + FD_SET (sock_, &r); + FD_SET (sock_, &e); + + int n = ::pselect (sock_ + 1, &r, 0, &e, &timeout.timespec (), 0); + + if (n > 0) + { + recv_size = recv (buf, buf_size); + return true; + } + else if (n == 0) // timeout + { + return false; + } + else + { + throw Failure ("pselect"); + } + } + */ + + protected: + Int sock_; + }; + } + } + } +} + + +#endif // CULT_OS_NET_IPV4_DATAGRAM_SOCKET_HXX diff --git a/libcult/cult/os/net/ipv4/multicast-socket.cxx b/libcult/cult/os/net/ipv4/multicast-socket.cxx new file mode 100644 index 0000000..1431adc --- /dev/null +++ b/libcult/cult/os/net/ipv4/multicast-socket.cxx @@ -0,0 +1,19 @@ +// file : cult/os/net/ipv4/multicast-socket.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace OS + { + namespace Net + { + namespace IPv4 + { + } + } + } +} diff --git a/libcult/cult/os/net/ipv4/multicast-socket.hxx b/libcult/cult/os/net/ipv4/multicast-socket.hxx new file mode 100644 index 0000000..70207a3 --- /dev/null +++ b/libcult/cult/os/net/ipv4/multicast-socket.hxx @@ -0,0 +1,133 @@ +// file : cult/os/net/ipv4/multicast-socket.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_OS_NET_IPV4_MULTICAST_SOCKET_HXX +#define CULT_OS_NET_IPV4_MULTICAST_SOCKET_HXX + +#include + +#include +#include +#include +#include + +#include // memcpy +#include // bind, setsockopt +#include // htonl + +namespace Cult +{ + namespace OS + { + namespace Net + { + namespace IPv4 + { + //@@ Add MulticastAddress (with proper checks)? + // + + class MulticastSocket : public virtual Net::MulticastSocket, + public virtual DatagramSocket + { + public: + virtual + ~MulticastSocket () + { + } + + public: + MulticastSocket (Boolean loop = true, UnsignedShort ttl = 1) + { + unsigned char ttl_ (static_cast (ttl)); + + { + Int flag (1); + + if (::setsockopt (sock_, + SOL_SOCKET, + SO_REUSEADDR, + &flag, + sizeof (flag)) == -1) + { + throw Exception (); + } + } + + if (ttl != 1) + { + if (::setsockopt (sock_, + IPPROTO_IP, + IP_MULTICAST_TTL, + &ttl_, + sizeof (ttl_)) == -1) + { + throw Exception (); + } + } + + if (!loop) + { + unsigned char flag (0); + + if (::setsockopt (sock_, + IPPROTO_IP, + IP_MULTICAST_LOOP, + &flag, + sizeof (flag)) == -1) + { + throw Exception (); + } + } + + } + + public: + virtual Void + join (Net::Address const& addr) + { + if (addr.familiy () != familiy ()) + throw InvalidAddress (); + + join (dynamic_cast
(addr)); + } + + virtual Void + join (Address const& addr) + { + ip_mreq mreq; + + std::memcpy (&mreq.imr_multiaddr, + &addr.addr ().sin_addr, + sizeof (in_addr)); + + mreq.imr_interface.s_addr = htonl (INADDR_ANY); + + if (::setsockopt (sock_, + IPPROTO_IP, + IP_ADD_MEMBERSHIP, + &mreq, + sizeof (mreq)) == -1) + { + throw Exception (); + } + + if (::bind (sock_, addr.raw_addr (), addr.raw_size ()) == -1) + throw Exception (); + } + + virtual Void + leave () + { + //@@ TODO + abort (); + } + }; + } + } + } +} + + +#endif // CULT_OS_NET_IPV4_MULTICAST_SOCKET_HXX diff --git a/libcult/cult/os/net/multicast-socket.cxx b/libcult/cult/os/net/multicast-socket.cxx new file mode 100644 index 0000000..64710cf --- /dev/null +++ b/libcult/cult/os/net/multicast-socket.cxx @@ -0,0 +1,26 @@ +// file : cult/os/net/multicast-socket.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace OS + { + namespace Net + { + MulticastSocket:: + MulticastSocket () + { + } + + MulticastSocket:: + ~MulticastSocket () + { + } + } + } +} + diff --git a/libcult/cult/os/net/multicast-socket.hxx b/libcult/cult/os/net/multicast-socket.hxx new file mode 100644 index 0000000..7aeff74 --- /dev/null +++ b/libcult/cult/os/net/multicast-socket.hxx @@ -0,0 +1,40 @@ +// file : cult/os/net/multicast-socket.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_OS_NET_MULTICAST_SOCKET_HXX +#define CULT_OS_NET_MULTICAST_SOCKET_HXX + +#include + +#include +#include + +namespace Cult +{ + namespace OS + { + namespace Net + { + class MulticastSocket : public virtual DatagramSocket + { + protected: + MulticastSocket (); + + virtual + ~MulticastSocket (); + + public: + virtual Void + join (Address const& addr) = 0; + + virtual Void + leave () = 0; + }; + } + } +} + + +#endif // CULT_OS_NET_MULTICAST_SOCKET_HXX diff --git a/libcult/cult/os/net/socket.cxx b/libcult/cult/os/net/socket.cxx new file mode 100644 index 0000000..bd9969c --- /dev/null +++ b/libcult/cult/os/net/socket.cxx @@ -0,0 +1,26 @@ +// file : cult/os/net/socket.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace OS + { + namespace Net + { + Socket:: + Socket () + { + } + + Socket:: + ~Socket () + { + } + } + } +} + diff --git a/libcult/cult/os/net/socket.hxx b/libcult/cult/os/net/socket.hxx new file mode 100644 index 0000000..a471186 --- /dev/null +++ b/libcult/cult/os/net/socket.hxx @@ -0,0 +1,54 @@ +// file : cult/os/net/socket.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_OS_NET_SOCKET_HXX +#define CULT_OS_NET_SOCKET_HXX + +#include +#include + +#include // sa_family_t + +namespace Cult +{ + namespace OS + { + namespace Net + { + class Socket: public NonCopyable + { + public: + struct Exception : virtual OS::Exception {}; + + struct InvalidAddress : virtual Exception {}; + + protected: + Socket (); + + virtual + ~Socket (); + + public: + // AF_INET, AF_INET6, etc. + // + virtual sa_family_t + familiy () const = 0; + + // SOCK_DGRAM, SOCK_STREAM, etc. + // + virtual Int + type () const = 0; + + // IPPROTO_UDP, IPPROTO_TCP, IPPROTO_SCTP, etc. + // + virtual Int + protocol () const = 0; + }; + } + } +} + + +#endif // CULT_OS_NET_SOCKET_HXX diff --git a/libcult/cult/rtti/type-id.hxx b/libcult/cult/rtti/type-id.hxx new file mode 100644 index 0000000..21494b1 --- /dev/null +++ b/libcult/cult/rtti/type-id.hxx @@ -0,0 +1,52 @@ +// file : cult/rtti/type-id.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_RTTI_TYPE_ID_HXX +#define CULT_RTTI_TYPE_ID_HXX + +#include + +#include // std::type_info + +namespace Cult +{ + namespace RTTI + { + class TypeId + { + public: + template + TypeId (X const volatile&); + + TypeId (std::type_info const&); + + public: + Char const* + name () const; + + friend Boolean + operator== (TypeId const&, TypeId const&); + + friend Boolean + operator!= (TypeId const&, TypeId const&); + + friend Boolean + operator< (TypeId const&, TypeId const&); + + /* + friend std::ostream& + operator << (std::ostream& os, TypeId const& t); + */ + + private: + std::type_info const* ti_; + }; + } +} + +#include +#include + +#endif // CULT_RTTI_TYPE_ID_HXX diff --git a/libcult/cult/rtti/type-id.ixx b/libcult/cult/rtti/type-id.ixx new file mode 100644 index 0000000..cc77d5f --- /dev/null +++ b/libcult/cult/rtti/type-id.ixx @@ -0,0 +1,45 @@ +// file : cult/rtti/type-id.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace RTTI + { + inline + TypeId:: + TypeId (std::type_info const& ti) + : ti_ (&ti) + { + } + + inline + Char const* TypeId:: + name () const + { + return ti_->name (); + } + + inline + Boolean + operator== (TypeId const& x, TypeId const& y) + { + return *x.ti_ == *y.ti_; + } + + inline + Boolean + operator!= (TypeId const& x, TypeId const& y) + { + return *x.ti_ != *y.ti_; + } + + inline + Boolean + operator< (TypeId const& x, TypeId const& y) + { + return x.ti_->before (*y.ti_); + } + } +} diff --git a/libcult/cult/rtti/type-id.txx b/libcult/cult/rtti/type-id.txx new file mode 100644 index 0000000..4fd771a --- /dev/null +++ b/libcult/cult/rtti/type-id.txx @@ -0,0 +1,18 @@ +// file : cult/rtti/type-id.txx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace RTTI + { + template + inline + TypeId:: + TypeId (X const volatile& x) + : ti_ (&typeid (x)) + { + } + } +} diff --git a/libcult/cult/rtti/type-info.cxx b/libcult/cult/rtti/type-info.cxx new file mode 100644 index 0000000..5bc4040 --- /dev/null +++ b/libcult/cult/rtti/type-info.cxx @@ -0,0 +1,42 @@ +// file : cult/rtti/type-info.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +#include + +namespace Cult +{ + namespace RTTI + { + Access const Access::private_ (Access::private__); + Access const Access::protected_ (Access::protected__); + Access const Access::public_ (Access::public__); + + typedef + Containers::Map + TypeInfoMap; + + static MM::StaticPtr map_; + + TypeInfo const& + lookup (TypeId const& type_id) + { + TypeInfoMap::ConstIterator i (map_->find (type_id)); + + if (i == map_->end ()) throw NoInfo (); + + return i->second; + } + + Void + insert (TypeInfo const& type_info) + { + map_->insert (TypeInfoMap::Pair (type_info.type_id (), type_info)); + } + } +} diff --git a/libcult/cult/rtti/type-info.hxx b/libcult/cult/rtti/type-info.hxx new file mode 100644 index 0000000..dce4923 --- /dev/null +++ b/libcult/cult/rtti/type-info.hxx @@ -0,0 +1,147 @@ +// file : cult/rtti/type-info.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_RTTI_TYPE_INFO_HXX +#define CULT_RTTI_TYPE_INFO_HXX + +#include + +#include + +#include + +#include // std::type_info + +namespace Cult +{ + namespace RTTI + { + // + // + // + class Access + { + public: + static Access const private_, protected_, public_; + + friend Boolean + operator== (Access const& a, Access const& b) + { + return a.v_ == b.v_; + } + + friend Boolean + operator!= (Access const& a, Access const& b) + { + return a.v_ != b.v_; + } + + private: + enum Value { private__, protected__, public__ } v_; + + Access (Value v) + : v_ (v) + { + } + }; + + // + // + class TypeInfo; + + + // + // + class BaseInfo + { + public: + BaseInfo (Access access, Boolean virtual_, TypeId const& type_id); + + public: + TypeInfo const& + type_info () const; + + Access + access () const; + + Boolean + virtual_ () const; + + private: + Access access_; + Boolean virtual__; + TypeId type_id_; + mutable TypeInfo const* type_info_; + }; + + + // + // + class TypeInfo + { + typedef Containers::Vector BaseInfoList; + + public: + typedef + BaseInfoList::ConstIterator + BaseIterator; + + public: + TypeInfo (TypeId const& type_id); + + TypeId + type_id () const; + + BaseIterator + begin_base () const; + + BaseIterator + end_base () const; + + Void + add_base (Access access, Boolean virtual_, TypeId const& type_id); + + private: + TypeId type_id_; + BaseInfoList base_list_; + }; + + + // + // + class NoInfo {}; + + TypeInfo const& + lookup (TypeId const& type_id); + + inline + TypeInfo const& + lookup (std::type_info const& type_info) + { + return lookup (TypeId (type_info)); + } + + template + TypeInfo const& + lookup (X const& x) + { + return lookup (typeid (x)); + } + + template + TypeInfo const& + lookup () + { + return lookup (typeid (X)); + } + + Void + insert (TypeInfo const&); + } +} + +#include + +#endif // CULT_RTTI_TYPE_INFO_HXX diff --git a/libcult/cult/rtti/type-info.ixx b/libcult/cult/rtti/type-info.ixx new file mode 100644 index 0000000..f96ad6c --- /dev/null +++ b/libcult/cult/rtti/type-info.ixx @@ -0,0 +1,87 @@ +// file : cult/rtti/type-info.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace RTTI + { + // BaseInfo + // + + inline + BaseInfo:: + BaseInfo (Access access, Boolean virtual_, TypeId const& type_id) + : access_ (access), + virtual__ (virtual_), + type_id_ (type_id), + type_info_ (0) + { + } + + inline + TypeInfo const& BaseInfo:: + type_info () const + { + if (type_info_ == 0) type_info_ = &(lookup (type_id_)); + + return *type_info_; + } + + + inline + Access BaseInfo:: + access () const + { + return access_; + } + + inline + Boolean BaseInfo:: + virtual_ () const + { + return virtual__; + } + + + // TypeInfo + // + + inline + TypeInfo:: + TypeInfo (TypeId const& type_id) + : type_id_ (type_id) + { + } + + inline + TypeId TypeInfo:: + type_id () const + { + return type_id_; + } + + inline + TypeInfo::BaseIterator TypeInfo:: + begin_base () const + { + return base_list_.begin (); + } + + + inline + TypeInfo::BaseIterator TypeInfo:: + end_base () const + { + return base_list_.end (); + } + + inline + Void TypeInfo:: + add_base (Access access, Boolean virtual_, TypeId const& type_id) + { + base_list_.push_back (BaseInfo (access, virtual_, type_id)); + } + } +} diff --git a/libcult/cult/sched/condition.cxx b/libcult/cult/sched/condition.cxx new file mode 100644 index 0000000..5f547c8 --- /dev/null +++ b/libcult/cult/sched/condition.cxx @@ -0,0 +1,49 @@ +// file : cult/sched/condition.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +namespace Cult +{ + namespace Sched + { + Condition:: + ~Condition () + { + if (Int e = pthread_cond_destroy (&cond_)) + throw Implementation (e); + } + + Condition:: + Condition (Mutex& mutex) + : mutex_ (mutex) + { + if (Int e = pthread_cond_init (&cond_, 0)) + throw Implementation (e); + } + + Void Condition:: + signal () + { + if (Int e = pthread_cond_signal (&cond_)) + throw Implementation (e); + } + + Void Condition:: + broadcast () + { + if (Int e = pthread_cond_broadcast (&cond_)) + throw Implementation (e); + } + + Void Condition:: + wait () + { + if (Int e = pthread_cond_wait (&cond_, &mutex_.mutex_)) + throw Implementation (e); + } + } +} diff --git a/libcult/cult/sched/condition.hxx b/libcult/cult/sched/condition.hxx new file mode 100644 index 0000000..b1a0f30 --- /dev/null +++ b/libcult/cult/sched/condition.hxx @@ -0,0 +1,42 @@ +// file : cult/sched/condition.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_SCHED_CONDITION_HXX +#define CULT_SCHED_CONDITION_HXX + +#include + +#include + +#include + +namespace Cult +{ + namespace Sched + { + class Condition: public NonCopyable + { + public: + ~Condition (); + + Condition (Mutex& mutex); + + Void + signal (); + + Void + broadcast (); + + Void + wait (); + + private: + Mutex& mutex_; + pthread_cond_t cond_; + }; + } +} + +#endif // CULT_SCHED_CONDITION_HXX diff --git a/libcult/cult/sched/exception.hxx b/libcult/cult/sched/exception.hxx new file mode 100644 index 0000000..3fa6e5f --- /dev/null +++ b/libcult/cult/sched/exception.hxx @@ -0,0 +1,30 @@ +// file : cult/sched/exception.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_SCHED_EXCEPTION_HXX +#define CULT_SCHED_EXCEPTION_HXX + +#include + +#include +#include + +namespace Cult +{ + namespace Sched + { + struct Exception: virtual EH::Exception {}; + + struct Implementation: virtual Exception, virtual OS::Exception + { + Implementation (Int code) throw () + : OS::Exception (code) + { + } + }; + } +} + +#endif // CULT_SCHED_EXCEPTION_HXX diff --git a/libcult/cult/sched/lock.cxx b/libcult/cult/sched/lock.cxx new file mode 100644 index 0000000..853d9b0 --- /dev/null +++ b/libcult/cult/sched/lock.cxx @@ -0,0 +1,13 @@ +// file : cult/sched/lock.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace Sched + { + } +} diff --git a/libcult/cult/sched/lock.hxx b/libcult/cult/sched/lock.hxx new file mode 100644 index 0000000..1ecf3fb --- /dev/null +++ b/libcult/cult/sched/lock.hxx @@ -0,0 +1,58 @@ +// file : cult/sched/lock.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_SCHED_LOCK_HXX +#define CULT_SCHED_LOCK_HXX + +#include + +namespace Cult +{ + namespace Sched + { + class Lock: public NonCopyable + { + public: + ~Lock () + { + unlock (); + } + + template + Lock (X& x) + : x_ (reinterpret_cast(&x)), + unlock_ (&unlock), + locked_ (true) + { + x.lock (); + } + + Void + unlock () + { + if (locked_) + { + unlock_ (x_); + locked_ = false; + } + } + + private: + template + static Void + unlock (Void* p) + { + reinterpret_cast (p)->unlock (); + } + + private: + Void* x_; + Void (*unlock_) (Void*); + Boolean locked_; + }; + } +} + +#endif // CULT_SCHED_LOCK_HXX diff --git a/libcult/cult/sched/mutex.cxx b/libcult/cult/sched/mutex.cxx new file mode 100644 index 0000000..9667a67 --- /dev/null +++ b/libcult/cult/sched/mutex.cxx @@ -0,0 +1,54 @@ +// file : cult/sched/mutex.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +namespace Cult +{ + namespace Sched + { + Mutex:: + ~Mutex () + { + if (Int e = pthread_mutex_destroy (&mutex_)) + throw Implementation (e); + } + + Mutex:: + Mutex () + { + if (Int e = pthread_mutex_init (&mutex_, 0)) + throw Implementation (e); + } + + Void Mutex:: + lock () + { + if (Int e = pthread_mutex_lock (&mutex_)) + throw Implementation (e); + } + + Boolean Mutex:: + try_lock () + { + Int e (pthread_mutex_trylock (&mutex_)); + + switch (e) + { + case 0: return true; + case EBUSY: return false; + default: throw Implementation (e); + } + } + + Void Mutex:: + unlock () + { + if (Int e = pthread_mutex_unlock (&mutex_)) + throw Implementation (e); + } + } +} diff --git a/libcult/cult/sched/mutex.hxx b/libcult/cult/sched/mutex.hxx new file mode 100644 index 0000000..0c6daee --- /dev/null +++ b/libcult/cult/sched/mutex.hxx @@ -0,0 +1,41 @@ +// file : cult/sched/mutex.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_SCHED_MUTEX_HXX +#define CULT_SCHED_MUTEX_HXX + +#include + +#include + +namespace Cult +{ + namespace Sched + { + class Mutex: public NonCopyable + { + public: + ~Mutex (); + + Mutex (); + + Void + lock (); + + Boolean + try_lock (); + + Void + unlock (); + + private: + friend class Condition; + + pthread_mutex_t mutex_; + }; + } +} + +#endif // CULT_SCHED_MUTEX_HXX diff --git a/libcult/cult/sched/spin.cxx b/libcult/cult/sched/spin.cxx new file mode 100644 index 0000000..54df7ce --- /dev/null +++ b/libcult/cult/sched/spin.cxx @@ -0,0 +1,28 @@ +// file : cult/sched/spin.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +namespace Cult +{ + namespace Sched + { + Spin:: + ~Spin () + { + if (Int e = pthread_spin_destroy (&spin_)) + throw Implementation (e); + } + + Spin:: + Spin () + { + if (Int e = pthread_spin_init (&spin_, PTHREAD_PROCESS_PRIVATE)) + throw Implementation (e); + } + } +} + diff --git a/libcult/cult/sched/spin.hxx b/libcult/cult/sched/spin.hxx new file mode 100644 index 0000000..c32e836 --- /dev/null +++ b/libcult/cult/sched/spin.hxx @@ -0,0 +1,41 @@ +// file : cult/sched/spin.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_SCHED_SPIN_HXX +#define CULT_SCHED_SPIN_HXX + +#include + +#include + +namespace Cult +{ + namespace Sched + { + class Spin: public NonCopyable + { + public: + ~Spin (); + + Spin (); + + Void + lock (); + + Boolean + try_lock (); + + Void + unlock (); + + private: + pthread_spinlock_t spin_; + }; + } +} + +#include + +#endif // CULT_SCHED_SPIN_HXX diff --git a/libcult/cult/sched/spin.ixx b/libcult/cult/sched/spin.ixx new file mode 100644 index 0000000..2accdde --- /dev/null +++ b/libcult/cult/sched/spin.ixx @@ -0,0 +1,43 @@ +// file : cult/sched/spin.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace Sched + { + inline + Void Spin:: + lock () + { + if (Int e = pthread_spin_lock (&spin_)) + throw Implementation (e); + } + + inline + Boolean Spin:: + try_lock () + { + Int e (pthread_spin_trylock (&spin_)); + + switch (e) + { + case 0: return true; + case EBUSY: return false; + default: throw Implementation (e); + } + } + + inline + Void Spin:: + unlock () + { + if (Int e = pthread_spin_unlock (&spin_)) + throw Implementation (e); + } + } +} + diff --git a/libcult/cult/sched/thread.cxx b/libcult/cult/sched/thread.cxx new file mode 100644 index 0000000..89368b6 --- /dev/null +++ b/libcult/cult/sched/thread.cxx @@ -0,0 +1,211 @@ +// file : cult/sched/thread.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include +#include + +#include // MM::inc_ref + +#include + +namespace Cult +{ + namespace Sched + { + namespace + { + Trace::Stream tout ("Cult::Sched::Thread", 7); + } + + namespace Bits + { + typedef Void* (*Routine) (Void*); + + struct StartData + { + StartData (Shptr const& thread, Routine routine, void* arg) + : thread_ (thread), routine_ (routine), arg_ (arg) + { + } + + ~StartData () + { + tout << 8 << "start data is being destroyed."; + } + + Shptr thread_; + Routine routine_; + Void* arg_; + }; + + static pthread_key_t key; + static pthread_once_t key_once = PTHREAD_ONCE_INIT; + + extern "C" Void + cult_thread_dtor (Void* p) + { + // Exception in this function will result in the call + // to std::terminate(). + // + + tout << "cult_thread_dtor is being executed."; + + Shptr self (reinterpret_cast (p)); + } + + extern "C" Void + cult_thread_make_key () + { + if (Int e = pthread_key_create (&key, &cult_thread_dtor)) + throw Implementation (e); + } + + extern "C" Void* + cult_thread_trampoline (Void* arg) + { + // Any failure in this function will result in the call + // to std::terminate(). + // + + Routine routine; + + { + Shptr data (reinterpret_cast (arg)); + + Thread* p (data->thread_.get ()); + + if (Int e = pthread_setspecific (key, p)) + throw Implementation (e); + else + MM::inc_ref (p); + + routine = data->routine_; + arg = data->arg_; + } + + return routine (arg); + } + } + + Thread:: + Thread (Void* (*routine) (Void*), Void* arg) + : detached_ (false) + { + using Bits::StartData; + + tout << "thread is being constructed."; + + pthread_once (&Bits::key_once, &Bits::cult_thread_make_key); + + Shptr self (MM::inc_ref (this)); + + Shptr data (new StartData (self, routine, arg)); + + if (Int e = pthread_create (&id_, + 0, + &Bits::cult_thread_trampoline, + data.get ())) + { + throw Implementation (e); + } + else + { + // If pthread_create did not fail then thread_trampoline + // will release the data. + // + data.release (); + } + } + + Thread:: + Thread () + : id_ (pthread_self ()), detached_ (false) //@@ We can't be sure + // the it is detached. + { + tout << "thread is being adopted."; + + pthread_once (&Bits::key_once, &Bits::cult_thread_make_key); + + if (pthread_getspecific (Bits::key) != 0) + throw Adopted (); + + Shptr self (MM::inc_ref (this)); + + if(Int e = pthread_setspecific (Bits::key, this)) + { + throw Implementation (e); + } + else + { + // TSD slot has the reference now. + // + self.release (); + } + } + + Void* Thread:: + join () + { + Lock lock (mutex_); + + if (detached_) + throw Joined (); + + Void* r; + + if (Int e = pthread_join (id_, &r)) + throw Implementation (e); + + detached_ = true; + + return r; + } + + Void Thread:: + cancel () + { + if (Int e = pthread_cancel (id_)) + throw Implementation (e); + } + + Void Thread:: + exit (Void* ret) + { + pthread_exit (ret); + } + + Shptr Thread:: + self () + { + Thread* p (reinterpret_cast (pthread_getspecific (Bits::key))); + + if (p != 0) + return Shptr (MM::inc_ref (p)); + else + throw Foreign (); + } + + Void Thread:: + test_cancel () + { + pthread_testcancel (); + } + + Thread:: + ~Thread () + { + tout << "thread is being destroyed."; + + Lock lock (mutex_); + + if (!detached_) + { + if (Int e = pthread_detach (id_)) + throw Implementation (e); + } + } + } +} diff --git a/libcult/cult/sched/thread.hxx b/libcult/cult/sched/thread.hxx new file mode 100644 index 0000000..49d6225 --- /dev/null +++ b/libcult/cult/sched/thread.hxx @@ -0,0 +1,86 @@ +// file : cult/sched/thread.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_SCHED_THREAD_HXX +#define CULT_SCHED_THREAD_HXX + +#include +#include + +#include +#include + +#include + +#include + +namespace Cult +{ + namespace Sched + { + // Instantiating an automatic variable of type Thread results + // in undefined behavior (read core dump). + // + class Thread: public MM::ServiceAwareObject + { + public: + struct Exception: virtual Sched::Exception {}; + + public: + virtual + ~Thread (); + + Thread (Void* (*StartRoutine) (Void*), Void* arg = 0); + + // Adopt an existing thread. Adoption of a detached thread + // results in undefined behavior. Adoption of an already + // adopted thread results in Adopted exception. + // + + struct Adopted: virtual Exception {}; + + Thread (); + + public: + // Joining an already joined thread results in Joined exception. + // + + struct Joined: virtual Exception {}; + + //@@ Need to work out the cancelled case. + // + Void* + join (); + + Void + cancel (); + + public: + static Void + exit (Void* ret); + + // self() may not be called in TSD destructors. Call to self() from + // a foreign thread (i.e., one that is neither native nor adopted) + // results in Foreign exception. + // + + struct Foreign: virtual Exception {}; + + static Shptr + self (); + + static Void + test_cancel (); + + private: + pthread_t id_; + + Boolean detached_; + Mutex mutex_; + }; + } +} + +#endif // CULT_SCHED_THREAD_HXX diff --git a/libcult/cult/trace/log.cxx b/libcult/cult/trace/log.cxx new file mode 100644 index 0000000..f77c2c3 --- /dev/null +++ b/libcult/cult/trace/log.cxx @@ -0,0 +1,49 @@ +// file : cult/trace/log.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace Cult +{ + namespace Trace + { + Log:: + Log (Int level) + : level_ (level) + { + } + + Int Log:: + level () const + { + return level_; + } + + Void Log:: + level (Int level) + { + level_ = level; + } + + Log& Log:: + instance () + { + //@@ Need to use -once initialization. Plus is it legal to + // use trace in (static) dtors? + // + static Log log; + return log; + } + + Void Log:: + log_impl (Record const& r) + { + std::cerr << '[' << r.id () << ':' << r.level () << "] " << r.text () + << std::endl; + } + } +} diff --git a/libcult/cult/trace/log.hxx b/libcult/cult/trace/log.hxx new file mode 100644 index 0000000..2b21acf --- /dev/null +++ b/libcult/cult/trace/log.hxx @@ -0,0 +1,51 @@ +// file : cult/trace/log.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_TRACE_LOG_HXX +#define CULT_TRACE_LOG_HXX + +#include + +#include + +namespace Cult +{ + namespace Trace + { + class Log: public NonCopyable + { + public: + Log (Int level = -1); + + public: + Int + level () const; + + Void + level (Int level); + + public: + //@@ should it be virtual? + // + Log& + operator<< (Record const& r); + + public: + static Log& + instance (); + + private: + Void + log_impl (Record const& r); + + private: + Int level_; + }; + } +} + +#include + +#endif // CULT_TRACE_LOG_HXX diff --git a/libcult/cult/trace/log.ixx b/libcult/cult/trace/log.ixx new file mode 100644 index 0000000..fbc23d9 --- /dev/null +++ b/libcult/cult/trace/log.ixx @@ -0,0 +1,20 @@ +// file : cult/trace/log.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace Trace + { + inline + Log& Log:: + operator<< (Record const& r) + { + if (r.level () <= level_) + log_impl (r); + + return *this; + } + } +} diff --git a/libcult/cult/trace/null/record.ixx b/libcult/cult/trace/null/record.ixx new file mode 100644 index 0000000..c93b1a0 --- /dev/null +++ b/libcult/cult/trace/null/record.ixx @@ -0,0 +1,45 @@ +// file : cult/trace/null/record.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace Trace + { + inline + Record:: + Record (Char const* id, Int level) + : id_ (id), level_ (level) + { + } + + inline + Char const* Record:: + text () const + { + return ""; + } + + inline + Char const* Record:: + id () const + { + return id_; + } + + inline + Int Record:: + level () const + { + return level_; + } + + inline + Void Record:: + level (Int level) + { + level_ = level; + } + } +} diff --git a/libcult/cult/trace/null/record.txx b/libcult/cult/trace/null/record.txx new file mode 100644 index 0000000..1413f1e --- /dev/null +++ b/libcult/cult/trace/null/record.txx @@ -0,0 +1,18 @@ +// file : cult/trace/null/record.txx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace Trace + { + template + inline + Record& Record:: + operator<< (T const&) + { + return *this; + } + } +} diff --git a/libcult/cult/trace/null/stream.ixx b/libcult/cult/trace/null/stream.ixx new file mode 100644 index 0000000..45b6e78 --- /dev/null +++ b/libcult/cult/trace/null/stream.ixx @@ -0,0 +1,67 @@ +// file : cult/trace/null/stream.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace Trace + { + inline + Stream:: + Stream (Char const* id, Int level, Log& l) + : id_ (id), level_ (level), log_ (l) + { + } + + inline + Char const* Stream:: + id () const + { + return id_; + } + + inline + Int Stream:: + level () const + { + return level_; + } + + inline + Stream& Stream:: + operator << (Record const& r) + { + return *this; + } + + inline + Stream::Mediator:: + Mediator (Stream& s) + : s_ (s), r_ (s.id (), s.level ()) + { + } + + inline + Stream::Mediator:: + ~Mediator () + { + } + + inline + Record& + operator<< (Stream::Mediator const& mc, Int level) + { + Stream::Mediator& m (const_cast (mc)); + // m.r_.level (level); + return m.r_; + } + + inline + Record& + operator<< (Stream::Mediator const& mc, Char const* s) + { + return const_cast (mc).r_; + } + } +} diff --git a/libcult/cult/trace/null/stream.txx b/libcult/cult/trace/null/stream.txx new file mode 100644 index 0000000..e9ab70c --- /dev/null +++ b/libcult/cult/trace/null/stream.txx @@ -0,0 +1,18 @@ +// file : cult/trace/null/stream.txx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace Trace + { + template + inline + Record& + operator<< (Stream::Mediator const& mc, T const&) + { + return const_cast (mc).r_; + } + } +} diff --git a/libcult/cult/trace/record.hxx b/libcult/cult/trace/record.hxx new file mode 100644 index 0000000..90276dd --- /dev/null +++ b/libcult/cult/trace/record.hxx @@ -0,0 +1,86 @@ +// file : cult/trace/record.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_TRACE_RECORD_HXX +#define CULT_TRACE_RECORD_HXX + +#include + +#include // memset +#include +#include + +namespace Cult +{ + namespace Trace + { + class Record: public NonCopyable + { + public: + Record (Char const* id, Int level); + + public: + Char const* + text () const; + + Char const* + id () const; + + Int + level () const; + + Void + level (Int); + + public: + template + Record& + operator<< (T const& arg); + + private: + Char const* id_; + Int level_; + + //@@ need to wrap streambuf. + // + class FixedBuffer : public std::streambuf + { + public: + FixedBuffer (Char* buf, Size size) + { + std::memset (buf, 0, size); + setp (buf, buf + size - 1); + }; + + virtual int_type + overflow (int_type c) + { + return c; + } + }; + +#ifndef CULT_TRACE_NULL + char buf_[1024]; + FixedBuffer sbuf_; + std::ostream os_; +#endif + }; + } +} + +#ifndef CULT_TRACE_NULL + +#include +#include + +#else + +#include +#include + +#endif + + +#endif // CULT_TRACE_RECORD_HXX diff --git a/libcult/cult/trace/record.ixx b/libcult/cult/trace/record.ixx new file mode 100644 index 0000000..ae564a4 --- /dev/null +++ b/libcult/cult/trace/record.ixx @@ -0,0 +1,45 @@ +// file : cult/trace/record.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace Trace + { + inline + Record:: + Record (Char const* id, Int level) + : id_ (id), level_ (level), sbuf_ (buf_, sizeof (buf_)), os_ (&sbuf_) + { + } + + inline + Char const* Record:: + text () const + { + return buf_; + } + + inline + Char const* Record:: + id () const + { + return id_; + } + + inline + Int Record:: + level () const + { + return level_; + } + + inline + Void Record:: + level (Int level) + { + level_ = level; + } + } +} diff --git a/libcult/cult/trace/record.txx b/libcult/cult/trace/record.txx new file mode 100644 index 0000000..0c4ef1b --- /dev/null +++ b/libcult/cult/trace/record.txx @@ -0,0 +1,19 @@ +// file : cult/trace/record.txx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace Trace + { + template + inline + Record& Record:: + operator<< (T const& arg) + { + os_ << arg; + return *this; + } + } +} diff --git a/libcult/cult/trace/stream.hxx b/libcult/cult/trace/stream.hxx new file mode 100644 index 0000000..728e973 --- /dev/null +++ b/libcult/cult/trace/stream.hxx @@ -0,0 +1,74 @@ +// file : cult/trace/stream.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_TRACE_STREAM_HXX +#define CULT_TRACE_STREAM_HXX + +#include + +#include +#include + +namespace Cult +{ + namespace Trace + { + class Stream: public NonCopyable + { + public: + Stream (Char const* id, Int level, Log& l = Log::instance ()); + + public: + Char const* + id () const; + + Int + level () const; + + public: + Stream& + operator<< (Record const& r); + + private: + struct Mediator + { + ~Mediator (); + Mediator (Stream&); + + Stream& s_; + Record r_; + }; + + friend Record& + operator<< (Mediator const&, Int level); + + friend Record& + operator<< (Mediator const&, Char const* s); + + template + friend Record& + operator<< (Mediator const&, T const& arg); + + private: + Char const* id_; + Int level_; + Log& log_; + }; + } +} + +#ifndef CULT_TRACE_NULL + +#include +#include + +#else + +#include +#include + +#endif + +#endif // CULT_TRACE_STREAM_HXX diff --git a/libcult/cult/trace/stream.ixx b/libcult/cult/trace/stream.ixx new file mode 100644 index 0000000..718383c --- /dev/null +++ b/libcult/cult/trace/stream.ixx @@ -0,0 +1,76 @@ +// file : cult/trace/stream.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace Trace + { + // Stream::Mediator + // + inline + Stream::Mediator:: + Mediator (Stream& s) + : s_ (s), r_ (s.id (), s.level ()) + { + } + + inline + Stream::Mediator:: + ~Mediator () + { + s_ << r_; + } + + // Stream + // + inline + Stream:: + Stream (Char const* id, Int level, Log& log) + : id_ (id), level_ (level), log_ (log) + { + } + + inline + char const* Stream:: + id () const + { + return id_; + } + + inline + int Stream:: + level () const + { + return level_; + } + + // + // + inline + Stream& Stream:: + operator << (Record const& r) + { + log_ << r; + return *this; + } + + inline + Record& + operator<< (Stream::Mediator const& mc, Int level) + { + Stream::Mediator& m (const_cast (mc)); + m.r_.level (level); + return m.r_; + } + + inline + Record& + operator<< (Stream::Mediator const& mc, Char const* s) + { + Stream::Mediator& m (const_cast (mc)); + return m.r_ << s; + } + } +} diff --git a/libcult/cult/trace/stream.txx b/libcult/cult/trace/stream.txx new file mode 100644 index 0000000..1ac20ed --- /dev/null +++ b/libcult/cult/trace/stream.txx @@ -0,0 +1,19 @@ +// file : cult/trace/stream.txx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace Trace + { + template + inline + Record& + operator<< (Stream::Mediator const& mc, T const& arg) + { + Stream::Mediator& m (const_cast (mc)); + return m.r_ << arg; + } + } +} diff --git a/libcult/cult/types.hxx b/libcult/cult/types.hxx new file mode 100644 index 0000000..5e4c9c2 --- /dev/null +++ b/libcult/cult/types.hxx @@ -0,0 +1,14 @@ +// file : cult/types.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_TYPES_HXX +#define CULT_TYPES_HXX + +#include +#include +#include +#include + +#endif // CULT_TYPES_HXX diff --git a/libcult/cult/types/evptr.hxx b/libcult/cult/types/evptr.hxx new file mode 100644 index 0000000..a39cd86 --- /dev/null +++ b/libcult/cult/types/evptr.hxx @@ -0,0 +1,21 @@ +// file : cult/types/evptr.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_TYPES_EVPTR_HXX +#define CULT_TYPES_EVPTR_HXX + +#include + +namespace Cult +{ + namespace Types + { + using MM::Evptr; + } + + using Types::Evptr; +} + +#endif // CULT_TYPES_EVPTR_HXX diff --git a/libcult/cult/types/fundamental.hxx b/libcult/cult/types/fundamental.hxx new file mode 100644 index 0000000..01116f1 --- /dev/null +++ b/libcult/cult/types/fundamental.hxx @@ -0,0 +1,175 @@ +// file : cult/types/fundamental.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_TYPES_FUNDAMENTAL_HXX +#define CULT_TYPES_FUNDAMENTAL_HXX + +#include // std::size_t, std::ptrdiff_t + +namespace Cult +{ + namespace Types + { + namespace Fundamental + { + // Fundamental types + // + typedef void Void; + + typedef bool Boolean; + + typedef char Char; + typedef wchar_t WideChar; + + typedef short Short; + typedef unsigned short UnsignedShort; + + typedef int Int; + typedef unsigned int UnsignedInt; + + typedef long Long; + typedef unsigned long UnsignedLong; + + //@@ what would be a good name for float, double and long double? + // ShortFloat, Float and LongFloat + // ShortReal, Real, LongReal + + typedef std::size_t Size; + typedef std::ptrdiff_t PtrDifference; + typedef Size Index; + + // Fixed-size types. + // + typedef signed char Int8; + typedef unsigned char UnsignedInt8; + + typedef signed short Int16; + typedef unsigned short UnsignedInt16; + + typedef signed int Int32; + typedef unsigned int UnsignedInt32; + + typedef signed long long Int64; + typedef unsigned long long UnsignedInt64; + + + typedef float Float32; + typedef double Float64; + typedef long double Float128; // Only 96 on x86-32. + } + + + // Fundamental types + // + using Fundamental::Void; + + using Fundamental::Boolean; + + using Fundamental::Char; + using Fundamental::WideChar; + + using Fundamental::Short; + using Fundamental::UnsignedShort; + + using Fundamental::Int; + using Fundamental::UnsignedInt; + + using Fundamental::Long; + using Fundamental::UnsignedLong; + + using Fundamental::Size; + using Fundamental::PtrDifference; + using Fundamental::Index; + + + // Fixed-size types. + // + using Fundamental::Int8; + using Fundamental::UnsignedInt8; + + using Fundamental::Int16; + using Fundamental::UnsignedInt16; + + using Fundamental::Int32; + using Fundamental::UnsignedInt32; + + using Fundamental::Int64; + using Fundamental::UnsignedInt64; + + + using Fundamental::Float32; + using Fundamental::Float64; + using Fundamental::Float128; // Only 96 on x86-32. + + + // Note: make sure you inherit publicly from this type for + // it could be used for metaprogramming. + // + class NonCopyable + { + NonCopyable (NonCopyable const&); + + NonCopyable& + operator= (NonCopyable const&); + + protected: + NonCopyable () + { + } + }; + + // class Clonable ? + // + + } + + // Fundamental types + // + using Types::Void; + + using Types::Boolean; + + using Types::Char; + using Types::WideChar; + + using Types::Short; + using Types::UnsignedShort; + + using Types::Int; + using Types::UnsignedInt; + + using Types::Long; + using Types::UnsignedLong; + + using Types::Size; + using Types::PtrDifference; + using Types::Index; + + + // Fixed-size types. + // + using Types::Int8; + using Types::UnsignedInt8; + + using Types::Int16; + using Types::UnsignedInt16; + + using Types::Int32; + using Types::UnsignedInt32; + + using Types::Int64; + using Types::UnsignedInt64; + + + using Types::Float32; + using Types::Float64; + using Types::Float128; // Only 96 on x86-32. + + // + // + using Types::NonCopyable; +} + +#endif // CULT_TYPES_FUNDAMENTAL_HXX diff --git a/libcult/cult/types/shptr.hxx b/libcult/cult/types/shptr.hxx new file mode 100644 index 0000000..c5d2d66 --- /dev/null +++ b/libcult/cult/types/shptr.hxx @@ -0,0 +1,21 @@ +// file : cult/types/shptr.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_TYPES_SHPTR_HXX +#define CULT_TYPES_SHPTR_HXX + +#include + +namespace Cult +{ + namespace Types + { + using MM::Shptr; + } + + using Types::Shptr; +} + +#endif // CULT_TYPES_SHPTR_HXX diff --git a/libcult/cult/types/string.hxx b/libcult/cult/types/string.hxx new file mode 100644 index 0000000..108f830 --- /dev/null +++ b/libcult/cult/types/string.hxx @@ -0,0 +1,397 @@ +// file : cult/types/string.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_TYPES_STRING_HXX +#define CULT_TYPES_STRING_HXX + +#include +#include + +//@@ Dependency on 'containers'. Maybe move iterator to 'types'? +// +#include + +#include +#include // mbstowcs + +namespace Cult +{ + namespace Types + { + //@@ Maybe create StringFwd.hxx + // + + namespace Bits + { + struct None {}; + + template + struct NarrowerChar + { + typedef None Type; + }; + + + template <> + struct NarrowerChar + { + typedef Char Type; + }; + } + + template ::Type> + class StringTemplate; + + template <> + class StringTemplate + { + }; + + + template + class StringTemplate : public std::basic_string + { + typedef std::basic_string Base; + typedef std::basic_string NarrowerBase; + + Base& + base () + { + return *this; + } + + Base const& + base () const + { + return *this; + } + + public: + typedef typename Base::value_type Value; + + /* + typedef traits traits_type; + typedef typename traits::char_type value_type; + typedef Allocator allocator_type; + typedef typename Allocator::size_type size_type; + typedef typename Allocator::difference_type difference_type; + typedef typename Allocator::reference reference; + typedef typename Allocator::const_reference const_reference; + typedef typename Allocator::pointer pointer; + typedef typename Allocator::const_pointer const_pointer; + */ + + typedef + Containers::IteratorAdapter + Iterator; + + typedef + Containers::IteratorAdapter + ConstIterator; + + + typedef + Containers::IteratorAdapter + ReverseIterator; + + typedef + Containers::IteratorAdapter + ConstReverseIterator; + + + using Base::npos; + using Base::empty; + + public: + explicit + StringTemplate () + { + } + + StringTemplate (StringTemplate const& str, Size pos, Size n = npos) + : Base (str, pos, n) + { + } + + StringTemplate (Value const* s, Size n) + : Base (s, n) + { + } + + StringTemplate (Value const* s) + : Base (s) + { + } + + StringTemplate (Size n, Value c) + : Base (n, c) + { + } + + template + StringTemplate(InputIterator begin, InputIterator end) + : Base (begin, end) + { + } + + StringTemplate (StringTemplate const& other) + : Base (other) + { + } + + // Conversion from Base. + // + StringTemplate (Base const& str) + : Base (str) + { + } + + // Conversion from the Narrower type. Experimental. + // + StringTemplate (NarrowerChar const* s) + { + from_narrow (s); + } + + StringTemplate (StringTemplate const& other) + { + from_narrow (other.c_str ()); + } + + StringTemplate (NarrowerBase const& other) + { + from_narrow (other.c_str ()); + } + + // Conversion to the Narrower type. Experimental. + // + struct NonRepresentable: virtual EH::Exception {}; + + StringTemplate + to_narrow () const; + + // Assignment. + // + StringTemplate& + operator= (StringTemplate const& str) + { + base () = str; + return *this; + } + + StringTemplate& + operator= (Value const* s) + { + base () = s; + return *this; + } + + StringTemplate& + operator= (Value c) + { + base () = c; + return *this; + } + + // Assignment from Base. + // + StringTemplate& + operator= (Base const& str) + { + base () = str; + return *this; + } + + public: + StringTemplate& + operator+= (StringTemplate const& str) + { + base () += str; + return *this; + } + + StringTemplate& + operator+= (Value const* s) + { + base () += s; + return *this; + } + + StringTemplate& + operator+= (Value c) + { + base () += c; + return *this; + } + + + public: + Iterator + begin () + { + return Iterator (base ().begin ()); + } + + Iterator + end () + { + return Iterator (base ().end ()); + } + + + ConstIterator + begin () const + { + return ConstIterator (base ().begin ()); + } + + ConstIterator + end () const + { + return ConstIterator (base ().end ()); + } + + // + // + + ReverseIterator + rbegin () + { + return ReverseIterator (base ().rbegin ()); + } + + ReverseIterator + rend () + { + return ReverseIterator (base ().rend ()); + } + + + ConstReverseIterator + rbegin () const + { + return ConstReverseIterator (base ().rbegin ()); + } + + ConstReverseIterator + rend () const + { + return ConstReverseIterator (base ().rend ()); + } + + + // Conversion to Boolean. + // + private: + typedef Void (StringTemplate::*BooleanConvertable)(); + + void + true_ () + { + } + + public: + operator BooleanConvertable () const + { + return empty () ? 0 : &StringTemplate::true_; + } + + private: + Void + from_narrow (NarrowerChar const* s); + }; + + + template + StringTemplate + operator+ (StringTemplate const& lhs, StringTemplate const& rhs) + { + return StringTemplate (lhs) += rhs; + } + + template + StringTemplate + operator+ (C const* lhs, StringTemplate const& rhs) + { + return StringTemplate (lhs) += rhs; + } + + template + StringTemplate + operator+ (StringTemplate const& lhs, C const* rhs) + { + return StringTemplate (lhs) += rhs; + } + + template + StringTemplate + operator+ (C lhs, StringTemplate const& rhs) + { + return StringTemplate (1, lhs) += rhs; + } + + + template + StringTemplate + operator+ (StringTemplate const& lhs, C rhs) + { + return StringTemplate (lhs) += rhs; + } + + // + // + typedef StringTemplate String; + typedef StringTemplate NarrowString; + typedef StringTemplate WideString; + + // Specialization for Char to WideChar conversion. + // + template <> + inline Void StringTemplate:: + from_narrow (Char const* s) + { + Size size (std::mbstowcs (0, s, 0) + 1); + + // I dare to change the guts! + // + resize (size - 1); + + WideChar* p (const_cast (data ())); + + std::mbstowcs (p, s, size); + } + + // Specialization for WideChar to Char conversion. + // + template <> + inline StringTemplate StringTemplate:: + to_narrow () const + { + Size size (std::wcstombs (0, c_str (), 0)); + + if (size == Size (-1)) + throw NonRepresentable (); + + // I dare to change the guts! + // + StringTemplate r; + r.resize (size); + + Char* p (const_cast (r.data ())); + + std::wcstombs (p, c_str (), size + 1); + + return r; + } + } + + using Types::String; + using Types::NarrowString; + using Types::WideString; + using Types::StringTemplate; +} + +#endif // CULT_TYPES_STRING_HXX -- cgit v1.2.3