diff options
Diffstat (limited to 'libcult')
187 files changed, 14840 insertions, 0 deletions
diff --git a/libcult/GPLv2 b/libcult/GPLv2 new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/libcult/GPLv2 @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/libcult/INSTALL b/libcult/INSTALL new file mode 100644 index 0000000..72c7a29 --- /dev/null +++ b/libcult/INSTALL @@ -0,0 +1,21 @@ +Prerequisites + + build-time: + + - build >= 0.3.2 http://www.codesynthesis.com/projects/build/ + - g++ >= 3.4.3 http://gcc.gnu.org + + +Building libcult + + To build in the source directory simply say `make'. You can also + build in a separate directory, e.g., + + $ mkdir libcult-i686-pc-linux-gnu + $ cd libcult-i686-pc-linux-gnu + $ make -f ../libcult-x.y.z/makefile + + +Installing libcult + + Not supported in this version. diff --git a/libcult/LICENSE b/libcult/LICENSE new file mode 100644 index 0000000..3204be4 --- /dev/null +++ b/libcult/LICENSE @@ -0,0 +1,25 @@ +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License version 2 as +published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +In addition, as a special exception, Boris Kolpackov gives permission +to combine this library with other incompatibly-licensed modules in a +single program and to distribute such a combination provided that there +is no use of the functionality implemented by this library, directly +or indirectly, by such modules. You must obey the GNU General Public +License version 2 in all respects for all of the code used other than +such modules. In particular, the resulting program must be licensed +under a license compatible with the GNU General Public License version +2. If you modify this copy of the library, you may extend this exception +to your version of the library, but you are not obligated to do so. If +you do not wish to do so, delete this exception statement from your +version. diff --git a/libcult/NEWS b/libcult/NEWS new file mode 100644 index 0000000..2924310 --- /dev/null +++ b/libcult/NEWS @@ -0,0 +1,126 @@ +Version 1.4.6 + + * Add support for deleting graph nodes. + +Version 1.4.5 + + * Add support for libcult bundling. + + * Suppress warning in exception inheritance. + +Version 1.4.4 + + * Add an exception to the licensing terms to allow combining with + incompatibly-licensed modules in a single program. See the LICENSE + file for details. + +Version 1.4.3 + + * Remove leading and trailing whitespaces from arguments in + CLI::FileArguments. + +Version 1.4.2 + + * Support for stripping leading and (some) trailing whitespaces + in the FileArguments class. + +Version 1.4.1 + + * The number of options in CLI was increased from 80 to 100. + + * Fixed a bug in import stubs. + + * Got rid of warnings reported by g++-4.3. + +Version 1.4.0 + + * New arguments scanners: BasicArguments and FileArguments. + + * Conversion to narrow format in StringTemplate. + +Version 1.3.0 + + * Upgraded to build-0.3.0. + +Version 1.2.3 + + * Compilation time and generated code size optimizations in CLI. + + * Set of typedefs in Containers::Iterator to be compatible with + std::iterator_traits. + +Version 1.2.2 + + * A bug in Cult::String has been fixed. + +Version 1.2.1 + + * The number of options in CLI was increased from 50 to 80. + + * A bug in Containers::Any has been fixed. + + +Version 1.2.0 + + * Containers::Graph now supports removal of edges. + + * Added missing member functions to container wrappers. + + +Version 1.1.0 + + * Generic, std::istream-based parser has been added to CLI parsers. + + * Containers::IteratorAdapter has been modified to use + std::iterator_traits for better portability. + + * Threading, networking and data representation subsystems were + made optional. + + +Version 1.0.6 + + * Upgraded to build-0.2.1. + + +Version 1.0.5 + + * Moved to the build 0.2 series. + + +Version 1.0.4 + + * Containers::Graph has been extended to support more arguments in + the new_node() and new_edge() functions. + + +Version 1.0.3 + + * MM::Counter has been re-implemented to use size_t instead of int + on i386 and x86_64. + + * Containers::Graph has been extended to support more arguments in + the new_node() function. + + * Fixed a bug in CLI::OptionsSpec that resulted in a wrong default + initialization of options. + + +Version 1.0.2 + + * New Containers::List wrapper for std::list. + + * CLI::OptionsParser now skips arguments instead of erasing them when + UnknownMode is set to skip. + + +Version 1.0.1 + + * WideString can now be initialized with NarrowString and NarrowChar const*. + + * Build system improvements. + + +Version 1.0.0 + + * First public release. diff --git a/libcult/README b/libcult/README new file mode 100644 index 0000000..2227831 --- /dev/null +++ b/libcult/README @@ -0,0 +1,15 @@ +libcult is a collection of c++ libraries that were designed to form +a cohesive union of clean, simple and readable c++ code that uses +the most powerful mechanisms available on the GNU development platform. + +See the NEWS file for the user-visible changes from the previous release. + +See the LICENSE file for distribution conditions. + +See the INSTALL file for prerequisites and installation instructions. + +See the documentation/index.xhtml file for documentation. + +The project page is at http://kolpackov.net/projects/c++/libcult/. + +Send bug reports or any other feedback to boris@kolpackov.net . diff --git a/libcult/build/bootstrap.make b/libcult/build/bootstrap.make new file mode 100644 index 0000000..fc9cd38 --- /dev/null +++ b/libcult/build/bootstrap.make @@ -0,0 +1,46 @@ +# file : build/bootstrap.make +# author : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +project_name := libcult + +# First try to include the bundled bootstrap.make if it exist. If that +# fails, let make search for the external bootstrap.make. +# +build := build-0.3 + +-include $(dir $(lastword $(MAKEFILE_LIST)))../../$(build)/bootstrap.make + +ifeq ($(patsubst %build/bootstrap.make,,$(lastword $(MAKEFILE_LIST))),) +include $(build)/bootstrap.make +endif + +# Aliases +# +.PHONY: $(out_base)/ \ + $(out_base)/.test \ + $(out_base)/.clean + +ifdef %interactive% + +.PHONY: test clean + +test: $(out_base)/.test +clean: $(out_base)/.clean + +ifneq ($(filter $(.DEFAULT_GOAL),test clean),) +.DEFAULT_GOAL := +endif + +endif + +# Don't include dependency info for certain targets. +# +define include-dep +$(call -include,$1) +endef + +ifneq ($(filter $(MAKECMDGOALS),clean cleandoc disfigure),) +include-dep = +endif diff --git a/libcult/build/configuration-dynamic.make b/libcult/build/configuration-dynamic.make new file mode 100644 index 0000000..e027b0b --- /dev/null +++ b/libcult/build/configuration-dynamic.make @@ -0,0 +1,3 @@ +cult_dr := n +cult_threads := n +cult_network := n diff --git a/libcult/build/configuration-rules.make b/libcult/build/configuration-rules.make new file mode 100644 index 0000000..e6df883 --- /dev/null +++ b/libcult/build/configuration-rules.make @@ -0,0 +1,18 @@ +# file : build/configuration-rules.make +# author : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2006-2010 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +$(dcf_root)/configuration-dynamic.make: | $(dcf_root)/. + $(call message,,$(scf_root)/configure $@) + +ifndef %foreign% + +disfigure:: + $(call message,rm $$1,rm -f $$1,$(dcf_root)/configuration-dynamic.make) + +endif + +ifeq ($(.DEFAULT_GOAL),$(dcf_root)/configuration-dynamic.make) +.DEFAULT_GOAL := +endif diff --git a/libcult/build/configuration.make b/libcult/build/configuration.make new file mode 100644 index 0000000..b8724c8 --- /dev/null +++ b/libcult/build/configuration.make @@ -0,0 +1,28 @@ +# file : build/configuration.make +# author : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2006-2010 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +$(call include-once,$(scf_root)/configuration-rules.make,$(dcf_root)) + + +# Dynamic configuration. +# +cult_dr := +cult_threads := +cult_network := + + +$(call -include,$(dcf_root)/configuration-dynamic.make) + +ifdef cult_dr + +$(out_root)/%: cult_threads := $(cult_threads) +$(out_root)/%: cult_network := $(cult_network) +$(out_root)/%: cult_dr := $(cult_dr) + +else + +.NOTPARALLEL: + +endif diff --git a/libcult/build/configure b/libcult/build/configure new file mode 100755 index 0000000..4473653 --- /dev/null +++ b/libcult/build/configure @@ -0,0 +1,47 @@ +#! /usr/bin/env bash + +# file : build/configure +# author : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2006-2010 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +# $1 out file +# +# bld_root - build root +# project_name - project name +# + +source $bld_root/dialog.bash + + +$echo +$echo +$echo "configuring '$project_name'" +$echo +$echo + + +$echo +$echo "Would you like to build a multi-threaded version of '$project_name'?" +$echo + +threads=`read_y_n y` + + +$echo +$echo "Would you like to build the network subsystem of '$project_name'?" +$echo + +network=`read_y_n y` + + +$echo +$echo "Would you like to build the data representation subsystem of '$project_name'?" +$echo + +dr=`read_y_n y` + + +echo "cult_dr := $dr" >$1 +echo "cult_threads := $threads" >>$1 +echo "cult_network := $network" >>$1 diff --git a/libcult/build/cxx/configuration-dynamic.make b/libcult/build/cxx/configuration-dynamic.make new file mode 100644 index 0000000..568ab40 --- /dev/null +++ b/libcult/build/cxx/configuration-dynamic.make @@ -0,0 +1,14 @@ +cxx_id := gnu +cxx_optimize := n +cxx_debug := n +cxx_rpath := n +cxx_pp_extra_options := $(CPPFLAGS) +cxx_extra_options := $(CXXFLAGS) +cxx_ld_extra_options := $(LDFLAGS) +cxx_extra_libs := $(LIBS) + +r := $(shell echo $(LDFLAGS) | sed -e 's/-L *\([^ ]*\)/-L\1/g') +r := $(patsubst -L%,%,$(filter -L%,$(r))) +r := $(shell echo $(r) | sed -e 's/ /:/g') + +cxx_extra_lib_paths := $(r) diff --git a/libcult/build/cxx/gnu/configuration-dynamic.make b/libcult/build/cxx/gnu/configuration-dynamic.make new file mode 100644 index 0000000..f3fe64d --- /dev/null +++ b/libcult/build/cxx/gnu/configuration-dynamic.make @@ -0,0 +1,8 @@ +ifneq ($(CXX),) +cxx_gnu := $(CXX) +else +cxx_gnu := g++ +endif + +cxx_gnu_libraries := +cxx_gnu_optimization_options := diff --git a/libcult/build/export/libcult/stub.make b/libcult/build/export/libcult/stub.make new file mode 100644 index 0000000..354b083 --- /dev/null +++ b/libcult/build/export/libcult/stub.make @@ -0,0 +1,10 @@ +# file : build/export/libcult/stub.make +# author : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +$(call include-once,$(src_root)/cult/makefile,$(out_root)) + +$(call export,\ + l: $(out_root)/cult/cult.l,\ + cpp-options: $(out_root)/cult/cult.l.cpp-options) diff --git a/libcult/build/import/libcult/LICENSE b/libcult/build/import/libcult/LICENSE new file mode 120000 index 0000000..5853aae --- /dev/null +++ b/libcult/build/import/libcult/LICENSE @@ -0,0 +1 @@ +../../../LICENSE
\ No newline at end of file diff --git a/libcult/build/import/libcult/configuration-rules.make b/libcult/build/import/libcult/configuration-rules.make new file mode 100644 index 0000000..5d8c939 --- /dev/null +++ b/libcult/build/import/libcult/configuration-rules.make @@ -0,0 +1,15 @@ +# file : build/import/libcult/configuration-rules.make +# author : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +$(dcf_root)/import/libcult/configuration-dynamic.make: | $(dcf_root)/import/libcult/. + $(call message,,$(scf_root)/import/libcult/configure $@) + +ifndef %foreign% + +disfigure:: + $(call message,rm $(dcf_root)/import/libcult/configuration-dynamic.make,\ +rm -f $(dcf_root)/import/libcult/configuration-dynamic.make) + +endif diff --git a/libcult/build/import/libcult/configure b/libcult/build/import/libcult/configure new file mode 100755 index 0000000..0eb142f --- /dev/null +++ b/libcult/build/import/libcult/configure @@ -0,0 +1,55 @@ +#! /usr/bin/env bash + +# file : build/import/libcult/configure +# author : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + + +# $1 - out file +# +# bld_root - build root +# project_name - project name +# + +source $bld_root/dialog.bash + + +$echo +$echo "Configuring external dependency on 'libcult' for '$project_name'." +$echo + +$echo +$echo "Would you like to configure dependency on the installed " +$echo "version of 'libcult' as opposed to the development build?" +$echo + +installed=`read_y_n y` + +path= + +if [ "$installed" = "n" ]; then + +$echo +$echo "Please enter the src_root for 'libcult'." +$echo + +src_root=`read_path --directory --exist` + +$echo +$echo "Please enter the out_root for 'libcult'." +$echo + +out_root=`read_path --directory $src_root` + +fi + +echo libcult_installed := $installed >$1 + +if [ "$installed" = "n" ]; then + +echo src_root := $src_root >>$1 +echo scf_root := \$\(src_root\)/build >>$1 +echo out_root := $out_root >>$1 + +fi diff --git a/libcult/build/import/libcult/stub.make b/libcult/build/import/libcult/stub.make new file mode 100644 index 0000000..7469300 --- /dev/null +++ b/libcult/build/import/libcult/stub.make @@ -0,0 +1,30 @@ +# file : build/import/libcult/stub.make +# author : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +$(call include-once,$(scf_root)/import/libcult/configuration-rules.make,$(dcf_root)) + +libcult_installed := + +$(call -include,$(dcf_root)/import/libcult/configuration-dynamic.make) + +ifdef libcult_installed + +ifeq ($(libcult_installed),y) + +$(call export,l: -lcult,cpp-options: ) + +else + +# Include export stub. +# +$(call include,$(scf_root)/export/libcult/stub.make) + +endif + +else + +.NOTPARALLEL: + +endif diff --git a/libcult/build/ld/configuration-lib-dynamic.make b/libcult/build/ld/configuration-lib-dynamic.make new file mode 100644 index 0000000..74c8885 --- /dev/null +++ b/libcult/build/ld/configuration-lib-dynamic.make @@ -0,0 +1,13 @@ +ld_lib_type := archive + +ifneq ($(AR),) +ld_lib_ar := $(AR) +else +ld_lib_ar := ar +endif + +ifneq ($(RANLIB),) +ld_lib_ranlib := $(RANLIB) +else +ld_lib_ranlib := ranlib +endif 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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/cli/arguments.hxx> + +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 <boris@kolpackov.net> +// 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 <cult/types.hxx> + +#include <cult/cli/exceptions.hxx> + +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<Size> (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 <cult/cli/arguments.ixx> + +#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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cassert> + +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 <boris@kolpackov.net> +// 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 <cult/types.hxx> + +#include <cult/eh/exception.hxx> + +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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cstring> // strcmp +#include <fstream> + +#include <cult/cli/file-arguments.hxx> + +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 <boris@kolpackov.net> +// 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 <cult/types.hxx> +#include <cult/containers/vector.hxx> + +#include <cult/cli/exceptions.hxx> +#include <cult/cli/arguments.hxx> + +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<String> 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 <boris@kolpackov.net> +# 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<x`'i>*); +')dnl + + template <char const* x> + struct Selector + { + typedef typeof (Mapper::f ((Tag<x>*) (0))) Type; + }; +`#else' + template <char const* x> + struct Selector + { + typedef typename if_<same<x, x1>::r, Y1,ifelse($1, 1, ` Void', ` + typename Mapper + < +forloop(`i', 2, $1, ` x`'i, Y`'i`'ifelse(i, $1, ,`,') +') >::template Selector<x>::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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/cli/options-parser.hxx> + +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 <boris@kolpackov.net> +// 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 <cult/types.hxx> + +#include <cult/containers/map.hxx> +#include <cult/containers/vector.hxx> + +#include <cult/trace/stream.hxx> + +#include <cult/cli/exceptions.hxx> +#include <cult/cli/scanner.hxx> +#include <cult/cli/options-spec.hxx> + +#include <sstream> + +//@! which types should be NonCopyable + +namespace Cult +{ + namespace CLI + { + struct UnknownMode + { + enum Value + { + skip, + stop, + fail + }; + }; + + template <typename T> + struct OptionParserBase + { + T + parse (Char const* o, Scanner& s); + }; + + template <typename Spec> + struct OptionParser: OptionParserBase<typename Spec::Type> + { + OptionParser (Spec const&) + { + } + }; + + template<Char const* o, typename T> + class OptionParser<OptionSpec<o, Containers::Vector<T> > > + { + public: + OptionParser (OptionSpec<o, Containers::Vector<T> > const&) + : impl_ (OptionSpec<o, T> ()) + { + } + + T + parse (Char const* k, Scanner& s) + { + return impl_.parse (k, s); + } + + private: + OptionParser<OptionSpec<o, T> > impl_; + }; + + struct OptionParserBooleanBase + { + Boolean + parse (Char const*, Scanner& s); + }; + + template<Char const* o> + struct OptionParser<OptionSpec<o, Boolean> >: OptionParserBooleanBase + { + OptionParser (OptionSpec<o, Boolean> const&) + { + } + }; + + struct OptionParserStringBase + { + String + parse (Char const*, Scanner& s); + }; + + template<Char const* o> + struct OptionParser<OptionSpec<o, String> >: OptionParserStringBase + { + OptionParser (OptionSpec<o, String> 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 <typename Spec> + class OptionsParser : OptionsParserBase + { + typedef + Containers::Map<String, Evptr<GlueBase> > + Map; + + template <typename> + struct Glue; + + template <Char const* k, typename T> + struct Glue<OptionSpec<k, T> > : GlueBase + { + Glue (OptionSpec<k, T> const& spec) + : parser_ (spec) + { + } + + virtual Void + operator() (Char const* o, Scanner& scan, Void* options) + { + typedef typename Spec::Options Options; + + Options& ops (*reinterpret_cast<Options*> (options)); + + ops.template value<k> () = parser_.parse (o, scan); + } + + private: + OptionParser<OptionSpec<k, T> > parser_; + }; + + //@@ It's bad that I also have to specialize Glue. Need to redesign + // this. + // + template <Char const* k, typename T> + struct Glue<OptionSpec<k, Containers::Vector<T> > > : GlueBase + { + Glue (OptionSpec<k, Containers::Vector<T> > const& spec) + : parser_ (spec) + { + } + + virtual Void + operator() (Char const* o, Scanner& scan, Void* options) + { + typedef typename Spec::Options Options; + + Options& ops (*reinterpret_cast<Options*> (options)); + + ops.template value<k> ().push_back (parser_.parse (o, scan)); + } + + private: + OptionParser<OptionSpec<k, Containers::Vector<T> > > parser_; + }; + + + // Option-specific specializations of some functions. + // + template <typename> + 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 <Char const* k, typename T> + struct S_<OptionSpec<k, T> > + { + static Void + add_parser (Spec const& spec, Map& map) + { + if (k[0] != '\0') + { + OptionSpec<k, T> const& os (spec.template option<k> ()); + map[os.name ()] = new Glue<OptionSpec<k, T> > (os); + } + } + + static Void + set_default (typename Spec::Options& o, Spec const& s) + { + o.template value<k> () = s.template option<k> ().default_value (); + } + }; + + public: + + OptionsParser (Spec const& spec) + : spec_ (spec) + { + S_<typename Spec::o01>::add_parser (spec_, map_); + S_<typename Spec::o02>::add_parser (spec_, map_); + S_<typename Spec::o03>::add_parser (spec_, map_); + S_<typename Spec::o04>::add_parser (spec_, map_); + S_<typename Spec::o05>::add_parser (spec_, map_); + S_<typename Spec::o06>::add_parser (spec_, map_); + S_<typename Spec::o07>::add_parser (spec_, map_); + S_<typename Spec::o08>::add_parser (spec_, map_); + S_<typename Spec::o09>::add_parser (spec_, map_); + S_<typename Spec::o10>::add_parser (spec_, map_); + S_<typename Spec::o11>::add_parser (spec_, map_); + S_<typename Spec::o12>::add_parser (spec_, map_); + S_<typename Spec::o13>::add_parser (spec_, map_); + S_<typename Spec::o14>::add_parser (spec_, map_); + S_<typename Spec::o15>::add_parser (spec_, map_); + S_<typename Spec::o16>::add_parser (spec_, map_); + S_<typename Spec::o17>::add_parser (spec_, map_); + S_<typename Spec::o18>::add_parser (spec_, map_); + S_<typename Spec::o19>::add_parser (spec_, map_); + S_<typename Spec::o20>::add_parser (spec_, map_); + S_<typename Spec::o21>::add_parser (spec_, map_); + S_<typename Spec::o22>::add_parser (spec_, map_); + S_<typename Spec::o23>::add_parser (spec_, map_); + S_<typename Spec::o24>::add_parser (spec_, map_); + S_<typename Spec::o25>::add_parser (spec_, map_); + S_<typename Spec::o26>::add_parser (spec_, map_); + S_<typename Spec::o27>::add_parser (spec_, map_); + S_<typename Spec::o28>::add_parser (spec_, map_); + S_<typename Spec::o29>::add_parser (spec_, map_); + S_<typename Spec::o30>::add_parser (spec_, map_); + S_<typename Spec::o31>::add_parser (spec_, map_); + S_<typename Spec::o32>::add_parser (spec_, map_); + S_<typename Spec::o33>::add_parser (spec_, map_); + S_<typename Spec::o34>::add_parser (spec_, map_); + S_<typename Spec::o35>::add_parser (spec_, map_); + S_<typename Spec::o36>::add_parser (spec_, map_); + S_<typename Spec::o37>::add_parser (spec_, map_); + S_<typename Spec::o38>::add_parser (spec_, map_); + S_<typename Spec::o39>::add_parser (spec_, map_); + S_<typename Spec::o40>::add_parser (spec_, map_); + S_<typename Spec::o41>::add_parser (spec_, map_); + S_<typename Spec::o42>::add_parser (spec_, map_); + S_<typename Spec::o43>::add_parser (spec_, map_); + S_<typename Spec::o44>::add_parser (spec_, map_); + S_<typename Spec::o45>::add_parser (spec_, map_); + S_<typename Spec::o46>::add_parser (spec_, map_); + S_<typename Spec::o47>::add_parser (spec_, map_); + S_<typename Spec::o48>::add_parser (spec_, map_); + S_<typename Spec::o49>::add_parser (spec_, map_); + S_<typename Spec::o50>::add_parser (spec_, map_); + S_<typename Spec::o51>::add_parser (spec_, map_); + S_<typename Spec::o52>::add_parser (spec_, map_); + S_<typename Spec::o53>::add_parser (spec_, map_); + S_<typename Spec::o54>::add_parser (spec_, map_); + S_<typename Spec::o55>::add_parser (spec_, map_); + S_<typename Spec::o56>::add_parser (spec_, map_); + S_<typename Spec::o57>::add_parser (spec_, map_); + S_<typename Spec::o58>::add_parser (spec_, map_); + S_<typename Spec::o59>::add_parser (spec_, map_); + S_<typename Spec::o60>::add_parser (spec_, map_); + S_<typename Spec::o61>::add_parser (spec_, map_); + S_<typename Spec::o62>::add_parser (spec_, map_); + S_<typename Spec::o63>::add_parser (spec_, map_); + S_<typename Spec::o64>::add_parser (spec_, map_); + S_<typename Spec::o65>::add_parser (spec_, map_); + S_<typename Spec::o66>::add_parser (spec_, map_); + S_<typename Spec::o67>::add_parser (spec_, map_); + S_<typename Spec::o68>::add_parser (spec_, map_); + S_<typename Spec::o69>::add_parser (spec_, map_); + S_<typename Spec::o70>::add_parser (spec_, map_); + S_<typename Spec::o71>::add_parser (spec_, map_); + S_<typename Spec::o72>::add_parser (spec_, map_); + S_<typename Spec::o73>::add_parser (spec_, map_); + S_<typename Spec::o74>::add_parser (spec_, map_); + S_<typename Spec::o75>::add_parser (spec_, map_); + S_<typename Spec::o76>::add_parser (spec_, map_); + S_<typename Spec::o77>::add_parser (spec_, map_); + S_<typename Spec::o78>::add_parser (spec_, map_); + S_<typename Spec::o79>::add_parser (spec_, map_); + S_<typename Spec::o80>::add_parser (spec_, map_); + S_<typename Spec::o81>::add_parser (spec_, map_); + S_<typename Spec::o82>::add_parser (spec_, map_); + S_<typename Spec::o83>::add_parser (spec_, map_); + S_<typename Spec::o84>::add_parser (spec_, map_); + S_<typename Spec::o85>::add_parser (spec_, map_); + S_<typename Spec::o86>::add_parser (spec_, map_); + S_<typename Spec::o87>::add_parser (spec_, map_); + S_<typename Spec::o88>::add_parser (spec_, map_); + S_<typename Spec::o89>::add_parser (spec_, map_); + S_<typename Spec::o90>::add_parser (spec_, map_); + S_<typename Spec::o91>::add_parser (spec_, map_); + S_<typename Spec::o92>::add_parser (spec_, map_); + S_<typename Spec::o93>::add_parser (spec_, map_); + S_<typename Spec::o94>::add_parser (spec_, map_); + S_<typename Spec::o95>::add_parser (spec_, map_); + S_<typename Spec::o96>::add_parser (spec_, map_); + S_<typename Spec::o97>::add_parser (spec_, map_); + S_<typename Spec::o98>::add_parser (spec_, map_); + S_<typename Spec::o99>::add_parser (spec_, map_); + S_<typename Spec::o100>::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_<typename Spec::o01>::set_default (ops, spec_); + S_<typename Spec::o02>::set_default (ops, spec_); + S_<typename Spec::o03>::set_default (ops, spec_); + S_<typename Spec::o04>::set_default (ops, spec_); + S_<typename Spec::o05>::set_default (ops, spec_); + S_<typename Spec::o06>::set_default (ops, spec_); + S_<typename Spec::o07>::set_default (ops, spec_); + S_<typename Spec::o08>::set_default (ops, spec_); + S_<typename Spec::o09>::set_default (ops, spec_); + S_<typename Spec::o10>::set_default (ops, spec_); + S_<typename Spec::o11>::set_default (ops, spec_); + S_<typename Spec::o12>::set_default (ops, spec_); + S_<typename Spec::o13>::set_default (ops, spec_); + S_<typename Spec::o14>::set_default (ops, spec_); + S_<typename Spec::o15>::set_default (ops, spec_); + S_<typename Spec::o16>::set_default (ops, spec_); + S_<typename Spec::o17>::set_default (ops, spec_); + S_<typename Spec::o18>::set_default (ops, spec_); + S_<typename Spec::o19>::set_default (ops, spec_); + S_<typename Spec::o20>::set_default (ops, spec_); + S_<typename Spec::o21>::set_default (ops, spec_); + S_<typename Spec::o22>::set_default (ops, spec_); + S_<typename Spec::o23>::set_default (ops, spec_); + S_<typename Spec::o24>::set_default (ops, spec_); + S_<typename Spec::o25>::set_default (ops, spec_); + S_<typename Spec::o26>::set_default (ops, spec_); + S_<typename Spec::o27>::set_default (ops, spec_); + S_<typename Spec::o28>::set_default (ops, spec_); + S_<typename Spec::o29>::set_default (ops, spec_); + S_<typename Spec::o30>::set_default (ops, spec_); + S_<typename Spec::o31>::set_default (ops, spec_); + S_<typename Spec::o32>::set_default (ops, spec_); + S_<typename Spec::o33>::set_default (ops, spec_); + S_<typename Spec::o34>::set_default (ops, spec_); + S_<typename Spec::o35>::set_default (ops, spec_); + S_<typename Spec::o36>::set_default (ops, spec_); + S_<typename Spec::o37>::set_default (ops, spec_); + S_<typename Spec::o38>::set_default (ops, spec_); + S_<typename Spec::o39>::set_default (ops, spec_); + S_<typename Spec::o40>::set_default (ops, spec_); + S_<typename Spec::o41>::set_default (ops, spec_); + S_<typename Spec::o42>::set_default (ops, spec_); + S_<typename Spec::o43>::set_default (ops, spec_); + S_<typename Spec::o44>::set_default (ops, spec_); + S_<typename Spec::o45>::set_default (ops, spec_); + S_<typename Spec::o46>::set_default (ops, spec_); + S_<typename Spec::o47>::set_default (ops, spec_); + S_<typename Spec::o48>::set_default (ops, spec_); + S_<typename Spec::o49>::set_default (ops, spec_); + S_<typename Spec::o50>::set_default (ops, spec_); + S_<typename Spec::o51>::set_default (ops, spec_); + S_<typename Spec::o52>::set_default (ops, spec_); + S_<typename Spec::o53>::set_default (ops, spec_); + S_<typename Spec::o54>::set_default (ops, spec_); + S_<typename Spec::o55>::set_default (ops, spec_); + S_<typename Spec::o56>::set_default (ops, spec_); + S_<typename Spec::o57>::set_default (ops, spec_); + S_<typename Spec::o58>::set_default (ops, spec_); + S_<typename Spec::o59>::set_default (ops, spec_); + S_<typename Spec::o60>::set_default (ops, spec_); + S_<typename Spec::o61>::set_default (ops, spec_); + S_<typename Spec::o62>::set_default (ops, spec_); + S_<typename Spec::o63>::set_default (ops, spec_); + S_<typename Spec::o64>::set_default (ops, spec_); + S_<typename Spec::o65>::set_default (ops, spec_); + S_<typename Spec::o66>::set_default (ops, spec_); + S_<typename Spec::o67>::set_default (ops, spec_); + S_<typename Spec::o68>::set_default (ops, spec_); + S_<typename Spec::o69>::set_default (ops, spec_); + S_<typename Spec::o70>::set_default (ops, spec_); + S_<typename Spec::o71>::set_default (ops, spec_); + S_<typename Spec::o72>::set_default (ops, spec_); + S_<typename Spec::o73>::set_default (ops, spec_); + S_<typename Spec::o74>::set_default (ops, spec_); + S_<typename Spec::o75>::set_default (ops, spec_); + S_<typename Spec::o76>::set_default (ops, spec_); + S_<typename Spec::o77>::set_default (ops, spec_); + S_<typename Spec::o78>::set_default (ops, spec_); + S_<typename Spec::o79>::set_default (ops, spec_); + S_<typename Spec::o80>::set_default (ops, spec_); + S_<typename Spec::o81>::set_default (ops, spec_); + S_<typename Spec::o82>::set_default (ops, spec_); + S_<typename Spec::o83>::set_default (ops, spec_); + S_<typename Spec::o84>::set_default (ops, spec_); + S_<typename Spec::o85>::set_default (ops, spec_); + S_<typename Spec::o86>::set_default (ops, spec_); + S_<typename Spec::o87>::set_default (ops, spec_); + S_<typename Spec::o88>::set_default (ops, spec_); + S_<typename Spec::o89>::set_default (ops, spec_); + S_<typename Spec::o90>::set_default (ops, spec_); + S_<typename Spec::o91>::set_default (ops, spec_); + S_<typename Spec::o92>::set_default (ops, spec_); + S_<typename Spec::o93>::set_default (ops, spec_); + S_<typename Spec::o94>::set_default (ops, spec_); + S_<typename Spec::o95>::set_default (ops, spec_); + S_<typename Spec::o96>::set_default (ops, spec_); + S_<typename Spec::o97>::set_default (ops, spec_); + S_<typename Spec::o98>::set_default (ops, spec_); + S_<typename Spec::o99>::set_default (ops, spec_); + S_<typename Spec::o100>::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> + 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<Spec> parser (s); + + return parser.parse (scan, option_mode, argument_mode); + } + + template <typename Options> + Options + parse (Arguments& args, + UnknownMode::Value option_mode = UnknownMode::fail, + UnknownMode::Value argument_mode = UnknownMode::stop) + { + OptionsSpec<Options> spec; + return parse (spec, args, option_mode, argument_mode); + } + + template <typename Spec> + 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 <typename Options> + Options + parse (Int& argc, + Char** argv, + UnknownMode::Value option_mode = UnknownMode::fail, + UnknownMode::Value argument_mode = UnknownMode::stop) + { + OptionsSpec<Options> spec; + + return parse (spec, argc, argv, option_mode, argument_mode); + } + } +} + +#include <cult/cli/options-parser.ixx> +#include <cult/cli/options-parser.txx> + +#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 <boris@kolpackov.net> +// 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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace CLI + { + // OptionParserBase + // + template <typename T> + T OptionParserBase<T>:: + 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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/cli/options-spec.hxx> + +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 <boris@kolpackov.net> +// 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 <cult/types.hxx> + +#include <cult/cli/options.hxx> + +namespace Cult +{ + namespace CLI + { + template <Char const* k, typename T> + 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 <Char const* k, typename T> + struct OptionSpecType + { + typedef OptionSpec<k, T> Type; + }; + + template <> + struct OptionSpecType<Bits::null, Bits::Null> + { + typedef Bits::Null Type; + }; + + + template <Char const* k, typename T> + Char const* const OptionSpec<k, T>::key = k; + + template <typename> + class OptionsSpec; + + template <Char const* k01, typename T01, + Char const* k02, typename T02, + Char const* k03, typename T03, + Char const* k04, typename T04, + Char const* k05, typename T05, + Char const* k06, typename T06, + Char const* k07, typename T07, + Char const* k08, typename T08, + Char const* k09, typename T09, + Char const* k10, typename T10, + Char const* k11, typename T11, + Char const* k12, typename T12, + Char const* k13, typename T13, + Char const* k14, typename T14, + Char const* k15, typename T15, + Char const* k16, typename T16, + Char const* k17, typename T17, + Char const* k18, typename T18, + Char const* k19, typename T19, + Char const* k20, typename T20, + Char const* k21, typename T21, + Char const* k22, typename T22, + Char const* k23, typename T23, + Char const* k24, typename T24, + Char const* k25, typename T25, + Char const* k26, typename T26, + Char const* k27, typename T27, + Char const* k28, typename T28, + Char const* k29, typename T29, + Char const* k30, typename T30, + Char const* k31, typename T31, + Char const* k32, typename T32, + Char const* k33, typename T33, + Char const* k34, typename T34, + Char const* k35, typename T35, + Char const* k36, typename T36, + Char const* k37, typename T37, + Char const* k38, typename T38, + Char const* k39, typename T39, + Char const* k40, typename T40, + Char const* k41, typename T41, + Char const* k42, typename T42, + Char const* k43, typename T43, + Char const* k44, typename T44, + Char const* k45, typename T45, + Char const* k46, typename T46, + Char const* k47, typename T47, + Char const* k48, typename T48, + Char const* k49, typename T49, + Char const* k50, typename T50, + Char const* k51, typename T51, + Char const* k52, typename T52, + Char const* k53, typename T53, + Char const* k54, typename T54, + Char const* k55, typename T55, + Char const* k56, typename T56, + Char const* k57, typename T57, + Char const* k58, typename T58, + Char const* k59, typename T59, + Char const* k60, typename T60, + Char const* k61, typename T61, + Char const* k62, typename T62, + Char const* k63, typename T63, + Char const* k64, typename T64, + Char const* k65, typename T65, + Char const* k66, typename T66, + Char const* k67, typename T67, + Char const* k68, typename T68, + Char const* k69, typename T69, + Char const* k70, typename T70, + Char const* k71, typename T71, + Char const* k72, typename T72, + Char const* k73, typename T73, + Char const* k74, typename T74, + Char const* k75, typename T75, + Char const* k76, typename T76, + Char const* k77, typename T77, + Char const* k78, typename T78, + Char const* k79, typename T79, + Char const* k80, typename T80, + Char const* k81, typename T81, + Char const* k82, typename T82, + Char const* k83, typename T83, + Char const* k84, typename T84, + Char const* k85, typename T85, + Char const* k86, typename T86, + Char const* k87, typename T87, + Char const* k88, typename T88, + Char const* k89, typename T89, + Char const* k90, typename T90, + Char const* k91, typename T91, + Char const* k92, typename T92, + Char const* k93, typename T93, + Char const* k94, typename T94, + Char const* k95, typename T95, + Char const* k96, typename T96, + Char const* k97, typename T97, + Char const* k98, typename T98, + Char const* k99, typename T99, + Char const* k100, typename T100> + + class OptionsSpec<Options<k01, T01, + k02, T02, + k03, T03, + k04, T04, + k05, T05, + k06, T06, + k07, T07, + k08, T08, + k09, T09, + k10, T10, + k11, T11, + k12, T12, + k13, T13, + k14, T14, + k15, T15, + k16, T16, + k17, T17, + k18, T18, + k19, T19, + k20, T20, + k21, T21, + k22, T22, + k23, T23, + k24, T24, + k25, T25, + k26, T26, + k27, T27, + k28, T28, + k29, T29, + k30, T30, + k31, T31, + k32, T32, + k33, T33, + k34, T34, + k35, T35, + k36, T36, + k37, T37, + k38, T38, + k39, T39, + k40, T40, + k41, T41, + k42, T42, + k43, T43, + k44, T44, + k45, T45, + k46, T46, + k47, T47, + k48, T48, + k49, T49, + k50, T50, + k51, T51, + k52, T52, + k53, T53, + k54, T54, + k55, T55, + k56, T56, + k57, T57, + k58, T58, + k59, T59, + k60, T60, + k61, T61, + k62, T62, + k63, T63, + k64, T64, + k65, T65, + k66, T66, + k67, T67, + k68, T68, + k69, T69, + k70, T70, + k71, T71, + k72, T72, + k73, T73, + k74, T74, + k75, T75, + k76, T76, + k77, T77, + k78, T78, + k79, T79, + k80, T80, + k81, T81, + k82, T82, + k83, T83, + k84, T84, + k85, T85, + k86, T86, + k87, T87, + k88, T88, + k89, T89, + k90, T90, + k91, T91, + k92, T92, + k93, T93, + k94, T94, + k95, T95, + k96, T96, + k97, T97, + k98, T98, + k99, T99, + k100, T100> > + { + public: + typedef CLI::Options<k01, T01, + k02, T02, + k03, T03, + k04, T04, + k05, T05, + k06, T06, + k07, T07, + k08, T08, + k09, T09, + k10, T10, + k11, T11, + k12, T12, + k13, T13, + k14, T14, + k15, T15, + k16, T16, + k17, T17, + k18, T18, + k19, T19, + k20, T20, + k21, T21, + k22, T22, + k23, T23, + k24, T24, + k25, T25, + k26, T26, + k27, T27, + k28, T28, + k29, T29, + k30, T30, + k31, T31, + k32, T32, + k33, T33, + k34, T34, + k35, T35, + k36, T36, + k37, T37, + k38, T38, + k39, T39, + k40, T40, + k41, T41, + k42, T42, + k43, T43, + k44, T44, + k45, T45, + k46, T46, + k47, T47, + k48, T48, + k49, T49, + k50, T50, + k51, T51, + k52, T52, + k53, T53, + k54, T54, + k55, T55, + k56, T56, + k57, T57, + k58, T58, + k59, T59, + k60, T60, + k61, T61, + k62, T62, + k63, T63, + k64, T64, + k65, T65, + k66, T66, + k67, T67, + k68, T68, + k69, T69, + k70, T70, + k71, T71, + k72, T72, + k73, T73, + k74, T74, + k75, T75, + k76, T76, + k77, T77, + k78, T78, + k79, T79, + k80, T80, + k81, T81, + k82, T82, + k83, T83, + k84, T84, + k85, T85, + k86, T86, + k87, T87, + k88, T88, + k89, T89, + k90, T90, + k91, T91, + k92, T92, + k93, T93, + k94, T94, + k95, T95, + k96, T96, + k97, T97, + k98, T98, + k99, T99, + k100, T100> Options; + + typedef typename OptionSpecType<k01, T01>::Type o01; + typedef typename OptionSpecType<k02, T02>::Type o02; + typedef typename OptionSpecType<k03, T03>::Type o03; + typedef typename OptionSpecType<k04, T04>::Type o04; + typedef typename OptionSpecType<k05, T05>::Type o05; + typedef typename OptionSpecType<k06, T06>::Type o06; + typedef typename OptionSpecType<k07, T07>::Type o07; + typedef typename OptionSpecType<k08, T08>::Type o08; + typedef typename OptionSpecType<k09, T09>::Type o09; + typedef typename OptionSpecType<k10, T10>::Type o10; + typedef typename OptionSpecType<k11, T11>::Type o11; + typedef typename OptionSpecType<k12, T12>::Type o12; + typedef typename OptionSpecType<k13, T13>::Type o13; + typedef typename OptionSpecType<k14, T14>::Type o14; + typedef typename OptionSpecType<k15, T15>::Type o15; + typedef typename OptionSpecType<k16, T16>::Type o16; + typedef typename OptionSpecType<k17, T17>::Type o17; + typedef typename OptionSpecType<k18, T18>::Type o18; + typedef typename OptionSpecType<k19, T19>::Type o19; + typedef typename OptionSpecType<k20, T20>::Type o20; + typedef typename OptionSpecType<k21, T21>::Type o21; + typedef typename OptionSpecType<k22, T22>::Type o22; + typedef typename OptionSpecType<k23, T23>::Type o23; + typedef typename OptionSpecType<k24, T24>::Type o24; + typedef typename OptionSpecType<k25, T25>::Type o25; + typedef typename OptionSpecType<k26, T26>::Type o26; + typedef typename OptionSpecType<k27, T27>::Type o27; + typedef typename OptionSpecType<k28, T28>::Type o28; + typedef typename OptionSpecType<k29, T29>::Type o29; + typedef typename OptionSpecType<k30, T30>::Type o30; + typedef typename OptionSpecType<k31, T31>::Type o31; + typedef typename OptionSpecType<k32, T32>::Type o32; + typedef typename OptionSpecType<k33, T33>::Type o33; + typedef typename OptionSpecType<k34, T34>::Type o34; + typedef typename OptionSpecType<k35, T35>::Type o35; + typedef typename OptionSpecType<k36, T36>::Type o36; + typedef typename OptionSpecType<k37, T37>::Type o37; + typedef typename OptionSpecType<k38, T38>::Type o38; + typedef typename OptionSpecType<k39, T39>::Type o39; + typedef typename OptionSpecType<k40, T40>::Type o40; + typedef typename OptionSpecType<k41, T41>::Type o41; + typedef typename OptionSpecType<k42, T42>::Type o42; + typedef typename OptionSpecType<k43, T43>::Type o43; + typedef typename OptionSpecType<k44, T44>::Type o44; + typedef typename OptionSpecType<k45, T45>::Type o45; + typedef typename OptionSpecType<k46, T46>::Type o46; + typedef typename OptionSpecType<k47, T47>::Type o47; + typedef typename OptionSpecType<k48, T48>::Type o48; + typedef typename OptionSpecType<k49, T49>::Type o49; + typedef typename OptionSpecType<k50, T50>::Type o50; + typedef typename OptionSpecType<k51, T51>::Type o51; + typedef typename OptionSpecType<k52, T52>::Type o52; + typedef typename OptionSpecType<k53, T53>::Type o53; + typedef typename OptionSpecType<k54, T54>::Type o54; + typedef typename OptionSpecType<k55, T55>::Type o55; + typedef typename OptionSpecType<k56, T56>::Type o56; + typedef typename OptionSpecType<k57, T57>::Type o57; + typedef typename OptionSpecType<k58, T58>::Type o58; + typedef typename OptionSpecType<k59, T59>::Type o59; + typedef typename OptionSpecType<k60, T60>::Type o60; + typedef typename OptionSpecType<k61, T61>::Type o61; + typedef typename OptionSpecType<k62, T62>::Type o62; + typedef typename OptionSpecType<k63, T63>::Type o63; + typedef typename OptionSpecType<k64, T64>::Type o64; + typedef typename OptionSpecType<k65, T65>::Type o65; + typedef typename OptionSpecType<k66, T66>::Type o66; + typedef typename OptionSpecType<k67, T67>::Type o67; + typedef typename OptionSpecType<k68, T68>::Type o68; + typedef typename OptionSpecType<k69, T69>::Type o69; + typedef typename OptionSpecType<k70, T70>::Type o70; + typedef typename OptionSpecType<k71, T71>::Type o71; + typedef typename OptionSpecType<k72, T72>::Type o72; + typedef typename OptionSpecType<k73, T73>::Type o73; + typedef typename OptionSpecType<k74, T74>::Type o74; + typedef typename OptionSpecType<k75, T75>::Type o75; + typedef typename OptionSpecType<k76, T76>::Type o76; + typedef typename OptionSpecType<k77, T77>::Type o77; + typedef typename OptionSpecType<k78, T78>::Type o78; + typedef typename OptionSpecType<k79, T79>::Type o79; + typedef typename OptionSpecType<k80, T80>::Type o80; + typedef typename OptionSpecType<k81, T81>::Type o81; + typedef typename OptionSpecType<k82, T82>::Type o82; + typedef typename OptionSpecType<k83, T83>::Type o83; + typedef typename OptionSpecType<k84, T84>::Type o84; + typedef typename OptionSpecType<k85, T85>::Type o85; + typedef typename OptionSpecType<k86, T86>::Type o86; + typedef typename OptionSpecType<k87, T87>::Type o87; + typedef typename OptionSpecType<k88, T88>::Type o88; + typedef typename OptionSpecType<k89, T89>::Type o89; + typedef typename OptionSpecType<k90, T90>::Type o90; + typedef typename OptionSpecType<k91, T91>::Type o91; + typedef typename OptionSpecType<k92, T92>::Type o92; + typedef typename OptionSpecType<k93, T93>::Type o93; + typedef typename OptionSpecType<k94, T94>::Type o94; + typedef typename OptionSpecType<k95, T95>::Type o95; + typedef typename OptionSpecType<k96, T96>::Type o96; + typedef typename OptionSpecType<k97, T97>::Type o97; + typedef typename OptionSpecType<k98, T98>::Type o98; + typedef typename OptionSpecType<k99, T99>::Type o99; + typedef typename OptionSpecType<k100, T100>::Type o100; + + + private: + typedef Bits::Mapper<k01, o01, + k02, o02, + k03, o03, + k04, o04, + k05, o05, + k06, o06, + k07, o07, + k08, o08, + k09, o09, + k10, o10, + k11, o11, + k12, o12, + k13, o13, + k14, o14, + k15, o15, + k16, o16, + k17, o17, + k18, o18, + k19, o19, + k20, o20, + k21, o21, + k22, o22, + k23, o23, + k24, o24, + k25, o25, + k26, o26, + k27, o27, + k28, o28, + k29, o29, + k30, o30, + k31, o31, + k32, o32, + k33, o33, + k34, o34, + k35, o35, + k36, o36, + k37, o37, + k38, o38, + k39, o39, + k40, o40, + k41, o41, + k42, o42, + k43, o43, + k44, o44, + k45, o45, + k46, o46, + k47, o47, + k48, o48, + k49, o49, + k50, o50, + k51, o51, + k52, o52, + k53, o53, + k54, o54, + k55, o55, + k56, o56, + k57, o57, + k58, o58, + k59, o59, + k60, o60, + k61, o61, + k62, o62, + k63, o63, + k64, o64, + k65, o65, + k66, o66, + k67, o67, + k68, o68, + k69, o69, + k70, o70, + k71, o71, + k72, o72, + k73, o73, + k74, o74, + k75, o75, + k76, o76, + k77, o77, + k78, o78, + k79, o79, + k80, o80, + k81, o81, + k82, o82, + k83, o83, + k84, o84, + k85, o85, + k86, o86, + k87, o87, + k88, o88, + k89, o89, + k90, o90, + k91, o91, + k92, o92, + k93, o93, + k94, o94, + k95, o95, + k96, o96, + k97, o97, + k98, o98, + k99, o99, + k100, o100> Mapper; + + public: + template <Char const* k> + typename Mapper::template Selector<k>::Type& + option () + { + typedef + typename Mapper::template Selector<k>::Type + Type; + + return *reinterpret_cast<Type*> (option (k)); + } + + template <Char const* k> + typename Mapper::template Selector<k>::Type const& + option () const + { + typedef + typename Mapper::template Selector<k>::Type + Type; + + return *reinterpret_cast<Type const*> (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 <cult/cli/options-spec.ixx> +#include <cult/cli/options-spec.txx> + +#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 <boris@kolpackov.net> +// 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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace CLI + { + template <Char const* k01, typename T01, + Char const* k02, typename T02, + Char const* k03, typename T03, + Char const* k04, typename T04, + Char const* k05, typename T05, + Char const* k06, typename T06, + Char const* k07, typename T07, + Char const* k08, typename T08, + Char const* k09, typename T09, + Char const* k10, typename T10, + Char const* k11, typename T11, + Char const* k12, typename T12, + Char const* k13, typename T13, + Char const* k14, typename T14, + Char const* k15, typename T15, + Char const* k16, typename T16, + Char const* k17, typename T17, + Char const* k18, typename T18, + Char const* k19, typename T19, + Char const* k20, typename T20, + Char const* k21, typename T21, + Char const* k22, typename T22, + Char const* k23, typename T23, + Char const* k24, typename T24, + Char const* k25, typename T25, + Char const* k26, typename T26, + Char const* k27, typename T27, + Char const* k28, typename T28, + Char const* k29, typename T29, + Char const* k30, typename T30, + Char const* k31, typename T31, + Char const* k32, typename T32, + Char const* k33, typename T33, + Char const* k34, typename T34, + Char const* k35, typename T35, + Char const* k36, typename T36, + Char const* k37, typename T37, + Char const* k38, typename T38, + Char const* k39, typename T39, + Char const* k40, typename T40, + Char const* k41, typename T41, + Char const* k42, typename T42, + Char const* k43, typename T43, + Char const* k44, typename T44, + Char const* k45, typename T45, + Char const* k46, typename T46, + Char const* k47, typename T47, + Char const* k48, typename T48, + Char const* k49, typename T49, + Char const* k50, typename T50, + Char const* k51, typename T51, + Char const* k52, typename T52, + Char const* k53, typename T53, + Char const* k54, typename T54, + Char const* k55, typename T55, + Char const* k56, typename T56, + Char const* k57, typename T57, + Char const* k58, typename T58, + Char const* k59, typename T59, + Char const* k60, typename T60, + Char const* k61, typename T61, + Char const* k62, typename T62, + Char const* k63, typename T63, + Char const* k64, typename T64, + Char const* k65, typename T65, + Char const* k66, typename T66, + Char const* k67, typename T67, + Char const* k68, typename T68, + Char const* k69, typename T69, + Char const* k70, typename T70, + Char const* k71, typename T71, + Char const* k72, typename T72, + Char const* k73, typename T73, + Char const* k74, typename T74, + Char const* k75, typename T75, + Char const* k76, typename T76, + Char const* k77, typename T77, + Char const* k78, typename T78, + Char const* k79, typename T79, + Char const* k80, typename T80, + Char const* k81, typename T81, + Char const* k82, typename T82, + Char const* k83, typename T83, + Char const* k84, typename T84, + Char const* k85, typename T85, + Char const* k86, typename T86, + Char const* k87, typename T87, + Char const* k88, typename T88, + Char const* k89, typename T89, + Char const* k90, typename T90, + Char const* k91, typename T91, + Char const* k92, typename T92, + Char const* k93, typename T93, + Char const* k94, typename T94, + Char const* k95, typename T95, + Char const* k96, typename T96, + Char const* k97, typename T97, + Char const* k98, typename T98, + Char const* k99, typename T99, + Char const* k100, typename T100> + Void* + OptionsSpec<Options<k01, T01, + k02, T02, + k03, T03, + k04, T04, + k05, T05, + k06, T06, + k07, T07, + k08, T08, + k09, T09, + k10, T10, + k11, T11, + k12, T12, + k13, T13, + k14, T14, + k15, T15, + k16, T16, + k17, T17, + k18, T18, + k19, T19, + k20, T20, + k21, T21, + k22, T22, + k23, T23, + k24, T24, + k25, T25, + k26, T26, + k27, T27, + k28, T28, + k29, T29, + k30, T30, + k31, T31, + k32, T32, + k33, T33, + k34, T34, + k35, T35, + k36, T36, + k37, T37, + k38, T38, + k39, T39, + k40, T40, + k41, T41, + k42, T42, + k43, T43, + k44, T44, + k45, T45, + k46, T46, + k47, T47, + k48, T48, + k49, T49, + k50, T50, + k51, T51, + k52, T52, + k53, T53, + k54, T54, + k55, T55, + k56, T56, + k57, T57, + k58, T58, + k59, T59, + k60, T60, + k61, T61, + k62, T62, + k63, T63, + k64, T64, + k65, T65, + k66, T66, + k67, T67, + k68, T68, + k69, T69, + k70, T70, + k71, T71, + k72, T72, + k73, T73, + k74, T74, + k75, T75, + k76, T76, + k77, T77, + k78, T78, + k79, T79, + k80, T80, + k81, T81, + k82, T82, + k83, T83, + k84, T84, + k85, T85, + k86, T86, + k87, T87, + k88, T88, + k89, T89, + k90, T90, + k91, T91, + k92, T92, + k93, T93, + k94, T94, + k95, T95, + k96, T96, + k97, T97, + k98, T98, + k99, T99, + k100, T100> >:: + 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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/cli/options.hxx> + +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 <boris@kolpackov.net> +// 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 <cult/types.hxx> + +#include <cassert> + +namespace Cult +{ + namespace CLI + { + namespace Bits + { + template <Boolean t, typename X, typename Y> + struct if_; + + template <typename X, typename Y> + struct if_<true, X, Y> + { + typedef X Type; + }; + + template <typename X, typename Y> + struct if_<false, X, Y> + { + typedef Y Type; + }; + + template <Char const* x, Char const* y> + struct same + { + static Boolean const r = false; + }; + + template <Char const* x> + struct same<x, x> + { + static Boolean const r = true; + }; + + template <Char const* x> + struct Tag + { + }; + + //@@ should end up in Cult::Meta + // + struct Null {}; + extern Char const null[]; + +#include <cult/cli/mapper.hxx> + + } + + template <Char const* k01, typename T01, + Char const* k02 = Bits::null, typename T02 = Bits::Null, + Char const* k03 = Bits::null, typename T03 = Bits::Null, + Char const* k04 = Bits::null, typename T04 = Bits::Null, + Char const* k05 = Bits::null, typename T05 = Bits::Null, + Char const* k06 = Bits::null, typename T06 = Bits::Null, + Char const* k07 = Bits::null, typename T07 = Bits::Null, + Char const* k08 = Bits::null, typename T08 = Bits::Null, + Char const* k09 = Bits::null, typename T09 = Bits::Null, + Char const* k10 = Bits::null, typename T10 = Bits::Null, + Char const* k11 = Bits::null, typename T11 = Bits::Null, + Char const* k12 = Bits::null, typename T12 = Bits::Null, + Char const* k13 = Bits::null, typename T13 = Bits::Null, + Char const* k14 = Bits::null, typename T14 = Bits::Null, + Char const* k15 = Bits::null, typename T15 = Bits::Null, + Char const* k16 = Bits::null, typename T16 = Bits::Null, + Char const* k17 = Bits::null, typename T17 = Bits::Null, + Char const* k18 = Bits::null, typename T18 = Bits::Null, + Char const* k19 = Bits::null, typename T19 = Bits::Null, + Char const* k20 = Bits::null, typename T20 = Bits::Null, + Char const* k21 = Bits::null, typename T21 = Bits::Null, + Char const* k22 = Bits::null, typename T22 = Bits::Null, + Char const* k23 = Bits::null, typename T23 = Bits::Null, + Char const* k24 = Bits::null, typename T24 = Bits::Null, + Char const* k25 = Bits::null, typename T25 = Bits::Null, + Char const* k26 = Bits::null, typename T26 = Bits::Null, + Char const* k27 = Bits::null, typename T27 = Bits::Null, + Char const* k28 = Bits::null, typename T28 = Bits::Null, + Char const* k29 = Bits::null, typename T29 = Bits::Null, + Char const* k30 = Bits::null, typename T30 = Bits::Null, + Char const* k31 = Bits::null, typename T31 = Bits::Null, + Char const* k32 = Bits::null, typename T32 = Bits::Null, + Char const* k33 = Bits::null, typename T33 = Bits::Null, + Char const* k34 = Bits::null, typename T34 = Bits::Null, + Char const* k35 = Bits::null, typename T35 = Bits::Null, + Char const* k36 = Bits::null, typename T36 = Bits::Null, + Char const* k37 = Bits::null, typename T37 = Bits::Null, + Char const* k38 = Bits::null, typename T38 = Bits::Null, + Char const* k39 = Bits::null, typename T39 = Bits::Null, + Char const* k40 = Bits::null, typename T40 = Bits::Null, + Char const* k41 = Bits::null, typename T41 = Bits::Null, + Char const* k42 = Bits::null, typename T42 = Bits::Null, + Char const* k43 = Bits::null, typename T43 = Bits::Null, + Char const* k44 = Bits::null, typename T44 = Bits::Null, + Char const* k45 = Bits::null, typename T45 = Bits::Null, + Char const* k46 = Bits::null, typename T46 = Bits::Null, + Char const* k47 = Bits::null, typename T47 = Bits::Null, + Char const* k48 = Bits::null, typename T48 = Bits::Null, + Char const* k49 = Bits::null, typename T49 = Bits::Null, + Char const* k50 = Bits::null, typename T50 = Bits::Null, + Char const* k51 = Bits::null, typename T51 = Bits::Null, + Char const* k52 = Bits::null, typename T52 = Bits::Null, + Char const* k53 = Bits::null, typename T53 = Bits::Null, + Char const* k54 = Bits::null, typename T54 = Bits::Null, + Char const* k55 = Bits::null, typename T55 = Bits::Null, + Char const* k56 = Bits::null, typename T56 = Bits::Null, + Char const* k57 = Bits::null, typename T57 = Bits::Null, + Char const* k58 = Bits::null, typename T58 = Bits::Null, + Char const* k59 = Bits::null, typename T59 = Bits::Null, + Char const* k60 = Bits::null, typename T60 = Bits::Null, + Char const* k61 = Bits::null, typename T61 = Bits::Null, + Char const* k62 = Bits::null, typename T62 = Bits::Null, + Char const* k63 = Bits::null, typename T63 = Bits::Null, + Char const* k64 = Bits::null, typename T64 = Bits::Null, + Char const* k65 = Bits::null, typename T65 = Bits::Null, + Char const* k66 = Bits::null, typename T66 = Bits::Null, + Char const* k67 = Bits::null, typename T67 = Bits::Null, + Char const* k68 = Bits::null, typename T68 = Bits::Null, + Char const* k69 = Bits::null, typename T69 = Bits::Null, + Char const* k70 = Bits::null, typename T70 = Bits::Null, + Char const* k71 = Bits::null, typename T71 = Bits::Null, + Char const* k72 = Bits::null, typename T72 = Bits::Null, + Char const* k73 = Bits::null, typename T73 = Bits::Null, + Char const* k74 = Bits::null, typename T74 = Bits::Null, + Char const* k75 = Bits::null, typename T75 = Bits::Null, + Char const* k76 = Bits::null, typename T76 = Bits::Null, + Char const* k77 = Bits::null, typename T77 = Bits::Null, + Char const* k78 = Bits::null, typename T78 = Bits::Null, + Char const* k79 = Bits::null, typename T79 = Bits::Null, + Char const* k80 = Bits::null, typename T80 = Bits::Null, + Char const* k81 = Bits::null, typename T81 = Bits::Null, + Char const* k82 = Bits::null, typename T82 = Bits::Null, + Char const* k83 = Bits::null, typename T83 = Bits::Null, + Char const* k84 = Bits::null, typename T84 = Bits::Null, + Char const* k85 = Bits::null, typename T85 = Bits::Null, + Char const* k86 = Bits::null, typename T86 = Bits::Null, + Char const* k87 = Bits::null, typename T87 = Bits::Null, + Char const* k88 = Bits::null, typename T88 = Bits::Null, + Char const* k89 = Bits::null, typename T89 = Bits::Null, + Char const* k90 = Bits::null, typename T90 = Bits::Null, + Char const* k91 = Bits::null, typename T91 = Bits::Null, + Char const* k92 = Bits::null, typename T92 = Bits::Null, + Char const* k93 = Bits::null, typename T93 = Bits::Null, + Char const* k94 = Bits::null, typename T94 = Bits::Null, + Char const* k95 = Bits::null, typename T95 = Bits::Null, + Char const* k96 = Bits::null, typename T96 = Bits::Null, + Char const* k97 = Bits::null, typename T97 = Bits::Null, + Char const* k98 = Bits::null, typename T98 = Bits::Null, + Char const* k99 = Bits::null, typename T99 = Bits::Null, + Char const* k100 = Bits::null, typename T100 = Bits::Null> + class Options + { + typedef Bits::Mapper<k01, T01, + k02, T02, + k03, T03, + k04, T04, + k05, T05, + k06, T06, + k07, T07, + k08, T08, + k09, T09, + k10, T10, + k11, T11, + k12, T12, + k13, T13, + k14, T14, + k15, T15, + k16, T16, + k17, T17, + k18, T18, + k19, T19, + k20, T20, + k21, T21, + k22, T22, + k23, T23, + k24, T24, + k25, T25, + k26, T26, + k27, T27, + k28, T28, + k29, T29, + k30, T30, + k31, T31, + k32, T32, + k33, T33, + k34, T34, + k35, T35, + k36, T36, + k37, T37, + k38, T38, + k39, T39, + k40, T40, + k41, T41, + k42, T42, + k43, T43, + k44, T44, + k45, T45, + k46, T46, + k47, T47, + k48, T48, + k49, T49, + k50, T50, + k51, T51, + k52, T52, + k53, T53, + k54, T54, + k55, T55, + k56, T56, + k57, T57, + k58, T58, + k59, T59, + k60, T60, + k61, T61, + k62, T62, + k63, T63, + k64, T64, + k65, T65, + k66, T66, + k67, T67, + k68, T68, + k69, T69, + k70, T70, + k71, T71, + k72, T72, + k73, T73, + k74, T74, + k75, T75, + k76, T76, + k77, T77, + k78, T78, + k79, T79, + k80, T80, + k81, T81, + k82, T82, + k83, T83, + k84, T84, + k85, T85, + k86, T86, + k87, T87, + k88, T88, + k89, T89, + k90, T90, + k91, T91, + k92, T92, + k93, T93, + k94, T94, + k95, T95, + k96, T96, + k97, T97, + k98, T98, + k99, T99, + k100, T100> 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 <Char const* k> + typename Mapper::template Selector<k>::Type& + value () + { + typedef + typename Mapper::template Selector<k>::Type + Type; + + return *reinterpret_cast<Type*> (value (k)); + } + + template <Char const* k> + typename Mapper::template Selector<k>::Type const& + value () const + { + typedef + typename Mapper::template Selector<k>::Type + Type; + + return *reinterpret_cast<Type const*> (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 <cult/cli/options.ixx> +#include <cult/cli/options.txx> + +#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 <boris@kolpackov.net> +// 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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace CLI + { + template <Char const* k01, typename T01, + Char const* k02, typename T02, + Char const* k03, typename T03, + Char const* k04, typename T04, + Char const* k05, typename T05, + Char const* k06, typename T06, + Char const* k07, typename T07, + Char const* k08, typename T08, + Char const* k09, typename T09, + Char const* k10, typename T10, + Char const* k11, typename T11, + Char const* k12, typename T12, + Char const* k13, typename T13, + Char const* k14, typename T14, + Char const* k15, typename T15, + Char const* k16, typename T16, + Char const* k17, typename T17, + Char const* k18, typename T18, + Char const* k19, typename T19, + Char const* k20, typename T20, + Char const* k21, typename T21, + Char const* k22, typename T22, + Char const* k23, typename T23, + Char const* k24, typename T24, + Char const* k25, typename T25, + Char const* k26, typename T26, + Char const* k27, typename T27, + Char const* k28, typename T28, + Char const* k29, typename T29, + Char const* k30, typename T30, + Char const* k31, typename T31, + Char const* k32, typename T32, + Char const* k33, typename T33, + Char const* k34, typename T34, + Char const* k35, typename T35, + Char const* k36, typename T36, + Char const* k37, typename T37, + Char const* k38, typename T38, + Char const* k39, typename T39, + Char const* k40, typename T40, + Char const* k41, typename T41, + Char const* k42, typename T42, + Char const* k43, typename T43, + Char const* k44, typename T44, + Char const* k45, typename T45, + Char const* k46, typename T46, + Char const* k47, typename T47, + Char const* k48, typename T48, + Char const* k49, typename T49, + Char const* k50, typename T50, + Char const* k51, typename T51, + Char const* k52, typename T52, + Char const* k53, typename T53, + Char const* k54, typename T54, + Char const* k55, typename T55, + Char const* k56, typename T56, + Char const* k57, typename T57, + Char const* k58, typename T58, + Char const* k59, typename T59, + Char const* k60, typename T60, + Char const* k61, typename T61, + Char const* k62, typename T62, + Char const* k63, typename T63, + Char const* k64, typename T64, + Char const* k65, typename T65, + Char const* k66, typename T66, + Char const* k67, typename T67, + Char const* k68, typename T68, + Char const* k69, typename T69, + Char const* k70, typename T70, + Char const* k71, typename T71, + Char const* k72, typename T72, + Char const* k73, typename T73, + Char const* k74, typename T74, + Char const* k75, typename T75, + Char const* k76, typename T76, + Char const* k77, typename T77, + Char const* k78, typename T78, + Char const* k79, typename T79, + Char const* k80, typename T80, + Char const* k81, typename T81, + Char const* k82, typename T82, + Char const* k83, typename T83, + Char const* k84, typename T84, + Char const* k85, typename T85, + Char const* k86, typename T86, + Char const* k87, typename T87, + Char const* k88, typename T88, + Char const* k89, typename T89, + Char const* k90, typename T90, + Char const* k91, typename T91, + Char const* k92, typename T92, + Char const* k93, typename T93, + Char const* k94, typename T94, + Char const* k95, typename T95, + Char const* k96, typename T96, + Char const* k97, typename T97, + Char const* k98, typename T98, + Char const* k99, typename T99, + Char const* k100, typename T100> + Void* + Options<k01, T01, + k02, T02, + k03, T03, + k04, T04, + k05, T05, + k06, T06, + k07, T07, + k08, T08, + k09, T09, + k10, T10, + k11, T11, + k12, T12, + k13, T13, + k14, T14, + k15, T15, + k16, T16, + k17, T17, + k18, T18, + k19, T19, + k20, T20, + k21, T21, + k22, T22, + k23, T23, + k24, T24, + k25, T25, + k26, T26, + k27, T27, + k28, T28, + k29, T29, + k30, T30, + k31, T31, + k32, T32, + k33, T33, + k34, T34, + k35, T35, + k36, T36, + k37, T37, + k38, T38, + k39, T39, + k40, T40, + k41, T41, + k42, T42, + k43, T43, + k44, T44, + k45, T45, + k46, T46, + k47, T47, + k48, T48, + k49, T49, + k50, T50, + k51, T51, + k52, T52, + k53, T53, + k54, T54, + k55, T55, + k56, T56, + k57, T57, + k58, T58, + k59, T59, + k60, T60, + k61, T61, + k62, T62, + k63, T63, + k64, T64, + k65, T65, + k66, T66, + k67, T67, + k68, T68, + k69, T69, + k70, T70, + k71, T71, + k72, T72, + k73, T73, + k74, T74, + k75, T75, + k76, T76, + k77, T77, + k78, T78, + k79, T79, + k80, T80, + k81, T81, + k82, T82, + k83, T83, + k84, T84, + k85, T85, + k86, T86, + k87, T87, + k88, T88, + k89, T89, + k90, T90, + k91, T91, + k92, T92, + k93, T93, + k94, T94, + k95, T95, + k96, T96, + k97, T97, + k98, T98, + k99, T99, + k100, T100>:: + 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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/cli/scanner.hxx> + +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 <boris@kolpackov.net> +// 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 <cult/types.hxx> + +#include <cult/cli/exceptions.hxx> +#include <cult/cli/arguments.hxx> + +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 <cult/cli/scanner.ixx> + +#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 <boris@kolpackov.net> +// 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 <boris@kolpackov.net> +// 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 <cult/types.hxx> + +#include <cult/rtti/type-id.hxx> + +namespace Cult +{ + namespace Containers + { + //@@ eager clonning: do I need it? + // + // + class Any + { + public: + struct Typing {}; + + public: + template <typename X> + Any (X const& x) + : holder_ (new HolderTemplate<X> (x)) + { + } + + Any (Any const& any) + : holder_ (any.holder_->clone ()) + { + } + + public: + template <typename X> + Any& + operator= (X const& x) + { + holder_ = Evptr<Holder> (new HolderTemplate<X> (x)); + return *this; + } + + Any& + operator= (Any const& any) + { + holder_ = any.holder_->clone (); + return *this; + } + + public: + /* + template <typename X> + operator X& () + { + return value<X> (); + } + + template <typename X> + operator X const& () const + { + return value<X> (); + } + */ + + public: + template <typename X> + X& + value () + { + //@@ too strict + // + if (holder_->type_id () == typeid (X)) + { + return dynamic_cast<HolderTemplate<X>*>(holder_.get ())->value (); + } + else + { + throw Typing (); + } + } + + template <typename X> + X const& + value () const + { + if (holder_->type_id () == typeid (X)) + { + return dynamic_cast<HolderTemplate<X>*>(holder_.get ())->value (); + } + else + { + throw Typing (); + } + } + + public: + RTTI::TypeId + type_id () const + { + return holder_->type_id (); + } + + public: + /* + template <typename x> + friend x + operator+ (any const& a, x const& b) + { + return a.value<x> () + b; + } + + template <typename x> + friend x + operator+ (x const& a, any const& b) + { + return a + b.value<x> (); + } + */ + + private: + class Holder + { + public: + virtual + ~Holder () + { + } + + Evptr<Holder> + clone () const + { + return clone_ (); + } + + virtual RTTI::TypeId + type_id () const = 0; + + protected: + virtual Evptr<Holder> + clone_ () const = 0; + }; + + template <typename X> + 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<Holder> + clone_ () const + { + return new HolderTemplate<X> (value_); + } + + private: + X value_; + }; + + private: + Evptr<Holder> holder_; + }; + } +} + +#include <cult/containers/any.txx> + +#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 <boris@kolpackov.net> +// 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 <boris@kolpackov.net> +// 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 <cult/types.hxx> + +#include <cult/containers/iterator.hxx> + +#include <deque> + +namespace Cult +{ + namespace Containers + { + template <typename T> + class Deque: public std::deque<T> + { + typedef std::deque<T> 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<typename Base::iterator> + Iterator; + + typedef + IteratorAdapter<typename Base::const_iterator> + ConstIterator; + + + typedef + IteratorAdapter<typename Base::reverse_iterator> + ReverseIterator; + + typedef + IteratorAdapter<typename Base::const_reverse_iterator> + 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 <typename InputIterator> + Deque (InputIterator first, InputIterator last) + : Base (first, last) + { + } + + Deque (Deque<Value> const& other) + : Base (other) + { + } + + Deque<Value>& + operator= (Deque<Value> 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<Value>& 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 <boris@kolpackov.net> +// 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 <cult/types.hxx> +#include <cult/eh/exception.hxx> +#include <cult/containers/map.hxx> + +namespace Cult +{ + namespace Containers + { + template <typename N, typename E> + class Graph + { + public: + typedef N Node; + typedef E Edge; + + struct NoEdge: virtual EH::Exception {}; + struct NoNode: virtual EH::Exception {}; + + public: + template <typename T> + T& + new_node (); + + template <typename T, typename A0> + T& + new_node (A0 const&); + + template <typename T, typename A0, typename A1> + T& + new_node (A0 const&, A1 const&); + + template <typename T, typename A0, typename A1, typename A2> + T& + new_node (A0 const&, A1 const&, A2 const&); + + template <typename T, typename A0, typename A1, typename A2, + typename A3> + T& + new_node (A0 const&, A1 const&, A2 const&, A3 const&); + + template <typename T, typename A0, typename A1, typename A2, + typename A3, typename A4> + T& + new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&); + + template <typename T, typename A0, typename A1, typename A2, + typename A3, typename A4, typename A5> + T& + new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&, + A5 const&); + + template <typename T, typename A0, typename A1, typename A2, + typename A3, typename A4, typename A5, typename A6> + T& + new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&, + A5 const&, A6 const&); + + template <typename T, typename A0, typename A1, typename A2, + typename A3, typename A4, typename A5, typename A6, + typename A7> + T& + new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&, + A5 const&, A6 const&, A7 const&); + + template <typename T, typename A0, typename A1, typename A2, + typename A3, typename A4, typename A5, typename A6, + typename A7, typename A8> + T& + new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&, + A5 const&, A6 const&, A7 const&, A8 const&); + + template <typename T, typename A0, typename A1, typename A2, + typename A3, typename A4, typename A5, typename A6, + typename A7, typename A8, typename A9> + 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 <typename T, typename Left, typename Right> + T& + new_edge (Left&, Right&); + + template <typename T, typename Left, typename Right, + typename A0> + T& + new_edge (Left&, Right&, A0 const&); + + template <typename T, typename Left, typename Right, + typename A0, typename A1> + T& + new_edge (Left&, Right&, A0 const&, A1 const&); + + template <typename T, typename Left, typename Right, + typename A0, typename A1, typename A2> + T& + new_edge (Left&, Right&, A0 const&, A1 const&, A2 const&); + + template <typename T, typename Left, typename Right, + typename A0, typename A1, typename A2, typename A3> + T& + new_edge (Left&, Right&, A0 const&, A1 const&, A2 const&, A3 const&); + + template <typename T, typename Left, typename Right, + typename A0, typename A1, typename A2, typename A3, + typename A4> + T& + new_edge (Left&, Right&, A0 const&, A1 const&, A2 const&, A3 const&, + A4 const&); + + template <typename T, typename Left, typename Right, + typename A0, typename A1, typename A2, typename A3, + typename A4, typename A5> + 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 <typename TE, typename TN> + Void + reset_left_node (TE& edge, TN& node) + { + edge.set_left_node (node); + } + + template <typename TE, typename TN> + Void + reset_right_node (TE& edge, TN& node) + { + edge.set_right_node (node); + } + + // Functions to add edges to a node. + // + public: + template <typename TN, typename TE> + Void + add_edge_left (TN& node, TE& edge) + { + node.add_edge_left (edge); + } + + template <typename TN, typename TE> + 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 <typename T, typename Left, typename Right> + 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<Node> NodePtr; + typedef Shptr<Edge> EdgePtr; + + typedef Map<Node*, NodePtr> Nodes; + typedef Map<Edge*, EdgePtr> Edges; + + Nodes nodes_; + Edges edges_; + }; + } +} + + +#include <cult/containers/graph.txx> + +#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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace Containers + { + + // Nodes. + // + + template <typename N, typename E> + template <typename T> + T& Graph<N, E>:: + new_node () + { + Shptr<T> node (new T); + nodes_[node.get ()] = node; + + return *node; + } + + + template <typename N, typename E> + template <typename T, typename A0> + T& Graph<N, E>:: + new_node (A0 const& a0) + { + Shptr<T> node (new T (a0)); + nodes_[node.get ()] = node; + + return *node; + } + + + template <typename N, typename E> + template <typename T, typename A0, typename A1> + T& Graph<N, E>:: + new_node (A0 const& a0, A1 const& a1) + { + Shptr<T> node (new T (a0, a1)); + nodes_[node.get ()] = node; + + return *node; + } + + template <typename N, typename E> + template <typename T, typename A0, typename A1, typename A2> + T& Graph<N, E>:: + new_node (A0 const& a0, A1 const& a1, A2 const& a2) + { + Shptr<T> node (new T (a0, a1, a2)); + nodes_[node.get ()] = node; + + return *node; + } + + template <typename N, typename E> + template <typename T, typename A0, typename A1, typename A2, + typename A3> + T& Graph<N, E>:: + new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3) + { + Shptr<T> node (new T (a0, a1, a2, a3)); + nodes_[node.get ()] = node; + + return *node; + } + + template <typename N, typename E> + template <typename T, typename A0, typename A1, typename A2, + typename A3, typename A4> + T& Graph<N, E>:: + new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, + A4 const& a4) + { + Shptr<T> node (new T (a0, a1, a2, a3, a4)); + nodes_[node.get ()] = node; + + return *node; + } + + template <typename N, typename E> + template <typename T, typename A0, typename A1, typename A2, + typename A3, typename A4, typename A5> + T& Graph<N, E>:: + new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, + A4 const& a4, A5 const& a5) + { + Shptr<T> node (new T (a0, a1, a2, a3, a4, a5)); + nodes_[node.get ()] = node; + + return *node; + } + + template <typename N, typename E> + template <typename T, typename A0, typename A1, typename A2, + typename A3, typename A4, typename A5, typename A6> + T& Graph<N, E>:: + new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, + A4 const& a4, A5 const& a5, A6 const& a6) + { + Shptr<T> node (new T (a0, a1, a2, a3, a4, a5, a6)); + nodes_[node.get ()] = node; + + return *node; + } + + template <typename N, typename E> + template <typename T, typename A0, typename A1, typename A2, + typename A3, typename A4, typename A5, typename A6, + typename A7> + T& Graph<N, E>:: + 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<T> node (new T (a0, a1, a2, a3, a4, a5, a6, a7)); + nodes_[node.get ()] = node; + + return *node; + } + + + template <typename N, typename E> + template <typename T, typename A0, typename A1, typename A2, + typename A3, typename A4, typename A5, typename A6, + typename A7, typename A8> + T& Graph<N, E>:: + 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<T> node (new T (a0, a1, a2, a3, a4, a5, a6, a7, a8)); + nodes_[node.get ()] = node; + + return *node; + } + + + template <typename N, typename E> + template <typename T, typename A0, typename A1, typename A2, + typename A3, typename A4, typename A5, typename A6, + typename A7, typename A8, typename A9> + T& Graph<N, E>:: + 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<T> node (new T (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); + nodes_[node.get ()] = node; + + return *node; + } + + + // Edges. + // + + template <typename N, typename E> + template <typename T, typename Left, typename Right> + T& Graph<N, E>:: + new_edge (Left& l, Right& r) + { + Shptr<T> 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 <typename N, typename E> + template <typename T, typename Left, typename Right, + typename A0> + T& Graph<N, E>:: + new_edge (Left& l, Right& r, A0 const& a0) + { + Shptr<T> 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 <typename N, typename E> + template <typename T, typename Left, typename Right, + typename A0, typename A1> + T& Graph<N, E>:: + new_edge (Left& l, Right& r, A0 const& a0, A1 const& a1) + { + Shptr<T> 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 <typename N, typename E> + template <typename T, typename Left, typename Right, + typename A0, typename A1, typename A2> + T& Graph<N, E>:: + new_edge (Left& l, Right& r, A0 const& a0, A1 const& a1, A2 const& a2) + { + Shptr<T> 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 <typename N, typename E> + template <typename T, typename Left, typename Right, + typename A0, typename A1, typename A2, typename A3> + T& Graph<N, E>:: + new_edge (Left& l, Right& r, A0 const& a0, A1 const& a1, A2 const& a2, + A3 const& a3) + { + Shptr<T> 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 <typename N, typename E> + template <typename T, typename Left, typename Right, + typename A0, typename A1, typename A2, typename A3, + typename A4> + T& Graph<N, E>:: + new_edge (Left& l, Right& r, A0 const& a0, A1 const& a1, A2 const& a2, + A3 const& a3, A4 const& a4) + { + Shptr<T> 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 <typename N, typename E> + template <typename T, typename Left, typename Right, + typename A0, typename A1, typename A2, typename A3, + typename A4, typename A5> + T& Graph<N, E>:: + 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<T> 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 <typename N, typename E> + template <typename T, typename Left, typename Right> + Void Graph<N, E>:: + 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 <boris@kolpackov.net> +// 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 <cult/types.hxx> + +#include <iterator> + +namespace Cult +{ + namespace Containers + { + template <typename I> + class IteratorAdapter + { + public: + typedef typename std::iterator_traits<I>::value_type Value; + typedef typename std::iterator_traits<I>::difference_type Difference; + typedef typename std::iterator_traits<I>::pointer Pointer; + typedef typename std::iterator_traits<I>::reference Reference; + typedef typename std::iterator_traits<I>::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 <typename J> + IteratorAdapter (IteratorAdapter<J> 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<typename> + 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 <typename I, typename J> + inline Boolean + operator== (IteratorAdapter<I> const& i, IteratorAdapter<J> const& j) + { + return i.base () == j.base (); + } + + template <typename I, typename J> + inline Boolean + operator!= (IteratorAdapter<I> const& i, IteratorAdapter<J> const& j) + { + return i.base () != j.base (); + } + + // Random access iterator requirements + // + template <typename I, typename J> + inline Boolean + operator< (IteratorAdapter<I> const& i, IteratorAdapter<J> const& j) + { + return i.base() < j.base(); + } + + template <typename I, typename J> + inline Boolean + operator> (IteratorAdapter<I> const& i, IteratorAdapter<J> const& j) + { + return i.base() > j.base(); + } + + template <typename I, typename J> + inline Boolean + operator<= (IteratorAdapter<I> const& i, IteratorAdapter<J> const& j) + { + return i.base() <= j.base(); + } + + template <typename I, typename J> + inline Boolean + operator>= (IteratorAdapter<I> const& i, IteratorAdapter<J> const& j) + { + return i.base() >= j.base(); + } + + template <typename I, typename J> + inline typename IteratorAdapter<I>::Difference + operator- (IteratorAdapter<I> const& i, IteratorAdapter<J> const& j) + { + return i.base () - j.base (); + } + + template <typename I> + IteratorAdapter<I> + operator+ (typename IteratorAdapter<I>::Difference n, + IteratorAdapter<I> 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 <boris@kolpackov.net> +// 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 <cult/types.hxx> + +#include <cult/containers/iterator.hxx> + +#include <list> + +namespace Cult +{ + namespace Containers + { + template <typename T> + class List: public std::list<T> + { + typedef std::list<T> 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<typename Base::iterator> + Iterator; + + typedef + IteratorAdapter<typename Base::const_iterator> + ConstIterator; + + + typedef + IteratorAdapter<typename Base::reverse_iterator> + ReverseIterator; + + typedef + IteratorAdapter<typename Base::const_reverse_iterator> + 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 <typename InputIterator> + List (InputIterator first, InputIterator last) + : Base (first, last) + { + } + + List (List<Value> const& other) + : Base (other) + { + } + + List<Value>& + operator= (List<Value> const& other) + { + base () = other; + return *this; + } + + public: + Void + swap (List<Value>& 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 <typename I> + Void + insert (Iterator const& p, I const& first, I const& last) + { + base ().insert (p.base (), first, last); + } + + template <typename I> + Void + insert (Iterator const& p, + IteratorAdapter<I> const& first, + IteratorAdapter<I> 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 <boris@kolpackov.net> +// 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 <cult/types.hxx> + +#include <cult/containers/iterator.hxx> + +#include <map> + +namespace Cult +{ + namespace Containers + { + template <typename K, typename T, typename C = std::less<K> > + class Map: public std::map<K, T, C> + { + typedef std::map<K, T, C> 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<typename Base::iterator> + Iterator; + + typedef + IteratorAdapter<typename Base::const_iterator> + ConstIterator; + + + typedef + IteratorAdapter<typename Base::reverse_iterator> + ReverseIterator; + + typedef + IteratorAdapter<typename Base::const_reverse_iterator> + 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 <typename InputIterator> + Map (InputIterator first, + InputIterator last, + Compare const& comp = Compare ()) + : Base (first, last, comp) + { + } + + Map (Map<Key, Value, Compare> const& other) + : Base (other) + { + } + + Map<Key, Value, Compare>& + operator= (Map<Key, Value, Compare> 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<Key, Value, Compare>& 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 <boris@kolpackov.net> +// 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 <utility> + +namespace Cult +{ + namespace Containers + { + template <typename T1, typename T2> + class Pair: public std::pair<T1, T2> + { + typedef std::pair<T1, T2> 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 <typename X, typename Y> + Pair (std::pair<X, Y> const& pair) + : Base (pair) + { + } + + template <typename X, typename Y> + Pair& + operator= (std::pair<X, Y> 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 <boris@kolpackov.net> +// 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 <cult/types.hxx> + +#include <cult/containers/iterator.hxx> + +#include <set> + +namespace Cult +{ + namespace Containers + { + template <typename K, typename C = std::less<K> > + class Set: public std::set<K, C> + { + typedef std::set<K, C> 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<typename Base::iterator> + Iterator; + + typedef + IteratorAdapter<typename Base::const_iterator> + ConstIterator; + + + typedef + IteratorAdapter<typename Base::reverse_iterator> + ReverseIterator; + + typedef + IteratorAdapter<typename Base::const_reverse_iterator> + 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 <typename InputIterator> + Set (InputIterator first, + InputIterator last, + Compare const& comp = Compare ()) + : Base (first, last, comp) + { + } + + Set (Set<Key, Compare> const& other) + : Base (other) + { + } + + Set<Key, Compare>& + operator= (Set<Key, Compare> 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<Key, Compare>& 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 <boris@kolpackov.net> +// 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 <cult/types.hxx> + +#include <cult/containers/deque.hxx> + +namespace Cult +{ + namespace Containers + { + template <typename T, typename C = Deque<T> > + 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 <class T, class Container> + bool operator==(const stack<T, Container>& x, + const stack<T, Container>& y); + template <class T, class Container> + bool operator< (const stack<T, Container>& x, + const stack<T, Container>& y); + template <class T, class Container> + bool operator!=(const stack<T, Container>& x, + const stack<T, Container>& y); + template <class T, class Container> + bool operator> (const stack<T, Container>& x, + const stack<T, Container>& y); + template <class T, class Container> + bool operator>=(const stack<T, Container>& x, + const stack<T, Container>& y); + template <class T, class Container> + bool operator<=(const stack<T, Container>& x, + const stack<T, Container>& 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 <boris@kolpackov.net> +// 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 <cult/types.hxx> + +#include <cult/containers/iterator.hxx> + +#include <vector> + +namespace Cult +{ + namespace Containers + { + template <typename T> + class Vector: public std::vector<T> + { + typedef std::vector<T> 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<typename Base::iterator> + Iterator; + + typedef + IteratorAdapter<typename Base::const_iterator> + ConstIterator; + + + typedef + IteratorAdapter<typename Base::reverse_iterator> + ReverseIterator; + + typedef + IteratorAdapter<typename Base::const_reverse_iterator> + 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 <typename InputIterator> + Vector (InputIterator first, InputIterator last) + : Base (first, last) + { + } + + Vector (Vector<Value> const& other) + : Base (other) + { + } + + Vector<Value>& + operator= (Vector<Value> 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<Value>& 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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/dr/xdr/input-stream.hxx> + +namespace Cult +{ + namespace DR + { + namespace XDR + { + InputStream:: + InputStream (Shptr<Buffer> 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<Char*> (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 <boris@kolpackov.net> +// 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 <cult/types.hxx> + +#include <cult/eh/exception.hxx> + +#include <cult/mm/buffer.hxx> + +#include <rpc/xdr.h> + +namespace Cult +{ + namespace DR + { + namespace XDR + { + struct Extraction: virtual EH::Exception {}; + + class InputStream: public NonCopyable + { + public: + InputStream (Shptr<Buffer> 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> 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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/dr/xdr/output-stream.hxx> + +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<Buffer> 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<Char*>(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<Char*> (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 <boris@kolpackov.net> +// 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 <cult/types.hxx> + +#include <cult/eh/exception.hxx> + +#include <cult/mm/buffer.hxx> + +#include <rpc/xdr.h> + +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> + 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> 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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/eh/exception.hxx> + +#include <typeinfo> + +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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +#include <exception> // 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 <boris@kolpackov.net> +# 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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +#include <cult/meta/answer.hxx> + +namespace Cult +{ + namespace Meta + { + template <typename X> + class class_p + { + //@@ g++ bug 14881 + public: + template <typename Y> static No test (...); + template <typename Y> static Yes test (Void* Y::*); + + public: + //@@ Qualification bug fixed for g++ 3.4.0. + static Boolean const r = + sizeof (class_p<X>::template test<X> (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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +#include <cult/meta/class-p.hxx> +#include <cult/meta/remove-cv.hxx> + +namespace Cult +{ + namespace Meta + { + template <typename CVX> + class polymorphic_p + { + typedef typename remove_cv<CVX>::R X; + + template <typename Y, Boolean c> + struct impl + { + static const Boolean r = false; + }; + + template <typename Y> + struct impl<Y, true> + { + //@@ 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<X, class_p<X>::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 <boris@kolpackov.net> +// 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 <typename X> + struct remove_c + { + typedef X R; + }; + + template <typename X> + struct remove_c<X const> + { + 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 <boris@kolpackov.net> +// 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 <cult/meta/remove-c.hxx> +#include <cult/meta/remove-v.hxx> + +namespace Cult +{ + namespace Meta + { + template <typename X> + struct remove_cv + { + typedef typename remove_v<typename remove_c<X>::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 <boris@kolpackov.net> +// 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 <typename X> + struct remove_v + { + typedef X R; + }; + + template <typename X> + struct remove_v<X volatile> + { + 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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> +#include <cult/sched/spin.hxx> + +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 <cult/mm/arch/generic/counter.ixx> + +#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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/sched/lock.hxx> + +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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +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 <cult/mm/arch/i386/counter.ixx> + +#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 <boris@kolpackov.net> +// 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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +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 <cult/mm/arch/i386/i486/i586/i686/x86_64/counter.ixx> + +#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 <boris@kolpackov.net> +// 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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +#include <cult/meta/answer.hxx> + +#include <cult/mm/counter.hxx> +#include <cult/mm/exception.hxx> + +#include <cassert> // assert + +namespace Cult +{ + namespace MM + { + + //@@ Should be in mm/evptr.hxx + // + struct Clone: virtual Exception {}; + + template <typename X> + class Evptr; + + namespace Bits + { + template <typename x, Evptr<x> (x::*f) () const = &x::clone> + struct Helper; + + //@@ Should be generalized and moved to Cult::meta + // + template <typename X> + struct has_clone + { + template <typename y> + static Meta::Yes + test (Helper<y>*); + + template <typename> + static Meta::No + test (...); + + static Boolean const r = sizeof (test<X> (0)) == sizeof (Meta::Yes); + }; + + //@@ Need to incorporate tests for polymorpism and NonCopyable. + // + + template <typename X, Boolean = has_clone<X>::r> + struct Cloner; + + template <typename X> + struct Cloner<X, true> + { + static X* + clone (X const* cp) + { + return cp->clone ().release (); + } + }; + + template <typename X> + struct Cloner<X, false> + { + static X* + clone (X const*) + { + throw MM::Clone (); + } + }; + } + + namespace Bits + { + template <typename X> + class Transfer; + } + + namespace Bits + { + template <typename X> + 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<X*> (cp_); + cp_ = 0; + } + else + { + assert (cp_ != 0); + + //p_ = cp_->clone ().release (); + + p_ = Cloner<X>::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 <typename> + friend class Evptr; + + template <typename> + friend class Transfer; + + mutable X* p_; + mutable X const* cp_; + mutable Counter* c_; + }; + + + template <typename X> + class EvptrBase<X const> + { + 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 <typename> + friend class Evptr; + + template <typename> + friend class Transfer; + + mutable X const* p_; + mutable X const* cp_; + mutable Counter* c_; + }; + } + + namespace Bits + { + template <typename X> + class Transfer : protected EvptrBase<X> + { + public: + Transfer (Transfer<X> const& ct) + : EvptrBase<X> (ct.p_, ct.cp_, ct.c_, false) + { + Transfer<X>& t (const_cast<Transfer<X>&> (ct)); + + t.c_ = 0; + t.p_ = 0; + t.cp_ = 0; + } + + private: + Transfer (X* p, X const* cp, Counter* c) + : EvptrBase<X> (p, cp, c, false) + { + } + + template <typename> + friend class Evptr; + + private: + Transfer<X>& + operator= (Transfer<X> 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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +#include <cult/mm/counter.hxx> +#include <cult/mm/exception.hxx> + +namespace Cult +{ + namespace MM + { + namespace Bits + { + template <typename X> + 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<typename y> + Void + assign (Shptr<y> 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 <typename> + 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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/mm/buffer.hxx> + +#include <cstdlib> // malloc, realloc, free +#include <cstring> // 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<Char const*> (b_); + } + + Char* Buffer:: + data () + { + return reinterpret_cast<Char*> (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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +#include <cult/mm/exception.hxx> + +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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/mm/counter.hxx> + +namespace Cult +{ + namespace MM + { + StaticPtr<Key<Counter> > 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 <boris@kolpackov.net> +// 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 <cult/mm/arch/counter.hxx> + +#else + +// Single-threaded version. +// + +#include <cult/types/fundamental.hxx> + +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 <cult/mm/counter.ixx> + +#endif // CULT_THREADS + + +#include <cult/mm/new.hxx> +#include <cult/mm/static-ptr.hxx> + +namespace Cult +{ + namespace MM + { + extern StaticPtr<Key<Counter> > counted; + + + // Non-member inc_ref. Especially useful for messing with `this'. + // + template <typename X> + 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 <boris@kolpackov.net> +// 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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +#include <cult/mm/exception.hxx> +#include <cult/mm/bits/evptr.hxx> + +#include <typeinfo> //@@ tmp + +namespace Cult +{ + namespace MM + { + // Leaks resource should dec_ref fail. + // + template <typename X> + class Evptr: public Bits::EvptrBase<X> + { + typedef Bits::EvptrBase<X> 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 <typename Y> + Evptr (Bits::Transfer<Y> const& ct) + : Base (ct.p_, ct.cp_, ct.c_, false) + { + Bits::Transfer<Y>& t (const_cast<Bits::Transfer<Y>&> (ct)); + + t.c_ = 0; + t.p_ = 0; + t.cp_ = 0; + } + + template <typename Y> + Evptr (Evptr<Y> 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 <typename Y> + Evptr (Evptr<Y const> 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 <typename Y> + Evptr& + operator= (Evptr<Y> const& ep) + { + this->assign (ep.cp_ ? ep.cp_ : ep.p_, ep.c_); + + return *this; + } + + template <typename Y> + Evptr& + operator= (Bits::Transfer<Y> const& ct) + { + Bits::Transfer<Y>& t (const_cast<Bits::Transfer<Y>&> (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<X> + operator~ () + { + Counter* c (c_); + X* p (p_); + X const* cp (cp_); + + c_ = 0; + p_ = 0; + cp_ = 0; + + return Bits::Transfer<X> (p, cp, c); + } + + public: + using Base::p_; + using Base::cp_; + using Base::c_; + + // Object pointed to by this becomes null. + // + template<typename Y> + Evptr<Y> + s_cast () + { + if (p_) + { + Counter* c (c_); + Y* p (static_cast<Y*> (p_)); + + + c_ = 0; + p_ = 0; + cp_ = 0; + + return Evptr<Y> (p, 0, c); + } + else + { + Counter* c (c_); + Y const* cp (static_cast<Y const*> (cp_)); + + c_ = 0; + p_ = 0; + cp_ = 0; + + return Evptr<Y> (0, cp, c); + } + } + + // Object pointed to by this becomes null if dynamic_cast succeeds. + // + template<typename Y> + Evptr<Y> + d_cast () + { + if (p_) + { + if (Y* p = dynamic_cast<Y*> (p_)) + { + Counter* c (c_); + + c_ = 0; + p_ = 0; + cp_ = 0; + + return Evptr<Y> (p, 0, c); + } + } + else if (Y const* cp = dynamic_cast<Y const*> (cp_)) + { + Counter* c (c_); + + c_ = 0; + p_ = 0; + cp_ = 0; + + return Evptr<Y> (0, cp, c); + } + + return Evptr<Y> (0); + } + + + private: + Evptr (X* p, X const* cp, Counter* c) // for *_cast + : Base (p, cp, c, false) + { + } + + private: + template <typename> + 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 <boris@kolpackov.net> +// 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 <cult/eh/exception.hxx> + +#include <new> // 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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/mm/new.hxx> +#include <cult/mm/counter.hxx> + +#include <cstdlib> // std::malloc, std::free + +#include <cult/trace/stream.hxx> + +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<Char*> ( + std::malloc (size + zone_size + map_size))); + + Char* base (block + zone_size + map_size); + + Offset* map (reinterpret_cast<Offset*> (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<Char*> (p)); + + Offset* map (reinterpret_cast<Offset*> (base) - 1); // Map bottom. + + Char* block (reinterpret_cast<Char*> (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<MM::Bits::Block&> (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<MM::Bits::Block&> (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 <boris@kolpackov.net> +// 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 <cult/config.hxx> + +#include <cult/types/fundamental.hxx> + +#include <cult/mm/exception.hxx> + +#include <cult/meta/polymorphic-p.hxx> + +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 <typename X> + 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<X*> (p)->~X (); + } + }; + + + struct Absent : virtual Exception {}; + + + namespace Bits + { + Void* + locate (Void const* p, KeyBase const& k) throw (Absent); + + template <typename X, Boolean poly = Meta::polymorphic_p<X>::r> + struct Locator; + + template <typename X> + struct Locator<X, false> + { + static Void* + locate (X* p, KeyBase const& k) throw (Absent) + { + return Bits::locate (p, k); + } + }; + + template <typename X> + struct Locator<X, true> + { + static Void* + locate (X* p, KeyBase const& k) throw (Absent) + { + return Bits::locate (dynamic_cast<Void const*> (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 <typename X, typename Y> + inline + Y* + locate (X* p, Key<Y> const& k) throw (Absent) + { + return p ? reinterpret_cast<Y*> (Bits::Locator<X>::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<Char*> (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 <cult/mm/new.ixx> + +#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 <boris@kolpackov.net> +// 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<Char*> (const_cast<Void*> (p))); + + Offset* map (reinterpret_cast<Offset*> (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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +#include <cult/mm/exception.hxx> +#include <cult/mm/bits/shptr.hxx> + +namespace Cult +{ + namespace MM + { + // Leaks resource should dec_ref fail. + // + template <typename X> + class Shptr : public Bits::Shptr<X> + { + typedef Bits::Shptr<X> Base; + + public: + Shptr (X* p = 0) + : Base (p, locate (p, *counted), false) + { + } + + Shptr (Shptr const& ap) + : Base (ap.p_, ap.c_) + { + } + + template <typename Y> + Shptr (Shptr<Y> 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 <typename Y> + Shptr& + operator= (Shptr<Y> 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<X>::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<typename Y> + Shptr<Y> + d_cast () const + { + Y* p (dynamic_cast<Y*> (p_)); + return Shptr<Y> (p, p ? c_ : 0); + } + + private: + Shptr (X* p, Counter* c) + : Base (p, c) + { + } + + template <typename> + 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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +#include <cult/mm/new.hxx> // operator new + +namespace Cult +{ + namespace MM + { + namespace Bits + { + struct Default {}; + } + + template <typename X, typename Id = Bits::Default> + 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 <typename X, typename Id> + X* StaticPtr<X, Id>::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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/os/exception.hxx> + +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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +#include <cult/eh/exception.hxx> + +#include <errno.h> + +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 <boris@kolpackov.Net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/os/net/address.hxx> + +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 <boris@kolpackov.Net> +// 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 <cult/types.hxx> + +#include <cult/os/exception.hxx> + +#include <sys/socket.h> // 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 <boris@kolpackov.Net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/os/net/datagram-socket.hxx> + +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 <boris@kolpackov.Net> +// 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 <cult/types.hxx> + +#include <cult/os/net/address.hxx> +#include <cult/os/net/socket.hxx> + +#include <sys/socket.h> // 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 <boris@kolpackov.Net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/os/net/ipv4/address.hxx> + +#include <ostream> + +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 <boris@kolpackov.Net> +// 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 <cult/types.hxx> + +#include <cult/os/net/address.hxx> + +#include <netinet/in.h> // IPv4 types (sockaddr_in, etc) +#include <arpa/inet.h> // hto{n,h}{s,l}, iNet_pton + +#include <iosfwd> +#include <cstring> // 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<sockaddr const*> (&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 <boris@kolpackov.Net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/os/net/ipv4/datagram-socket.hxx> + +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 <boris@kolpackov.Net> +// 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 <cult/types.hxx> + +#include <cult/os/net/address.hxx> +#include <cult/os/net/datagram-socket.hxx> +#include <cult/os/net/ipv4/address.hxx> + +#include <unistd.h> // close +#include <sys/socket.h> // 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<Size> (r); + } + + Void + recv_buffer_size (Size size) + { + Int r (static_cast<Int> (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<Size> (r); + } + + void + send_buffer_size (Size size) + { + Int r (static_cast<Int> (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<sockaddr*> (&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<Address const&> (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<Size> (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<Size> (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<sockaddr*> (&raw_addr), + &raw_size)); + + if (n == -1) + throw Exception (); + + addr = Address (raw_addr); + + return static_cast<Size> (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<sockaddr*> (&raw_addr), + &raw_size)); + + if (n == -1) + throw Exception (); + + addr = Address (raw_addr); + + return static_cast<Size> (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 <boris@kolpackov.Net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/os/net/ipv4/multicast-socket.hxx> + +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 <boris@kolpackov.Net> +// 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 <cult/types.hxx> + +#include <cult/os/net/address.hxx> +#include <cult/os/net/multicast-socket.hxx> +#include <cult/os/net/ipv4/address.hxx> +#include <cult/os/net/ipv4/datagram-socket.hxx> + +#include <cstring> // memcpy +#include <sys/socket.h> // bind, setsockopt +#include <arpa/inet.h> // 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<unsigned char> (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<Address const&> (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 <boris@kolpackov.Net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/os/net/multicast-socket.hxx> + +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 <boris@kolpackov.Net> +// 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 <cult/types.hxx> + +#include <cult/os/net/address.hxx> +#include <cult/os/net/datagram-socket.hxx> + +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 <boris@kolpackov.Net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/os/net/socket.hxx> + +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 <boris@kolpackov.Net> +// 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 <cult/types.hxx> +#include <cult/os/exception.hxx> + +#include <sys/socket.h> // 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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +#include <typeinfo> // std::type_info + +namespace Cult +{ + namespace RTTI + { + class TypeId + { + public: + template<typename X> + 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 <cult/rtti/type-id.ixx> +#include <cult/rtti/type-id.txx> + +#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 <boris@kolpackov.net> +// 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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace RTTI + { + template <typename X> + 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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/rtti/type-info.hxx> + +#include <cult/mm/static-ptr.hxx> + +#include <cult/containers/map.hxx> + +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<TypeId, TypeInfo> + TypeInfoMap; + + static MM::StaticPtr<TypeInfoMap> 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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +#include <cult/rtti/type-id.hxx> + +#include <cult/containers/vector.hxx> + +#include <typeinfo> // 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<BaseInfo> 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<typename X> + TypeInfo const& + lookup (X const& x) + { + return lookup (typeid (x)); + } + + template<typename X> + TypeInfo const& + lookup () + { + return lookup (typeid (X)); + } + + Void + insert (TypeInfo const&); + } +} + +#include <cult/rtti/type-info.ixx> + +#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 <boris@kolpackov.net> +// 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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/sched/condition.hxx> +#include <cult/sched/exception.hxx> + +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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +#include <cult/sched/mutex.hxx> + +#include <pthread.h> + +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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +#include <cult/eh/exception.hxx> +#include <cult/os/exception.hxx> + +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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/sched/lock.hxx> + +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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +namespace Cult +{ + namespace Sched + { + class Lock: public NonCopyable + { + public: + ~Lock () + { + unlock (); + } + + template <typename X> + Lock (X& x) + : x_ (reinterpret_cast<Void*>(&x)), + unlock_ (&unlock<X>), + locked_ (true) + { + x.lock (); + } + + Void + unlock () + { + if (locked_) + { + unlock_ (x_); + locked_ = false; + } + } + + private: + template <typename X> + static Void + unlock (Void* p) + { + reinterpret_cast<X*> (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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/sched/mutex.hxx> +#include <cult/sched/exception.hxx> + +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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +#include <pthread.h> + +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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/sched/spin.hxx> +#include <cult/sched/exception.hxx> + +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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +#include <pthread.h> + +namespace Cult +{ + namespace Sched + { + class Spin: public NonCopyable + { + public: + ~Spin (); + + Spin (); + + Void + lock (); + + Boolean + try_lock (); + + Void + unlock (); + + private: + pthread_spinlock_t spin_; + }; + } +} + +#include <cult/sched/spin.ixx> + +#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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/sched/exception.hxx> + +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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/sched/thread.hxx> +#include <cult/sched/lock.hxx> +#include <cult/sched/exception.hxx> + +#include <cult/mm/counter.hxx> // MM::inc_ref + +#include <cult/trace/stream.hxx> + +namespace Cult +{ + namespace Sched + { + namespace + { + Trace::Stream tout ("Cult::Sched::Thread", 7); + } + + namespace Bits + { + typedef Void* (*Routine) (Void*); + + struct StartData + { + StartData (Shptr<Thread> const& thread, Routine routine, void* arg) + : thread_ (thread), routine_ (routine), arg_ (arg) + { + } + + ~StartData () + { + tout << 8 << "start data is being destroyed."; + } + + Shptr<Thread> 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<Thread> self (reinterpret_cast<Thread*> (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<StartData> data (reinterpret_cast<StartData*> (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<Thread> self (MM::inc_ref (this)); + + Shptr<StartData> 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<Thread> 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> Thread:: + self () + { + Thread* p (reinterpret_cast<Thread*> (pthread_getspecific (Bits::key))); + + if (p != 0) + return Shptr<Thread> (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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> +#include <cult/types/shptr.hxx> + +#include <cult/sched/mutex.hxx> +#include <cult/sched/exception.hxx> + +#include <cult/mm/new.hxx> + +#include <pthread.h> + +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<Thread> + 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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/trace/log.hxx> + +#include <iostream> + +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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +#include <cult/trace/record.hxx> + +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 <cult/trace/log.ixx> + +#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 <boris@kolpackov.net> +// 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 <boris@kolpackov.net> +// 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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace Trace + { + template <typename T> + 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 <boris@kolpackov.net> +// 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<Stream::Mediator&> (mc)); + // m.r_.level (level); + return m.r_; + } + + inline + Record& + operator<< (Stream::Mediator const& mc, Char const* s) + { + return const_cast<Stream::Mediator&> (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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace Trace + { + template <typename T> + inline + Record& + operator<< (Stream::Mediator const& mc, T const&) + { + return const_cast<stream::mediator&> (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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +#include <cstring> // memset +#include <ostream> +#include <streambuf> + +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 <typename T> + 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 <cult/trace/record.ixx> +#include <cult/trace/record.txx> + +#else + +#include <cult/trace/null/record.ixx> +#include <cult/trace/null/record.txx> + +#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 <boris@kolpackov.net> +// 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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace Trace + { + template <typename T> + 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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> + +#include <cult/trace/log.hxx> +#include <cult/trace/record.hxx> + +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 <typename T> + friend Record& + operator<< (Mediator const&, T const& arg); + + private: + Char const* id_; + Int level_; + Log& log_; + }; + } +} + +#ifndef CULT_TRACE_NULL + +#include <cult/trace/stream.ixx> +#include <cult/trace/stream.txx> + +#else + +#include <cult/trace/null/stream.ixx> +#include <cult/trace/null/stream.txx> + +#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 <boris@kolpackov.net> +// 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<Stream::Mediator&> (mc)); + m.r_.level (level); + return m.r_; + } + + inline + Record& + operator<< (Stream::Mediator const& mc, Char const* s) + { + Stream::Mediator& m (const_cast<Stream::Mediator&> (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 <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace Cult +{ + namespace Trace + { + template <typename T> + inline + Record& + operator<< (Stream::Mediator const& mc, T const& arg) + { + Stream::Mediator& m (const_cast<Stream::Mediator&> (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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> +#include <cult/types/string.hxx> +#include <cult/types/evptr.hxx> +#include <cult/types/shptr.hxx> + +#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 <boris@kolpackov.net> +// 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 <cult/mm/evptr.hxx> + +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 <boris@kolpackov.net> +// 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 <cstddef> // 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 <boris@kolpackov.net> +// 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 <cult/mm/shptr.hxx> + +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 <boris@kolpackov.net> +// 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 <cult/types/fundamental.hxx> +#include <cult/eh/exception.hxx> + +//@@ Dependency on 'containers'. Maybe move iterator to 'types'? +// +#include <cult/containers/iterator.hxx> + +#include <string> +#include <cstdlib> // mbstowcs + +namespace Cult +{ + namespace Types + { + //@@ Maybe create StringFwd.hxx + // + + namespace Bits + { + struct None {}; + + template <typename C> + struct NarrowerChar + { + typedef None Type; + }; + + + template <> + struct NarrowerChar<WideChar> + { + typedef Char Type; + }; + } + + template <typename C, + typename NarrowerChar = typename Bits::NarrowerChar<C>::Type> + class StringTemplate; + + template <> + class StringTemplate<Bits::None, Bits::None> + { + }; + + + template <typename C, typename NarrowerChar> + class StringTemplate : public std::basic_string<C> + { + typedef std::basic_string<C> Base; + typedef std::basic_string<NarrowerChar> 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<typename Base::iterator> + Iterator; + + typedef + Containers::IteratorAdapter<typename Base::const_iterator> + ConstIterator; + + + typedef + Containers::IteratorAdapter<typename Base::reverse_iterator> + ReverseIterator; + + typedef + Containers::IteratorAdapter<typename Base::const_reverse_iterator> + 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 <typename InputIterator> + 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<NarrowerChar> 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<NarrowerChar> + 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<typename C> + StringTemplate<C> + operator+ (StringTemplate<C> const& lhs, StringTemplate<C> const& rhs) + { + return StringTemplate<C> (lhs) += rhs; + } + + template<typename C> + StringTemplate<C> + operator+ (C const* lhs, StringTemplate<C> const& rhs) + { + return StringTemplate<C> (lhs) += rhs; + } + + template<typename C> + StringTemplate<C> + operator+ (StringTemplate<C> const& lhs, C const* rhs) + { + return StringTemplate<C> (lhs) += rhs; + } + + template<typename C> + StringTemplate<C> + operator+ (C lhs, StringTemplate<C> const& rhs) + { + return StringTemplate<C> (1, lhs) += rhs; + } + + + template<typename C> + StringTemplate<C> + operator+ (StringTemplate<C> const& lhs, C rhs) + { + return StringTemplate<C> (lhs) += rhs; + } + + // + // + typedef StringTemplate<Char> String; + typedef StringTemplate<Char> NarrowString; + typedef StringTemplate<WideChar> WideString; + + // Specialization for Char to WideChar conversion. + // + template <> + inline Void StringTemplate<WideChar, Char>:: + 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<WideChar*> (data ())); + + std::mbstowcs (p, s, size); + } + + // Specialization for WideChar to Char conversion. + // + template <> + inline StringTemplate<Char> StringTemplate<WideChar, Char>:: + to_narrow () const + { + Size size (std::wcstombs (0, c_str (), 0)); + + if (size == Size (-1)) + throw NonRepresentable (); + + // I dare to change the guts! + // + StringTemplate<Char> r; + r.resize (size); + + Char* p (const_cast<Char*> (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 diff --git a/libcult/documentation/BUGS b/libcult/documentation/BUGS new file mode 100644 index 0000000..139597f --- /dev/null +++ b/libcult/documentation/BUGS @@ -0,0 +1,2 @@ + + diff --git a/libcult/documentation/CORE b/libcult/documentation/CORE new file mode 100644 index 0000000..76e1a69 --- /dev/null +++ b/libcult/documentation/CORE @@ -0,0 +1,14 @@ +* types + +* eh + +* trace + +* mm -> eh, sched + +* meta + +* rtti -> containers!! + +* sched -> eh, mm + diff --git a/libcult/documentation/DESIGN b/libcult/documentation/DESIGN new file mode 100644 index 0000000..6d469a5 --- /dev/null +++ b/libcult/documentation/DESIGN @@ -0,0 +1,12 @@ + +@@ First layer include language usage policies (e.g. namespaces, eh) + and base libraries: + + eh, threading, memory management, tracing, containers + +@@ Tracing in libraries? Is it possible? + + + + +
\ No newline at end of file diff --git a/libcult/documentation/DOC b/libcult/documentation/DOC new file mode 100644 index 0000000..a593886 --- /dev/null +++ b/libcult/documentation/DOC @@ -0,0 +1 @@ +@@ Update README, NEWS and INSTALL (from index.xhtml) diff --git a/libcult/documentation/NOTES b/libcult/documentation/NOTES new file mode 100644 index 0000000..81b48e5 --- /dev/null +++ b/libcult/documentation/NOTES @@ -0,0 +1,3 @@ +@@ SUS dlsym has some ideas about symbol interpositions. + This could be relevant to the problem of calling orginal + operator new. diff --git a/libcult/documentation/RELEASE b/libcult/documentation/RELEASE new file mode 100644 index 0000000..3a7f1ab --- /dev/null +++ b/libcult/documentation/RELEASE @@ -0,0 +1 @@ +@@ copyright diff --git a/libcult/documentation/THOGHTS b/libcult/documentation/THOGHTS new file mode 100644 index 0000000..7bf1767 --- /dev/null +++ b/libcult/documentation/THOGHTS @@ -0,0 +1 @@ +@@ Access local resources the same way you access remote resources. diff --git a/libcult/documentation/TODO b/libcult/documentation/TODO new file mode 100644 index 0000000..a35515b --- /dev/null +++ b/libcult/documentation/TODO @@ -0,0 +1,3 @@ +@@ installation + +@@ Add short description for each example.
\ No newline at end of file diff --git a/libcult/documentation/TODO-CLI b/libcult/documentation/TODO-CLI new file mode 100644 index 0000000..242c0da --- /dev/null +++ b/libcult/documentation/TODO-CLI @@ -0,0 +1,7 @@ +@@ I should not assume that Utility::CommandLine is the only mechanism + used to parse command line. Application developer may be using + different components that employ different command line parsers. + Thus it seem to me that I should use argv/argc as input/output + format. + +@@ Notion of a default command (e.g., a& --help). diff --git a/libcult/documentation/TODO-EH b/libcult/documentation/TODO-EH new file mode 100644 index 0000000..ed7c133 --- /dev/null +++ b/libcult/documentation/TODO-EH @@ -0,0 +1,5 @@ +@@ Since there is only one header in eh maybe I should just make it + top-level eh.hxx? One disadvantage of this is that I will have to + qualify it with cult::exception when I inherit class-specific + exception base (maybe it is not too bad actually). +
\ No newline at end of file diff --git a/libcult/documentation/TODO-META b/libcult/documentation/TODO-META new file mode 100644 index 0000000..21eabd5 --- /dev/null +++ b/libcult/documentation/TODO-META @@ -0,0 +1,2 @@ + +@@ Move meta tests from other places to meta/. diff --git a/libcult/documentation/TODO-MM b/libcult/documentation/TODO-MM new file mode 100644 index 0000000..7979d15 --- /dev/null +++ b/libcult/documentation/TODO-MM @@ -0,0 +1,3 @@ +@@ new with arbitrary alignment + +%% Does not work if thread is not the most derived type. See 12.7.5. diff --git a/libcult/documentation/TODO-SCHED b/libcult/documentation/TODO-SCHED new file mode 100644 index 0000000..eeea3bb --- /dev/null +++ b/libcult/documentation/TODO-SCHED @@ -0,0 +1,12 @@ +@@ typedef std::thread_cancel in cult::os::sched? + +@@ maybe define USE_CXX_UNWIND or something in pthread.h + so I can detect that? + +@@ rename auto_lock to lock? + +@@ maybe add sched::exception: os::exception i.e., "scheduling exception"? + +@@ I am throwing exceptions in sched::thread that are not derived from + sched::exception. +
\ No newline at end of file diff --git a/libcult/documentation/cli/index.xhtml b/libcult/documentation/cli/index.xhtml new file mode 100644 index 0000000..9c3f1a8 --- /dev/null +++ b/libcult/documentation/cli/index.xhtml @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> + +<!-- + +file : documentation/cli/index.xhtml +author : Boris Kolpackov <boris@kolpackov.net> +copyright : Copyright (c) 2005-2010 Boris Kolpackov +license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt + +--> + +<head> + + <title>libcult/documentation/cli</title> + + <meta name="author" content="Boris Kolpackov"/> + <meta name="copyright" content="© 2005-2010 Boris Kolpackov"/> + <meta name="keywords" content="libcult,c++,command,line,interface,option,argument"/> + <meta name="description" content="libcult/documentation/cli"/> + + <link rel="stylesheet" type="text/css" href="../default.css"/> + +</head> + +<body> + +<div id="navigation"> +<p> +<a href="../.."><code>libcult</code></a> <code>/</code> +<a href=".."><code>documentation</code></a> <code>/</code> +<code>cli</code> +</p> +</div> + +<div id="content"> +<p>The <em>libcult</em> command line interace library provides +mechanisms for extracting informtaion from the command line. The +following code fragment is from <code>libcult/examples/cli</code>:</p> + +<pre class="cxx"> +namespace +{ + extern Char const help[] = "help"; + extern Char const version[] = "version"; + extern Char const outdir[] = "outdir"; +} + +typedef +CLI::Options<help, Boolean, + version, Boolean, + outdir, String> +Options; + +Int +main (Int argc, Char* argv[]) +{ + try + { + Options options (CLI::parse<Options> (argc, argv)); + + if (options.value<help> ()) + { + cerr << "usage: " << argv[0] << " [--help] [--version] [--outdir <dir>]" + << endl; + return 0; + } + + if (options.value<version> ()) + { + cerr << argv[0] << " 1.2.3" << endl; + return 0; + } + + if (String dir = options.value<outdir> ()) + { + cerr << "outdir: " << dir << endl; + } + } + catch (CLI::UnexpectedOption const& e) + { + cerr << "unexpected option " << e.option () <<endl; + } + catch (CLI::OptionFormat const& e) + { + cerr << "bad format for " << e.option () << endl; + } +} +</pre> +</div> + +<div id="docinfo"> +<p>Copyright © 2005-2010 <a title="Boris Kolpackov" +href="http://kolpackov.net">Boris Kolpackov</a>.</p> + +<div class="terms"> +Permission is granted to copy, distribute and/or modify this document under +the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free +Documentation License, version 1.2</a>; with no Invariant Sections, no +Front-Cover Texts and no Back-Cover Texts. +</div> +</div> + +</body> +</html> diff --git a/libcult/documentation/default.css b/libcult/documentation/default.css new file mode 100644 index 0000000..7242a94 --- /dev/null +++ b/libcult/documentation/default.css @@ -0,0 +1,160 @@ +body { + font-family : sans-serif; + font-weight : normal; + + color : black; + background : white; + + max-width : 42em; + padding : 2em 2em 2em 3em; + margin : 0 auto; +} + +h1, h2, h3, h4, h5, h6 { + font-family : sans-serif; + font-weight : 500; +} + +h1 { font-size : 170%; } +h2 { font-size : 145%; } +h3 { font-size : 125%; } +h4 { font-size : 110%; } +h5 { font-size : 106%; } +h6 { font-size : 100%; } + + +p.indent { + margin-left : 1.5em; +} + + +/* table of content */ +ul.toc li { + padding : .4em 0em 0em 0em; +} + + + +/* list of links */ +ul.menu { + list-style-type : none; +} + +ul.menu li { + padding-top : 0.3em; + padding-bottom : 0.3em; +} + + + +/* @@ I should probably use child selector here */ +/* list with multiline list-elements */ +ul.multiline li { + padding-top : 0.4em; + padding-bottom : 0.4em; +} + +ol.multiline li { + padding-top : 0.4em; + padding-bottom : 0.4em; +} + +dl.multiline dd { + padding-top : 0.4em; + padding-bottom : 0.4em; +} + +/* code */ + +code { + font-size : 114%; + font-family : monospace; +} + + +/* C++ code snippet */ +pre.cxx { + + margin-top : 0em; + margin-bottom : 2em; + + margin-left : 1em; +} + + + +/* make code snippet */ +pre.make { + + margin-top : 0em; + margin-bottom : 2em; + + margin-left : 1em; +} + + + +/* terminal output */ +pre.term { + + margin-top : 0em; + margin-bottom : 2em; + + margin-left : 1em; +} + + +/* Images */ +div.center { + text-align: center; +} + +/* Navigation. */ +#navigation { + margin-top: 1em; + border-bottom: 1px dashed #000000; +} + +#content { + margin-top: 2.5em; +} + + +/* Document info. */ +#docinfo { + margin-top: 4em; + border-top: 1px dashed #000000; + font-size: 70%; +} + +/* distribution terms */ +div.terms { + font-size : 114%; + font-family : monospace; +} + + + +/* Footnote */ + +#footnote { + margin-top: 2em; +} + +#footnote hr { + margin-left: 0; + margin-bottom: 1.5em; + width: 8em; + border-top: 1px solid #000000; + border-right: none; + border-bottom: none; + border-left: none; + +} + +#footnote p { + font-size: .91em; + text-indent: -0.8em; + padding-left: 0.8em; +} + diff --git a/libcult/documentation/dr/index.xhtml b/libcult/documentation/dr/index.xhtml new file mode 100644 index 0000000..0726adb --- /dev/null +++ b/libcult/documentation/dr/index.xhtml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> + +<!-- + +file : documentation/dr/index.xhtml +author : Boris Kolpackov <boris@kolpackov.net> +copyright : Copyright (c) 2005-2010 Boris Kolpackov +license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt + +--> + +<head> + + <title>libcult/documentation/dr</title> + + <meta name="author" content="Boris Kolpackov"/> + <meta name="copyright" content="© 2005-2010 Boris Kolpackov"/> + <meta name="keywords" content="libcult,c++,data,representation,xdr"/> + <meta name="description" content="libcult/documentation/dr"/> + + <link rel="stylesheet" type="text/css" href="../default.css"/> + +</head> + +<body> + +<div id="navigation"> +<p> +<a href="../.."><code>libcult</code></a> <code>/</code> +<a href=".."><code>documentation</code></a> <code>/</code> +<code>dr</code> +</p> +</div> + +<div id="content"> +<p>The <em>libcult</em> data representation library provides serialization +streams for reading/writing data representations. Only XDR is supported +in current version.</p> +</div> + + +<div id="docinfo"> +<p>Copyright © 2005-2010 <a title="Boris Kolpackov" +href="http://kolpackov.net">Boris Kolpackov</a>.</p> + +<div class="terms"> +Permission is granted to copy, distribute and/or modify this document under +the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free +Documentation License, version 1.2</a>; with no Invariant Sections, no +Front-Cover Texts and no Back-Cover Texts. +</div> +</div> + +</body> +</html> diff --git a/libcult/documentation/eh/index.xhtml b/libcult/documentation/eh/index.xhtml new file mode 100644 index 0000000..7847c11 --- /dev/null +++ b/libcult/documentation/eh/index.xhtml @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> + +<!-- + +file : documentation/eh/index.xhtml +author : Boris Kolpackov <boris@kolpackov.net> +copyright : Copyright (c) 2005-2010 Boris Kolpackov +license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt + +--> + +<head> + + <title>libcult/documentation/eh</title> + + <meta name="author" content="Boris Kolpackov"/> + <meta name="copyright" content="© 2005-2010 Boris Kolpackov"/> + <meta name="keywords" content="libcult,c++,exception,handling"/> + <meta name="description" content="libcult/documentation/eh"/> + + <link rel="stylesheet" type="text/css" href="../default.css"/> + +</head> + +<body> + +<div id="navigation"> +<p> +<a href="../.."><code>libcult</code></a> <code>/</code> +<a href=".."><code>documentation</code></a> <code>/</code> +<code>eh</code> +</p> +</div> + +<div id="content"> +<p>The <code>libcult</code> exception handling library defines a base +exception type to be used by the rest of <code>libcult</code>. It has +a very basic interface:</p> + +<pre class="cxx"> +namespace Cult +{ + namespace EH + { + class Exception: public virtual std::exception + { + public: + virtual char const* + what () const throw (); + }; + } +} +</pre> + +<p>It derives from <code>std::exception</code> to allow catching +all exceptions with a single handler. Default implementation of the +<code>what()</code> member function returns type-name of the exception. +</p> + +<p>Every non-trivial library in <em>libcult</em> derives its own +base exception which all library-defined exceptions inherit. This +way you can catch all exceptions from a library with one handler.</p> + +<p>Sometimes it may seem convenient to further partition (by providing +corresponding base classes) exceptions space into <em>logic</em> +exceptions (shared by all implementations) and <em>implementation</em> +exceptions. For example, if you pass an allocator illegal size 0 then +the allocator throws an exception which can be classified as a logic +exception. If, however, you passed valid size but there is not enough +memory then the allocator throws an exception which can be classified +as an implementation exception<sup><a href="#fn1">1</a></sup>.</p> + +<p>The problem with this approach lies in the fact that someone's logic +exception is someone else's implementation exception. Consider, for +instance, a buffer type that is implemented in terms of our allocator. +If the buffer happened to request a memory block of size 0 and let +the exception propagate through the interface boundaries it is no longer +a logic exception.</p> + + +<div id="footnote"> +<hr/> +<p id="fn1"><sup>1</sup> It can be argued that the +<code>NoMemory</code> exception should rather be classified +as logic. However, let's assume there are allocator implementations +that have infinite memory.</p> +</div> + +</div> + +<div id="docinfo"> +<p>Copyright © 2005-2010 <a title="Boris Kolpackov" +href="http://kolpackov.net">Boris Kolpackov</a>.</p> + +<div class="terms"> +Permission is granted to copy, distribute and/or modify this document under +the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free +Documentation License, version 1.2</a>; with no Invariant Sections, no +Front-Cover Texts and no Back-Cover Texts. +</div> +</div> + +</body> +</html> diff --git a/libcult/documentation/index.xhtml b/libcult/documentation/index.xhtml new file mode 100644 index 0000000..cc2f45d --- /dev/null +++ b/libcult/documentation/index.xhtml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> + +<!-- + +file : documentation/index.xhtml +author : Boris Kolpackov <boris@kolpackov.net> +copyright : Copyright (c) 2005-2010 Boris Kolpackov +license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt + +--> + +<head> + + <title>libcult/documentation</title> + + <meta name="author" content="Boris Kolpackov"/> + <meta name="copyright" content="© 2005-2010 Boris Kolpackov"/> + <meta name="keywords" content="c++,library"/> + <meta name="description" content="libcult/documentation"/> + + <link rel="stylesheet" type="text/css" href="default.css"/> + +</head> + +<body> + +<div id="navigation"> +<p> +<a href=".."><code>libcult</code></a> <code>/</code> +<code>documentation</code> +</p> +</div> + +<div id="content"> +<p>A number of lower-level libraries are grouped to form a core. Certain +organizational rules are relaxed for this group. For instance, libraries +from the core are allowed to have cyclic dependecies and can inject names +into the top-level namespace <code>cult</code>. Below is the list of +libraries that currently constitute the core:</p> + +<ul class="menu"> + <li><a href="eh/"><code>eh</code></a></li> + <li><a href="meta/"><code>meta</code></a></li> + <li><a href="mm/"><code>mm</code></a></li> + <li><a href="rtti/"><code>rtti</code></a></li> + <li><a href="sched/"><code>sched</code></a></li> + <li><a href="trace/"><code>trace</code></a></li> + <li><a href="types/"><code>types</code></a></li> +</ul> + +<p>The rest of the libraries normally depend on the core but not +vice-versa. Below is the list of them:</p> + +<ul class="menu"> + <li><a href="cli/"><code>cli</code></a></li> + <!--li><a href="containers/"><code>containers</code></a></li --> + <li><a href="dr/"><code>dr</code></a></li> + <li><a href="os/"><code>os</code></a></li> +</ul> +</div> + + +<div id="docinfo"> +<p>Copyright © 2005-2010 <a title="Boris Kolpackov" +href="http://kolpackov.net">Boris Kolpackov</a>.</p> + +<div class="terms"> +Permission is granted to copy, distribute and/or modify this document under +the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free +Documentation License, version 1.2</a>; with no Invariant Sections, no +Front-Cover Texts and no Back-Cover Texts. +</div> +</div> + +</body> +</html> diff --git a/libcult/documentation/meta/index.xhtml b/libcult/documentation/meta/index.xhtml new file mode 100644 index 0000000..15ae7a5 --- /dev/null +++ b/libcult/documentation/meta/index.xhtml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> + +<!-- + +file : documentation/meta/index.xhtml +author : Boris Kolpackov <boris@kolpackov.net> +copyright : Copyright (c) 2005-2010 Boris Kolpackov +license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt + +--> + +<head> + + <title>libcult/documentation/meta</title> + + <meta name="author" content="Boris Kolpackov"/> + <meta name="copyright" content="© 2005-2010 Boris Kolpackov"/> + <meta name="keywords" content="libcult,c++,meta,programming"/> + <meta name="description" content="libcult/documentation/meta"/> + + <link rel="stylesheet" type="text/css" href="../default.css"/> + +</head> + +<body> + +<div id="navigation"> +<p> +<a href="../.."><code>libcult</code></a> <code>/</code> +<a href=".."><code>documentation</code></a> <code>/</code> +<code>meta</code> +</p> +</div> + +<div id="content"> +<p>The <em>libcult</em> metaprogramming library provides a template +metaprogramming framework, tests and transformations.</p> + +<p>Tests:</p> + +<ul class="menu"> + <li><code>class_p</code></li> + <li><code>polymorphic_p</code></li> +</ul> + +<p>Transformations:</p> + +<ul class="menu"> + <li><code>remove_c</code></li> + <li><code>remove_v</code></li> + <li><code>remove_cv</code></li> +</ul> +</div> + +<div id="docinfo"> +<p>Copyright © 2005-2010 <a title="Boris Kolpackov" +href="http://kolpackov.net">Boris Kolpackov</a>.</p> + +<div class="terms"> +Permission is granted to copy, distribute and/or modify this document under +the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free +Documentation License, version 1.2</a>; with no Invariant Sections, no +Front-Cover Texts and no Back-Cover Texts. +</div> +</div> + +</body> +</html> diff --git a/libcult/documentation/mm/index.xhtml b/libcult/documentation/mm/index.xhtml new file mode 100644 index 0000000..8ed79d4 --- /dev/null +++ b/libcult/documentation/mm/index.xhtml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> + +<!-- + +file : documentation/mm/index.xhtml +author : Boris Kolpackov <boris@kolpackov.net> +copyright : Copyright (c) 2005-2010 Boris Kolpackov +license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt + +--> + +<head> + + <title>libcult/documentation/mm</title> + + <meta name="author" content="Boris Kolpackov"/> + <meta name="copyright" content="© 2005-2010 Boris Kolpackov"/> + <meta name="keywords" content="libcult,c++,memory,management"/> + <meta name="description" content="libcult/documentation/mm"/> + + <link rel="stylesheet" type="text/css" href="../default.css"/> + +</head> + +<body> + +<div id="navigation"> +<p> +<a href="../.."><code>libcult</code></a> <code>/</code> +<a href=".."><code>documentation</code></a> <code>/</code> +<code>mm</code> +</p> +</div> + +<div id="content"> +<p>The <em>libcult</em> memory management library provides +non-intrusive reference counter and a couple of smart pointers.</p> + +<p>It also overrides and overloads default memory management operators +(<code>operator new</code> and <code>operator delete</code>) to allow +special service objects (reference counter being one of them) to be +constructed in the memory block preceding the instance. This allows +transparent <em>instrumentation</em> of objects with a special +functionality like reference counting or locking.</p> + +<p>The two flavors of smart pointers are exclusive (called +<code>Evptr</code>, from <b>e</b>xclusi<b>v</b>e +<b>p</b>oin<b>t</b>e<b>r</b>) and shared (called <code>Shptr</code>, +from <b>sh</b>ared <b>p</b>oin<b>t</b>e<b>r</b>) pointers.</p> + +<p>The exclusive pointer has semantics similar to <code>std::auto_ptr</code> +(i.e., exclusive ownership of the object pointed to) except that it performs +automatic copying of the object pointed to when copied or assigned to another +exclusive pointer. Built-in copy-on-write optimization eliminates unnecessary +copying when instances of exclusive pointers are returned from functions or +stored in containers.</p> + +<p>The shared pointer has standard semantics of a reference-counting smart +pointer.</p> +</div> + +<div id="docinfo"> +<p>Copyright © 2005-2010 <a title="Boris Kolpackov" +href="http://kolpackov.net">Boris Kolpackov</a>.</p> + +<div class="terms"> +Permission is granted to copy, distribute and/or modify this document under +the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free +Documentation License, version 1.2</a>; with no Invariant Sections, no +Front-Cover Texts and no Back-Cover Texts. +</div> +</div> + +</body> +</html> diff --git a/libcult/documentation/os/index.xhtml b/libcult/documentation/os/index.xhtml new file mode 100644 index 0000000..62914fa --- /dev/null +++ b/libcult/documentation/os/index.xhtml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> + +<!-- + +file : documentation/os/index.xhtml +author : Boris Kolpackov <boris@kolpackov.net> +copyright : Copyright (c) 2005-2010 Boris Kolpackov +license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt + +--> + +<head> + + <title>libcult/documentation/os</title> + + <meta name="author" content="Boris Kolpackov"/> + <meta name="copyright" content="© 2005-2010 Boris Kolpackov"/> + <meta name="keywords" content="libcult,os,net"/> + <meta name="description" content="libcult/documentation/os"/> + + <link rel="stylesheet" type="text/css" href="../default.css"/> + +</head> + +<body> + +<div id="navigation"> +<p> +<a href="../.."><code>libcult</code></a> <code>/</code> +<a href=".."><code>documentation</code></a> <code>/</code> +<code>os</code> +</p> +</div> + +<div id="content"> +<p>The <em>libcult</em> operating system library provides an object-oriented +interface to the OS primitives as defined by the Single +UNIX Specification. Only basic networking is supported in this +version.</p> +</div> + +<div id="docinfo"> +<p>Copyright © 2005-2010 <a title="Boris Kolpackov" +href="http://kolpackov.net">Boris Kolpackov</a>.</p> + +<div class="terms"> +Permission is granted to copy, distribute and/or modify this document under +the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free +Documentation License, version 1.2</a>; with no Invariant Sections, no +Front-Cover Texts and no Back-Cover Texts. +</div> +</div> + +</body> +</html> diff --git a/libcult/documentation/rtti/index.xhtml b/libcult/documentation/rtti/index.xhtml new file mode 100644 index 0000000..ff3238c --- /dev/null +++ b/libcult/documentation/rtti/index.xhtml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> + +<!-- + +file : documentation/rtti/index.xhtml +author : Boris Kolpackov <boris@kolpackov.net> +copyright : Copyright (c) 2005-2010 Boris Kolpackov +license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt + +--> + +<head> + + <title>libcult/documentation/rtti</title> + + <meta name="author" content="Boris Kolpackov"/> + <meta name="copyright" content="© 2005-2010 Boris Kolpackov"/> + <meta name="keywords" content="libcult,c++,rtti,run-time,type,information"/> + <meta name="description" content="libcult/documentation/rtti"/> + + <link rel="stylesheet" type="text/css" href="../default.css"/> + +</head> + +<body> + +<div id="navigation"> +<p> +<a href="../.."><code>libcult</code></a> <code>/</code> +<a href=".."><code>documentation</code></a> <code>/</code> +<code>rtti</code> +</p> +</div> + +<div id="content"> +<p>The <em>libcult</em> run-time type information (rtti) library provides +a convenience wrapper around <code>std::type_info</code> as well as +facilities for optional extended type information (e.g., inheritance +graph).</p> +</div> + +<div id="docinfo"> +<p>Copyright © 2005-2010 <a title="Boris Kolpackov" +href="http://kolpackov.net">Boris Kolpackov</a>.</p> + +<div class="terms"> +Permission is granted to copy, distribute and/or modify this document under +the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free +Documentation License, version 1.2</a>; with no Invariant Sections, no +Front-Cover Texts and no Back-Cover Texts. +</div> +</div> + +</body> +</html> diff --git a/libcult/documentation/sched/index.xhtml b/libcult/documentation/sched/index.xhtml new file mode 100644 index 0000000..b685471 --- /dev/null +++ b/libcult/documentation/sched/index.xhtml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> + +<!-- + +file : documentation/sched/index.xhtml +author : Boris Kolpackov <boris@kolpackov.net> +copyright : Copyright (c) 2005-2010 Boris Kolpackov +license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt + +--> + +<head> + + <title>libcult/documentation/sched</title> + + <meta name="author" content="Boris Kolpackov"/> + <meta name="copyright" content="© 2005-2010 Boris Kolpackov"/> + <meta name="keywords" content="libcult,c++,scheduling,thread,lock,mutex"/> + <meta name="description" content="libcult/documentation/sched"/> + + <link rel="stylesheet" type="text/css" href="../default.css"/> + +</head> + +<body> + +<div id="navigation"> +<p> +<a href="../.."><code>libcult</code></a> <code>/</code> +<a href=".."><code>documentation</code></a> <code>/</code> +<code>sched</code> +</p> +</div> + +<div id="content"> +<p>The <em>libcult</em> scheduling library provides an object-oriented +interface to POSIX thread primitives as defined by the Single +UNIX Specification.</p> +</div> + + +<div id="docinfo"> +<p>Copyright © 2005-2010 <a title="Boris Kolpackov" +href="http://kolpackov.net">Boris Kolpackov</a>.</p> + +<div class="terms"> +Permission is granted to copy, distribute and/or modify this document under +the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free +Documentation License, version 1.2</a>; with no Invariant Sections, no +Front-Cover Texts and no Back-Cover Texts. +</div> +</div> + +</body> +</html> diff --git a/libcult/documentation/trace/index.xhtml b/libcult/documentation/trace/index.xhtml new file mode 100644 index 0000000..eb00f04 --- /dev/null +++ b/libcult/documentation/trace/index.xhtml @@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> + +<!-- + +file : documentation/trace/index.xhtml +author : Boris Kolpackov <boris@kolpackov.net> +copyright : Copyright (c) 2005-2010 Boris Kolpackov +license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt + +--> + +<head> + + <title>libcult/documentation/trace</title> + + <meta name="author" content="Boris Kolpackov"/> + <meta name="copyright" content="© 2005-2010 Boris Kolpackov"/> + <meta name="keywords" content="libcult,c++,tracing"/> + <meta name="description" content="libcult/documentation/trace"/> + + <link rel="stylesheet" type="text/css" href="../default.css"/> + +</head> + +<body> + +<div id="navigation"> +<p> +<a href="../.."><code>libcult</code></a> <code>/</code> +<a href=".."><code>documentation</code></a> <code>/</code> +<code>trace</code> +</p> +</div> + +<div id="content"> +<p>The <em>libcult</em> trace library provides a general-purpose +program tracing facility. The following code fragment can be found +in <code>libcult/examples/trace</code>:</p> + +<pre class="cxx"> +struct foo {}; + +std::ostream& +operator<< (std::ostream& o, foo const&) +{ + return o << "::foo"; +} + +namespace trace = cult::trace; + +trace::stream tout ("main", 4); + +int +main () +{ + using trace::record; + + trace::log::instance ().level (9); + + record a ("main", 2); + a << "notationally burdensome"; + tout << a; + + record b ("main", 2); + tout << (b << "a bit better, but still burdensome"); + + tout << (record ("main", 2) << "this is" + << " somewhat" + << " twisted but nice to be able to"); + + tout << "concise, using default level"; + + tout << 9 << "concise, using custom level"; + + foo f; + + tout << 3 << f << " " << 5; +} +</pre> + +<p>Along with the proper implementation, a <em>null</em> implementation is +provided which can be used to completely optimize trace code away. For details +see the <a href="http://kolpackov.net/pipermail/notes/2004-July/000010.html"> +Inlining code away</a> essay.</p> +</div> + +<div id="docinfo"> +<p>Copyright © 2005-2010 <a title="Boris Kolpackov" +href="http://kolpackov.net">Boris Kolpackov</a>.</p> + +<div class="terms"> +Permission is granted to copy, distribute and/or modify this document under +the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free +Documentation License, version 1.2</a>; with no Invariant Sections, no +Front-Cover Texts and no Back-Cover Texts. +</div> +</div> + +</body> +</html> diff --git a/libcult/documentation/types/index.xhtml b/libcult/documentation/types/index.xhtml new file mode 100644 index 0000000..07cb7db --- /dev/null +++ b/libcult/documentation/types/index.xhtml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> + +<!-- + +file : documentation/types/index.xhtml +author : Boris Kolpackov <boris@kolpackov.net> +copyright : Copyright (c) 2005-2010 Boris Kolpackov +license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt + +--> + +<head> + + <title>libcult/documentation/types</title> + + <meta name="author" content="Boris Kolpackov"/> + <meta name="copyright" content="© 2005-2010 Boris Kolpackov"/> + <meta name="keywords" content="libcult,c++,types"/> + <meta name="description" content="libcult/documentation/types"/> + + <link rel="stylesheet" type="text/css" href="../default.css"/> + +</head> + +<body> + +<div id="navigation"> +<p> +<a href="../.."><code>libcult</code></a> <code>/</code> +<a href=".."><code>documentation</code></a> <code>/</code> +<code>types</code> +</p> +</div> + +<div id="content"> +<p>The <em>libcult</em> type library provides convenience aliases +for basic c++ types (e.g., <code>wchar</code> and <code>size</code>) +as well as a set of fixed-size integer types.</p> +</div> + +<div id="docinfo"> +<p>Copyright © 2005-2010 <a title="Boris Kolpackov" +href="http://kolpackov.net">Boris Kolpackov</a>.</p> + +<div class="terms"> +Permission is granted to copy, distribute and/or modify this document under +the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free +Documentation License, version 1.2</a>; with no Invariant Sections, no +Front-Cover Texts and no Back-Cover Texts. +</div> +</div> + +</body> +</html> diff --git a/libcult/examples/cli/cli.cxx b/libcult/examples/cli/cli.cxx new file mode 100644 index 0000000..922a23d --- /dev/null +++ b/libcult/examples/cli/cli.cxx @@ -0,0 +1,65 @@ +// file : examples/cli/cli.cxx +// author : Boris Kolpackov <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/types.hxx> + +#include <cult/cli/options.hxx> +#include <cult/cli/options-spec.hxx> +#include <cult/cli/options-parser.hxx> + +#include <iostream> + +using std::cerr; +using std::endl; + +using namespace Cult; + +namespace +{ + extern Char const help[] = "help"; + extern Char const version[] = "version"; + extern Char const outdir[] = "outdir"; +} + +typedef +CLI::Options<help, Boolean, + version, Boolean, + outdir, String> +Options; + +Int +main (Int argc, Char* argv[]) +{ + try + { + Options options (CLI::parse<Options> (argc, argv)); + + if (options.value<help> ()) + { + cerr << "usage: " << argv[0] << " [--help] [--version] [--outdir <dir>]" + << endl; + return 0; + } + + if (options.value<version> ()) + { + cerr << argv[0] << " 1.2.3" << endl; + return 0; + } + + if (String dir = options.value<outdir> ()) + { + cerr << "outdir: " << dir << endl; + } + } + catch (CLI::UnexpectedOption const& e) + { + cerr << "unexpected option " << e.option () <<endl; + } + catch (CLI::OptionFormat const& e) + { + cerr << "bad format for " << e.option () << endl; + } +} diff --git a/libcult/examples/cli/makefile b/libcult/examples/cli/makefile new file mode 100644 index 0000000..004f135 --- /dev/null +++ b/libcult/examples/cli/makefile @@ -0,0 +1,48 @@ +# file : examples/cli/makefile +# author : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make + +cxx_tun := cli.cxx +cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o)) +cxx_od := $(cxx_obj:.o=.o.d) + +cult.l := $(out_root)/cult/cult.l +cult.l.cpp-options := $(out_root)/cult/cult.l.cpp-options + +cli := $(out_base)/cli +clean := $(out_base)/.clean + + +# Build. +# +$(cli): $(cxx_obj) $(cult.l) + +$(cxx_obj) $(cxx_od): $(cult.l.cpp-options) + +$(call include-dep,$(cxx_od)) + + +# Convenience alias for default target. +# +$(out_base)/: $(cli) + + +# Clean. +# +$(clean): $(cli).o.clean \ + $(addsuffix .cxx.clean,$(cxx_obj)) \ + $(addsuffix .cxx.clean,$(cxx_od)) + + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) + +# Dependencies. +# +$(call import,$(src_root)/cult/makefile) diff --git a/libcult/examples/dr/xdr/makefile b/libcult/examples/dr/xdr/makefile new file mode 100644 index 0000000..6a4fa8f --- /dev/null +++ b/libcult/examples/dr/xdr/makefile @@ -0,0 +1,49 @@ +# file : examples/dr/xdr/makefile +# author : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make + +cxx_tun := xdr.cxx +cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o)) +cxx_od := $(cxx_obj:.o=.o.d) + +cult.l := $(out_root)/cult/cult.l +cult.l.cpp-options := $(out_root)/cult/cult.l.cpp-options + +xdr := $(out_base)/xdr +clean := $(out_base)/.clean + + +# Build. +# +$(xdr): $(cxx_obj) $(cult.l) + +$(cxx_obj) $(cxx_od): $(cult.l.cpp-options) + +$(call include-dep,$(cxx_od)) + + +# Convenience alias for default target. +# +$(out_base)/: $(xdr) + + +# Clean. +# +$(clean): $(xdr).o.clean \ + $(addsuffix .cxx.clean,$(cxx_obj)) \ + $(addsuffix .cxx.clean,$(cxx_od)) + + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) + + +# Dependencies. +# +$(call import,$(src_root)/cult/makefile) diff --git a/libcult/examples/dr/xdr/xdr.cxx b/libcult/examples/dr/xdr/xdr.cxx new file mode 100644 index 0000000..38e948d --- /dev/null +++ b/libcult/examples/dr/xdr/xdr.cxx @@ -0,0 +1,87 @@ +// file : examples/dr/xdr/xdr.cxx +// author : Boris Kolpackov <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/types.hxx> + +#include <cult/dr/xdr/input-stream.hxx> +#include <cult/dr/xdr/output-stream.hxx> + +#include <iostream> + +using namespace Cult; +using namespace DR::XDR; + +using std::cerr; +using std::endl; + +Int +main () +{ + try + { + OutputStream o (8); + + o << true << false; + + UnsignedInt8 a8 (0xDE); + UnsignedInt16 a16 (0xDEAD); + UnsignedInt32 a32 (0xDEADBEEF); + UnsignedInt64 a64 (0xDEADBEEFDEADBEEFULL); + + o << a8 << a16 << a32 << a64; + + Int8 b8 (-8); + Int16 b16 (-16); + Int32 b32 (-32); + Int64 b64 (-64); + + o << b8 << b16 << b32 << b64; + + String s ("reasonably loooooooooooooong string with some junk in it"); + + o << s; + + InputStream i (o.buffer ()); + + Boolean t, f; + String s1; + + i >> t >> f; + i >> a8 >> a16 >> a32 >> a64; + i >> b8 >> b16 >> b32 >> b64; + i >> s1; + + if (!t + || f + || a8 != 0xDE + || a16 != 0xDEAD + || a32 != 0xDEADBEEF + || a64 != 0xDEADBEEFDEADBEEFULL + || b8 != -8 + || b16 != -16 + || b32 != -32 + || b64 != -64 + || s1 != s) return 1; + + try + { + i >> t; + } + catch (Extraction const&) + { + return 0; + } + } + catch (Insertion const&) + { + cerr << "insertion" << endl; + } + catch (Extraction const&) + { + cerr << "extraction" << endl; + } + + return 1; +} diff --git a/libcult/examples/makefile b/libcult/examples/makefile new file mode 100644 index 0000000..d264910 --- /dev/null +++ b/libcult/examples/makefile @@ -0,0 +1,36 @@ +# file : examples/makefile +# author : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make +include $(scf_root)/configuration.make + +default := $(out_base)/ +clean := $(out_base)/.clean + +examples := $(out_base)/cli \ + $(out_base)/mm/shptr \ + $(out_base)/mm/transfer \ + $(out_base)/trace + +ifeq ($(cult_threads),y) +examples += $(out_base)/sched/main \ + $(out_base)/sched/cancel +endif + + +ifeq ($(cult_network),y) +examples += $(out_base)/os/net/ipv4/datagram \ + $(out_base)/os/net/ipv4/multicast +endif + +ifeq ($(cult_dr),y) +examples += $(out_base)/dr/xdr +endif + + +$(default): $(addsuffix /,$(examples)) +$(clean): $(addsuffix /.clean,$(examples)) + +$(foreach e,$(subst $(out_base),$(src_base),$(examples)),$(call import,$e/makefile)) diff --git a/libcult/examples/mm/shptr/makefile b/libcult/examples/mm/shptr/makefile new file mode 100644 index 0000000..2bf1598 --- /dev/null +++ b/libcult/examples/mm/shptr/makefile @@ -0,0 +1,48 @@ +# file : examples/mm/shptr/makefile +# author : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make + +cxx_tun := shptr.cxx +cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o)) +cxx_od := $(cxx_obj:.o=.o.d) + +cult.l := $(out_root)/cult/cult.l +cult.l.cpp-options := $(out_root)/cult/cult.l.cpp-options + +shptr := $(out_base)/shptr +clean := $(out_base)/.clean + + +# Build. +# +$(shptr): $(cxx_obj) $(cult.l) + +$(cxx_obj) $(cxx_od): $(cult.l.cpp-options) + +$(call include-dep,$(cxx_od)) + + +# Convenience alias for default target. +# +$(out_base)/: $(shptr) + + +# Clean. +# +$(clean): $(shptr).o.clean \ + $(addsuffix .cxx.clean,$(cxx_obj)) \ + $(addsuffix .cxx.clean,$(cxx_od)) + + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) + +# Dependencies. +# +$(call import,$(src_root)/cult/makefile) diff --git a/libcult/examples/mm/shptr/shptr.cxx b/libcult/examples/mm/shptr/shptr.cxx new file mode 100644 index 0000000..cb026d4 --- /dev/null +++ b/libcult/examples/mm/shptr/shptr.cxx @@ -0,0 +1,73 @@ +// file : examples/mm/shptr/shptr.cxx +// author : Boris Kolpackov <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/mm/shptr.hxx> +#include <cult/mm/new.hxx> // MM::locate +#include <cult/mm/counter.hxx> // MM::inc_ref + +#include <iostream> + +using std::cerr; +using std::endl; + +using namespace Cult; +using namespace MM; + +struct Foo +{ + virtual ~Foo () {} + char c; +}; + +struct Bar: virtual Foo {char c;}; + +struct Baz: virtual Foo {char c;}; + +struct Fox: Bar, Baz {}; + + +struct A +{ + char c[8]; +}; + +struct B +{ + char c[8]; +}; + +struct C : A, B +{ + char c[8]; +}; + +int +main () +{ + { + Baz* bp (new Fox); + Foo* fp (bp); + + Counter* cp (locate (fp, *counted)); + + inc_ref (bp); + + cp->dec_ref (); + + if (cp->dec_ref ()) cerr << "good: destroying" << endl; + else cerr << "bad: leaking" << endl; + + delete bp; + } + + { + Shptr<Fox> pfox (new Fox); + Shptr<Bar> pbar (pfox); + + Shptr<Foo> pfoo; + + pfoo = pbar; + } +} diff --git a/libcult/examples/mm/transfer/makefile b/libcult/examples/mm/transfer/makefile new file mode 100644 index 0000000..3380f10 --- /dev/null +++ b/libcult/examples/mm/transfer/makefile @@ -0,0 +1,48 @@ +# file : examples/mm/transfer/makefile +# author : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make + +cxx_tun := transfer.cxx +cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o)) +cxx_od := $(cxx_obj:.o=.o.d) + +cult.l := $(out_root)/cult/cult.l +cult.l.cpp-options := $(out_root)/cult/cult.l.cpp-options + +transfer := $(out_base)/transfer +clean := $(out_base)/.clean + + +# Build. +# +$(transfer): $(cxx_obj) $(cult.l) + +$(cxx_obj) $(cxx_od): $(cult.l.cpp-options) + +$(call include-dep,$(cxx_od)) + + +# Convenience alias for default target. +# +$(out_base)/: $(transfer) + + +# Clean. +# +$(clean): $(transfer).o.clean \ + $(addsuffix .cxx.clean,$(cxx_obj)) \ + $(addsuffix .cxx.clean,$(cxx_od)) + + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) + +# Dependencies. +# +$(call import,$(src_root)/cult/makefile) diff --git a/libcult/examples/mm/transfer/transfer.cxx b/libcult/examples/mm/transfer/transfer.cxx new file mode 100644 index 0000000..81014d0 --- /dev/null +++ b/libcult/examples/mm/transfer/transfer.cxx @@ -0,0 +1,117 @@ +// file : examples/mm/transfer/transfer.cxx +// author : Boris Kolpackov <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/mm/evptr.hxx> + +#include <iostream> + +using std::cerr; +using std::endl; + +using namespace Cult; + +unsigned long count = 0; +unsigned long clone_count = 0; + +struct Type +{ + Type () + { + ++count; + } + + ~Type () + { + --count; + } + + Evptr<Type> + clone () const + { + ++clone_count; + return Evptr<Type> (new Type); + } + + Void + f () const + { + Int i = i_; + ++i; + } + + Int i_; +}; + + +Evptr<Type> +source () +{ + return Evptr<Type> (new Type); +} + +Void +sink (Evptr<Type> a, Boolean r = true) +{ + if (r) + { + sink (a, false); + } + else + { + Evptr<Type> b (a); + + cerr << "\tshare count: " << b.count () << endl; + + // Any of these will trigger cloning. + // + b->f (); + } +} + +Int +main () +{ + // case 1 + // + { + cerr << "sink (new type)" << endl; + + clone_count = 0; + sink (new Type); + + cerr << "\tclone count: " << clone_count << endl + << endl; + } + + // case 2 + // + { + cerr << "sink (source ())" << endl; + + clone_count = 0; + sink (source ()); + + cerr << "\tclone count: " << clone_count << endl + << endl; + } + + + // case 3 + // + { + cerr << "sink (p)" << endl; + + clone_count = 0; + + Evptr<Type> p (new Type); + sink (p); + + cerr << "\tclone count: " << clone_count << endl + << endl; + } + + + cerr << "balance: " << count << endl; +} diff --git a/libcult/examples/os/net/ipv4/datagram/client.cxx b/libcult/examples/os/net/ipv4/datagram/client.cxx new file mode 100644 index 0000000..863fc25 --- /dev/null +++ b/libcult/examples/os/net/ipv4/datagram/client.cxx @@ -0,0 +1,66 @@ +// file : examples/os/net/ipv4/datagram/client.cxx +// author : Boris Kolpackov <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/types.hxx> + +#include <cult/os/net/ipv4/address.hxx> +#include <cult/os/net/ipv4/datagram-socket.hxx> + +#include <iostream> +#include <unistd.h> // usleep + +#include "protocol.hxx" + +using std::cerr; +using std::endl; + +using namespace Cult; +using namespace OS::Net::IPv4; + +class Args {}; + +Int +main (Int argc, Char* argv[]) +{ + try + { + if (argc < 2) + throw Args (); + + Address addr (argv[1], 10000); + + DatagramSocket socket; + + Message msg; + msg.sn = 0; + + cerr << "message size : " << sizeof (msg) << " bytes" << endl; + cerr << "send buffer : " << socket.send_buffer_size () << " bytes" << endl; + + for (Index i = 0; i < payload_size; i++) + { + msg.payload[i] = i; + } + + for (; msg.sn < message_count; msg.sn++) + { + socket.send (&msg, sizeof (msg), addr); + + // ::usleep (10); + } + + return 0; + } + catch (OS::Exception const& e) + { + cerr << "errno: " << strerror (e.code ()) << endl; + } + catch (Args const&) + { + cerr << "usage: client <IPv4 address>" << endl; + } + + return 1; +} diff --git a/libcult/examples/os/net/ipv4/datagram/makefile b/libcult/examples/os/net/ipv4/datagram/makefile new file mode 100644 index 0000000..2dc8e1b --- /dev/null +++ b/libcult/examples/os/net/ipv4/datagram/makefile @@ -0,0 +1,55 @@ +# file : examples/os/net/ipv4/datagram/makefile +# author : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../../../build/bootstrap.make + +client_cxx_tun := client.cxx +server_cxx_tun := server.cxx + +client_cxx_obj := $(addprefix $(out_base)/,$(client_cxx_tun:.cxx=.o)) +server_cxx_obj := $(addprefix $(out_base)/,$(server_cxx_tun:.cxx=.o)) + +cxx_obj := $(client_cxx_obj) $(server_cxx_obj) +cxx_od := $(cxx_obj:.o=.o.d) + +cult.l := $(out_root)/cult/cult.l +cult.l.cpp-options := $(out_root)/cult/cult.l.cpp-options + +client := $(out_base)/client +server := $(out_base)/server +clean := $(out_base)/.clean + +# Convenience alias for default target. +# +$(out_base)/: $(client) $(server) + +# Build. +# + +$(client): $(client_cxx_obj) $(cult.l) +$(server): $(server_cxx_obj) $(cult.l) + +$(cxx_obj) $(cxx_od): $(cult.l.cpp-options) + +$(call include-dep,$(cxx_od)) + + +# Clean. +# +$(clean): $(client).o.clean \ + $(server).o.clean \ + $(addsuffix .cxx.clean,$(cxx_obj)) \ + $(addsuffix .cxx.clean,$(cxx_od)) + + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) + +# Dependencies. +# +$(call import,$(src_root)/cult/makefile) diff --git a/libcult/examples/os/net/ipv4/datagram/protocol.hxx b/libcult/examples/os/net/ipv4/datagram/protocol.hxx new file mode 100644 index 0000000..0f418e8 --- /dev/null +++ b/libcult/examples/os/net/ipv4/datagram/protocol.hxx @@ -0,0 +1,20 @@ +// file : examples/os/net/ipv4/datagram/protocol.hxx +// author : Boris Kolpackov <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef PROTOCOL_HXX +#define PROTOCOL_HXX + +#include <cult/types.hxx> + +Cult::UnsignedShort const payload_size = 256; +Cult::UnsignedLong const message_count = 100; + +struct Message +{ + Cult::UnsignedLong sn; + Cult::UnsignedShort payload[payload_size]; +}; + +#endif // PROTOCOL_HXX diff --git a/libcult/examples/os/net/ipv4/datagram/server.cxx b/libcult/examples/os/net/ipv4/datagram/server.cxx new file mode 100644 index 0000000..e788056 --- /dev/null +++ b/libcult/examples/os/net/ipv4/datagram/server.cxx @@ -0,0 +1,123 @@ +// file : examples/os/net/ipv4/datagram/server.cxx +// author : Boris Kolpackov <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/types.hxx> +#include <cult/containers/vector.hxx> + +#include <cult/os/net/ipv4/address.hxx> +#include <cult/os/net/ipv4/datagram-socket.hxx> + +#include <iostream> +#include <cstring> // memcmp + +#include "protocol.hxx" + +using std::cerr; +using std::endl; + +using namespace Cult; +using namespace OS::Net::IPv4; + +typedef Containers::Vector<Boolean> StatusList; + +Int +main () +{ + try + { + Address addr (INADDR_ANY, 10000); + + DatagramSocket socket (addr); + + Message expected_msg; + expected_msg.sn = 0; + + for (UnsignedShort i = 0; i < payload_size; ++i) + { + expected_msg.payload[i] = i; + } + + StatusList received (message_count, 0); + StatusList damaged (message_count, 0); + StatusList duplicate (message_count, 0); + + Message msg; + + while (true) + { + socket.recv (&msg, sizeof (msg)); + + if (received[msg.sn]) + { + duplicate[msg.sn] = true; + } + else + { + received[msg.sn] = true; + + if (std::memcmp (expected_msg.payload, msg.payload, payload_size) != 0) + { + damaged[msg.sn] = true; + } + } + + if (msg.sn + 1 == message_count) break; + } + + UnsignedLong lost_count (0), damaged_count (0), duplicate_count (0); + + for (StatusList::Iterator i (received.begin ()), end (received.end ()); + i != end; + ++i) + if (!*i) ++lost_count; + + for (StatusList::Iterator i (damaged.begin ()), end (damaged.end ()); + i != end; + ++i) + if (*i) ++damaged_count; + + for (StatusList::Iterator i (duplicate.begin ()), end (duplicate.end ()); + i != end; + ++i) + if (*i) ++duplicate_count; + + cerr << "lost : " << lost_count << endl + << "damaged : " << damaged_count << endl + << "duplicate : " << duplicate_count << endl << endl; + + if (lost_count != 0) + { + cerr << "lost message dump:" << endl; + + UnsignedLong total = 0; + + for (StatusList::Iterator + begin (received.begin ()), i (begin), end (received.end ()); + i != end;) + { + if (!*i) + { + UnsignedLong count = 1; + + for (StatusList::Iterator j = i + 1; j < end && !*j; j++, count++) ; + + cerr << '\t' << i - begin << " : " << count << endl; + + i += count; + total += count; + } + else + ++i; + } + + if (total != lost_count) + cerr << "trouble" << endl; + } + } + catch (OS::Exception const& e) + { + cerr << "errno: " << e.code () << endl; + } +} diff --git a/libcult/examples/os/net/ipv4/multicast/client.cxx b/libcult/examples/os/net/ipv4/multicast/client.cxx new file mode 100644 index 0000000..863fc25 --- /dev/null +++ b/libcult/examples/os/net/ipv4/multicast/client.cxx @@ -0,0 +1,66 @@ +// file : examples/os/net/ipv4/datagram/client.cxx +// author : Boris Kolpackov <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/types.hxx> + +#include <cult/os/net/ipv4/address.hxx> +#include <cult/os/net/ipv4/datagram-socket.hxx> + +#include <iostream> +#include <unistd.h> // usleep + +#include "protocol.hxx" + +using std::cerr; +using std::endl; + +using namespace Cult; +using namespace OS::Net::IPv4; + +class Args {}; + +Int +main (Int argc, Char* argv[]) +{ + try + { + if (argc < 2) + throw Args (); + + Address addr (argv[1], 10000); + + DatagramSocket socket; + + Message msg; + msg.sn = 0; + + cerr << "message size : " << sizeof (msg) << " bytes" << endl; + cerr << "send buffer : " << socket.send_buffer_size () << " bytes" << endl; + + for (Index i = 0; i < payload_size; i++) + { + msg.payload[i] = i; + } + + for (; msg.sn < message_count; msg.sn++) + { + socket.send (&msg, sizeof (msg), addr); + + // ::usleep (10); + } + + return 0; + } + catch (OS::Exception const& e) + { + cerr << "errno: " << strerror (e.code ()) << endl; + } + catch (Args const&) + { + cerr << "usage: client <IPv4 address>" << endl; + } + + return 1; +} diff --git a/libcult/examples/os/net/ipv4/multicast/makefile b/libcult/examples/os/net/ipv4/multicast/makefile new file mode 100644 index 0000000..cb35bf6 --- /dev/null +++ b/libcult/examples/os/net/ipv4/multicast/makefile @@ -0,0 +1,55 @@ +# file : examples/os/net/ipv4/multicast/makefile +# author : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../../../build/bootstrap.make + +client_cxx_tun := client.cxx +server_cxx_tun := server.cxx + +client_cxx_obj := $(addprefix $(out_base)/,$(client_cxx_tun:.cxx=.o)) +server_cxx_obj := $(addprefix $(out_base)/,$(server_cxx_tun:.cxx=.o)) + +cxx_obj := $(client_cxx_obj) $(server_cxx_obj) +cxx_od := $(cxx_obj:.o=.o.d) + +cult.l := $(out_root)/cult/cult.l +cult.l.cpp-options := $(out_root)/cult/cult.l.cpp-options + +client := $(out_base)/client +server := $(out_base)/server +clean := $(out_base)/.clean + +# Convenience alias for default target. +# +$(out_base)/: $(client) $(server) + +# Build. +# + +$(client): $(client_cxx_obj) $(cult.l) +$(server): $(server_cxx_obj) $(cult.l) + +$(cxx_obj) $(cxx_od): $(cult.l.cpp-options) + +$(call include-dep,$(cxx_od)) + + +# Clean. +# +$(clean): $(client).o.clean \ + $(server).o.clean \ + $(addsuffix .cxx.clean,$(cxx_obj)) \ + $(addsuffix .cxx.clean,$(cxx_od)) + + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) + +# Dependencies. +# +$(call import,$(src_root)/cult/makefile) diff --git a/libcult/examples/os/net/ipv4/multicast/protocol.hxx b/libcult/examples/os/net/ipv4/multicast/protocol.hxx new file mode 100644 index 0000000..a4057de --- /dev/null +++ b/libcult/examples/os/net/ipv4/multicast/protocol.hxx @@ -0,0 +1,20 @@ +// file : examples/os/net/ipv4/multicast/protocol.hxx +// author : Boris Kolpackov <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef PROTOCOL_HXX +#define PROTOCOL_HXX + +#include <cult/types.hxx> + +Cult::UnsignedShort const payload_size = 256; +Cult::UnsignedLong const message_count = 100; + +struct Message +{ + Cult::UnsignedLong sn; + Cult::UnsignedShort payload[payload_size]; +}; + +#endif // PROTOCOL_HXX diff --git a/libcult/examples/os/net/ipv4/multicast/server.cxx b/libcult/examples/os/net/ipv4/multicast/server.cxx new file mode 100644 index 0000000..5d8fe99 --- /dev/null +++ b/libcult/examples/os/net/ipv4/multicast/server.cxx @@ -0,0 +1,134 @@ +// file : examples/os/net/ipv4/datagram/server.cxx +// author : Boris Kolpackov <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/types.hxx> +#include <cult/containers/vector.hxx> + +#include <cult/os/net/ipv4/address.hxx> +#include <cult/os/net/ipv4/multicast-socket.hxx> + +#include <iostream> +#include <cstring> // memcmp + +#include "protocol.hxx" + +using std::cerr; +using std::endl; + +using namespace Cult; +using namespace OS::Net::IPv4; + +typedef Containers::Vector<Boolean> StatusList; + +class Args {}; + +Int +main (Int argc, Char* argv[]) +{ + try + { + if (argc < 2) + throw Args (); + + Address addr (argv[1], 10000); + + MulticastSocket socket; + + socket.join (addr); + + Message expected_msg; + expected_msg.sn = 0; + + for (UnsignedShort i = 0; i < payload_size; ++i) + { + expected_msg.payload[i] = i; + } + + StatusList received (message_count, 0); + StatusList damaged (message_count, 0); + StatusList duplicate (message_count, 0); + + Message msg; + + while (true) + { + socket.recv (&msg, sizeof (msg)); + + if (received[msg.sn]) + { + duplicate[msg.sn] = true; + } + else + { + received[msg.sn] = true; + + if (std::memcmp (expected_msg.payload, msg.payload, payload_size) != 0) + { + damaged[msg.sn] = true; + } + } + + if (msg.sn + 1 == message_count) break; + } + + UnsignedLong lost_count (0), damaged_count (0), duplicate_count (0); + + for (StatusList::Iterator i (received.begin ()), end (received.end ()); + i != end; + ++i) + if (!*i) ++lost_count; + + for (StatusList::Iterator i (damaged.begin ()), end (damaged.end ()); + i != end; + ++i) + if (*i) ++damaged_count; + + for (StatusList::Iterator i (duplicate.begin ()), end (duplicate.end ()); + i != end; + ++i) + if (*i) ++duplicate_count; + + cerr << "lost : " << lost_count << endl + << "damaged : " << damaged_count << endl + << "duplicate : " << duplicate_count << endl << endl; + + if (lost_count != 0) + { + cerr << "lost message dump:" << endl; + + UnsignedLong total = 0; + + for (StatusList::Iterator + begin (received.begin ()), i (begin), end (received.end ()); + i != end;) + { + if (!*i) + { + UnsignedLong count = 1; + + for (StatusList::Iterator j = i + 1; j < end && !*j; j++, count++) ; + + cerr << '\t' << i - begin << " : " << count << endl; + + i += count; + total += count; + } + else + ++i; + } + + if (total != lost_count) + cerr << "trouble" << endl; + } + } + catch (OS::Exception const& e) + { + cerr << "errno: " << e.code () << endl; + } + catch (Args const&) + { + cerr << "usage: client <IPv4 address>" << endl; + } +} diff --git a/libcult/examples/sched/cancel/cancel.cxx b/libcult/examples/sched/cancel/cancel.cxx new file mode 100644 index 0000000..ee71449 --- /dev/null +++ b/libcult/examples/sched/cancel/cancel.cxx @@ -0,0 +1,63 @@ +// file : examples/sched/cancel/cancel.cxx +// author : Boris Kolpackov <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/types.hxx> + +#include <cult/mm/shptr.hxx> + +#include <cult/sched/lock.hxx> +#include <cult/sched/mutex.hxx> +#include <cult/sched/thread.hxx> +#include <cult/sched/condition.hxx> + + +#include <iostream> +#include <unistd.h> // sleep + +using std::cerr; +using std::endl; + +using namespace Cult; +using namespace Sched; + +Void* +cond_wait_thread_proc (Void*) +{ + try + { + Mutex mutex; + Condition cond (mutex); + + Lock lock (mutex); + + cond.wait (); + } + /* + catch (std::thread_canceled const& e) + { + cerr << "caught thread_canceled" << endl; + throw; + } + */ + catch (...) + { + cerr << "presumably caught thread_canceled" << endl; + throw; + } + + return 0; +} + + +Int +main () +{ + Shptr<Thread> thread (new Thread (cond_wait_thread_proc)); + + sleep (1); + + thread->cancel (); + thread->join (); +} diff --git a/libcult/examples/sched/cancel/makefile b/libcult/examples/sched/cancel/makefile new file mode 100644 index 0000000..38a96bd --- /dev/null +++ b/libcult/examples/sched/cancel/makefile @@ -0,0 +1,48 @@ +# file : examples/sched/cancel/makefile +# author : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make + +cxx_tun := cancel.cxx +cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o)) +cxx_od := $(cxx_obj:.o=.o.d) + +cult.l := $(out_root)/cult/cult.l +cult.l.cpp-options := $(out_root)/cult/cult.l.cpp-options + +cancel := $(out_base)/cancel +clean := $(out_base)/.clean + + +# Build. +# +$(cancel): $(cxx_obj) $(cult.l) + +$(cxx_obj) $(cxx_od): $(cult.l.cpp-options) + +$(call include-dep,$(cxx_od)) + + +# Convenience alias for default target. +# +$(out_base)/: $(cancel) + + +# clean +# +$(clean): $(cancel).o.clean \ + $(addsuffix .cxx.clean,$(cxx_obj)) \ + $(addsuffix .cxx.clean,$(cxx_od)) + + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) + +# Dependencies. +# +$(call import,$(src_root)/cult/makefile) diff --git a/libcult/examples/sched/main/main.cxx b/libcult/examples/sched/main/main.cxx new file mode 100644 index 0000000..58cc2cc --- /dev/null +++ b/libcult/examples/sched/main/main.cxx @@ -0,0 +1,43 @@ +// file : examples/sched/main/main.cxx +// author : Boris Kolpackov <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/types.hxx> + +#include <cult/mm/shptr.hxx> +#include <cult/sched/thread.hxx> + +#include <iostream> +#include <unistd.h> // sleep + +using namespace Cult; +using namespace Sched; + +using std::cerr; +using std::endl; + +Void* +thread_func (Void*) +{ + cerr << "second thread: going to sleep for a few seconds" << endl; + + sleep (2); + + cerr << "second thread: woke up, now exiting" << endl; + + return 0; +} + + +Int +main () +{ + Shptr<Thread> self (new Thread); + + Shptr<Thread> other (new Thread (thread_func)); + + cerr << "initial thread: exiting" << endl; + + Thread::exit (0); +} diff --git a/libcult/examples/sched/main/makefile b/libcult/examples/sched/main/makefile new file mode 100644 index 0000000..945237f --- /dev/null +++ b/libcult/examples/sched/main/makefile @@ -0,0 +1,48 @@ +# file : examples/sched/main/makefile +# author : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make + +cxx_tun := main.cxx +cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o)) +cxx_od := $(cxx_obj:.o=.o.d) + +cult.l := $(out_root)/cult/cult.l +cult.l.cpp-options := $(out_root)/cult/cult.l.cpp-options + +main := $(out_base)/main +clean := $(out_base)/.clean + + +# Build. +# +$(main): $(cxx_obj) $(cult.l) + +$(cxx_obj) $(cxx_od): $(cult.l.cpp-options) + +$(call include-dep,$(cxx_od)) + + +# Convenience alias for default target. +# +$(out_base)/: $(main) + + +# Clean. +# +$(clean): $(main).o.clean \ + $(addsuffix .cxx.clean,$(cxx_obj)) \ + $(addsuffix .cxx.clean,$(cxx_od)) + + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) + +# Dependencies. +# +$(call import,$(src_root)/cult/makefile) diff --git a/libcult/examples/trace/makefile b/libcult/examples/trace/makefile new file mode 100644 index 0000000..57e2b7b --- /dev/null +++ b/libcult/examples/trace/makefile @@ -0,0 +1,48 @@ +# file : examples/trace/makefile +# author : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make + +cxx_tun := trace.cxx +cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o)) +cxx_od := $(cxx_obj:.o=.o.d) + +cult.l := $(out_root)/cult/cult.l +cult.l.cpp-options := $(out_root)/cult/cult.l.cpp-options + +trace := $(out_base)/trace +clean := $(out_base)/.clean + + +# Build. +# +$(trace): $(cxx_obj) $(cult.l) + +$(cxx_obj) $(cxx_od): $(cult.l.cpp-options) + +$(call include-dep,$(cxx_od)) + + +# Convenience alias for default target. +# +$(out_base)/: $(trace) + + +# Clean. +# +$(clean): $(trace).o.clean \ + $(addsuffix .cxx.clean,$(cxx_obj)) \ + $(addsuffix .cxx.clean,$(cxx_od)) + + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) + +# Dependencies. +# +$(call import,$(src_root)/cult/makefile) diff --git a/libcult/examples/trace/trace.cxx b/libcult/examples/trace/trace.cxx new file mode 100644 index 0000000..e2a09d4 --- /dev/null +++ b/libcult/examples/trace/trace.cxx @@ -0,0 +1,51 @@ +// file : examples/trace/trace.cxx +// author : Boris Kolpackov <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/types.hxx> + +#include <cult/trace/log.hxx> +#include <cult/trace/record.hxx> +#include <cult/trace/stream.hxx> + +#include <ostream> + +using namespace Cult; + +struct Foo {}; + +std::ostream& +operator<< (std::ostream& o, Foo const&) +{ + return o << "::Foo"; +} + +Trace::Stream tout ("Examples::Trace", 4); + +Int +main () +{ + using Trace::Record; + + Trace::Log::instance ().level (9); + + Record a ("main", 2); + a << "notationally burdensome"; + tout << a; + + Record b ("main", 2); + tout << (b << "a bit better, but still burdensome"); + + tout << (Record ("main", 2) << "this is" + << " somewhat" + << " twisted but nice to be able to"); + + tout << "concise, using default level"; + + tout << 9 << "concise, using custom level"; + + Foo f; + + tout << 3 << f << " " << 5; +} diff --git a/libcult/makefile b/libcult/makefile new file mode 100644 index 0000000..64c9286 --- /dev/null +++ b/libcult/makefile @@ -0,0 +1,15 @@ +# file : makefile +# author : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))build/bootstrap.make + +default := $(out_base)/ +clean := $(out_base)/.clean + +$(default): $(out_base)/cult/ $(out_base)/examples/ +$(clean): $(out_base)/cult/.clean $(out_base)/examples/.clean + +$(call import,$(src_base)/cult/makefile) +$(call import,$(src_base)/examples/makefile) diff --git a/libcult/version b/libcult/version new file mode 100644 index 0000000..c514bd8 --- /dev/null +++ b/libcult/version @@ -0,0 +1 @@ +1.4.6 |