Mercurial > nand-ecoscentric
changeset 2904:88af52c64ce4
* ecos.db: Add uSTL library package record.
* language/cxx/ustl/*: Initial check-in of the port of uSTL 1.3 to eCos
contributed by Uwe Kindler.
line wrap: on
line diff
--- a/packages/ChangeLog +++ b/packages/ChangeLog @@ -1,3 +1,7 @@ +2009-08-20 John Dallaway <john@dallaway.org.uk> + + * ecos.db: Add uSTL package. + 2009-07-14 John Dallaway <john@dallaway.org.uk> * ecos.db: Add CYGPKG_IO_USB and CYGPKG_IO_USB_SLAVE hardware packages
--- a/packages/NEWS +++ b/packages/NEWS @@ -1,12 +1,13 @@ +* Port of uSTL 1.3 by Uwe Kindler * Port of PDCurses 3.4 by Sergei Gavrikov *********** eCos 3.0 release ************ -* Port to Olimex LPC-L2294-1MB include ethernet and Flash drvers by +* Port to Olimex LPC-L2294-1MB including ethernet and Flash drivers by Sergei Gavrikov -* Port to Olimex LPC-E2294 include ethernet and Flash drvers by +* Port to Olimex LPC-E2294 including ethernet and Flash drivers by Sergei Gavrikov -* Port to Olimex LPC-H2294 include a Flash drvers by Sergei Gavrikov +* Port to Olimex LPC-H2294 including Flash drivers by Sergei Gavrikov * Intel Strataflash v2 flash driver contributed by eCosCentric Ltd. * New Flash API with lots of new goodies. * ADC device driver for EA2468 OEM board
--- a/packages/ecos.db +++ b/packages/ecos.db @@ -2672,6 +2672,18 @@ ISO standard floating point mathematical useful functions for mathematical calculations." } +package CYGPKG_USTL { + alias { "uSTL library" ustl } + directory language/cxx/ustl + script ustl.cdl + description " +This package provides the uSTL library. uSTL is a +partial implementation of the STL specification intended to +reduce code size of the derivative programs. This allows the +user application to use well known standard C++ STL library +containers, streams, iterators, algorithms and functors." +} + package CYGPKG_ERROR { alias { "Common error code support" error errors } directory error
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/ChangeLog @@ -0,0 +1,27 @@ +2009-08-20 Uwe Kindler <uwe_kindler@web.de> + + * Initial contribution of uSTL library + +//=========================================================================== +// ####GPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2009 Free Software Foundation, Inc. +// +// 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 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 Street, +// Fifth Floor, Boston, MA 02110-1301, USA. +// ------------------------------------------- +// ####GPLCOPYRIGHTEND#### +//===========================================================================
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/HISTORY @@ -0,0 +1,349 @@ +2009-08-04 Release 1.3 + * Some API changes to comply with the current C++ standard + binary_search algo returns true, not the found iterator + stack and queue are now type templates, not container adaptors. + Correctly set eof and fail flags in all stream functions + This allows the use of the non-exception path in streams + verify_remaining will no longer throw unless exceptions are on in the stream + verify_remaining will return false if space is insufficient and set flags + exceptions are on by default in istream and ostream and off elsewhere + Updated return values of stream functions to match the standard + what() on message exceptions returns the text passed to the ctor + set insert also returns an iterator/bool pair + map insert now returns an iterator,bool pair + * streamsize and streamoff types defined + * Added string resize with a value arg + * Added standalone getline + * Added numeric_limits digits and digits10 + * Name demangling is now an option, off by default, removing ~20k + * A new and improved nonrecursive make system + * Numerous small size and speed optimizations + * A few minor bugfixes + +2008-02-17 Release 1.2 + * Fixed ifstream readsome to work correctly on nonblocking fds. + * Yet another try at fixing noalias rearrangments. + Added a memory clobber and +g to noalias templates. + * Added dtors template which will embody range destructors for + destroy and vector dtor instead of vector deallocate. It is + called by destroy through a selector template, turning it off + completely for integral types. This removes empty deallocate + instantiations for integral type vectors. + * Fixed bitset stream_size (bits-words confusion) + * Added workaround for compile error when printing a char array. + * Added static_assert from Loki. + +2007-09-02 Release 1.1 + * Due to the demise of SourceForge compile farm, this and subsequent + releases are not as well tested the previous ones. So please + report compilation problems, if any, on non-x86_64 platforms. + * Fixed various aliasing problems complained about by gcc 4.2. + * Added noalias_cast<type>(v) to aid in working around the above + aliasing problem. The aliased variables also must be + explicitly touched by an empty asm statement or something. + * Reimplemented stream_size_of as a template stack because the old + implmentation is invalid in gcc 4.2+ due to a change in + overloaded set lookup scope. vector and tuple now have the + standard read/write/stream_size members. + * Reimplemented flow operators as templates. + * STD_STREAMABLE and TEXT_STREAMABLE are no longer necessary. + * Merged some template metaprogramming stuff from Alexandrescu's Loki + library, including typelists and type traits. + * Implemented generic macro list macros. See metamac.h. + * Fixed some bsconf warnings. + * memblock is_linked now correctly returns true when linked to NULL. + * Added back() to string. + * Fixed a memory leak in CBacktrace GetSymbols. + * Changed written exception data to look like an IFF chunk. + * Removed "memory" from some simd spec clobber lists. + * Reduced the amount of code generated by vector stream templates. + * talign will no longer generate a temp object when called with + non-trivial classes. Uses NullValue template to avoid. + * Linking with gcc instead of using -nodefaultlibs is simpler. + * Removed link number overloads. Sadly, I don't know what this will + break, if anything. On my machine the only case is link(p,0), + which generates an ambiguity error and is easily fixed by + explicitly casting the zero to a size_t. The benefit is + cleaner code and fewer problems for the Symbian port, so the + change stays until/unless somebody reports it as a problem. + * Added long4grain and ptr4grain wrappers to explicitly write long + values on 4-grain, even on 64bit platforms. + +2006-10-27 Release 1.0 SVN 428 + * API CHANGE: ostringstream now works like std::ostringstream, with + an internal buffer instead of writing to an external one + through a link. Instead of passing the buffer to the ctor, + write directly to a default-constructed stream object and + assign buf = os.str() when finished. + * Format change: containers will now write their size as a uint32_t + instead of size_t to allow binary compatibility with 64 bit + architectures. On 32 bit machines this makes no difference. + * Renamed fdostringstream to ofstream. + * Renamed fdistringstream to ifstream. + * Renamed iterator_swap to iter_swap, as in the standard. + * file.h/cc was removed; fstream replaces its functionality. + * Added most remaining i/ostringstream functions that make sense in + this implementation: str, put, get, getline, ignore, peek, + readsome, putback, unget, tellg, seekg, sync, flush, seekp, + tellp, good. The rest will probably not be implemented at + all, since they reference streambufs which don't exist in uSTL. + * Implemented fstream and used it in ifstream/ofstream. + * Added remaining algorithms: find_end, find_first_of, includes, + is_sorted, lexicographical_compare, max_element, min_element, + partial_sort, partial_sort_copy, partition, next_permutation, + prev_permutation, reverse_copy, rotate_copy, search, search_n, + set_difference, set_intersection, set_symmetric_difference, + set_union, and stable_partition. All the algorithms defined by + the C++ standard are now implemented. + * Made ios_base and ios classes instead of namespaces and derived + all stream objects from ios_base. Pulled up state and all + related functions into it. The only problem with this is that + end() conflicts with seekdir end, so you'll need to use + ios scope when you want the latter. + * Align container ends on 4 grain. + While this is not very friendly to 64bit architectures, it is + the only way to allow writing containers portably. It is + better to always align to an arbitrary value than to align to + a platform-dependent one. + * Removed non-const data pointer from memlink. + While enforcing const-correctness is a good thing, the errors + this catches are relatively rare and are all programmer errors. + I must concede that the benefits of having memblocks, strings, + and containers be 16 bytes in size is a great advantage in both + speed and codesize. As a result, one needs to be more mindful + to not modify memlink-derived objects that are linked to const + data; before this change it would have caused a crash, now it + might or might not do that, as with regular pointers. + * Added CBacktrace class for printing backtrace information. + * x86_64 cleanup and improvements, including MMX support. + * Micro-optimization pass for size. Saved 24% (32k)! + * exception now creates a backtrace when thrown. + * Do cout.flush() before read in cin, like std does. + * max_size() on linked objects should return size(), because it is. + * >=, <=, and compare templates no longer require == (>= is !<) + * Pulled rotate code into rotate_fast for memory blocks. + * stream_bounds_exception demangles type names. + * set,map,multiset,multimap now instantiate less crud. + * Abandoned any attempt to use the goddamned byteswap.h. + * Implemented bitset any, none, and count. + * New popcount algorithms. + * Implemented compose1 and compose2 extensions. + * Support building as a .dylib on MacOS. + * Removed --without-cout configure option. + +2005-11-10 Release 0.8 + * API CHANGE: changed all string's find members to return offsets + instead of iterators. That's what the STL standard requires. + Also added standard-required replace/inserts with offset + arguments. Yes, this is a bit painful. I was using it a lot... + But it's all for the better. I promise! + * Removed char_at and ichar from string; use utf8_begin/end instead. + * Iterator-based string insert now return an iterator, like vector. + * Added more wchar_t overloads to string, include append and assign. + * Updated bsconf to use malloc instead of static buffers. + * construct/destruct will now disappear for integral types. + Integral types have no destructors/constructors. + * Fixed istream_iterator to read on construction and in operator++ + as the standard says. Unfortunately, this makes it almost + totally useless, since using it as a source for copy will + always overread by one because copy will call ++ past the + end, which will read one element past the end. This behaviour + is understandable when reading to EOF (which is the only + example ever shown for using it), but worthless when you + have a fixed number of elements you want to read. I'm only + using it to implement utf8 from streams, so, having fixed + that to not overread, I'll chalk it up to standard + compliance. + * Made istream_iterator default constructible and implemented the + EOF check during reading. This should make read-to-EOF + scenario possible. + * Made streams runtime bounds checking on by default. + * Added operator-- to istream_iterator to do unputs. + This works only once for variable-length types because there + is no way to know the length to back up to get the element + before the currently cached one. Constant-length types can + be unput multiple times, and can use -= and - operators. + * fdistringstream underflow will no longer erase the entire buffer. + This helps to keep ungetc working most of the time. + * Similarly fixed utf8in_iterator to read on construction. + This fixed the double-advance bug in utf8in_iterator. + * Fixed utf8in_iterator to not read ahead (except in constructor) + before operator++ is called. This ensures that it does not + read past the end of the string if it isn't 0-terminated. + (Although it will still do so if you call ++) + * Field width should be padded with spaces, not zeroes. + * Implemented some heap algorithms. + * Added VectorRange macro. + * Added relink() call to memlinks for faster resizing. + relink does the work of link, but without calling unlink. + * Added to string substr and like functions. + * Moved simd fill into ualgobase.cc + * configure now recompiles bsconf if its sources change. + * Fixed a rare off-by-one error in ostringstream vprintf. + * Removed fdostringstream printf, since ostringstream has it already. + * Fixed bsconf crash when all inline options are enabled. + * Fixed crash when NULL filename given to file_exception. + * Corrected potential buffer overflow in file_exception and sistream. + * Fixed string rfind for strings; was returning a wrong value sometimes. + * Added copy_link call to memblock to make a copy of linked data. + * Added assert to memlink begin() to warn when writing to a const block. + * Makefile now correctly uses ${MAKE} to recurse. + * Removed all usage of "y" in SIMD asm blocks; gcc<4-> movd, not movq. + This fixes problems with MMX fround on some platforms. + * Removed SSE3 detection from bsconf; it just doesn't work! + * Added BYTE_ORDER detection in bsconf. + * Made BYTE_ORDER and bswap always defined. + +2005-06-28 Release 0.7-1 + * Now compiles with gcc 4.0.0 + * Standard exception constructors now take const char* instead + of string&; this generates much less code. + * Fixed reversed conditional ostringstream.format + This was causing a seek exception sometimes. + * Added ostringstream.vformat + * Added FPU registers to reset_mmx modlist; apparently gcc doesn't + know that they are shared with MMX registers. + * Moved simd copy into ualgobase.cc; they are not inlined anyway. + * Added workaround for BSD which has no __va_copy. + I wonder why nobody reported this as a bug. Is anyone running + BSD out there? Anyone? Anyone at all? Is the damn thing dead? + * So it now compiles on BSD again... Whoohoo... + +2005-04-16 Release 0.7 + * Removed vector inheritance from memblock. + There are just too many problems with treating a vector + this way. You can still do it explicitly by linking a + memblock to the vector. Removing the inheritance causes + vector to be non-virtual, which drastically reduces + instantiation cost. + * Removed elementSize, elementBytes member functions from cmemlink. + Only vector inheritance needed elementSize. + * Restricted vector link calls to T* instead of void*. + This way there would be explicit casts to warn of weirdness. + * Optimized vector push_back + * ostream will now zero bytes skipped by align. + * memblock will no longer zero newly allocated storage. + * Inlined empty constructors on map,multimap,set,multiset. + * NUMERIC_LIMITS macros to facilitate specialization. + * Fixed string vformat problem crashing on x86_64 + Because vsnprintf is called twice, need to copy arglist. + * Added an rm before ln in install to avoid "already exists" errors. + SunOS still doesn't know about the -f flag... + * Split the distribution into ustl and ustl-docs + * New SIZE_OF_BOOL system substitution in bsconf + Only Alpha and Mac have bool as a long, so a define is better. + * Fixed configure being confused with multiple gcc versions. + * Reduced Align code for nonstandard values. + * Pulled up vector/tuple stream operators into generic container + templates in uctrstm.h and made use of resulting macros. + * New TEMPLATE_TYPE macros to allow template building with macros. + * Fixed SSE3 detection in bsconf; thanks to Aloysius Indrayanto. + * Fixed get_temporary_buffer to return size in elements, not in bytes. + This is the proper behaviour as specified in the C++ standard. + * Now using libc qsort in the sort algorithm. + This may give you trouble if you are using a custom comparator + that requires initialization outside the constructor. You can + write a wrapper class that does the initialization in the + constructor. Or, you can use stable_sort. + I'm doing this to both speed up the common case and to reuse + the functionality already linked to in libc. If you really + need to have a sort with a parametrized comparator and don't + want to change your code, file a bug report and I'll change + it back. I just don't think anyone is using this type of + construction. + * Finished heap algorithms. + * Added priority_queue. + * Added deque as a define to list. + * Added noalias template to circumvent the type-punned pointer + dereference warning given by gcc 4.1.0+ + +2005-01-17 Release 0.6 + * The library is relicensed under the MIT License (was LGPL) + * Dropped support for locale due to its great complexity and ugliness. + You can include <locale> from libstdc++ if you still want it. + * ostringstream now uses snprintf for all integer types, so the output + will be localized according to libc locale settings. As a side + effect of this, you will not be able to print negative hex + numbers any more (as in -6AD4), not that it was a good idea... + * tuple will no longer align at the end: + This affects you if you write tuples with small elements + off default grain. For example, writing tuple<2,int16> + on grain 2 would have aligned prior to this change, causing + sub-optimal packing if you wrote an array of such tuples, + since each one only needs grain 2 alignment. + * Fixed incorrect use of __alignof__ in pair stream operators. + * Added size_t ul-or-ui detection code to bsconf and fixed the + size_t/pointer overload in uutility to use it. + * Added erase(iterator,const_iterator) overload for string + * Added alloca_link macro. + * cmemlink will now throw bad_alloc if linking to !p && n. + * multiset and multimap will insert equal elements in order. + I wasn't able to find any guidance concerning the order of + equal elements; it appears to be unspecified. Prior to this + change equal elements were inserted in reverse order, which + is bad idea because it causes a larger copy to make space. + (Note that multimap only compares the key, since the mapped + value is not required to have an operator<. If you want them + sorted, you can use sort() on it.) + * Fixed remove_copy algorithms to not require value operator !=. + * bool will now be written as a byte regardless of the type size. + * sistream now handles 64bit types correctly. + +2004-11-11 Release 0.5 + * configure will now properly enable mmx compiler flags. + * configure has a --with-profile option. + * Fixed a bug in ostringstream format inserting extra '\0' + * Fixed a bug in string find which sometimes did not match at the + beginning of the text. + * ostringstream will now use faster paged allocation. + * New alignof specializations for cmemlink(size_t) and string(1) + * Fixed tuple's value constructors to zero unspecified values. + * Added parentheses around ctr argument in foreach for computed vars. + * General simd interface for tuple optimization. + * Proper link interface in vector, that takes element count. + * set_terminate and set_unxpected prototypes are now available. + * LOOKUP_TEXT_STREAMABLE macro for printing through name arrays. + * Fixed iterator_swap to take iterators by value (reference& swap bad) + * Container random_shuffle. + * vformat method for string to allow implementation of custom printfs. + * TestAndSet inline utility function with the cmpxchg instruction. + * Fixed tuple stream_size_of to add up the elements if nonintegral. + * Added is_integral member to numeric_limits for specialization aid. + * Changed limits is_signed from a function to a bool like SGI does it. + +2004-07-28 Release 0.4-3 + * A ChangeLog! After all these years... + * SIMD instruction support for fill and copy + * matrix template (on top of tuple) + 3dNow! instructions are supported for vector transforms. + * New utility templates + absv - absolute value. + sign - -1 for negative, 0 for 0, 1 for positive + abs_distance - returns an absolute value of the difference. + distance - now returns ptrdiff_t, as in SGI STL. + size_of_elements - useful for working with static arrays in + templates; returns sizeof(T) * n. + pack_type - useful for unrolling loops, packs a small + type into a big one. + alignof - recommended alignment for a type (uses GCC + __alignof__ extension, if available) + eachfor - same as foreach, but for reverse_iterator + * get_temporary_buffer implemented using alloca and macros + * Updated rotate to use alloca for small moves. + This should speed up vector operations, like insert and erase. + * Fixed copy_backward to actually copy backward rather than reverse. + * Made resize virtual in memblock to properly handle strings. + * sostream/sistream will handle wchar_t properly (as utf8 read/write) + * ustring.cc: fixed multiple wchar_t insert + * ustring.cc: changed allocation strategy to simply reserve the space + for the null terminator instead of tweaking size() all the + time. It's cleaner and saner this way. + * benchmarking tool in bvt + * More functions implemented in bitset. + * Added --with-static and --without-shared flags to configure. + +2004-05-22 Release 0.4-2 + * ostringstreams will now correctly resize the buffer as needed. + * Fixed floating point output + (well, not really, just switched to using snprintf) +
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/LICENSE @@ -0,0 +1,24 @@ + + The MIT License + +Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net> + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/README @@ -0,0 +1,51 @@ +Welcome to uSTL Library 1.3 +=========================== + +The eCos uSTL library is a port of Mike Sharov's uSTL implementation. +It has the particular feature of generating small object code sizes +- an important requirement for embedded eCos based applications. +The latest version can be found at: + + http://ustl.sourceforge.net/ + http://sourceforge.net/projects/ustl/ + +The library provides a subset of the full C++ STL standard library. +uSTL is a partial implementation of the STL specification intended to +reduce code size of the derivative programs. This allows the +eCos application to use well known standard C++ STL library +containers, streams, iterators, algorithms and functors. + +For changes, see the HISTORY file. + + +eCos port specific changes/enhancements +--------------------------------------- + +By default eCos is build without exceptions and without RTTI support +(compiler switches -fno-exceptions -fno-rtti). Normally the uSTL +library relies on C++ exceptions to propagate errors and exceptions. +To build the library for eCos all occurrences of try, cath and throw +are replaced by macros USLT_TRY, USLT_CATCH_ALL, and USLT_THROW. Thus +the eCos uSTL port compiles without exceptions and without RTTI support. + +The macro USLT_THROW calls an eCos specific exception handling function +that prints exception information to the diagnostic channel. + +All features of the uSTL library are available except for memory mapped +files or memory mapped streams. + +If you use cout for printing to the console you should know that the +data is only sent if you finish all output with endl and then call +cout.flush(). + +example: + +cout << "Console output" << endl; +cout.flush(); + + +Legal Stuff +----------- + +The uSTL library is subject of copyright under MIT license. For +the license text see LICENSE file.
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/cdl/ustl.cdl @@ -0,0 +1,197 @@ +# ==================================================================== +# +# ustl.cdl +# +# uSTL - "Size-optimized STL" library package configuration data +# +# ==================================================================== +## ####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 2009 Free Software Foundation, Inc. +## +## eCos 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 or (at your option) any later +## version. +## +## eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +## +## As a special exception, if other files instantiate templates or use +## macros or inline functions from this file, or you compile this file +## and link it with other works to produce a work based on this file, +## this file does not by itself cause the resulting work to be covered by +## the GNU General Public License. However the source code for this file +## must still be made available in accordance with section (3) of the GNU +## General Public License v2. +## +## This exception does not invalidate any other reasons why a work based +## on this file might be covered by the GNU General Public License. +## ------------------------------------------- +## ####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): Uwe Kindler +# Contributors: +# Date: 2009-07-28 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + + +cdl_package CYGPKG_USTL { + display "uSTL library" + description " + This package provides the uSTL library. uSTL is a + partial implementation of the STL specification intended to + reduce code size of the derivative programs. This allows the + user application to use well known standard C++ STL library + containers, streams, iterators, algorithms and functors." + requires CYGPKG_IO + requires CYGPKG_ERROR + requires CYGPKG_ISOINFRA + requires CYGPKG_LIBM + + # malloc + requires CYGINT_ISO_MALLOC + + # stdio + requires CYGINT_ISO_STDIO_FORMATTED_IO + requires CYGINT_ISO_STDIO_CHAR_IO + requires CYGINT_ISO_STDIO_DIRECT_IO + requires CYGINT_ISO_STDIO_ERROR + + # signals + requires CYGINT_ISO_SIGNAL_NUMBERS + requires CYGINT_ISO_SIGNAL_IMPL + + # time + requires CYGINT_ISO_C_TIME_TYPES + + # startup + requires CYGINT_ISO_EXIT + requires CYGINT_ISO_MAIN_STARTUP + requires CYGINT_ISO_ENVIRON + + #string + requires CYGINT_ISO_STRTOK_R + requires CYGINT_ISO_STRING_LOCALE_FUNCS + requires CYGINT_ISO_STRING_MEMFUNCS + requires CYGINT_ISO_STRING_STRFUNCS + + # common + requires CYGINT_ISO_CTYPE + requires CYGINT_ISO_ERRNO_CODES + requires CYGINT_ISO_ERRNO + requires CYGINT_ISO_LOCALE + requires CYGIMP_LIBC_STDIO_C99_SNPRINTF + + compile bktrace.cpp \ + cmemlink.cpp \ + memblock.cpp \ + memlink.cpp \ + ualgobase.cpp \ + ubitset.cpp \ + uexception.cpp \ + unew.cpp \ + ustdxept.cpp \ + ustring.cpp \ + ustlecos.cpp \ + mistream.cpp \ + sistream.cpp \ + sostream.cpp + + cdl_component CYGCLS_USTL_FSTREAMS { + display "File streams support" + flavor bool + default_value CYGPKG_IO_FILEIO + description " + This option enables file stream support. For file stream + support the File I/O package is required." + requires CYGPKG_IO_FILEIO + requires CYGINT_ISO_STDIO_FILETYPES + requires CYGINT_ISO_STDIO_FILEACCESS + requires CYGINT_ISO_STDIO_FILEPOS + requires CYGINT_ISO_STDIO_STREAMS + compile fstream.cpp \ + ofstream.cpp + + cdl_option CYGVAR_USTL_CIN_COUT_CERR { + display "cin, cout & cerr support" + flavor bool + default_value 1 + description " + Enable this option if you want the standard streams + cin, cout and cerr to be included. You will not be able + to run bvt tests if you don't enable this option." + } + } + + cdl_option CYGSEM_USTL_STREAM_BOUNDS_CHECK { + display "Stream bounds checking" + flavor bool + default_value 0 + description " + Enable this option if you want stream operations to throw + exceptions on insufficient data or insufficient space. + All these errors should be preventable in output code; + the input code should verify the data in a separate step. + It slows down stream operations a lot, but it's your call. + Debug builds always throws exceptions - this option is + only valid for release builds." + } + + cdl_component CYGPKG_USTL_OPTIONS { + display "uSTL library build options" + flavor none + no_define + description " + Package specific build options including control over + compiler flags used only in building this package, + and details of which tests are built." + + + cdl_option CYGPKG_USTL_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building the uSTL library. These flags are used in addition + to the set of global flags." + } + + cdl_option CYGPKG_USTL_CFLAGS_REMOVE { + display "Suppressed compiler flags" + flavor data + no_define + default_value { "-Wundef" } + description " + This option modifies the set of compiler flags for + building the uSTL library. These flags are removed from + the set of global flags if present." + } + + cdl_option CYGPKG_USTL_TESTS { + display "uSTL tests" + flavor data + no_define + calculated { (CYGVAR_USTL_CIN_COUT_CERR ? "tests/bvt00 tests/bvt01 tests/bvt02 tests/bvt03 tests/bvt04 tests/bvt05 tests/bvt06 tests/bvt07 tests/bvt08 tests/bvt09 tests/bvt10 tests/bvt11 tests/bvt12 tests/bvt13 tests/bvt14 tests/bvt15 tests/bvt16 tests/bvt17 tests/bvt18 tests/bvt19 tests/bvt20 tests/bvt21 tests/bvt22 tests/bvt23 tests/bvt24 tests/bvt25 tests/bvt26 tests/bvt27" : "" )} + description " + This option specifies the set of tests for the uSTL library." + } + } +} + +# ==================================================================== +# EOF ustl.cdl
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/bktrace.h @@ -0,0 +1,52 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2006-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef BKTRACE_H_63ABB1E4388CEDD975DBE58B57DE474F +#define BKTRACE_H_63ABB1E4388CEDD975DBE58B57DE474F + +#include "ulimits.h" +#include <stdlib.h> + +namespace ustl { + +class ostringstream; +class istream; +class ostream; + +/// \class CBacktrace bktrace.h ustl.h +/// +/// \brief Stores the backtrace from the point of construction. +/// +/// The backtrace, or callstack, is the listing of functions called to +/// reach the construction of this object. This is useful for debugging, +/// to print the location of an error. To get meaningful output you'll +/// need to use a debug build with symbols and with frame pointers. For +/// GNU ld you will also need to link with the -rdynamic option to see +/// actual function names instead of __gxx_personality0+0xF4800. +/// +class CBacktrace { +public: + CBacktrace (void) throw(); + CBacktrace (const CBacktrace& v) throw(); + inline ~CBacktrace (void) throw() { if (m_Symbols) free (m_Symbols); } + const CBacktrace& operator= (const CBacktrace& v) throw(); + void text_write (ostringstream& os) const; + void read (istream& is); + void write (ostream& os) const; + size_t stream_size (void) const; +private: + void GetSymbols (void) throw() DLL_LOCAL; +private: + void* m_Addresses [64]; ///< Addresses of each function on the stack. + char* m_Symbols; ///< Symbols corresponding to each address. + uint32_t m_nFrames; ///< Number of addresses in m_Addresses. + uint32_t m_SymbolsSize; ///< Size of m_Symbols. +}; + +} // namespace ustl + +ALIGNOF(ustl::CBacktrace, sizeof(void*)) + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/cmemlink.h @@ -0,0 +1,103 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef CMEMLINK_H_7CFAB32C5C6732ED29B34EF00EA40A12 +#define CMEMLINK_H_7CFAB32C5C6732ED29B34EF00EA40A12 + +#include "ualgobase.h" +#include "config.h" + +/// The ustl namespace contains all ustl classes and algorithms. +namespace ustl { + +class istream; +class ostream; +class ostringstream; + +/// \class cmemlink cmemlink.h ustl.h +/// \ingroup MemoryManagement +/// +/// \brief A read-only pointer to a sized block of memory. +/// +/// Use this class the way you would a const pointer to an allocated unstructured block. +/// The pointer and block size are available through member functions and cast operator. +/// +/// Example usage: +/// +/// \code +/// void* p = malloc (46721); +/// cmemlink a, b; +/// a.link (p, 46721); +/// assert (a.size() == 46721)); +/// b = a; +/// assert (b.size() == 46721)); +/// assert (b.DataAt(34) == a.DataAt(34)); +/// assert (0 == memcmp (a, b, 12)); +/// \endcode +/// +class cmemlink { +public: + typedef char value_type; + typedef const value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type reference; + typedef value_type const_reference; + typedef size_t size_type; + typedef uint32_t written_size_type; + typedef ptrdiff_t difference_type; + typedef const_pointer const_iterator; + typedef const_iterator iterator; + typedef const cmemlink& rcself_t; +public: + inline cmemlink (void) : m_Data (NULL), m_Size (0) { } + inline cmemlink (const void* p, size_type n) : m_Data (const_pointer(p)), m_Size (n) { assert (p || !n); } + inline cmemlink (const cmemlink& l) : m_Data (l.m_Data), m_Size (l.m_Size) {} + inline virtual ~cmemlink (void) throw() {} + void link (const void* p, size_type n); + inline void link (const cmemlink& l) { link (l.begin(), l.size()); } + inline void link (const void* first, const void* last) { link (first, distance (first, last)); } + inline void relink (const void* p, size_type n); + virtual void unlink (void) throw(); + inline rcself_t operator= (const cmemlink& l) { link (l); return (*this); } + bool operator== (const cmemlink& l) const; + inline void swap (cmemlink& l) { ::ustl::swap (m_Data, l.m_Data); ::ustl::swap (m_Size, l.m_Size); } + inline size_type size (void) const { return (m_Size); } + inline size_type max_size (void) const { return (size()); } + inline size_type readable_size (void) const { return (size()); } + inline bool empty (void) const { return (!size()); } + inline const_pointer cdata (void) const { return (m_Data); } + inline iterator begin (void) const { return (iterator (cdata())); } + inline iterator iat (size_type i) const { assert (i <= size()); return (begin() + i); } + inline iterator end (void) const { return (iat (size())); } + inline void resize (size_type n) { m_Size = n; } + inline void read (istream&) { assert (!"ustl::cmemlink is a read-only object."); } + void write (ostream& os) const; + size_type stream_size (void) const; + void text_write (ostringstream& os) const; +#ifdef CYGCLS_USTL_FSTREAMS + void write_file (const char* filename, int mode = 0644) const; +#endif +private: + const_pointer m_Data; ///< Pointer to the data block (const) + size_type m_Size; ///< size of the data block +}; + +//---------------------------------------------------------------------- + +/// A fast alternative to link which can be used when relinking to the same block (i.e. when it is resized) +inline void cmemlink::relink (const void* p, size_type n) +{ + m_Data = reinterpret_cast<const_pointer>(p); + m_Size = n; +} + +//---------------------------------------------------------------------- + +/// Use with cmemlink-derived classes to link to a static array +#define static_link(v) link (VectorBlock(v)) + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/config.h @@ -0,0 +1,389 @@ +#ifndef CYGONCE_CONFIG_H +#define CYGONCE_CONFIG_H +// ========================================================================== +// +// config.h +// +// Manually constructed uSTL configuration file for eCos RTOS +// +// =========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2009 Free Software Foundation, Inc. +// +// eCos 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 or (at your option) any later +// version. +// +// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +// =========================================================================== +// =========================================================================== +// #####DESCRIPTIONBEGIN#### +// +// Author(s): Uwe Kindler +// Contributors: +// Date: 2009-07-28 +// Purpose: eCos specific uSTL configuration +// Description: +// +// ####DESCRIPTIONEND#### +// +// ========================================================================*/ +#include <stdint.h> +#include <pkgconf/ustl.h> // ustl package configuration + + +// +// If there is no RTTI support (normally this is the default eCos setting) +// C++ typeid keyword is not supported. We hide this by using a macro instead +// of using typeid keyword directly. +// +#ifdef __GXX_RTTI + #define USTL_TYPENAME(_t_) typeid(_t_).name() +#else + #define USTL_TYPENAME(_t_) "unknown type (RTTI disabled)" +#endif + +// +// If there is no exception support (normally this is the default eCos setting) +// C++ keywords try, catch and throw are not supported. To compile uSTL without +// exception support we use macros USLT_TRY, USLT_CATCH_ALL and USLT_THROW +// instead of the real keywords. To handle exceptions in debug builds we define +// a "lightwight" exception handler. This handler is simply a function that +// prints exception information do diagnostic channel. +// +#ifdef __EXCEPTIONS + #define USTL_TRY try + #define USTL_CATCH_ALL catch (...) {} + #define USTL_THROW(_exception_) throw (_exception_) +#else + namespace ustl + { + class exception; + extern void exception_handler(const exception& ex); + } + #define USTL_TRY + #define USTL_CATCH_ALL + #define USTL_THROW(_exception_) ustl::exception_handler(_exception_) +#endif + +// +// There is no eCos header that exports this function so we do it here +// +#ifdef CYGCLS_USTL_FSTREAMS +__externC int ioctl( int fd, CYG_ADDRWORD com, ... ); +#endif + + +/// Define to 1 if you want stream operations to throw exceptions on +/// insufficient data or insufficient space. All these errors should +/// be preventable in output code; the input code should verify the +/// data in a separate step. It slows down stream operations a lot, +/// but it's your call. By default only debug builds throw. +/// +#ifdef CYGSEM_USTL_STREAM_BOUNDS_CHECK +#define WANT_STREAM_BOUNDS_CHECKING 1 +#else +#undef WANT_STREAM_BOUNDS_CHECKING +#endif + +#if !defined(WANT_STREAM_BOUNDS_CHECKING) && !defined(NDEBUG) + #define WANT_STREAM_BOUNDS_CHECKING 1 +#endif + +/// Define to 1 if you want backtrace symbols demangled. +/// This adds some 15k to the library size, and requires that you link it and +/// any executables you make with the -rdynamic flag (increasing library size +/// even more). By default this option is disable. Enabling this option also +/// pulls in __cxa_demangle from libsupc++ +#undef WANT_NAME_DEMANGLING + +/// Define to 1 if you want to build without libstdc++ +#define WITHOUT_LIBSTDCPP 1 + +/// Define GNU extensions if unavailable. +#ifndef __GNUC__ + /// GCC (and some other compilers) define '__attribute__'; ustl is using this + /// macro to alert the compiler to flag inconsistencies in printf/scanf-like + /// function calls. Just in case '__attribute__' is undefined, make a dummy. + /// + #ifndef __attribute__ + #define __attribute__(p) + #endif +#endif +#if defined(__GNUC__) && __GNUC__ >= 4 + #define INLINE __attribute__((always_inline)) +#else + #define INLINE +#endif +#define DLL_EXPORT +#define DLL_LOCAL +#if defined(__GNUC__) && __GNUC__ >= 3 && (__i386__ || __x86_64__) + /// GCC 3+ supports the prefetch directive, which some CPUs use to improve caching + #define prefetch(p,rw,loc) __builtin_prefetch(p,rw,loc) +#else + #define prefetch(p,rw,loc) +#endif +#if !defined(__GNUC__) || __GNUC__ < 3 + /// __alignof__ returns the recommended alignment for the type + #define __alignof__(v) min(sizeof(v), sizeof(void*)) + /// This macro returns 1 if the value of x is known at compile time. + #ifndef __builtin_constant_p + #define __builtin_constant_p(x) 0 + #endif +#endif + +// Define to 1 if you have the `atexit' function. +#define HAVE_ATEXIT 1 + +// Define to 1 if you have the <assert.h> header file. +#define HAVE_ASSERT_H 1 + +// Define to 1 if you have the <ctype.h> header file. +#define HAVE_CTYPE_H 1 + +// Define to 1 if you have the <errno.h> header file. +#define HAVE_ERRNO_H 1 + +// Define to 1 if you have the <fcntl.h> header file. +#define HAVE_FCNTL_H 1 + +// Define to 1 if you have the <float.h> header file. +#define HAVE_FLOAT_H 1 + +// Define to 1 if you have the <limits.h> header file. +#define HAVE_LIMITS_H 1 + +// Define to 1 if you have the <locale.h> header file. +#define HAVE_LOCALE_H 1 + +// Define to 1 if your system has a working `malloc' function. +#define HAVE_MALLOC 1 + +// Define to 1 if you have the `memchr' function. +#define HAVE_MEMCHR 1 + +// Define to 1 if you have the `memmove' function. +#define HAVE_MEMMOVE 1 + +// Define to 1 if you have the `memset' function. +#define HAVE_MEMSET 1 + +// Define to 1 if the system has the type `ptrdiff_t'. +#define HAVE_PTRDIFF_T 1 + +// Define to 1 if you have the <signal.h> header file. +#define HAVE_SIGNAL_H 1 + +// Define to 1 if you have the <stdarg.h> header file. +#define HAVE_STDARG_H 1 + +// Define to 1 if you have the <stddef.h> header file. +#define HAVE_STDDEF_H 1 + +// Define to 1 if you have the <stdint.h> header file. +#define HAVE_STDINT_H 1 + +// Define to 1 if you have the <stdio.h> header file. +#define HAVE_STDIO_H 1 + +// Define to 1 if you have the <stdlib.h> header file. +#define HAVE_STDLIB_H 1 + +// Define to 1 if you have the `strerror' function. +#define HAVE_STRERROR 1 + +// Define to 1 if you have the <string.h> header file. +#define HAVE_STRING_H 1 + +// Define to 1 if you have the `strrchr' function. +#define HAVE_STRRCHR 1 + +// Define to 1 if you have the `strtol' function. +#define HAVE_STRTOL 1 + +// Define to 1 if you have the <sys/stat.h> header file. +#define HAVE_SYS_STAT_H 1 + +// Define to 1 if you have the <sys/types.h> header file. +#define HAVE_SYS_TYPES_H 1 + +// Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. +#define HAVE_SYS_WAIT_H 1 + +// Define to 1 if you have the <time.h> header file. +#define HAVE_TIME_H 1 + +// Define to 1 if you have the <unistd.h> header file. +#define HAVE_UNISTD_H 1 + +// Define to 1 if you have the <math.h> header file. +#define HAVE_MATH_H 1 + +// Define to 1 if you have the long long type +#define HAVE_LONG_LONG 1 + +// Define to 1 if you have 64 bit types available +#define HAVE_INT64_T 1 + +// Define to 1 if your compiler treats char as a separate type along with +// signed char and unsigned char. This will create overloads for char. +#define HAVE_THREE_CHAR_TYPES 1 + +// Define to 1 if you have the <cxxabi.h> header file. +#if __GNUC__ >= 3 + #define HAVE_CXXABI_H 1 +#endif + +// Define to 1 if you have the rintf function. Will use rint otherwise. +#undef HAVE_RINTF + +// Define to 1 if you have the <strings.h> header file. +#undef HAVE_STRINGS_H + +// Define to 1 if you have the `strsignal' function. +#undef HAVE_STRSIGNAL + +// Define to 1 if you have the __va_copy function +#undef HAVE_VA_COPY + +// Define to 1 if you have the <inttypes.h> header file. +#undef HAVE_INTTYPES_H + +// Define to 1 if you have the <malloc.h> header file. +#undef HAVE_MALLOC_H + +// Define to 1 if you have the <memory.h> header file. +#undef HAVE_MEMORY_H + +// Define to 1 if you have the <alloca.h> header file. +#undef HAVE_ALLOCA_H + +// Define to 1 if `stat' has the bug that it succeeds when given the +// zero-length file name argument. +#undef HAVE_STAT_EMPTY_STRING_BUG + +// STDC_HEADERS is defined to 1 on sane systems. +#if defined(HAVE_ASSERT_H) && defined(HAVE_CTYPE_H) &&\ + defined(HAVE_ERRNO_H) && defined(HAVE_FLOAT_H) &&\ + defined(HAVE_LIMITS_H) && defined(HAVE_LOCALE_H) &&\ + defined(HAVE_MATH_H) && defined(HAVE_SIGNAL_H) &&\ + defined(HAVE_STDARG_H) && defined(HAVE_STDDEF_H) &&\ + defined(HAVE_STDIO_H) && defined(HAVE_STDLIB_H) &&\ + defined(HAVE_STRING_H) && defined(HAVE_TIME_H) +#define STDC_HEADERS 1 +#endif + +// STDC_HEADERS is defined to 1 on unix systems. +#if defined(HAVE_FCNTL_H) && defined(HAVE_SYS_STAT_H) && defined(HAVE_UNISTD_H) +#define STDUNIX_HEADERS 1 +#endif + +// Define to 1 if you have the <byteswap.h> header file. +#if (__GNUC__ >= 3) // gcc 2.95 somehow doesn't recognize 'asm volatile' in libc byteswap.h +#undef HAVE_BYTESWAP_H +#endif + +// Define to 1 if `lstat' dereferences a symlink specified with a trailing slash. +#undef LSTAT_FOLLOWS_SLASHED_SYMLINK + +// Define as the return type of signal handlers (`int' or `void'). +#undef RETSIGTYPE + +// Define to 1 if you want unrolled specializations for fill and copy +#undef WANT_UNROLLED_COPY + +// Define to 1 if you want to use MMX/SSE/3dNow! processor instructions +#undef WANT_MMX + +// Define to byte sizes of types +#define SIZE_OF_CHAR 1 +#define SIZE_OF_SHORT 2 +#define SIZE_OF_INT 4 +#define SIZE_OF_LONG 4 +#define SIZE_OF_LONG_LONG 8 +#define SIZE_OF_POINTER 4 +#define SIZE_OF_SIZE_T 4 +#define SIZE_OF_BOOL 1 + + +// Byte order macros, converted in utypes.h +#define USTL_LITTLE_ENDIAN 4321 +#define USTL_BIG_ENDIAN 1234 +#if (CYG_BYTEORDER == CYG_LSBFIRST) +#define USTL_BYTE_ORDER USTL_BIG_ENDIAN +#else +#define USTL_BYTE_ORDER USTL_LITTLE_ENDIAN +#endif + +// Extended CPU capabilities +#undef CPU_HAS_FPU +#undef CPU_HAS_EXT_DEBUG +#undef CPU_HAS_TIMESTAMPC +#undef CPU_HAS_MSR +#undef CPU_HAS_CMPXCHG8 +#undef CPU_HAS_APIC +#undef CPU_HAS_SYSCALL +#undef CPU_HAS_MTRR +#undef CPU_HAS_CMOV +#undef CPU_HAS_FCMOV +#if defined WANT_MMX +#undef CPU_HAS_MMX +#undef CPU_HAS_FXSAVE +#undef CPU_HAS_SSE +#undef CPU_HAS_SSE2 +#undef CPU_HAS_SSE3 +#undef CPU_HAS_EXT_3DNOW +#undef CPU_HAS_3DNOW +#endif + +// GCC vector extensions +#if defined(CPU_HAS_MMX) || defined(CPU_HAS_SSE) + #undef HAVE_VECTOR_EXTENSIONS +#endif + +#if defined(CPU_HAS_SSE) && defined(__GNUC__) + #define __sse_align __attribute__((aligned(16))) +#else + #define __sse_align +#endif + + +// Define to empty if `const' does not conform to ANSI C. +//#undef const + +// Define as `__inline' if that's what the C compiler calls it, or to nothing +// if it is not supported. +//#undef inline + +// Define to `long' if <sys/types.h> does not define. +//#undef off_t + +// Define to `unsigned' if <sys/types.h> does not define. +//#undef size_t + +// --------------------------------------------------------------------------- +#endif // CYGONCE_CONFIG_H +
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/fstream.h @@ -0,0 +1,77 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef FSTREAM_H_056E10F70EAD416443E3B36A2D6B5FA3 +#define FSTREAM_H_056E10F70EAD416443E3B36A2D6B5FA3 + +#include "uios.h" +#include "ustring.h" + +struct stat; + +namespace ustl { + +/// \class fstream fstream.h ustl.h +/// \ingroup DeviceStreams +/// +/// \brief Implements file operations. +/// +/// This is not implemented as a stream, but rather as a base for one. You +/// should use ifstream or ofstream if you want flow operators. Otherwise +/// this only implements functions for binary i/o. +/// +class fstream : public ios_base { +public: + fstream (void); + explicit fstream (const char* filename, openmode mode = in | out); + explicit fstream (int nfd, const char* filename = ""); + ~fstream (void) throw(); + void open (const char* filename, openmode mode, mode_t perms = 0644); + void attach (int nfd, const char* filename = ""); + void detach (void); + void close (void); + void sync (void); + off_t read (void* p, off_t n); + off_t readsome (void* p, off_t n); + off_t write (const void* p, off_t n); + off_t size (void) const; + off_t seek (off_t n, seekdir whence = beg); + off_t pos (void) const; + void stat (struct stat& rs) const; + int ioctl (const char* rname, int request, long argument = 0); + inline int ioctl (const char* rname, int request, int argument) { return (fstream::ioctl (rname, request, long(argument))); } + inline int ioctl (const char* rname, int request, void* argument) { return (fstream::ioctl (rname, request, intptr_t(argument))); } + int fcntl (const char* rname, int request, long argument = 0); + inline int fcntl (const char* rname, int request, int argument) { return (fstream::fcntl (rname, request, long(argument))); } + inline int fcntl (const char* rname, int request, void* argument) { return (fstream::fcntl (rname, request, intptr_t(argument))); } +#if 0 // memory mapped files are not supported in eCos + memlink mmap (off_t n, off_t offset = 0); + void munmap (memlink& l); + void msync (memlink& l); +#endif // #if 0 + void set_nonblock (bool v = true); + inline int fd (void) const { return (m_fd); } + inline bool is_open (void) const { return (fd() >= 0); } + inline off_t tellg (void) const { return (pos()); } + inline off_t tellp (void) const { return (pos()); } + inline void seekg (off_t n, seekdir whence = beg) { seek (n, whence); } + inline void seekp (off_t n, seekdir whence = beg) { seek (n, whence); } + inline void flush (void) { sync(); } + inline const string& name (void) const { return (m_Filename); } +private: + DLL_LOCAL static int om_to_flags (openmode m); + DLL_LOCAL void set_and_throw (iostate s, const char* op); +private: + int m_fd; ///< Currently open file descriptor. + string m_Filename; ///< Currently open filename. +}; + +/// Argument macro for fstream::ioctl. Use like fs.ioctl (IOCTLID (TCGETS), &ts). +#define IOCTLID(r) "ioctl("#r")", r +#define FCNTLID(r) "fcntl("#r")", r + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/memblock.h @@ -0,0 +1,64 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef MEMBLOCK_H_7ED63A891164CC43578E63664D52A196 +#define MEMBLOCK_H_7ED63A891164CC43578E63664D52A196 + +#include "memlink.h" +#include "config.h" + +namespace ustl { + +/// \class memblock memblock.h ustl.h +/// \ingroup MemoryManagement +/// +/// \brief Allocated memory block. +/// +/// Adds memory management capabilities to memlink. Uses malloc and realloc to +/// maintain the internal pointer, but only if allocated using members of this class, +/// or if linked to using the Manage() member function. Managed memory is automatically +/// freed in the destructor. +/// +class memblock : public memlink { +public: + memblock (void); + memblock (const void* p, size_type n); + explicit memblock (size_type n); + explicit memblock (const cmemlink& b); + explicit memblock (const memlink& b); + memblock (const memblock& b); + virtual ~memblock (void) throw(); + virtual void unlink (void) throw(); + inline void assign (const cmemlink& l) { assign (l.cdata(), l.readable_size()); } + inline const memblock& operator= (const cmemlink& l) { assign (l); return (*this); } + inline const memblock& operator= (const memlink& l) { assign (l); return (*this); } + inline const memblock& operator= (const memblock& l) { assign (l); return (*this); } + inline void swap (memblock& l) { memlink::swap (l); ::ustl::swap (m_Capacity, l.m_Capacity); } + void assign (const void* p, size_type n); + void reserve (size_type newSize, bool bExact = true); + void resize (size_type newSize, bool bExact = true); + iterator insert (iterator start, size_type size); + iterator erase (iterator start, size_type size); + inline void clear (void) { resize (0); } + inline size_type capacity (void) const { return (m_Capacity); } + inline bool is_linked (void) const { return (!capacity()); } + inline size_type max_size (void) const { return (is_linked() ? memlink::max_size() : SIZE_MAX); } + inline void manage (memlink& l) { manage (l.begin(), l.size()); } + void deallocate (void) throw(); + void manage (void* p, size_type n); + void copy_link (void); + void read (istream& is); +#ifdef CYGCLS_USTL_FSTREAMS + void read_file (const char* filename); +#endif +protected: + virtual size_type minimumFreeCapacity (void) const throw() __attribute__((const)); +private: + size_type m_Capacity; ///< Number of bytes allocated by Resize. +}; + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/memlink.h @@ -0,0 +1,102 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef MEMLINK_H_798D25827C8E322D2D7E734B169FF5FC +#define MEMLINK_H_798D25827C8E322D2D7E734B169FF5FC + +#include "cmemlink.h" +#include "ualgo.h" + +namespace ustl { + +/// \class memlink memlink.h ustl.h +/// \ingroup MemoryManagement +/// +/// \brief Wrapper for pointer to block with size. +/// +/// Use this class the way you would a pointer to an allocated unstructured block. +/// The pointer and block size are available through member functions and cast operator. +/// +/// Example usage: +/// \code +/// void* p = malloc (46721); +/// memlink a, b; +/// a.link (p, 46721); +/// assert (a.size() == 46721)); +/// b = a; +/// assert (b.size() == 46721)); +/// assert (b.begin() + 34 == a.begin + 34); +/// assert (0 == memcmp (a, b, 12)); +/// a.fill (673, b, 42, 67); +/// b.erase (87, 12); +/// \endcode +/// +class memlink : public cmemlink { +public: + typedef value_type* pointer; + typedef cmemlink::pointer const_pointer; + typedef cmemlink::const_iterator const_iterator; + typedef pointer iterator; + typedef const memlink& rcself_t; +public: + inline memlink (void) : cmemlink() {} + inline memlink (void* p, size_type n) : cmemlink (p, n) {} + inline memlink (const void* p, size_type n) : cmemlink (p, n) {} + inline memlink (rcself_t l) : cmemlink (l) {} + inline explicit memlink (const cmemlink& l) : cmemlink (l) {} + inline pointer data (void) { return (const_cast<pointer>(cdata())); } + inline iterator begin (void) { return (iterator (data())); } + inline iterator iat (size_type i) { assert (i <= size()); return (begin() + i); } + inline iterator end (void) { return (iat (size())); } + inline const_iterator begin (void) const { return (cmemlink::begin()); } + inline const_iterator end (void) const { return (cmemlink::end()); } + inline const_iterator iat (size_type i) const { return (cmemlink::iat (i)); } + size_type writable_size (void) const { return (size()); } + inline rcself_t operator= (const cmemlink& l) { cmemlink::operator= (l); return (*this); } + inline rcself_t operator= (rcself_t l) { cmemlink::operator= (l); return (*this); } + inline void link (const void* p, size_type n) { cmemlink::link (p, n); } + inline void link (void* p, size_type n) { cmemlink::link (p, n); } + inline void link (const cmemlink& l) { cmemlink::link (l); } + inline void link (memlink& l) { cmemlink::link (l); } + inline void link (const void* first, const void* last) { link (first, distance (first, last)); } + inline void link (void* first, void* last) { link (first, distance (first, last)); } + inline void relink (const void* p, size_type n) { cmemlink::relink (p, n); } + inline void relink (void* p, size_type n) { cmemlink::relink (p, n); } + inline void copy (const cmemlink& l) { copy (begin(), l.cdata(), l.size()); } + inline void copy (const void* p, size_type n) { copy (begin(), p, n); } + void copy (iterator offset, const void* p, size_type n); + inline void swap (memlink& l) { cmemlink::swap (l); } + void fill (iterator start, const void* p, size_type elsize, size_type elCount = 1); + inline void insert (iterator start, size_type size); + inline void erase (iterator start, size_type size); + void read (istream& is); +}; + +/// Shifts the data in the linked block from \p start to \p start + \p n. +/// The contents of the uncovered bytes is undefined. +inline void memlink::insert (iterator start, size_type n) +{ + assert (data() || !n); + assert (cmemlink::begin() || !n); + assert (start >= begin() && start + n <= end()); + rotate (start, end() - n, end()); +} + +/// Shifts the data in the linked block from \p start + \p n to \p start. +/// The contents of the uncovered bytes is undefined. +inline void memlink::erase (iterator start, size_type n) +{ + assert (data() || !n); + assert (cmemlink::begin() || !n); + assert (start >= begin() && start + n <= end()); + rotate (start, start + n, end()); +} + +/// Use with memlink-derived classes to allocate and link to stack space. +#define alloca_link(m,n) (m).link (alloca (n), (n)) + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/metamac.h @@ -0,0 +1,92 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. +// +/// \file metamac.h +/// \brief Macros for complex metaprogramming involving pseudoiteration. + +#ifndef METAMAC_H_7235D14A209C29332F2330EF553B81AF +#define METAMAC_H_7235D14A209C29332F2330EF553B81AF + +//---------------------------------------------------------------------- +// Functors and general utilities. +//---------------------------------------------------------------------- + +/// Evaluates to itself +#define ITSELF(x) x + +/// Concatenates \p a and \p b +#define PASTE(a,b) a##b + +//---------------------------------------------------------------------- +// Lists and other iterators +//---------------------------------------------------------------------- + +/// The maximum number of elements in REPEAT, LIST, and COMMA_LIST +#define METAMAC_MAXN 9 + +/// Simple list with no separators. Repeats x N times. +/// @{ +#define REPEAT_1(x) x(1) +#define REPEAT_2(x) REPEAT_1(x) x(2) +#define REPEAT_3(x) REPEAT_2(x) x(3) +#define REPEAT_4(x) REPEAT_3(x) x(4) +#define REPEAT_5(x) REPEAT_4(x) x(5) +#define REPEAT_6(x) REPEAT_5(x) x(6) +#define REPEAT_7(x) REPEAT_6(x) x(7) +#define REPEAT_8(x) REPEAT_7(x) x(8) +#define REPEAT_9(x) REPEAT_8(x) x(9) +#define REPEAT(N,x) PASTE(REPEAT_,N)(x) +/// @} + +/// Simple separated list. Repeats x N times with sep in between. +/// @{ +#define LIST_1(x,sep) x(1) +#define LIST_2(x,sep) LIST_1(x,sep) sep x(2) +#define LIST_3(x,sep) LIST_2(x,sep) sep x(3) +#define LIST_4(x,sep) LIST_3(x,sep) sep x(4) +#define LIST_5(x,sep) LIST_4(x,sep) sep x(5) +#define LIST_6(x,sep) LIST_5(x,sep) sep x(6) +#define LIST_7(x,sep) LIST_6(x,sep) sep x(7) +#define LIST_8(x,sep) LIST_7(x,sep) sep x(8) +#define LIST_9(x,sep) LIST_8(x,sep) sep x(9) +#define LIST(N,x,sep) PASTE(LIST_,N)(x,sep) +/// @} + +/// Comma separated list. A special case of LIST needed because the preprocessor can't substitute commas. +/// @{ +#define COMMA_LIST_1(x) x(1) +#define COMMA_LIST_2(x) COMMA_LIST_1(x), x(2) +#define COMMA_LIST_3(x) COMMA_LIST_2(x), x(3) +#define COMMA_LIST_4(x) COMMA_LIST_3(x), x(4) +#define COMMA_LIST_5(x) COMMA_LIST_4(x), x(5) +#define COMMA_LIST_6(x) COMMA_LIST_5(x), x(6) +#define COMMA_LIST_7(x) COMMA_LIST_6(x), x(7) +#define COMMA_LIST_8(x) COMMA_LIST_7(x), x(8) +#define COMMA_LIST_9(x) COMMA_LIST_8(x), x(9) +#define COMMA_LIST(N,x) PASTE(COMMA_LIST_,N)(x) +/// @} + +//---------------------------------------------------------------------- +// Macros for defining LIST arguments. +//---------------------------------------------------------------------- + +/// Ignores N, producing lists of identically named arguments. +#define LARG_NONE(name,N) name + +/// Appends N to name. +#define LARG_NUMBER(name,N) name##N + +/// name is a reference type. +#define LARG_REF(name,N) name##N& + +/// Sequential parameter passed by value with sequential types. +#define LARG_MT_PARAM_BY_VALUE(type,name,N) type##N name##N + +/// Sequential parameter passed by reference with sequential types. +#define LARG_MT_PARAM_BY_REF(type,name,N) type##N& name##N + +//---------------------------------------------------------------------- + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/mistream.h @@ -0,0 +1,325 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef MISTREAM_H_103AEF1F266C04AA1A817D38705983DA +#define MISTREAM_H_103AEF1F266C04AA1A817D38705983DA + +#include "memlink.h" +#include "uexception.h" +#include "strmsize.h" +#include "utf8.h" +#include "uios.h" +#include "config.h" +#if WANT_STREAM_BOUNDS_CHECKING + #include <typeinfo> +#endif + +namespace ustl { + +class ostream; +class memlink; +class string; + +/// \class istream mistream.h ustl.h +/// \ingroup BinaryStreams +/// +/// \brief Helper class to read packed binary streams. +/// +/// This class contains a set of functions to read integral types from an +/// unstructured memory block. Unpacking binary file data can be done this +/// way, for instance. aligning the data is your responsibility, and can +/// be accomplished by proper ordering of reads and by calling the align() +/// function. Unaligned access is usually slower by orders of magnitude and, +/// on some architectures, such as PowerPC, can cause your program to crash. +/// Therefore, all read functions have asserts to check alignment. +/// Overreading the end of the stream will also cause a crash (an assert in +/// debug builds). Oh, and don't be intimidated by the size of the inlines +/// here. In the assembly code the compiler will usually chop everything down +/// to five instructions each. +/// +/// Alignment rules for your objects: +/// - Assume your writes start off 4-byte aligned. +/// - After completion, \ref istream::align the stream to at least 4. +/// - If data portability between 32bit and 64bit platforms is important +/// (it often is not, in config files and the like), ensure you are always +/// using fixed-size types and are aligning to a fixed grain. Avoid writing +/// 8-byte types, and if you do, manually align before doing so. +/// - Non-default alignment is allowed if you plan to frequently write this +/// object in array form and alignment would be costly. For example, an +/// array of uint16_t-sized objects may leave the stream uint16_t aligned +/// as long as you know about it and will default-align the stream after +/// writing the array (note: \ref vector will already do this for you) +/// +/// Example code: +/// \code +/// memblock b; +/// b.read_file ("test.file"); +/// ostream is (b); +/// is >> boolVar >> ios::talign<int>(); +/// is >> intVar >> floatVar; +/// is.read (binaryData, binaryDataSize); +/// is.align(); +/// \endcode +/// +class istream : public cmemlink, public ios_base { +public: + inline istream (void); + inline istream (const void* p, streamsize n); + inline explicit istream (const cmemlink& source); + explicit istream (const ostream& source); + inline iterator end (void) const { return (cmemlink::end()); } + inline void link (const void* p, streamsize n) { cmemlink::link (p, n); } + inline void link (const cmemlink& l) { cmemlink::link (l.cdata(), l.readable_size()); } + inline void link (const void* f, const void* l) { cmemlink::link (f, l); } + inline void relink (const void* p, streamsize n) { cmemlink::relink (p, n); m_Pos = 0; } + inline void relink (const cmemlink& l) { relink (l.cdata(), l.readable_size()); } + virtual void unlink (void) throw(); + inline virtual streamsize underflow (streamsize = 1) { return (remaining()); } + inline uoff_t pos (void) const { return (m_Pos); } + inline const_iterator ipos (void) const { return (begin() + pos()); } + inline streamsize remaining (void) const { return (size() - pos()); } + inline void seek (uoff_t newPos); + inline void iseek (const_iterator newPos); + inline void skip (streamsize nBytes); + inline bool aligned (streamsize grain = c_DefaultAlignment) const; + inline bool verify_remaining (const char* op, const char* type, streamsize n); + inline streamsize align_size (streamsize grain = c_DefaultAlignment) const; + inline void align (streamsize grain = c_DefaultAlignment); + inline void swap (istream& is); + inline void read (void* buffer, streamsize size); + inline void read (memlink& buf) { read (buf.begin(), buf.writable_size()); } + void read_strz (string& str); + streamsize readsome (void* s, streamsize n); + inline void read (istream&) { } + void write (ostream& os) const; + void text_write (ostringstream& os) const; + inline streamsize stream_size (void) const { return (remaining()); } + template <typename T> + inline void iread (T& v); + inline void ungetc (void) { seek (pos() - 1); } + inline off_t tellg (void) const { return (pos()); } + inline void seekg (off_t p, seekdir d = beg); +private: + streamoff m_Pos; ///< The current read position. +}; + +//---------------------------------------------------------------------- + +template <typename T, typename Stream> +inline streamsize required_stream_size (T, const Stream&) { return (1); } +template <typename T> +inline streamsize required_stream_size (T v, const istream&) { return (stream_size_of(v)); } + +template <typename Stream> +inline bool stream_at_eof (const Stream& stm) { return (stm.eof()); } +template <> +inline bool stream_at_eof (const istream&) { return (false); } + +/// \class istream_iterator +/// \ingroup BinaryStreamIterators +/// +/// \brief An iterator over an istream to use with uSTL algorithms. +/// +template <typename T, typename Stream = istream> +class istream_iterator { +public: + typedef T value_type; + typedef ptrdiff_t difference_type; + typedef const value_type* pointer; + typedef const value_type& reference; + typedef typename Stream::size_type size_type; +public: + istream_iterator (void) : m_pis (NULL), m_v() {} + explicit istream_iterator (Stream& is) : m_pis (&is), m_v() { Read(); } + istream_iterator (const istream_iterator& i) : m_pis (i.m_pis), m_v (i.m_v) {} + /// Reads and returns the next value. + inline const T& operator* (void) { return (m_v); } + inline istream_iterator& operator++ (void) { Read(); return (*this); } + inline istream_iterator& operator-- (void) { m_pis->seek (m_pis->pos() - 2 * stream_size_of(m_v)); return (operator++()); } + inline istream_iterator operator++ (int) { istream_iterator old (*this); operator++(); return (old); } + inline istream_iterator operator-- (int) { istream_iterator old (*this); operator--(); return (old); } + inline istream_iterator& operator+= (streamsize n) { while (n--) operator++(); return (*this); } + inline istream_iterator& operator-= (streamsize n) { m_pis->seek (m_pis->pos() - (n + 1) * stream_size_of(m_v)); return (operator++()); } + inline istream_iterator operator- (streamoff n) const { istream_iterator result (*this); return (result -= n); } + inline difference_type operator- (const istream_iterator& i) const { return (distance (i.m_pis->pos(), m_pis->pos()) / stream_size_of(m_v)); } + inline bool operator== (const istream_iterator& i) const { return ((!m_pis && !i.m_pis) || (m_pis && i.m_pis && m_pis->pos() == i.m_pis->pos())); } + inline bool operator< (const istream_iterator& i) const { return (!i.m_pis || (m_pis && m_pis->pos() < i.m_pis->pos())); } +private: + void Read (void) + { + if (!m_pis) + return; + const streamsize rs (required_stream_size (m_v, *m_pis)); + if (m_pis->remaining() < rs && m_pis->underflow (rs) < rs) { + m_pis = NULL; + return; + } + *m_pis >> m_v; + if (stream_at_eof (*m_pis)) + m_pis = NULL; + } +private: + Stream* m_pis; ///< The host stream. + T m_v; ///< Last read value; cached to be returnable as a const reference. +}; + +//---------------------------------------------------------------------- + +/// \brief Constructs a stream attached to nothing. +/// A stream attached to nothing is not usable. Call Link() functions +/// inherited from cmemlink to attach to some memory block. +/// +inline istream::istream (void) +: cmemlink (), + m_Pos (0) +{ +} + +/// Attaches the stream to a block at \p p of size \p n. +inline istream::istream (const void* p, streamsize n) +: cmemlink (p, n), + m_Pos (0) +{ +} + +/// Attaches to the block pointed to by \p source. +inline istream::istream (const cmemlink& source) +: cmemlink (source), + m_Pos (0) +{ +} + +/// Checks that \p n bytes are available in the stream, or else throws. +inline bool istream::verify_remaining (const char* op, const char* type, streamsize n) +{ + const streamsize rem = remaining(); + bool enough = n <= rem; + if (!enough) overrun (op, type, n, pos(), rem); + return (enough); +} + +/// Sets the current read position to \p newPos +inline void istream::seek (uoff_t newPos) +{ +#if WANT_STREAM_BOUNDS_CHECKING + if (newPos > size()) + USTL_THROW(stream_bounds_exception ("seekg", "byte", pos(), newPos - pos(), size())); +#else + assert (newPos <= size()); +#endif + m_Pos = newPos; +} + +/// Sets the current read position to \p newPos +inline void istream::iseek (const_iterator newPos) +{ + seek (distance (begin(), newPos)); +} + +/// Sets the current write position to \p p based on \p d. +inline void istream::seekg (off_t p, seekdir d) +{ + switch (d) { + case beg: seek (p); break; + case cur: seek (pos() + p); break; + case ios_base::end: seek (size() - p); break; + } +} + +/// Skips \p nBytes without reading them. +inline void istream::skip (streamsize nBytes) +{ + seek (pos() + nBytes); +} + +/// Returns the number of bytes to skip to be aligned on \p grain. +inline streamsize istream::align_size (streamsize grain) const +{ + return (Align (pos(), grain) - pos()); +} + +/// Returns \c true if the read position is aligned on \p grain +inline bool istream::aligned (streamsize grain) const +{ + assert (uintptr_t(begin()) % grain == 0 && "Streams should be attached aligned at the maximum element grain to avoid bus errors."); + return (pos() % grain == 0); +} + +/// aligns the read position on \p grain +inline void istream::align (streamsize grain) +{ + seek (Align (pos(), grain)); +} + +/// Reads type T from the stream via a direct pointer cast. +template <typename T> +inline void istream::iread (T& v) +{ + assert (aligned (alignof (v))); +#if WANT_STREAM_BOUNDS_CHECKING + if (!verify_remaining ("read", USTL_TYPENAME(v), sizeof(T))) + return; +#else + assert (remaining() >= sizeof(T)); +#endif + v = *reinterpret_cast<const T*>(ipos()); + m_Pos += sizeof(T); +} + +/// Swaps contents with \p is +inline void istream::swap (istream& is) +{ + cmemlink::swap (is); + ::ustl::swap (m_Pos, is.m_Pos); +} + +/// Reads \p n bytes into \p buffer. +inline void istream::read (void* buffer, size_type n) +{ +#if WANT_STREAM_BOUNDS_CHECKING + if (!verify_remaining ("read", "binary data", n)) + return; +#else + assert (remaining() >= n && "Reading past end of buffer. Make sure you are reading the right format."); +#endif + memcpy (reinterpret_cast<value_type*>(buffer), ipos(), n); + m_Pos += n; +} + +//---------------------------------------------------------------------- + +template <typename T> struct object_reader { + inline void operator()(istream& is, T& v) const { v.read (is); } +}; +template <typename T> struct integral_object_reader { + inline void operator()(istream& is, T& v) const { is.iread (v); } +}; +template <typename T> +inline istream& operator>> (istream& is, T& v) { + typedef typename tm::Select <numeric_limits<T>::is_integral, + integral_object_reader<T>, object_reader<T> >::Result object_reader_t; + object_reader_t()(is, v); + return (is); +} +template <typename T> +inline istream& operator>> (istream& is, const T& v) { v.read (is); return (is); } + +//---------------------------------------------------------------------- + +typedef istream_iterator<utf8subchar_t> istream_iterator_for_utf8; +typedef utf8in_iterator<istream_iterator_for_utf8> utf8istream_iterator; + +/// Returns a UTF-8 adaptor reading from \p is. +inline utf8istream_iterator utf8in (istream& is) +{ + istream_iterator_for_utf8 si (is); + return (utf8istream_iterator (si)); +} + +//---------------------------------------------------------------------- + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/mostream.h @@ -0,0 +1,294 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef MOSTREAM_H_24A8C5397E0848216573E5670930FC9A +#define MOSTREAM_H_24A8C5397E0848216573E5670930FC9A + +#include "memlink.h" +#include "uexception.h" +#include "utf8.h" +#include "uios.h" +#include "config.h" +#if WANT_STREAM_BOUNDS_CHECKING + #include <typeinfo> +#endif + +namespace ustl { + +class istream; +class string; + +/// \class ostream mostream.h ustl.h +/// \ingroup BinaryStreams +/// +/// \brief Helper class to write packed binary streams. +/// +/// This class contains a set of functions to write integral types into an +/// unstructured memory block. Packing binary file data can be done this +/// way, for instance. aligning the data is your responsibility, and can +/// be accomplished by proper ordering of writes and by calling \ref ostream::align. +/// Unaligned access is usually slower by orders of magnitude and, +/// on some architectures, such as PowerPC, can cause your program to crash. +/// Therefore, all write functions have asserts to check alignment. +/// See \ref istream documentation for rules on designing your data format. +/// Overwriting the end of the stream will also cause a crash (an assert in +/// debug builds). Oh, and don't be intimidated by the size of the inlines +/// here. In the assembly code the compiler will usually chop everything down +/// to five instructions each. +/// +/// Example code: +/// \code +/// memblock b; +/// ostream os (b); +/// os << boolVar << ios::talign<int>(); +/// os << intVar << floatVar; +/// os.write (binaryData, binaryDataSize); +/// os.align(); +/// b.resize (os.pos()); +/// b.write_file ("test.file"); +/// \endcode +/// +class ostream : public memlink, public ios_base { +public: + inline ostream (void); + inline ostream (void* p, streamsize n); + inline explicit ostream (const memlink& source); + inline iterator end (void) { return (memlink::end()); } + inline const_iterator end (void) const { return (memlink::end()); } + inline void seek (uoff_t newPos); + inline void iseek (const_iterator newPos); + inline void skip (streamsize nBytes); + inline uoff_t pos (void) const { return (m_Pos); } + inline iterator ipos (void) { return (begin() + pos()); } + inline const_iterator ipos (void) const { return (begin() + pos()); } + inline streamsize remaining (void) const; + inline bool aligned (streamsize grain = c_DefaultAlignment) const; + bool verify_remaining (const char* op, const char* type, size_t n); + inline streamsize align_size (streamsize grain = c_DefaultAlignment) const; + void align (streamsize grain = c_DefaultAlignment); + inline void write (const void* buffer, streamsize size); + inline void write (const cmemlink& buf); + void write_strz (const char* str); + void read (istream& is); + inline void write (ostream& os) const { os.write (begin(), pos()); } + void text_write (ostringstream& os) const; + inline size_t stream_size (void) const { return (pos()); } + void insert (iterator start, streamsize size); + void erase (iterator start, streamsize size); + inline void swap (ostream& os); + template <typename T> + inline void iwrite (const T& v); + inline virtual streamsize overflow (streamsize = 1){ return (remaining()); } + virtual void unlink (void) throw(); + inline void link (void* p, streamsize n) { memlink::link (p, n); } + inline void link (memlink& l) { memlink::link (l.data(), l.writable_size()); } + inline void link (void* f, void* l) { memlink::link (f, l); } + inline void relink (void* p, streamsize n) { memlink::relink (p, n); m_Pos = 0; } + inline void relink (memlink& l) { relink (l.data(), l.writable_size()); } + inline void seekp (off_t p, seekdir d = beg); + inline off_t tellp (void) const { return (pos()); } +protected: + inline void SetPos (uoff_t newPos) { m_Pos = newPos; } +private: + streamoff m_Pos; ///< Current write position. +}; + +//---------------------------------------------------------------------- + +/// \class ostream_iterator mostream.h ustl.h +/// \ingroup BinaryStreamIterators +/// +/// \brief An iterator over an ostream to use with uSTL algorithms. +/// +template <typename T, typename Stream = ostream> +class ostream_iterator { +public: + typedef T value_type; + typedef ptrdiff_t difference_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef typename Stream::size_type size_type; +public: + inline explicit ostream_iterator (Stream& os) + : m_Os (os) {} + inline ostream_iterator (const ostream_iterator& iter) + : m_Os (iter.m_Os) {} + /// Writes \p v into the stream. + inline ostream_iterator& operator= (const T& v) + { m_Os << v; return (*this); } + inline ostream_iterator& operator* (void) { return (*this); } + inline ostream_iterator& operator++ (void) { return (*this); } + inline ostream_iterator operator++ (int) { return (*this); } + inline ostream_iterator& operator+= (streamsize n) { m_Os.skip (n); return (*this); } + inline bool operator== (const ostream_iterator& i) const + { return (m_Os.pos() == i.m_Os.pos()); } + inline bool operator< (const ostream_iterator& i) const + { return (m_Os.pos() < i.m_Os.pos()); } +private: + Stream& m_Os; +}; + +//---------------------------------------------------------------------- + +typedef ostream_iterator<utf8subchar_t> ostream_iterator_for_utf8; +typedef utf8out_iterator<ostream_iterator_for_utf8> utf8ostream_iterator; + +/// Returns a UTF-8 adaptor writing to \p os. +inline utf8ostream_iterator utf8out (ostream& os) +{ + ostream_iterator_for_utf8 si (os); + return (utf8ostream_iterator (si)); +} + +//---------------------------------------------------------------------- + +/// \brief Constructs a stream attached to nothing. +/// A stream attached to nothing is not usable. Call Link() functions +/// inherited from memlink to attach to some memory block. +/// +inline ostream::ostream (void) +: memlink (), + m_Pos (0) +{ +} + +/// Attaches the stream to a block at \p p of size \p n. +inline ostream::ostream (void* p, streamsize n) +: memlink (p, n), + m_Pos (0) +{ +} + +/// Attaches to the block pointed to by \p source. +inline ostream::ostream (const memlink& source) +: memlink (source), + m_Pos (0) +{ +} + +/// Checks that \p n bytes are available in the stream, or else throws. +inline bool ostream::verify_remaining (const char* op, const char* type, size_t n) +{ + const size_t rem = remaining(); + bool enough = n <= rem; + if (!enough) overrun (op, type, n, pos(), rem); + return (enough); +} + +/// Move the write pointer to \p newPos +inline void ostream::seek (uoff_t newPos) +{ +#if WANT_STREAM_BOUNDS_CHECKING + if (newPos > size()) + USTL_THROW(stream_bounds_exception ("seekp", "byte", pos(), newPos - pos(), size())); +#else + assert (newPos <= size()); +#endif + SetPos (newPos); +} + +/// Sets the current write position to \p newPos +inline void ostream::iseek (const_iterator newPos) +{ + seek (distance (begin(), const_cast<iterator>(newPos))); +} + +/// Sets the current write position to \p p based on \p d. +inline void ostream::seekp (off_t p, seekdir d) +{ + switch (d) { + case beg: seek (p); break; + case cur: seek (pos() + p); break; + case ios_base::end: seek (size() - p); break; + } +} + +/// Skips \p nBytes without writing anything. +inline void ostream::skip (streamsize nBytes) +{ + seek (pos() + nBytes); +} + +/// Returns number of bytes remaining in the write buffer. +inline streamsize ostream::remaining (void) const +{ + return (size() - pos()); +} + +/// Returns \c true if the write pointer is aligned on \p grain +inline bool ostream::aligned (streamsize grain) const +{ + assert (uintptr_t(begin()) % grain == 0 && "Streams should be attached aligned at the maximum element grain to avoid bus errors."); + return (pos() % grain == 0); +} + +/// Returns the number of bytes to skip to be aligned on \p grain. +inline streamsize ostream::align_size (streamsize grain) const +{ + return (Align (pos(), grain) - pos()); +} + +/// Writes \p n bytes from \p buffer. +inline void ostream::write (const void* buffer, size_type n) +{ +#if WANT_STREAM_BOUNDS_CHECKING + if (!verify_remaining ("write", "binary data", n)) + return; +#else + assert (remaining() >= n && "Buffer overrun. Check your stream size calculations."); +#endif + memcpy (ipos(), const_iterator(buffer), n); + m_Pos += n; +} + +/// Writes the contents of \p buf into the stream as a raw dump. +inline void ostream::write (const cmemlink& buf) +{ + write (buf.begin(), buf.size()); +} + +/// Writes type T into the stream via a direct pointer cast. +template <typename T> +inline void ostream::iwrite (const T& v) +{ + assert (aligned (alignof (v))); +#if WANT_STREAM_BOUNDS_CHECKING + if (!verify_remaining ("write", USTL_TYPENAME(v), sizeof(T))) + return; +#else + assert (remaining() >= sizeof(T)); +#endif + *reinterpret_cast<T*>(ipos()) = v; + SetPos (pos() + sizeof(T)); +} + +/// Swaps with \p os +inline void ostream::swap (ostream& os) +{ + memlink::swap (os); + ::ustl::swap (m_Pos, os.m_Pos); +} + +//---------------------------------------------------------------------- + +template <typename T> struct object_writer { + inline void operator()(ostream& os, const T& v) const { v.write (os); } +}; +template <typename T> struct integral_object_writer { + inline void operator()(ostream& os, const T& v) const { os.iwrite (v); } +}; +template <typename T> +inline ostream& operator<< (ostream& os, const T& v) { + typedef typename tm::Select <numeric_limits<T>::is_integral, + integral_object_writer<T>, object_writer<T> >::Result object_writer_t; + object_writer_t()(os, v); + return (os); +} + +//---------------------------------------------------------------------- + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/ofstream.h @@ -0,0 +1,81 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef FDOSTREAM_H_5E27FC3D530BF3CA04D6C73F5700EECC +#define FDOSTREAM_H_5E27FC3D530BF3CA04D6C73F5700EECC + +#include "sistream.h" +#include "sostream.h" +#include "fstream.h" +#include "config.h" + +namespace ustl { + +/// \class ofstream fdostream.h ustl.h +/// \ingroup DeviceStreams +/// \brief A string stream that writes to an fd. Implements cout and cerr. +class ofstream : public ostringstream { +public: + ofstream (void); + explicit ofstream (int Fd); + explicit ofstream (const char* filename, openmode mode = out); + virtual ~ofstream (void) throw(); + inline void open (const char* filename, openmode mode = out) { m_File.open (filename, mode); clear (m_File.rdstate()); } + void close (void); + inline bool is_open (void) const { return (m_File.is_open()); } + inline iostate exceptions (iostate v) { ostringstream::exceptions(v); return (m_File.exceptions(v)); } + inline void setstate (iostate v) { ostringstream::setstate(v); m_File.setstate(v); } + inline void clear (iostate v = goodbit) { ostringstream::clear(v); m_File.clear(v); } + inline off_t tellp (void) const { return (m_File.tellp() + ostringstream::tellp()); } + inline int fd (void) const { return (m_File.fd()); } + inline void stat (struct stat& rs) const { m_File.stat (rs); } + inline void set_nonblock (bool v = true) { m_File.set_nonblock (v); } + inline int ioctl (const char* rname, int request, long argument = 0) { return (m_File.ioctl (rname, request, argument)); } + inline int ioctl (const char* rname, int request, int argument) { return (m_File.ioctl (rname, request, argument)); } + inline int ioctl (const char* rname, int request, void* argument) { return (m_File.ioctl (rname, request, argument)); } + ofstream& seekp (off_t p, seekdir d = beg); + ofstream& flush (void); + virtual size_type overflow (size_type n = 1); +private: + fstream m_File; +}; + +/// \class ifstream fdostream.h ustl.h +/// \ingroup DeviceStreams +/// \brief A string stream that reads from an fd. Implements cin. +class ifstream : public istringstream { +public: + ifstream (void); + explicit ifstream (int Fd); + explicit ifstream (const char* filename, openmode mode = in); + inline void open (const char* filename, openmode mode = in) { m_File.open (filename, mode); clear (m_File.rdstate()); } + inline void close (void) { m_File.close(); clear (m_File.rdstate()); } + inline bool is_open (void) const { return (m_File.is_open()); } + inline iostate exceptions (iostate v) { istringstream::exceptions(v); return (m_File.exceptions(v)); } + inline void setstate (iostate v) { istringstream::setstate(v); m_File.setstate(v); } + inline void clear (iostate v = goodbit) { istringstream::clear(v); m_File.clear(v); } + inline off_t tellg (void) const { return (m_File.tellg() - remaining()); } + inline int fd (void) const { return (m_File.fd()); } + inline void stat (struct stat& rs) const { m_File.stat (rs); } + inline void set_nonblock (bool v = true) { m_File.set_nonblock (v); } + inline int ioctl (const char* rname, int request, long argument = 0) { return (m_File.ioctl (rname, request, argument)); } + inline int ioctl (const char* rname, int request, int argument) { return (m_File.ioctl (rname, request, argument)); } + inline int ioctl (const char* rname, int request, void* argument) { return (m_File.ioctl (rname, request, argument)); } + ifstream& seekg (off_t p, seekdir d = beg); + int sync (void); + virtual size_type underflow (size_type n = 1); +private: + string m_Buffer; + fstream m_File; +}; + +#ifdef CYGVAR_USTL_CIN_COUT_CERR +extern ofstream cout, cerr; +extern ifstream cin; +#endif + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/simd.h @@ -0,0 +1,466 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. +// +/// \file simd.h +/// \brief SIMD-type algorithms, with hardware acceleration, if available. +/// +/// All algorithms are container-based because iterator syntax is just too +/// damn verbose and because the specializations need to be able to tell +/// how many elements are in the container in order to choose proper SIMD +/// instruction set (i.e.: 4 floats select SSE, while 2 floats select 3dNow!) +/// Specializations are only for the tuple template because the container +/// must be of a fixed and compile-time-known size for the compiler to be +/// able to choose the specialization. + +#ifndef SIMD_H_39BE2D970DF4BD00508CCFFB482496F9 +#define SIMD_H_39BE2D970DF4BD00508CCFFB482496F9 + +#include "ulimits.h" +#if HAVE_MATH_H + #include <math.h> +#endif + +namespace ustl { +namespace simd { + +//---------------------------------------------------------------------- +// Generic algorithms +//---------------------------------------------------------------------- + +/// Applies \p op to each element in \p op1. +template <typename Ctr, typename UnaryOperation> +inline void packop (Ctr& op1, UnaryOperation op) +{ + foreach (typename Ctr::iterator, i, op1) + op (*i); +} + +/// Applies \p op to each element in \p op1 and \p op2 and stores in \p op2. +template <typename Ctr, typename BinaryOperation> +inline void packop (const Ctr& op1, Ctr& op2, BinaryOperation op) +{ + assert (op2.size() <= op1.size()); + typename Ctr::const_iterator i1 (op1.begin()); + typename Ctr::iterator i2 (op2.begin()); + for (; i2 != op2.end(); ++i1, ++i2) + *i2 = op (*i2, *i1); +} + +/// Applies \p op to corresponding elements in \p op1 and \p op2 and stores in \p result. +template <typename Ctr, typename BinaryOperation> +inline void packop (const Ctr& op1, const Ctr& op2, Ctr& result, BinaryOperation op) +{ + assert (op1.size() <= op2.size() && op1.size() <= result.size()); + passign (op1, result); + packop (op2, result); +} + +/// Copies \p op1 into \p result. +template <typename Ctr> +inline void passign (const Ctr& op1, Ctr& result) +{ + assert (op1.size() <= result.size()); + typename Ctr::iterator d (result.begin()); + foreach (typename Ctr::const_iterator, s, op1) + *d++ = *s; +} + +/// Copies \p result.size() elements from \p op1 to \p result. +template <typename Ctr> +inline void ipassign (typename Ctr::const_iterator op1, Ctr& result) +{ + foreach (typename Ctr::iterator, d, result) + *d = *op1++; +} + +template <typename Ctr1, typename Ctr2, typename ConvertFunction> +inline void pconvert (const Ctr1& op1, Ctr2& op2, ConvertFunction f) +{ + assert (op1.size() <= op2.size()); + typename Ctr1::const_iterator i1 (op1.begin()); + typename Ctr2::iterator i2 (op2.begin()); + for (; i1 != op1.end(); ++i1, ++i2) + *i2 = f (*i1); +} + +// Functionoids for SIMD operations, like saturation arithmetic, shifts, etc. +STD_BINARY_FUNCTOR (fpadds, T, ((b > numeric_limits<T>::max() - a) ? numeric_limits<T>::max() : a + b)) +STD_BINARY_FUNCTOR (fpsubs, T, ((a < numeric_limits<T>::min() + b) ? numeric_limits<T>::min() : a - b)) +STD_BINARY_FUNCTOR (fpshl, T, (a << b)) +STD_BINARY_FUNCTOR (fpshr, T, (a >> b)) +STD_BINARY_FUNCTOR (fpmin, T, (min (a, b))) +STD_BINARY_FUNCTOR (fpmax, T, (max (a, b))) +STD_BINARY_FUNCTOR (fpavg, T, ((a + b + 1) / 2)) +STD_CONVERSION_FUNCTOR (fcast, (D(a))) +#if HAVE_MATH_H +STD_UNARY_FUNCTOR (fpreciprocal,T, (1 / a)) +STD_UNARY_FUNCTOR (fpsqrt, T, (reset_mmx(), T (sqrt (a)))) +STD_UNARY_FUNCTOR (fprecipsqrt, T, (reset_mmx(), 1 / T(sqrt (a)))) +STD_UNARY_FUNCTOR (fsin, T, (reset_mmx(), T (sin (a)))) +STD_UNARY_FUNCTOR (fcos, T, (reset_mmx(), T (cos (a)))) +STD_UNARY_FUNCTOR (ftan, T, (reset_mmx(), T (tan (a)))) +#if HAVE_RINTF +STD_CONVERSION_FUNCTOR (fround, (reset_mmx(), D(rintf(a)))) +#else +STD_CONVERSION_FUNCTOR (fround, (reset_mmx(), D(rint(a)))) +#endif +template <> inline int32_t fround<double,int32_t>::operator()(const double& a) const { reset_mmx(); return (int32_t(rint(a))); } +#endif +template <> inline float fpavg<float>::operator()(const float& a, const float& b) const { return ((a + b) / 2); } +template <> inline double fpavg<double>::operator()(const double& a, const double& b) const { return ((a + b) / 2); } + +#define SIMD_PACKEDOP1(name, operation) \ +template <typename Ctr> \ +inline void name (Ctr& op1) \ +{ \ + typedef typename Ctr::value_type value_t; \ + packop (op1, operation<value_t>()); \ +} +#define SIMD_PACKEDOP2(name, operation) \ +template <typename Ctr> \ +inline void name (const Ctr& op1, Ctr& op2) \ +{ \ + typedef typename Ctr::value_type value_t; \ + packop (op1, op2, operation<value_t>()); \ +} +#define SIMD_PACKEDOP3(name, operation) \ +template <typename Ctr> \ +inline void name (const Ctr& op1, const Ctr& op2, Ctr& result) \ +{ \ + typedef typename Ctr::value_type value_t; \ + packop (op1, op2, result, operation<value_t>()); \ +} +#define SIMD_SINGLEOP1(name, operation) \ +template <typename T> \ +inline T name (T op) \ +{ \ + operation<T> obj; \ + return (obj(op)); \ +} +#define SIMD_CONVERTOP(name, operation) \ +template <typename Ctr1, typename Ctr2> \ +inline void name (const Ctr1& op1, Ctr2& op2) \ +{ \ + typedef typename Ctr1::value_type value1_t; \ + typedef typename Ctr2::value_type value2_t; \ + pconvert (op1, op2, operation<value1_t, value2_t>());\ +} + +SIMD_PACKEDOP2 (padd, plus) +SIMD_PACKEDOP2 (psub, minus) +SIMD_PACKEDOP2 (pmul, multiplies) +SIMD_PACKEDOP2 (pdiv, divides) +SIMD_PACKEDOP2 (pand, bitwise_and) +SIMD_PACKEDOP2 (por, bitwise_or) +SIMD_PACKEDOP2 (pxor, bitwise_xor) +SIMD_PACKEDOP2 (pshl, fpshl) +SIMD_PACKEDOP2 (pshr, fpshr) +SIMD_PACKEDOP2 (psubs, fpsubs) +SIMD_PACKEDOP2 (pmin, fpmin) +SIMD_PACKEDOP2 (pmax, fpmax) +SIMD_PACKEDOP2 (pavg, fpavg) + +SIMD_PACKEDOP3 (padd, plus) +SIMD_PACKEDOP3 (psub, minus) +SIMD_PACKEDOP3 (pmul, multiplies) +SIMD_PACKEDOP3 (pdiv, divides) +SIMD_PACKEDOP3 (pand, bitwise_and) +SIMD_PACKEDOP3 (por, bitwise_or) +SIMD_PACKEDOP3 (pxor, bitwise_xor) +SIMD_PACKEDOP3 (pshl, fpshl) +SIMD_PACKEDOP3 (pshr, fpshr) +SIMD_PACKEDOP3 (padds, fpadds) +SIMD_PACKEDOP3 (psubs, fpsubs) +SIMD_PACKEDOP3 (pmin, fpmin) +SIMD_PACKEDOP3 (pmax, fpmax) +SIMD_PACKEDOP3 (pavg, fpavg) + +#if HAVE_MATH_H +SIMD_PACKEDOP1 (precip, fpreciprocal) +SIMD_PACKEDOP1 (psqrt, fpsqrt) +SIMD_PACKEDOP1 (precipsqrt, fprecipsqrt) +SIMD_PACKEDOP1 (psin, fsin) +SIMD_PACKEDOP1 (pcos, fcos) +SIMD_PACKEDOP1 (ptan, ftan) + +SIMD_SINGLEOP1 (srecip, fpreciprocal) +SIMD_SINGLEOP1 (ssqrt, fpsqrt) +SIMD_SINGLEOP1 (srecipsqrt, fprecipsqrt) +SIMD_SINGLEOP1 (ssin, fsin) +SIMD_SINGLEOP1 (scos, fcos) +SIMD_SINGLEOP1 (stan, ftan) + +SIMD_CONVERTOP (pround, fround) + +template <typename T> inline int32_t sround (T op) { fround<T,int32_t> obj; return (obj (op)); } +#endif + +#undef SIMD_SINGLEOP1 +#undef SIMD_PACKEDOP3 +#undef SIMD_PACKEDOP2 +#undef SIMD_PACKEDOP1 + +//---------------------------------------------------------------------- +// Vector types to cast tuple data to +//---------------------------------------------------------------------- + +#if HAVE_VECTOR_EXTENSIONS && __GNUC__ >= 4 +#define VECTOR_ATTRIBUTE(mode,vs) __attribute__((vector_size(vs))) +#else +#define VECTOR_ATTRIBUTE(mode,vs) +#endif +typedef uint8_t v8qi_t VECTOR_ATTRIBUTE (V8QI,8); +typedef uint16_t v4hi_t VECTOR_ATTRIBUTE (V4HI,8); +typedef uint16_t v8hi_t VECTOR_ATTRIBUTE (V8HI,16); +typedef uint32_t v2si_t VECTOR_ATTRIBUTE (V2SI,8); +typedef uint32_t v4si_t VECTOR_ATTRIBUTE (V4SI,16); +#if HAVE_INT64_T +typedef uint64_t v1di_t VECTOR_ATTRIBUTE (V1DI,8); +#endif +typedef float v2sf_t VECTOR_ATTRIBUTE (V2SF,8); +typedef float v4sf_t VECTOR_ATTRIBUTE (V4SF,16); +typedef double v2df_t VECTOR_ATTRIBUTE (V2DF,16); +#undef VECTOR_ATTRIBUTE + +#define SIMDA_RI(n) "m"(oin[n]) +#define SIMDA_RO(n) "m"(oout[n]) +#define SIMDA_WI(n) "=m"(oin[n]) +#define SIMDA_WO(n) "=m"(oout[n]) + +//---------------------------------------------------------------------- +// Hardware accelerated specializations +//---------------------------------------------------------------------- + +#define SIMD_PKOP2_SPEC(n, type, optype) \ +template <> \ +inline void packop (const tuple<n,type>& oin, tuple<n,type>& oout, optype<type>) +#define SIMD_PASSIGN_SPEC(n, type) \ +template <> \ +inline void passign (const tuple<n,type>& oin, tuple<n,type>& oout) +#define SIMD_IPASSIGN_SPEC(n, type) \ +template <> \ +inline void ipassign (tuple<n,type>::const_iterator oin, tuple<n,type>& oout) +#define SIMD_CONVERT_SPEC(n, type1, type2, optype) \ +template <> \ +inline void pconvert (const tuple<n,type1>& oin, tuple<n,type2>& oout, optype<type1,type2>) + +#if CPU_HAS_MMX +#define STD_MMX_ARGS : "m"(oout[0]), "m"(oin[0]) : "mm0", "st", "memory" +#define DBL_MMX_ARGS : "m"(oout[0]), "m"(oout[2]), "m"(oin[0]), "m"(oin[2]) : "mm0", "mm1", "st", "st(1)", "memory" +#define MMX_PKOP2_SPEC(n,type,optype,instruction) \ +SIMD_PKOP2_SPEC(n,type,optype) \ +{ asm ("movq %0, %%mm0\n\t" #instruction " %1, %%mm0\n\tmovq %%mm0, %0" : STD_MMX_ARGS); reset_mmx(); } +#define MMX_DBL_PKOP2_SPEC(n,type,optype,instruction) \ +SIMD_PKOP2_SPEC(n,type,optype) \ +{ asm ("movq %0, %%mm0\n\tmovq %1, %%mm1\n\t" #instruction " %2, %%mm0\n\t" #instruction " %3, %%mm1\n\tmovq %%mm0, %0\n\tmovq %%mm1, %1" : DBL_MMX_ARGS); reset_mmx(); } +#define MMX_PASSIGN_SPEC(n,type) \ +SIMD_PASSIGN_SPEC(n,type) \ +{ asm ("movq %1, %%mm0\n\tmovq %%mm0, %0" : STD_MMX_ARGS); reset_mmx(); } +#define MMX_DBL_PASSIGN_SPEC(n,type) \ +SIMD_PASSIGN_SPEC(n,type) \ +{ asm ("movq %2, %%mm0\n\tmovq %3, %%mm1\n\tmovq %%mm0, %0\n\tmovq %%mm1, %1" : DBL_MMX_ARGS); reset_mmx(); } +#define MMX_IPASSIGN_SPEC(n,type) \ +SIMD_IPASSIGN_SPEC(n,type) \ +{ asm ("movq %1, %%mm0\n\tmovq %%mm0, %0" : STD_MMX_ARGS); reset_mmx(); } +#define MMX_DBL_IPASSIGN_SPEC(n,type) \ +SIMD_IPASSIGN_SPEC(n,type) \ +{ asm ("movq %2, %%mm0\n\tmovq %3, %%mm1\n\tmovq %%mm0, %0\n\tmovq %%mm1, %1" : DBL_MMX_ARGS); reset_mmx(); } + +MMX_PASSIGN_SPEC(8,uint8_t) +MMX_PKOP2_SPEC(8,uint8_t,plus,paddb) +MMX_PKOP2_SPEC(8,uint8_t,minus,psubb) +MMX_PKOP2_SPEC(8,uint8_t,bitwise_and,pand) +MMX_PKOP2_SPEC(8,uint8_t,bitwise_or,por) +MMX_PKOP2_SPEC(8,uint8_t,bitwise_xor,pxor) +MMX_PKOP2_SPEC(8,uint8_t,fpadds,paddusb) +MMX_PKOP2_SPEC(8,uint8_t,fpsubs,psubusb) + +MMX_PASSIGN_SPEC(8,int8_t) +MMX_PKOP2_SPEC(8,int8_t,plus,paddb) +MMX_PKOP2_SPEC(8,int8_t,minus,psubb) +MMX_PKOP2_SPEC(8,int8_t,bitwise_and,pand) +MMX_PKOP2_SPEC(8,int8_t,bitwise_or,por) +MMX_PKOP2_SPEC(8,int8_t,bitwise_xor,pxor) +MMX_PKOP2_SPEC(8,int8_t,fpadds,paddsb) +MMX_PKOP2_SPEC(8,int8_t,fpsubs,psubsb) + +MMX_PASSIGN_SPEC(4,uint16_t) +MMX_PKOP2_SPEC(4,uint16_t,plus,paddw) +MMX_PKOP2_SPEC(4,uint16_t,minus,psubw) +MMX_PKOP2_SPEC(4,uint16_t,bitwise_and,pand) +MMX_PKOP2_SPEC(4,uint16_t,bitwise_or,por) +MMX_PKOP2_SPEC(4,uint16_t,bitwise_xor,pxor) +/// \todo psllw does not work like other operations, it uses the first element for shift count. +//MMX_PKOP2_SPEC(4,uint16_t,fpshl,psllw) +//MMX_PKOP2_SPEC(4,uint16_t,fpshr,psrlw) +MMX_PKOP2_SPEC(4,uint16_t,fpadds,paddusw) +MMX_PKOP2_SPEC(4,uint16_t,fpsubs,psubusw) + +MMX_PASSIGN_SPEC(4,int16_t) +MMX_PKOP2_SPEC(4,int16_t,plus,paddw) +MMX_PKOP2_SPEC(4,int16_t,minus,psubw) +MMX_PKOP2_SPEC(4,int16_t,bitwise_and,pand) +MMX_PKOP2_SPEC(4,int16_t,bitwise_or,por) +MMX_PKOP2_SPEC(4,int16_t,bitwise_xor,pxor) +//MMX_PKOP2_SPEC(4,int16_t,fpshl,psllw) +//MMX_PKOP2_SPEC(4,int16_t,fpshr,psrlw) +MMX_PKOP2_SPEC(4,int16_t,fpadds,paddsw) +MMX_PKOP2_SPEC(4,int16_t,fpsubs,psubsw) + +MMX_PASSIGN_SPEC(2,uint32_t) +MMX_PKOP2_SPEC(2,uint32_t,plus,paddd) +MMX_PKOP2_SPEC(2,uint32_t,minus,psubd) +MMX_PKOP2_SPEC(2,uint32_t,bitwise_and,pand) +MMX_PKOP2_SPEC(2,uint32_t,bitwise_or,por) +MMX_PKOP2_SPEC(2,uint32_t,bitwise_xor,pxor) +//MMX_PKOP2_SPEC(2,uint32_t,fpshl,pslld) +//MMX_PKOP2_SPEC(2,uint32_t,fpshr,psrld) + +MMX_PASSIGN_SPEC(2,int32_t) +MMX_PKOP2_SPEC(2,int32_t,plus,paddd) +MMX_PKOP2_SPEC(2,int32_t,minus,psubd) +MMX_PKOP2_SPEC(2,int32_t,bitwise_and,pand) +MMX_PKOP2_SPEC(2,int32_t,bitwise_or,por) +MMX_PKOP2_SPEC(2,int32_t,bitwise_xor,pxor) +//MMX_PKOP2_SPEC(2,int32_t,fpshl,pslld) +//MMX_PKOP2_SPEC(2,int32_t,fpshr,psrld) + +MMX_DBL_PKOP2_SPEC(4,uint32_t,plus,paddd) +MMX_DBL_PKOP2_SPEC(4,uint32_t,minus,psubd) +MMX_DBL_PKOP2_SPEC(4,uint32_t,bitwise_and,pand) +MMX_DBL_PKOP2_SPEC(4,uint32_t,bitwise_or,por) +MMX_DBL_PKOP2_SPEC(4,uint32_t,bitwise_xor,pxor) +//MMX_DBL_PKOP2_SPEC(2,uint32_t,fpshl,pslld) +//MMX_DBL_PKOP2_SPEC(2,uint32_t,fpshr,psrld) + +MMX_DBL_PKOP2_SPEC(4,int32_t,plus,paddd) +MMX_DBL_PKOP2_SPEC(4,int32_t,minus,psubd) +MMX_DBL_PKOP2_SPEC(4,int32_t,bitwise_and,pand) +MMX_DBL_PKOP2_SPEC(4,int32_t,bitwise_or,por) +MMX_DBL_PKOP2_SPEC(4,int32_t,bitwise_xor,pxor) +//MMX_DBL_PKOP2_SPEC(2,int32_t,fpshl,pslld) +//MMX_DBL_PKOP2_SPEC(2,int32_t,fpshr,psrld) + +#if CPU_HAS_SSE || CPU_HAS_3DNOW +MMX_PKOP2_SPEC(8,uint8_t,fpavg,pavgb) +MMX_PKOP2_SPEC(8,int8_t,fpavg,pavgb) +MMX_PKOP2_SPEC(4,uint16_t,fpavg,pavgw) +MMX_PKOP2_SPEC(4,int16_t,fpavg,pavgw) +MMX_PKOP2_SPEC(8,uint8_t,fpmin,pminub) +MMX_PKOP2_SPEC(8,uint8_t,fpmax,pmaxub) +MMX_PKOP2_SPEC(4,int16_t,fpmax,pmaxsw) +MMX_PKOP2_SPEC(4,int16_t,fpmin,pminsw) +#endif // CPU_HAS_SSE || CPU_HAS_3DNOW + +#if CPU_HAS_3DNOW +MMX_PASSIGN_SPEC(2,float) +MMX_PKOP2_SPEC(2,float,plus,pfadd) +MMX_PKOP2_SPEC(2,float,minus,pfsub) +MMX_PKOP2_SPEC(2,float,multiplies,pfmul) +MMX_PKOP2_SPEC(2,float,fpmin,pfmin) +MMX_PKOP2_SPEC(2,float,fpmax,pfmax) +#ifndef CPU_HAS_SSE +MMX_DBL_PKOP2_SPEC(4,float,plus,pfadd) +MMX_DBL_PKOP2_SPEC(4,float,minus,pfsub) +MMX_DBL_PKOP2_SPEC(4,float,multiplies,pfmul) +MMX_DBL_PKOP2_SPEC(4,float,fpmin,pfmin) +MMX_DBL_PKOP2_SPEC(4,float,fpmax,pfmax) +#endif +#endif // CPU_HAS_3DNOW + +MMX_IPASSIGN_SPEC(8,uint8_t) +MMX_IPASSIGN_SPEC(4,uint16_t) +MMX_IPASSIGN_SPEC(2,uint32_t) +MMX_IPASSIGN_SPEC(2,float) + +#ifndef CPU_HAS_SSE +MMX_DBL_PASSIGN_SPEC(4,float) +MMX_DBL_PASSIGN_SPEC(4,uint32_t) +MMX_DBL_PASSIGN_SPEC(4,int32_t) +MMX_DBL_IPASSIGN_SPEC(4,float) +MMX_DBL_IPASSIGN_SPEC(4,uint32_t) +MMX_DBL_IPASSIGN_SPEC(4,int32_t) +#endif + +#undef MMX_IPASSIGN_SPEC +#undef MMX_PASSIGN_SPEC +#undef MMX_PKOP2_SPEC +#undef STD_MMX_ARGS +#endif // CPU_HAS_MMX + +#if CPU_HAS_SSE +#define STD_SSE_ARGS : "m"(oout[0]), "m"(oin[0]) : "xmm0", "memory" +#define SSE_PKOP2_SPEC(n,type,optype,instruction) \ +SIMD_PKOP2_SPEC(n,type,optype) \ +{ asm ("movups %0, %%xmm0\n\tmovups %1, %%xmm1\n\t" #instruction " %%xmm1, %%xmm0\n\tmovups %%xmm0, %0" : STD_SSE_ARGS);} +#define SSE_PASSIGN_SPEC(n,type) \ +SIMD_PASSIGN_SPEC(n,type) \ +{ asm ("movups %1, %%xmm0\n\tmovups %%xmm0, %0" : STD_SSE_ARGS);} +#define SSE_IPASSIGN_SPEC(n,type) \ +SIMD_IPASSIGN_SPEC(n,type) \ +{ asm ("movups %1, %%xmm0\n\tmovups %%xmm0, %0" : STD_SSE_ARGS);} +SSE_PASSIGN_SPEC(4,float) +SSE_PASSIGN_SPEC(4,int32_t) +SSE_PASSIGN_SPEC(4,uint32_t) +SSE_PKOP2_SPEC(4,float,plus,addps) +SSE_PKOP2_SPEC(4,float,minus,subps) +SSE_PKOP2_SPEC(4,float,multiplies,mulps) +SSE_PKOP2_SPEC(4,float,divides,divps) +SSE_PKOP2_SPEC(4,float,bitwise_and,andps) +SSE_PKOP2_SPEC(4,float,bitwise_or,orps) +SSE_PKOP2_SPEC(4,float,bitwise_xor,xorps) +SSE_PKOP2_SPEC(4,float,fpmax,maxps) +SSE_PKOP2_SPEC(4,float,fpmin,minps) + +SIMD_CONVERT_SPEC(4,float,int32_t,fround) { + asm ("cvtps2pi %2, %%mm0\n\t" + "cvtps2pi %3, %%mm1\n\t" + "movq %%mm0, %0\n\t" + "movq %%mm1, %1" + : DBL_MMX_ARGS); + reset_mmx(); +} +SIMD_CONVERT_SPEC(4,int32_t,float,fround) { + asm ("cvtpi2ps %2, %%xmm0\n\t" + "shufps $0x4E,%%xmm0,%%xmm0\n\t" + "cvtpi2ps %1, %%xmm0\n\t" + "movups %%xmm0, %0" + :: "m"(oout[0]), "m"(oin[0]), "m"(oin[2]) : "xmm0", "memory"); +} +template <> inline int32_t fround<float,int32_t>::operator()(const float& a) const { + register int32_t rv; + asm ("movss %1, %%xmm0\n\t" + "cvtss2si %%xmm0, %0" + : "=r"(rv) : "m"(a) : "xmm0" ); + return (rv); +} +template <> inline uint32_t fround<float,uint32_t>::operator()(const float& a) const { + register uint32_t rv; + asm ("movss %1, %%xmm0\n\t" + "cvtss2si %%xmm0, %0" + : "=r"(rv) : "m"(a) : "xmm0" ); + return (rv); +} + +SSE_IPASSIGN_SPEC(4,float) +SSE_IPASSIGN_SPEC(4,int32_t) +SSE_IPASSIGN_SPEC(4,uint32_t) + +#undef SSE_IPASSIGN_SPEC +#undef SSE_PASSIGN_SPEC +#undef SSE_PKOP2_SPEC +#undef STD_SSE_ARGS +#endif // CPU_HAS_SSE + +#undef SIMDA_RI +#undef SIMDA_RO +#undef SIMDA_WI +#undef SIMDA_WO +#undef SIMD_PACKEDOP_SPEC + +} // namespace simd +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/sistream.h @@ -0,0 +1,153 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef SISTREAM_H_0CCA102229A49F5D65EE852E62B27CE2 +#define SISTREAM_H_0CCA102229A49F5D65EE852E62B27CE2 + +#include "mistream.h" +#include "ustring.h" + +namespace ustl { + +/// \class istringstream sistream.h ustl.h +/// \ingroup TextStreams +/// +/// \brief A stream that reads textual data from a memory block. +/// +class istringstream : public istream { +public: + static const size_type c_MaxDelimiters = 16; ///< Maximum number of word delimiters. +public: + istringstream (void); + istringstream (const void* p, size_type n); + explicit istringstream (const cmemlink& source); + void iread (int8_t& v) { v = skip_delimiters(); } + void iread (int32_t& v); + void iread (double& v); + void iread (bool& v); + void iread (wchar_t& v); + void iread (string& v); +#if HAVE_INT64_T + void iread (int64_t& v); +#endif +#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8) + void iread (long long& v); +#endif + inline string str (void) const { string s; s.link (*this); return (s); } + inline istringstream& str (const string& s) { link (s); return (*this); } + inline istringstream& get (char& c) { return (read (&c, sizeof(c))); } + inline int get (void) { char c; get(c); return (c); } + istringstream& get (char* p, size_type n, char delim = '\n'); + istringstream& get (string& s, char delim = '\n'); + istringstream& getline (char* p, size_type n, char delim = '\n'); + istringstream& getline (string& s, char delim = '\n'); + istringstream& ignore (size_type n, char delim = '\0'); + inline char peek (void) { int8_t v; iread (v); ungetc(); return (v); } + inline istringstream& putback (char) { ungetc(); return (*this); } + inline istringstream& unget (void) { ungetc(); return (*this); } + inline void set_delimiters (const char* delimiters); + inline void set_base (short base); + inline void set_decimal_separator (char) { } + inline void set_thousand_separator (char) { } + istringstream& read (void* buffer, size_type size); + inline istringstream& read (memlink& buf) { return (read (buf.begin(), buf.size())); } + inline istringstream& seekg (off_t p, seekdir d =beg) { istream::seekg(p,d); return (*this); } + inline int sync (void) { skip (remaining()); return (0); } +protected: + char skip_delimiters (void); +private: + inline void read_strz (string&) { assert (!"Reading nul characters is not allowed from text streams"); } + inline bool is_delimiter (char c) const; + template <typename T> void read_number (T& v); +private: + char m_Delimiters [c_MaxDelimiters]; + uint8_t m_Base; +}; + +//---------------------------------------------------------------------- + +/// Sets the numeric base used to read numbers. +inline void istringstream::set_base (short base) +{ + m_Base = base; +} + +/// Sets delimiters to the contents of \p delimiters. +inline void istringstream::set_delimiters (const char* delimiters) +{ +#if (__i386__ || __x86_64__) && CPU_HAS_SSE && HAVE_VECTOR_EXTENSIONS + typedef uint32_t v16ud_t __attribute__((vector_size(16))); + asm("xorps\t%%xmm0, %%xmm0\n\tmovups\t%%xmm0, %0":"=m"(*noalias_cast<v16ud_t*>(m_Delimiters))::"xmm0"); +#else + memset (m_Delimiters, 0, sizeof(m_Delimiters)); +#endif + memcpy (m_Delimiters, delimiters, min (strlen(delimiters),sizeof(m_Delimiters)-1)); +} + +/// Reads one type as another. +template <typename RealT, typename CastT> +inline void _cast_read (istringstream& is, RealT& v) +{ + CastT cv; + is.iread (cv); + v = RealT (cv); +} + +/// Reads a line of text from \p is into \p s +inline istringstream& getline (istringstream& is, string& s) + { return (is.getline (s)); } + +//---------------------------------------------------------------------- + +template <typename T> struct object_text_reader { + inline void operator()(istringstream& is, T& v) const { v.text_read (is); } +}; +template <typename T> struct integral_text_object_reader { + inline void operator()(istringstream& is, T& v) const { is.iread (v); } +}; +template <typename T> +inline istringstream& operator>> (istringstream& is, T& v) { + typedef typename tm::Select <numeric_limits<T>::is_integral, + integral_text_object_reader<T>, object_text_reader<T> >::Result object_reader_t; + object_reader_t()(is, v); + return (is); +} + +//---------------------------------------------------------------------- + +template <> struct object_text_reader<string> { + inline void operator()(istringstream& is, string& v) const { is.iread (v); } +}; +#define ISTRSTREAM_CAST_OPERATOR(RealT, CastT) \ +template <> struct integral_text_object_reader<RealT> { \ + inline void operator() (istringstream& is, RealT& v) const \ + { _cast_read<RealT,CastT>(is, v); } \ +}; +ISTRSTREAM_CAST_OPERATOR (uint8_t, int8_t) +ISTRSTREAM_CAST_OPERATOR (int16_t, int32_t) +ISTRSTREAM_CAST_OPERATOR (uint16_t, int32_t) +ISTRSTREAM_CAST_OPERATOR (uint32_t, int32_t) +ISTRSTREAM_CAST_OPERATOR (float, double) +#if HAVE_THREE_CHAR_TYPES +ISTRSTREAM_CAST_OPERATOR (char, int8_t) +#endif +#if HAVE_INT64_T +ISTRSTREAM_CAST_OPERATOR (uint64_t, int64_t) +#endif +#if SIZE_OF_LONG == SIZE_OF_INT +// This works only properly if stdint.h typedefs int to int32_t. If stdint.h +// typedefs long to int32_t then this causes compiler errors. So make shure +// that your stdint.h file typedefs int to int32_t. +ISTRSTREAM_CAST_OPERATOR (long, int) +ISTRSTREAM_CAST_OPERATOR (unsigned long,int) +#endif +#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8) +ISTRSTREAM_CAST_OPERATOR (unsigned long long, long long) +#endif +#undef ISTRSTREAM_CAST_OPERATOR + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/sostream.h @@ -0,0 +1,161 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef SOSTREAM_H_5323DC8C26E181D43278F2F53FDCF19F +#define SOSTREAM_H_5323DC8C26E181D43278F2F53FDCF19F + +#include "ustring.h" +#include "mostream.h" + +namespace ustl { + +class string; + +/// \class ostringstream sostream.h ustl.h +/// \ingroup TextStreams +/// +/// \brief This stream writes textual data into a memory block. +/// +class ostringstream : public ostream { +public: + ostringstream (const string& v = ""); + ostringstream (void* p, size_t n); + void iwrite (uint8_t v); + void iwrite (wchar_t v); + inline void iwrite (int v) { iformat (v); } + inline void iwrite (unsigned int v) { iformat (v); } + inline void iwrite (long int v) { iformat (v); } + inline void iwrite (unsigned long int v) { iformat (v); } + inline void iwrite (float v) { iformat (v); } + inline void iwrite (double v) { iformat (v); } + void iwrite (bool v); + inline void iwrite (const char* s) { write (s, strlen(s)); } + inline void iwrite (const string& v) { write (v.begin(), v.size()); } + inline void iwrite (fmtflags f); +#if HAVE_LONG_LONG + inline void iwrite (long long v) { iformat (v); } + inline void iwrite (unsigned long long v) { iformat (v); } +#endif + inline size_type max_size (void) const { return (m_Buffer.max_size()); } + inline ostringstream& put (char c) { iwrite (uint8_t(c)); return (*this); } + int vformat (const char* fmt, va_list args); + int format (const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))); + inline void set_base (uint16_t b) { m_Base = b; } + inline void set_width (uint16_t w) { m_Width = w; } + inline void set_decimal_separator (char) { } + inline void set_thousand_separator (char) { } + inline void set_precision (uint16_t v) { m_Precision = v; } + void link (void* p, size_type n); + inline void link (memlink& l) { link (l.data(), l.writable_size()); } + inline const string& str (void) { flush(); return (m_Buffer); } + void str (const string& s); + ostringstream& write (const void* buffer, size_type size); + inline ostringstream& write (const cmemlink& buf) { return (write (buf.begin(), buf.size())); } + inline ostringstream& seekp (off_t p, seekdir d =beg) { ostream::seekp(p,d); return (*this); } + ostringstream& flush (void) { m_Buffer.resize (pos()); return (*this); } + virtual size_type overflow (size_type n = 1); +protected: + inline void reserve (size_type n) { m_Buffer.reserve (n, false); } + inline size_type capacity (void) const { return (m_Buffer.capacity()); } +private: + inline void write_strz (const char*) { assert (!"Writing nul characters into a text stream is not allowed"); } + inline char* encode_dec (char* fmt, uint32_t n) const; + void fmtstring (char* fmt, const char* typestr, bool bInteger) const; + template <typename T> + void iformat (T v); +private: + string m_Buffer; ///< The output buffer. + uint32_t m_Flags; ///< See ios_base::fmtflags. + uint16_t m_Width; ///< Field width. + uint8_t m_Base; ///< Numeric base for writing numbers. + uint8_t m_Precision; ///< Number of digits after the decimal separator. +}; + +//---------------------------------------------------------------------- + +template <typename T> +inline const char* printf_typestring (const T&) { return (""); } +#define PRINTF_TYPESTRING_SPEC(type,str) \ +template <> inline const char* printf_typestring (const type&) { return (str); } +PRINTF_TYPESTRING_SPEC (int, "d") +PRINTF_TYPESTRING_SPEC (unsigned int, "u") +PRINTF_TYPESTRING_SPEC (long, "ld") +PRINTF_TYPESTRING_SPEC (unsigned long, "lu") +PRINTF_TYPESTRING_SPEC (float, "f") +PRINTF_TYPESTRING_SPEC (double, "lf") +#if HAVE_LONG_LONG +PRINTF_TYPESTRING_SPEC (long long, "lld") +PRINTF_TYPESTRING_SPEC (unsigned long long, "llu") +#endif +#undef PRINTF_TYPESTRING_SPEC + +template <typename T> +void ostringstream::iformat (T v) +{ + char fmt [16]; + fmtstring (fmt, printf_typestring(v), numeric_limits<T>::is_integer); + format (fmt, v); +} + +/// Sets the flag \p f in the stream. +inline void ostringstream::iwrite (fmtflags f) +{ + switch (f) { + case oct: set_base (8); break; + case dec: set_base (10); break; + case hex: set_base (16); break; + case left: m_Flags |= left; m_Flags &= ~right; break; + case right: m_Flags |= right; m_Flags &= ~left; break; + default: m_Flags |= f; break; + } +} + +//---------------------------------------------------------------------- + +template <typename T> struct object_text_writer { + inline void operator()(ostringstream& os, const T& v) const { v.text_write (os); } +}; +template <typename T> struct integral_text_object_writer { + inline void operator()(ostringstream& os, const T& v) const { os.iwrite (v); } +}; +template <typename T> +inline ostringstream& operator<< (ostringstream& os, const T& v) { + typedef typename tm::Select <numeric_limits<T>::is_integral, + integral_text_object_writer<T>, object_text_writer<T> >::Result object_writer_t; + object_writer_t()(os, v); + return (os); +} +// Needed because if called with a char[], numeric_limits will not work. Should be removed if I find out how to partial specialize for arrays... +inline ostringstream& operator<< (ostringstream& os, const char* v) + { os.iwrite (v); return (os); } +inline ostringstream& operator<< (ostringstream& os, char* v) + { os.iwrite (v); return (os); } + +//---------------------------------------------------------------------- + +template <> struct object_text_writer<string> { + inline void operator()(ostringstream& os, const string& v) const { os.iwrite (v); } +}; +template <typename T> struct integral_text_object_writer<T*> { + inline void operator() (ostringstream& os, const T* const& v) const + { os.iwrite ((uintptr_t)(v)); } +}; +#define OSTRSTREAM_CAST_OPERATOR(RealT, CastT) \ +template <> inline ostringstream& operator<< (ostringstream& os, const RealT& v) \ + { os.iwrite ((CastT)(v)); return (os); } +OSTRSTREAM_CAST_OPERATOR (uint8_t* const, const char*) +OSTRSTREAM_CAST_OPERATOR (int8_t, uint8_t) +OSTRSTREAM_CAST_OPERATOR (short int, int) +OSTRSTREAM_CAST_OPERATOR (unsigned short, unsigned int) +#if HAVE_THREE_CHAR_TYPES +OSTRSTREAM_CAST_OPERATOR (char, uint8_t) +#endif +#undef OSTRSTREAM_CAST_OPERATOR + +//---------------------------------------------------------------------- + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/stdint.h @@ -0,0 +1,569 @@ +#ifndef CYGONCE_STDINT_H +#define CYGONCE_STDINT_H +/*============================================================================ +// +// stdint.h +// +// ISO C9x 7.18 Integer types +// +// =========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2009 Free Software Foundation, Inc. +// +// eCos 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 or (at your option) any later +// version. +// +// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +// =========================================================================== +//============================================================================ +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Uwe Kindler +// Contributors: +// Date: 2009-07-22 +// Purpose: +// Description: eCos stdint.h header file for ISO C9x 7.18 Integer types +// Usage: #include <stdint.h> +// +//####DESCRIPTIONEND#### +// +//============================================================================ +*/ + +// use the types defined in cyg_type.h to define the standard data types +#include <cyg/infra/cyg_type.h> + + +/* + * Copyright (c) 2004, 2005 by + * Ralf Corsepius, Ulm/Germany. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software + * is freely granted, provided that this notice is preserved. + */ +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__GNUC__) && \ + ( (__GNUC__ >= 4) || \ + ( (__GNUC__ >= 3) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ > 2) ) ) +/* gcc > 3.2 implicitly defines the values we are interested */ +#define __STDINT_EXP(x) __##x##__ +#else +#define __STDINT_EXP(x) x +#include <limits.h> +#endif + +/* Check if "long long" is 64bit wide */ +/* Modern GCCs provide __LONG_LONG_MAX__, SUSv3 wants LLONG_MAX */ +#if ( defined(__LONG_LONG_MAX__) && (__LONG_LONG_MAX__ > 0x7fffffff) ) \ + || ( defined(LLONG_MAX) && (LLONG_MAX > 0x7fffffff) ) +#define __have_longlong64 1 +#endif + +/* Check if "long" is 64bit or 32bit wide */ +#if __STDINT_EXP(LONG_MAX) > 0x7fffffff +#define __have_long64 1 +#elif __STDINT_EXP(LONG_MAX) == 0x7fffffff && !defined(__SPU__) +#define __have_long32 1 +#endif + +#if __STDINT_EXP(SCHAR_MAX) == 0x7f +typedef signed char int8_t ; +typedef unsigned char uint8_t ; +#define __int8_t_defined 1 +#endif + +#if __int8_t_defined +typedef signed char int_least8_t; +typedef unsigned char uint_least8_t; +#define __int_least8_t_defined 1 +#endif + +#if __STDINT_EXP(SHRT_MAX) == 0x7fff +typedef signed short int16_t; +typedef unsigned short uint16_t; +#define __int16_t_defined 1 +#elif __STDINT_EXP(INT_MAX) == 0x7fff +typedef signed int int16_t; +typedef unsigned int uint16_t; +#define __int16_t_defined 1 +#elif __STDINT_EXP(SCHAR_MAX) == 0x7fff +typedef signed char int16_t; +typedef unsigned char uint16_t; +#define __int16_t_defined 1 +#endif + +#if __int16_t_defined +typedef int16_t int_least16_t; +typedef uint16_t uint_least16_t; +#define __int_least16_t_defined 1 + +#if !__int_least8_t_defined +typedef int16_t int_least8_t; +typedef uint16_t uint_least8_t; +#define __int_least8_t_defined 1 +#endif +#endif + +// if long and int are both 32 bit then we prefer int for int32_t and uint32_t +// instead of long +#if __STDINT_EXP(INT_MAX) == 0x7fffffffL +typedef signed int int32_t; +typedef unsigned int uint32_t; +#define __int32_t_defined 1 +#elif __have_long32 +typedef signed long int32_t; +typedef unsigned long uint32_t; +#define __int32_t_defined 1 +#elif __STDINT_EXP(SHRT_MAX) == 0x7fffffffL +typedef signed short int32_t; +typedef unsigned short uint32_t; +#define __int32_t_defined 1 +#elif __STDINT_EXP(SCHAR_MAX) == 0x7fffffffL +typedef signed char int32_t; +typedef unsigned char uint32_t; +#define __int32_t_defined 1 +#endif + +#if __int32_t_defined +typedef int32_t int_least32_t; +typedef uint32_t uint_least32_t; +#define __int_least32_t_defined 1 + +#if !__int_least8_t_defined +typedef int32_t int_least8_t; +typedef uint32_t uint_least8_t; +#define __int_least8_t_defined 1 +#endif + +#if !__int_least16_t_defined +typedef int32_t int_least16_t; +typedef uint32_t uint_least16_t; +#define __int_least16_t_defined 1 +#endif +#endif + +#if __have_long64 +typedef signed long int64_t; +typedef unsigned long uint64_t; +#define __int64_t_defined 1 +#elif __have_longlong64 +typedef signed long long int64_t; +typedef unsigned long long uint64_t; +#define __int64_t_defined 1 +#elif __STDINT_EXP(INT_MAX) > 0x7fffffff +typedef signed int int64_t; +typedef unsigned int uint64_t; +#define __int64_t_defined 1 +#endif + +#if __int64_t_defined +typedef int64_t int_least64_t; +typedef uint64_t uint_least64_t; +#define __int_least64_t_defined 1 + +#if !__int_least8_t_defined +typedef int64_t int_least8_t; +typedef uint64_t uint_least8_t; +#define __int_least8_t_defined 1 +#endif + +#if !__int_least16_t_defined +typedef int64_t int_least16_t; +typedef uint64_t uint_least16_t; +#define __int_least16_t_defined 1 +#endif + +#if !__int_least32_t_defined +typedef int64_t int_least32_t; +typedef uint64_t uint_least32_t; +#define __int_least32_t_defined 1 +#endif +#endif + +/* + * Fastest minimum-width integer types + * + * Assume int to be the fastest type for all types with a width + * less than __INT_MAX__ rsp. INT_MAX + */ +#if 0 // we use the cyg_halcount types here instead of the newlib implementation +#if __STDINT_EXP(INT_MAX) >= 0x7f + typedef signed int int_fast8_t; + typedef unsigned int uint_fast8_t; +#define __int_fast8_t_defined 1 +#endif + +#if __STDINT_EXP(INT_MAX) >= 0x7fff + typedef signed int int_fast16_t; + typedef unsigned int uint_fast16_t; +#define __int_fast16_t_defined 1 +#endif + +#if __STDINT_EXP(INT_MAX) >= 0x7fffffff + typedef signed int int_fast32_t; + typedef unsigned int uint_fast32_t; +#define __int_fast32_t_defined 1 +#endif + +#if __STDINT_EXP(INT_MAX) > 0x7fffffff + typedef signed int int_fast64_t; + typedef unsigned int uint_fast64_t; +#define __int_fast64_t_defined 1 +#endif + + +/* + * Fall back to [u]int_least<N>_t for [u]int_fast<N>_t types + * not having been defined, yet. + * Leave undefined, if [u]int_least<N>_t should not be available. + */ +#if !__int_fast8_t_defined +#if __int_least8_t_defined + typedef int_least8_t int_fast8_t; + typedef uint_least8_t uint_fast8_t; +#define __int_fast8_t_defined 1 +#endif +#endif + +#if !__int_fast16_t_defined +#if __int_least16_t_defined + typedef int_least16_t int_fast16_t; + typedef uint_least16_t uint_fast16_t; +#define __int_fast16_t_defined 1 +#endif +#endif + +#if !__int_fast32_t_defined +#if __int_least32_t_defined + typedef int_least32_t int_fast32_t; + typedef uint_least32_t uint_fast32_t; +#define __int_fast32_t_defined 1 +#endif +#endif + +#if !__int_fast64_t_defined +#if __int_least64_t_defined + typedef int_least64_t int_fast64_t; + typedef uint_least64_t uint_fast64_t; +#define __int_fast64_t_defined 1 +#endif +#endif +#endif // 0 + +/* 7.18.1.3 Fastest minimum-width integer types + * Not actually guaranteed to be fastest for all purposes + * Here we use the cyg_halcount types from <cyg/infra/cyg_type.h> + */ +typedef cyg_halcount8 int_fast8_t; +typedef unsigned cyg_halcount8 uint_fast8_t; +typedef cyg_halcount16 int_fast16_t; +typedef unsigned cyg_halcount16 uint_fast16_t; +typedef cyg_halcount32 int_fast32_t; +typedef unsigned cyg_halcount32 uint_fast32_t; +typedef cyg_halcount64 int_fast64_t; +typedef unsigned cyg_halcount64 uint_fast64_t; + + +/* Greatest-width integer types */ +/* Modern GCCs provide __INTMAX_TYPE__ */ +#if defined(__INTMAX_TYPE__) + typedef __INTMAX_TYPE__ intmax_t; +#elif __have_longlong64 + typedef signed long long intmax_t; +#else + typedef signed long intmax_t; +#endif + +/* Modern GCCs provide __UINTMAX_TYPE__ */ +#if defined(__UINTMAX_TYPE__) + typedef __UINTMAX_TYPE__ uintmax_t; +#elif __have_longlong64 + typedef unsigned long long uintmax_t; +#else + typedef unsigned long uintmax_t; +#endif + +/* + * GCC doesn't provide an appropriate macro for [u]intptr_t + * For now, use __PTRDIFF_TYPE__ + */ +#if defined(__PTRDIFF_TYPE__) +typedef signed __PTRDIFF_TYPE__ intptr_t; +typedef unsigned __PTRDIFF_TYPE__ uintptr_t; +#define INTPTR_MAX PTRDIFF_MAX +#define INTPTR_MIN PTRDIFF_MIN +#ifdef __UINTPTR_MAX__ +#define UINTPTR_MAX __UINTPTR_MAX__ +#else +#define UINTPTR_MAX (2UL * PTRDIFF_MAX + 1) +#endif +#else +/* + * Fallback to hardcoded values, + * should be valid on cpu's with 32bit int/32bit void* + */ +typedef signed long intptr_t; +typedef unsigned long uintptr_t; +#define INTPTR_MAX __STDINT_EXP(LONG_MAX) +#define INTPTR_MIN (-__STDINT_EXP(LONG_MAX) - 1) +#define UINTPTR_MAX (__STDINT_EXP(LONG_MAX) * 2UL + 1) +#endif + +/* Limits of Specified-Width Integer Types */ + +#if __int8_t_defined +#define INT8_MIN -128 +#define INT8_MAX 127 +#define UINT8_MAX 255 +#endif + +#if __int_least8_t_defined +#define INT_LEAST8_MIN -128 +#define INT_LEAST8_MAX 127 +#define UINT_LEAST8_MAX 255 +#else +#error required type int_least8_t missing +#endif + +#if __int16_t_defined +#define INT16_MIN -32768 +#define INT16_MAX 32767 +#define UINT16_MAX 65535 +#endif + +#if __int_least16_t_defined +#define INT_LEAST16_MIN -32768 +#define INT_LEAST16_MAX 32767 +#define UINT_LEAST16_MAX 65535 +#else +#error required type int_least16_t missing +#endif + +#if __int32_t_defined +#if __have_long32 +#define INT32_MIN (-2147483647L-1) +#define INT32_MAX 2147483647L +#define UINT32_MAX 4294967295UL +#else +#define INT32_MIN (-2147483647-1) +#define INT32_MAX 2147483647 +#define UINT32_MAX 4294967295U +#endif +#endif + +#if __int_least32_t_defined +#if __have_long32 +#define INT_LEAST32_MIN (-2147483647L-1) +#define INT_LEAST32_MAX 2147483647L +#define UINT_LEAST32_MAX 4294967295UL +#else +#define INT_LEAST32_MIN (-2147483647-1) +#define INT_LEAST32_MAX 2147483647 +#define UINT_LEAST32_MAX 4294967295U +#endif +#else +#error required type int_least32_t missing +#endif + +#if __int64_t_defined +#if __have_long64 +#define INT64_MIN (-9223372036854775807L-1L) +#define INT64_MAX 9223372036854775807L +#define UINT64_MAX 18446744073709551615U +#elif __have_longlong64 +#define INT64_MIN (-9223372036854775807LL-1LL) +#define INT64_MAX 9223372036854775807LL +#define UINT64_MAX 18446744073709551615ULL +#endif +#endif + +#if __int_least64_t_defined +#if __have_long64 +#define INT_LEAST64_MIN (-9223372036854775807L-1L) +#define INT_LEAST64_MAX 9223372036854775807L +#define UINT_LEAST64_MAX 18446744073709551615U +#elif __have_longlong64 +#define INT_LEAST64_MIN (-9223372036854775807LL-1LL) +#define INT_LEAST64_MAX 9223372036854775807LL +#define UINT_LEAST64_MAX 18446744073709551615ULL +#endif +#endif + +#if __int_fast8_t_defined +#if __STDINT_EXP(INT_MAX) >= 0x7f +#define INT_FAST8_MIN (-__STDINT_EXP(INT_MAX)-1) +#define INT_FAST8_MAX __STDINT_EXP(INT_MAX) +#define UINT_FAST8_MAX (__STDINT_EXP(INT_MAX)*2U+1U) +#else +#define INT_FAST8_MIN INT_LEAST8_MIN +#define INT_FAST8_MAX INT_LEAST8_MAX +#define UINT_FAST8_MAX UINT_LEAST8_MAX +#endif +#endif + +#if __int_fast16_t_defined +#if __STDINT_EXP(INT_MAX) >= 0x7fff +#define INT_FAST16_MIN (-__STDINT_EXP(INT_MAX)-1) +#define INT_FAST16_MAX __STDINT_EXP(INT_MAX) +#define UINT_FAST16_MAX (__STDINT_EXP(INT_MAX)*2U+1U) +#else +#define INT_FAST16_MIN INT_LEAST16_MIN +#define INT_FAST16_MAX INT_LEAST16_MAX +#define UINT_FAST16_MAX UINT_LEAST16_MAX +#endif +#endif + +#if __int_fast32_t_defined +#if __STDINT_EXP(INT_MAX) >= 0x7fffffff +#define INT_FAST32_MIN (-__STDINT_EXP(INT_MAX)-1) +#define INT_FAST32_MAX __STDINT_EXP(INT_MAX) +#define UINT_FAST32_MAX (__STDINT_EXP(INT_MAX)*2U+1U) +#else +#define INT_FAST32_MIN INT_LEAST32_MIN +#define INT_FAST32_MAX INT_LEAST32_MAX +#define UINT_FAST32_MAX UINT_LEAST32_MAX +#endif +#endif + +#if __int_fast64_t_defined +#if __STDINT_EXP(INT_MAX) > 0x7fffffff +#define INT_FAST64_MIN (-__STDINT_EXP(INT_MAX)-1) +#define INT_FAST64_MAX __STDINT_EXP(INT_MAX) +#define UINT_FAST64_MAX (__STDINT_EXP(INT_MAX)*2U+1U) +#else +#define INT_FAST64_MIN INT_LEAST64_MIN +#define INT_FAST64_MAX INT_LEAST64_MAX +#define UINT_FAST64_MAX UINT_LEAST64_MAX +#endif +#endif + +#ifdef __INTMAX_MAX__ +#define INTMAX_MAX __INTMAX_MAX__ +#define INTMAX_MIN (-INTMAX_MAX - 1) +#elif defined(__INTMAX_TYPE__) +/* All relevant GCC versions prefer long to long long for intmax_t. */ +#define INTMAX_MAX INT64_MAX +#define INTMAX_MIN INT64_MIN +#endif + +#ifdef __UINTMAX_MAX__ +#define UINTMAX_MAX __UINTMAX_MAX__ +#elif defined(__UINTMAX_TYPE__) +/* All relevant GCC versions prefer long to long long for intmax_t. */ +#define UINTMAX_MAX UINT64_MAX +#endif + +/* This must match size_t in stddef.h, currently long unsigned int */ +#ifdef __SIZE_MAX__ +#define SIZE_MAX __SIZE_MAX__ +#else +#define SIZE_MAX (__STDINT_EXP(LONG_MAX) * 2UL + 1) +#endif + +/* This must match sig_atomic_t in <signal.h> (currently int) */ +#define SIG_ATOMIC_MIN (-__STDINT_EXP(INT_MAX) - 1) +#define SIG_ATOMIC_MAX __STDINT_EXP(INT_MAX) + +/* This must match ptrdiff_t in <stddef.h> (currently long int) */ +#ifdef __PTRDIFF_MAX__ +#define PTRDIFF_MAX __PTRDIFF_MAX__ +#else +#define PTRDIFF_MAX __STDINT_EXP(LONG_MAX) +#endif +#define PTRDIFF_MIN (-PTRDIFF_MAX - 1) + +#ifdef __WCHAR_MAX__ +#define WCHAR_MAX __WCHAR_MAX__ +#endif +#ifdef __WCHAR_MIN__ +#define WCHAR_MIN __WCHAR_MIN__ +#endif + +/* wint_t is unsigned int on almost all GCC targets. */ +#ifdef __WINT_MAX__ +#define WINT_MAX __WINT_MAX__ +#else +#define WINT_MAX (__STDINT_EXP(INT_MAX) * 2U + 1U) +#endif +#ifdef __WINT_MIN__ +#define WINT_MIN __WINT_MIN__ +#else +#define WINT_MIN 0U +#endif + +/** Macros for minimum-width integer constant expressions */ +#define INT8_C(x) x +#if __STDINT_EXP(INT_MAX) > 0x7f +#define UINT8_C(x) x +#else +#define UINT8_C(x) x##U +#endif + +#define INT16_C(x) x +#if __STDINT_EXP(INT_MAX) > 0x7fff +#define UINT16_C(x) x +#else +#define UINT16_C(x) x##U +#endif + +#if __have_long32 +#define INT32_C(x) x##L +#define UINT32_C(x) x##UL +#else +#define INT32_C(x) x +#define UINT32_C(x) x##U +#endif + +#if __int64_t_defined +#if __have_long64 +#define INT64_C(x) x##L +#define UINT64_C(x) x##UL +#else +#define INT64_C(x) x##LL +#define UINT64_C(x) x##ULL +#endif +#endif + +/** Macros for greatest-width integer constant expression */ +#if __have_long64 +#define INTMAX_C(x) x##L +#define UINTMAX_C(x) x##UL +#else +#define INTMAX_C(x) x##LL +#define UINTMAX_C(x) x##ULL +#endif + + +#ifdef __cplusplus +} +#endif + + +#endif // CYGONCE_STDINT_H
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/strmsize.h @@ -0,0 +1,82 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. +// +/// \file strmsize.h +/// \brief This file contains stream_size_of functions for basic types and *STREAMABLE macros. +/// stream_size_of functions return the size of the object's data that is written or +/// read from a stream. + +#ifndef STRMSIZE_H_052FF16B2D8A608761BF10333D065073 +#define STRMSIZE_H_052FF16B2D8A608761BF10333D065073 + +namespace ustl { + +/// For partial specialization of stream_size_of for objects +template <typename T> struct object_stream_size { + inline streamsize operator()(const T& v) const { return (v.stream_size()); } +}; +template <typename T> struct integral_object_stream_size { + inline streamsize operator()(const T& v) const { return (sizeof(v)); } +}; +/// Returns the size of the given object. Overloads for standard types are available. +template <typename T> +inline streamsize stream_size_of (const T& v) { + typedef typename tm::Select <numeric_limits<T>::is_integral, + integral_object_stream_size<T>, object_stream_size<T> >::Result stream_sizer_t; + return (stream_sizer_t()(v)); +} + +} // namespace ustl + +// +// Extra overloads in this macro are needed because it is the one used for +// marshalling pointers. Passing a pointer to stream_size_of creates a +// conversion ambiguity between converting to const pointer& and converting +// to bool; the compiler always chooses the bool conversion (because it +// requires 1 conversion instead of 2 for the other choice). There is little +// point in adding the overloads to other macros, since they are never used +// for pointers. +// +/// Declares that T is to be written as is into binary streams. +#define INTEGRAL_STREAMABLE(T) \ + namespace ustl { \ + inline istream& operator>> (istream& is, T& v) { is.iread(v); return (is); } \ + inline ostream& operator<< (ostream& os, const T& v) { os.iwrite(v); return (os); } \ + inline ostream& operator<< (ostream& os, T& v) { os.iwrite(v); return (os); } \ + template <> inline streamsize stream_size_of (const T& v) { return (sizeof(v)); } \ + } + +/// Declares that T contains read, write, and stream_size methods. This is no longer needed and is deprecated. +#define STD_STREAMABLE(T) + +/// Declares \p T to be writable to text streams. This is no longer needed and is deprecated. +#define TEXT_STREAMABLE(T) + +/// Declares that T is to be cast into TSUB for streaming. +#define CAST_STREAMABLE(T,TSUB) \ + namespace ustl { \ + inline istream& operator>> (istream& is, T& v) { TSUB sv; is >> sv; v = (T)(sv); return (is); } \ + inline ostream& operator<< (ostream& os, const T& v) { os << TSUB(v); return (os); } \ + template <> inline streamsize stream_size_of (const T& v) { return (stream_size_of (TSUB(v))); } \ + } + +/// Placed into a class it declares the methods required by STD_STREAMABLE. Syntactic sugar. +#define DECLARE_STD_STREAMABLE \ + public: \ + void read (istream& is); \ + void write (ostream& os) const; \ + streamsize stream_size (void) const + +/// Specifies that \p T is printed by using it as an index into \p Names string array. +#define LOOKUP_TEXT_STREAMABLE(T,Names,nNames) \ + namespace ustl { \ + inline ostringstream& operator<< (ostringstream& os, const T& v) \ + { \ + os << Names[min(uoff_t(v),uoff_t(nNames-1))]; \ + return (os); \ + } \ + } + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/traits.h @@ -0,0 +1,251 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2007-2009 by Mike Sharov <msharov@users.sourceforge.net> +// +// This implementation is adapted from the Loki library, distributed under +// the MIT license with Copyright (c) 2001 by Andrei Alexandrescu. + +#ifndef TRAITS_H_4AA3DDE15E16C947392711ED08FB1FF6 +#define TRAITS_H_4AA3DDE15E16C947392711ED08FB1FF6 + +#include "typelist.h" + +namespace ustl { +namespace tm { +namespace { + +//---------------------------------------------------------------------- +// Type classes and type modifiers +//---------------------------------------------------------------------- + +typedef tl::Seq<unsigned char, unsigned short, unsigned, unsigned long>::Type + StdUnsignedInts; +typedef tl::Seq<signed char, short, int, long>::Type StdSignedInts; +typedef tl::Seq<bool, char, wchar_t>::Type StdOtherInts; +typedef tl::Seq<float, double>::Type StdFloats; + +template <typename U> struct AddPointer { typedef U* Result; }; +template <typename U> struct AddPointer<U&> { typedef U* Result; }; +template <typename U> struct AddReference { typedef U& Result; }; +template <typename U> struct AddReference<U&> { typedef U& Result; }; +template <> struct AddReference<void> { typedef NullType Result; }; +template <typename U> struct AddParameterType { typedef const U& Result; }; +template <typename U> struct AddParameterType<U&> { typedef U& Result; }; +template <> struct AddParameterType<void> { typedef NullType Result; }; + +//---------------------------------------------------------------------- +// Function pointer testers +//---------------------------------------------------------------------- +// Macros expand to numerous parameters + +template <typename T> +struct IsFunctionPointerRaw { enum { result = false}; }; +template <typename T> +struct IsMemberFunctionPointerRaw { enum { result = false}; }; + +#define TM_FPR_MAXN 9 +#define TM_FPR_TYPE(n) PASTE(T,n) +#define TM_FPR_TYPENAME(n) typename TM_FPR_TYPE(n) + +// First specialize for regular functions +template <typename T> +struct IsFunctionPointerRaw<T(*)(void)> +{enum {result = true};}; + +#define TM_FPR_SPEC(n) \ +template <typename T, COMMA_LIST(n, TM_FPR_TYPENAME)> \ +struct IsFunctionPointerRaw<T(*)(COMMA_LIST(n, TM_FPR_TYPE))> \ +{ enum { result = true }; } + +LIST (TM_FPR_MAXN, TM_FPR_SPEC, ;); + +// Then for those with an ellipsis argument +template <typename T> +struct IsFunctionPointerRaw<T(*)(...)> +{enum {result = true};}; + +#define TM_FPR_SPEC_ELLIPSIS(n) \ +template <typename T, COMMA_LIST(n, TM_FPR_TYPENAME)> \ +struct IsFunctionPointerRaw<T(*)(COMMA_LIST(n, TM_FPR_TYPE), ...)> \ +{ enum { result = true }; } + +LIST (TM_FPR_MAXN, TM_FPR_SPEC_ELLIPSIS, ;); + +// Then for member function pointers +template <typename T, typename S> +struct IsMemberFunctionPointerRaw<T (S::*)(void)> +{ enum { result = true }; }; + +#define TM_MFPR_SPEC(n) \ +template <typename T, typename S, COMMA_LIST(n, TM_FPR_TYPENAME)> \ +struct IsMemberFunctionPointerRaw<T (S::*)(COMMA_LIST(n, TM_FPR_TYPE))> \ +{ enum { result = true };}; + +LIST (TM_FPR_MAXN, TM_MFPR_SPEC, ;); + +// Then for member function pointers with an ellipsis argument +template <typename T, typename S> +struct IsMemberFunctionPointerRaw<T (S::*)(...)> +{ enum { result = true }; }; + +#define TM_MFPR_SPEC_ELLIPSIS(n) \ +template <typename T, typename S, COMMA_LIST(n, TM_FPR_TYPENAME)> \ +struct IsMemberFunctionPointerRaw<T (S::*)(COMMA_LIST(n, TM_FPR_TYPE), ...)> \ +{ enum { result = true }; }; + +LIST (TM_FPR_MAXN, TM_MFPR_SPEC_ELLIPSIS, ;); + +// Then for const member function pointers (getting tired yet?) +template <typename T, typename S> +struct IsMemberFunctionPointerRaw<T (S::*)(void) const> +{ enum { result = true }; }; + +#define TM_CMFPR_SPEC(n) \ +template <typename T, typename S, COMMA_LIST(n, TM_FPR_TYPENAME)> \ +struct IsMemberFunctionPointerRaw<T (S::*)(COMMA_LIST(n, TM_FPR_TYPE)) const> \ +{ enum { result = true };}; + +LIST (TM_FPR_MAXN, TM_CMFPR_SPEC, ;); + +// Finally for const member function pointers with an ellipsis argument (whew!) +template <typename T, typename S> +struct IsMemberFunctionPointerRaw<T (S::*)(...) const> +{ enum { result = true }; }; + +#define TM_CMFPR_SPEC_ELLIPSIS(n) \ +template <typename T, typename S, COMMA_LIST(n, TM_FPR_TYPENAME)> \ +struct IsMemberFunctionPointerRaw<T (S::*)(COMMA_LIST(n, TM_FPR_TYPE), ...) const> \ +{ enum { result = true }; }; + +LIST (TM_FPR_MAXN, TM_CMFPR_SPEC_ELLIPSIS, ;); + +#undef TM_FPR_SPEC +#undef TM_FPR_SPEC_ELLIPSIS +#undef TM_MFPR_SPEC +#undef TM_MFPR_SPEC_ELLIPSIS +#undef TM_CMFPR_SPEC +#undef TM_CMFPR_SPEC_ELLIPSIS +#undef TM_FPR_TYPENAME +#undef TM_FPR_TYPE +#undef TM_FPR_MAXN + +} // namespace + +//---------------------------------------------------------------------- +// Type traits template +//---------------------------------------------------------------------- + +/// Figures out at compile time various properties of any given type +/// Invocations (T is a type, TypeTraits<T>::Propertie): +/// +/// - isPointer : returns true if T is a pointer type +/// - PointeeType : returns the type to which T points if T is a pointer +/// type, NullType otherwise +/// - isReference : returns true if T is a reference type +/// - ReferredType : returns the type to which T refers if T is a reference +/// type, NullType otherwise +/// - isMemberPointer : returns true if T is a pointer to member type +/// - isStdUnsignedInt: returns true if T is a standard unsigned integral type +/// - isStdSignedInt : returns true if T is a standard signed integral type +/// - isStdIntegral : returns true if T is a standard integral type +/// - isStdFloat : returns true if T is a standard floating-point type +/// - isStdArith : returns true if T is a standard arithmetic type +/// - isStdFundamental: returns true if T is a standard fundamental type +/// - isUnsignedInt : returns true if T is a unsigned integral type +/// - isSignedInt : returns true if T is a signed integral type +/// - isIntegral : returns true if T is a integral type +/// - isFloat : returns true if T is a floating-point type +/// - isArith : returns true if T is a arithmetic type +/// - isFundamental : returns true if T is a fundamental type +/// - ParameterType : returns the optimal type to be used as a parameter for +/// functions that take Ts +/// - isConst : returns true if T is a const-qualified type +/// - NonConstType : Type with removed 'const' qualifier from T, if any +/// - isVolatile : returns true if T is a volatile-qualified type +/// - NonVolatileType : Type with removed 'volatile' qualifier from T, if any +/// - UnqualifiedType : Type with removed 'const' and 'volatile' qualifiers from +/// T, if any +/// - ConstParameterType: returns the optimal type to be used as a parameter +/// for functions that take 'const T's +/// +template <typename T> +class TypeTraits { +private: + #define TMTT1 template <typename U> struct + #define TMTT2 template <typename U, typename V> struct + TMTT1 ReferenceTraits { enum { result = false }; typedef U ReferredType; }; + TMTT1 ReferenceTraits<U&> { enum { result = true }; typedef U ReferredType; }; + TMTT1 PointerTraits { enum { result = false }; typedef NullType PointeeType; }; + TMTT1 PointerTraits<U*> { enum { result = true }; typedef U PointeeType; }; + TMTT1 PointerTraits<U*&> { enum { result = true }; typedef U PointeeType; }; + TMTT1 PToMTraits { enum { result = false }; }; + TMTT2 PToMTraits<U V::*> { enum { result = true }; }; + TMTT2 PToMTraits<U V::*&> { enum { result = true }; }; + TMTT1 FunctionPointerTraits { enum { result = IsFunctionPointerRaw<U>::result }; }; + TMTT1 PToMFunctionTraits { enum { result = IsMemberFunctionPointerRaw<U>::result }; }; + TMTT1 UnConst { typedef U Result; enum { isConst = false }; }; + TMTT1 UnConst<const U> { typedef U Result; enum { isConst = true }; }; + TMTT1 UnConst<const U&> { typedef U& Result; enum { isConst = true }; }; + TMTT1 UnVolatile { typedef U Result; enum { isVolatile = false }; }; + TMTT1 UnVolatile<volatile U>{ typedef U Result; enum { isVolatile = true }; }; + TMTT1 UnVolatile<volatile U&> {typedef U& Result;enum { isVolatile = true }; }; + #undef TMTT2 + #undef TMTT1 +public: + typedef typename UnConst<T>::Result + NonConstType; + typedef typename UnVolatile<T>::Result + NonVolatileType; + typedef typename UnVolatile<typename UnConst<T>::Result>::Result + UnqualifiedType; + typedef typename PointerTraits<UnqualifiedType>::PointeeType + PointeeType; + typedef typename ReferenceTraits<T>::ReferredType + ReferredType; + + enum { isConst = UnConst<T>::isConst }; + enum { isVolatile = UnVolatile<T>::isVolatile }; + enum { isReference = ReferenceTraits<UnqualifiedType>::result }; + enum { isFunction = FunctionPointerTraits<typename AddPointer<T>::Result >::result }; + enum { isFunctionPointer= FunctionPointerTraits< + typename ReferenceTraits<UnqualifiedType>::ReferredType >::result }; + enum { isMemberFunctionPointer= PToMFunctionTraits< + typename ReferenceTraits<UnqualifiedType>::ReferredType >::result }; + enum { isMemberPointer = PToMTraits< + typename ReferenceTraits<UnqualifiedType>::ReferredType >::result || + isMemberFunctionPointer }; + enum { isPointer = PointerTraits< + typename ReferenceTraits<UnqualifiedType>::ReferredType >::result || + isFunctionPointer }; + enum { isStdUnsignedInt = tl::IndexOf<StdUnsignedInts, UnqualifiedType>::value >= 0 || + tl::IndexOf<StdUnsignedInts, + typename ReferenceTraits<UnqualifiedType>::ReferredType>::value >= 0}; + enum { isStdSignedInt = tl::IndexOf<StdSignedInts, UnqualifiedType>::value >= 0 || + tl::IndexOf<StdSignedInts, + typename ReferenceTraits<UnqualifiedType>::ReferredType>::value >= 0}; + enum { isStdIntegral = isStdUnsignedInt || isStdSignedInt || + tl::IndexOf<StdOtherInts, UnqualifiedType>::value >= 0 || + tl::IndexOf<StdOtherInts, + typename ReferenceTraits<UnqualifiedType>::ReferredType>::value >= 0}; + enum { isStdFloat = tl::IndexOf<StdFloats, UnqualifiedType>::value >= 0 || + tl::IndexOf<StdFloats, + typename ReferenceTraits<UnqualifiedType>::ReferredType>::value >= 0}; + enum { isStdArith = isStdIntegral || isStdFloat }; + enum { isStdFundamental = isStdArith || isStdFloat || Conversion<T, void>::sameType }; + + enum { isUnsignedInt = isStdUnsignedInt }; + enum { isSignedInt = isStdSignedInt }; + enum { isIntegral = isStdIntegral || isUnsignedInt || isSignedInt }; + enum { isFloat = isStdFloat }; + enum { isArith = isIntegral || isFloat }; + enum { isFundamental = isStdFundamental || isArith }; + + typedef typename Select<isStdArith || isPointer || isMemberPointer, T, + typename AddParameterType<T>::Result>::Result + ParameterType; +}; + +} // namespace tm +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/typelist.h @@ -0,0 +1,223 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2007-2009 by Mike Sharov <msharov@users.sourceforge.net> +// +// This implementation is adapted from the Loki library, distributed under +// the MIT license with Copyright (c) 2001 by Andrei Alexandrescu. + +#ifndef TYPELIST_H_2A8F84704780530D531716D41B3EA3FE +#define TYPELIST_H_2A8F84704780530D531716D41B3EA3FE + +#include "metamac.h" +#include "typet.h" + +namespace ustl { +namespace tm { + +/// The building block of typelists. Use it throught the Seq templates. +template <typename T, typename U> +struct Typelist { + typedef T Head; + typedef U Tail; +}; + +/// Namespace containing typelist-related functionality. +namespace tl { + +//---------------------------------------------------------------------- +// Seq template definitions. The macros expand to a spec per arg count +// +#define TL_MAX_SEQ_TYPES 9 +#define TL_MAX_SEQ_SPECS 8 +#define TL_SEQ_TYPE(n) T##n +#define TL_SEQ_TYPENAME(n) typename TL_SEQ_TYPE(n) +#define TL_SEQ_NULLTYPE_DEFAULT(n) TL_SEQ_TYPENAME(n)=NullType +#define TL_SEQ_TL_END(n) > +#define TL_SEQ_ONE_TYPELIST(n) Typelist<TL_SEQ_TYPE(n) + +/// Creates a typelist from a sequence of types +template <COMMA_LIST(TL_MAX_SEQ_TYPES,TL_SEQ_NULLTYPE_DEFAULT)> +struct Seq { + typedef COMMA_LIST(TL_MAX_SEQ_TYPES,TL_SEQ_ONE_TYPELIST), + NullType REPEAT(TL_MAX_SEQ_TYPES,TL_SEQ_TL_END) Type; +}; + +#define TL_SEQ_SPEC(n) \ +template <COMMA_LIST (n, TL_SEQ_TYPENAME)> \ +struct Seq<COMMA_LIST (n, TL_SEQ_TYPE)> { \ + typedef COMMA_LIST(n,TL_SEQ_ONE_TYPELIST), \ + NullType REPEAT(n,TL_SEQ_TL_END) Type; \ +} +LIST(TL_MAX_SEQ_SPECS,TL_SEQ_SPEC, ;); + +#undef TL_SEQ_SPEC +#undef TL_SEQ_TL_END +#undef TL_SEQ_ONE_TYPELIST +#undef TL_SEQ_NULLTYPE_DEFAULT +#undef TL_SEQ_TYPE +#undef TL_MAX_SEQ_SPECS + +//---------------------------------------------------------------------- +// Various utility functions follow. + +/// Length<List>::value is the number of types in the typelist. +template <typename List> struct Length { }; +template <> struct Length<NullType> { enum { value = 0 }; }; +template <typename T, typename U> +struct Length<Typelist<T, U> > { enum { value = 1 + Length<U>::value }; }; + +/// TypeAt<List, i>::Result is the ith type in List +template <typename List, unsigned index> struct TypeAt { }; +template <class Head, class Tail> +struct TypeAt<Typelist<Head, Tail>, 0> { + typedef Head Result; +}; +template <class Head, class Tail, unsigned index> +struct TypeAt<Typelist<Head, Tail>, index> { + typedef typename TypeAt<Tail, index-1>::Result Result; +}; + +/// TypeAtNonStrict<List,i,DefaultType>::Result is List[i] or DefaultType if out of range. +template <typename List, unsigned index, typename DefaultType = NullType> +struct TypeAtNonStrict { + typedef DefaultType Result; +}; +template <typename Head, typename Tail, typename DefaultType> +struct TypeAtNonStrict<Typelist<Head, Tail>, 0, DefaultType> { + typedef Head Result; +}; +template <typename Head, typename Tail, unsigned index, typename DefaultType> +struct TypeAtNonStrict<Typelist<Head, Tail>, index, DefaultType> { + typedef typename TypeAtNonStrict<Tail, index-1, DefaultType>::Result Result; +}; + +/// IndexOf<List,T>::value is the position of T in List, or -1 if not found. +template <typename List, typename T> struct IndexOf; +template <typename T> +struct IndexOf<NullType, T> { enum { value = -1 }; }; +template <typename T, typename Tail> +struct IndexOf<Typelist<T, Tail>, T> { enum { value = 0 }; }; +template <typename Head, typename Tail, typename T> +struct IndexOf<Typelist<Head, Tail>, T> { +private: + enum { iintail = IndexOf<Tail, T>::value }; +public: + enum { value = (iintail == -1 ? -1 : 1+iintail) }; +}; + +/// Appends a type or a typelist to another in Append<TList, T>::Result +template <typename List, typename T> struct Append; +template <> struct Append<NullType, NullType> { typedef NullType Result; }; +template <typename T> struct Append<NullType, T> { + typedef Typelist<T,NullType> Result; +}; +template <typename Head, typename Tail> +struct Append<NullType, Typelist<Head, Tail> > { + typedef Typelist<Head, Tail> Result; +}; +template <typename Head, typename Tail, typename T> +struct Append<Typelist<Head, Tail>, T> { + typedef Typelist<Head, typename Append<Tail, T>::Result> Result; +}; + +// Erase<List, T>::Result contains List without the first T. +template <typename TList, typename T> struct Erase; +template <typename T> +struct Erase<NullType, T> { typedef NullType Result; }; +template <typename T, typename Tail> +struct Erase<Typelist<T, Tail>, T> { typedef Tail Result; }; +template <typename Head, typename Tail, typename T> +struct Erase<Typelist<Head, Tail>, T> { + typedef Typelist<Head, typename Erase<Tail, T>::Result> Result; +}; + +// EraseAll<List, T>::Result contains List without any T. +template <typename List, typename T> struct EraseAll; +template <typename T> +struct EraseAll<NullType, T> { typedef NullType Result; }; +template <typename T, typename Tail> +struct EraseAll<Typelist<T, Tail>, T> { + typedef typename EraseAll<Tail, T>::Result Result; +}; +template <typename Head, typename Tail, typename T> +struct EraseAll<Typelist<Head, Tail>, T> { + typedef Typelist<Head, typename EraseAll<Tail, T>::Result> Result; +}; + +/// Removes all duplicate types in a typelist +template <typename List> struct NoDuplicates; +template <> struct NoDuplicates<NullType> { typedef NullType Result; }; +template <typename Head, typename Tail> +struct NoDuplicates< Typelist<Head, Tail> > { +private: + typedef typename NoDuplicates<Tail>::Result L1; + typedef typename Erase<L1, Head>::Result L2; +public: + typedef Typelist<Head, L2> Result; +}; + +// Replaces the first occurence of a type in a typelist, with another type +template <typename List, typename T, typename U> struct Replace; +template <typename T, typename U> +struct Replace<NullType, T, U> { typedef NullType Result; }; +template <typename T, typename Tail, typename U> +struct Replace<Typelist<T, Tail>, T, U> { + typedef Typelist<U, Tail> Result; +}; +template <typename Head, typename Tail, typename T, typename U> +struct Replace<Typelist<Head, Tail>, T, U> { + typedef Typelist<Head, typename Replace<Tail, T, U>::Result> Result; +}; + +// Replaces all occurences of a type in a typelist, with another type +template <typename List, typename T, typename U> struct ReplaceAll; +template <typename T, typename U> +struct ReplaceAll<NullType, T, U> { typedef NullType Result; }; +template <typename T, typename Tail, typename U> +struct ReplaceAll<Typelist<T, Tail>, T, U> { + typedef Typelist<U, typename ReplaceAll<Tail, T, U>::Result> Result; +}; +template <typename Head, typename Tail, typename T, typename U> +struct ReplaceAll<Typelist<Head, Tail>, T, U> { + typedef Typelist<Head, typename ReplaceAll<Tail, T, U>::Result> Result; +}; + +// Reverses a typelist +template <typename List> struct Reverse; +template <> struct Reverse<NullType> { typedef NullType Result; }; +template <typename Head, typename Tail> +struct Reverse< Typelist<Head, Tail> > { + typedef typename Append<typename Reverse<Tail>::Result, Head>::Result Result; +}; + +// Finds the type in a typelist that is the most derived from a given type +template <typename List, typename T> struct MostDerived; +template <typename T> struct MostDerived<NullType, T> { typedef T Result; }; +template <typename Head, typename Tail, typename T> +struct MostDerived<Typelist<Head, Tail>, T> { +private: + typedef typename MostDerived<Tail, T>::Result Candidate; +public: + typedef typename Select<SuperSubclass<Candidate,Head>::value, Head, Candidate>::Result Result; +}; + +// Arranges the types in a typelist so that the most derived types appear first +template <typename List> struct DerivedToFront; +template <> struct DerivedToFront<NullType> { typedef NullType Result; }; +template <typename Head, typename Tail> +struct DerivedToFront< Typelist<Head, Tail> > { +private: + typedef typename MostDerived<Tail, Head>::Result TheMostDerived; + typedef typename Replace<Tail, TheMostDerived, Head>::Result Temp; + typedef typename DerivedToFront<Temp>::Result L; +public: + typedef Typelist<TheMostDerived, L> Result; +}; + +//---------------------------------------------------------------------- + +} // namespace tl +} // namespace tm +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/typet.h @@ -0,0 +1,98 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2007-2009 by Mike Sharov <msharov@users.sourceforge.net> +// +// This implementation is adapted from the Loki library, distributed under +// the MIT license with Copyright (c) 2001 by Andrei Alexandrescu. + +#ifndef TYPET_H_70B4C9693A05E0B405B225F356DE5450 +#define TYPET_H_70B4C9693A05E0B405B225F356DE5450 + +namespace ustl { +/// Template metaprogramming tools +namespace tm { + +/// An empty type useful as a placeholder. +class NullType { }; + +/// Converts an integer to a type. +template <int v> struct Int2Type { enum { value = v }; }; + +/// Converts an type to a unique empty type. +template <typename T> struct Type2Type { typedef T OriginalType; }; + +/// Selects type Result = flag ? T : U +template <bool flag, typename T, typename U> +struct Select { typedef T Result; }; +template <typename T, typename U> +struct Select<false, T, U> { typedef U Result; }; + +/// IsSameType<T,U>::value is true when T=U +template <typename T, typename U> +struct IsSameType { enum { value = false }; }; +template <typename T> +struct IsSameType<T,T> { enum { value = true }; }; + +/// \brief Checks for conversion possibilities between T and U +/// Conversion<T,U>::exists is true if T is convertible to U +/// Conversion<T,U>::exists2Way is true if U is also convertible to T +/// Conversion<T,U>::sameType is true if U is T +template <typename T, typename U> +class Conversion { + typedef char UT; + typedef short TT; + static UT Test (U); + static TT Test (...); + static T MakeT (void); +public: + enum { + exists = sizeof(UT) == sizeof(Test(MakeT())), + exists2Way = exists && Conversion<U,T>::exists, + sameType = false + }; +}; +template <typename T> +struct Conversion<T, T> { enum { exists = true, exists2Way = true, sameType = true }; }; +template <typename T> +struct Conversion<void, T> { enum { exists = false, exists2Way = false, sameType = false }; }; +template <typename T> +struct Conversion<T, void> { enum { exists = false, exists2Way = false, sameType = false }; }; +template <> +struct Conversion<void, void> { enum { exists = true, exists2Way = true, sameType = true }; }; + +/// SuperSubclass<T,U>::value is true when U is derived from T, or when U is T +template <typename T, typename U> +struct SuperSubclass { + enum { value = (::ustl::tm::Conversion<const volatile U*, const volatile T*>::exists && + !::ustl::tm::Conversion<const volatile T*, const volatile void*>::sameType) }; + enum { dontUseWithIncompleteTypes = sizeof(T)==sizeof(U) }; // Dummy enum to make sure that both classes are fully defined. +}; +template <> +struct SuperSubclass<void, void> { enum { value = false }; }; +template <typename U> +struct SuperSubclass<void, U> { + enum { value = false }; + enum { dontUseWithIncompleteTypes = 0==sizeof(U) }; +}; +template <typename T> +struct SuperSubclass<T, void> { + enum { value = false }; + enum { dontUseWithIncompleteTypes = 0==sizeof(T) }; +}; + +/// SuperSubclassStrict<T,U>::value is true when U is derived from T +template <typename T, typename U> +struct SuperSubclassStrict { + enum { value = SuperSubclass<T,U>::value && + !::ustl::tm::Conversion<const volatile T*, const volatile U*>::sameType }; +}; + +// static assert support +template <bool> struct CompileTimeError; +template <> struct CompileTimeError<true> {}; +#define static_assert(cond,msg) { ::ustl::tm::CompileTimeError<!!(cond)> ERROR_##msg; (void) ERROR_##msg; } + +} // namespace tm +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/ualgo.h @@ -0,0 +1,667 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UALGO_H_711AB4214D417A51166694D47A662D6E +#define UALGO_H_711AB4214D417A51166694D47A662D6E + +#include "upair.h" +#include "ualgobase.h" +#include "ufunction.h" +#include "upredalgo.h" +#include "umemory.h" +#include <stdlib.h> // for rand() + +namespace ustl { + +/// Swaps corresponding elements of [first, last) and [result,) +/// \ingroup SwapAlgorithms +/// +template <typename ForwardIterator1, typename ForwardIterator2> +inline ForwardIterator2 swap_ranges (ForwardIterator1 first, ForwardIterator2 last, ForwardIterator2 result) +{ + for (; first != last; ++first, ++result) + iter_swap (first, result); + return (result); +} + +/// Returns the first iterator i in the range [first, last) such that +/// *i == value. Returns last if no such iterator exists. +/// \ingroup SearchingAlgorithms +/// +template <typename InputIterator, typename EqualityComparable> +inline InputIterator find (InputIterator first, InputIterator last, const EqualityComparable& value) +{ + while (first != last && !(*first == value)) + ++ first; + return (first); +} + +/// Returns the first iterator such that *i == *(i + 1) +/// \ingroup SearchingAlgorithms +/// +template <typename ForwardIterator> +ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last) +{ + if (first != last) + for (ForwardIterator prev = first; ++first != last; ++ prev) + if (*prev == *first) + return (prev); + return (last); +} + +/// Returns the pointer to the first pair of unequal elements. +/// \ingroup SearchingAlgorithms +/// +template <typename InputIterator> +pair<InputIterator,InputIterator> +mismatch (InputIterator first1, InputIterator last1, InputIterator first2) +{ + while (first1 != last1 && *first1 == *first2) + ++ first1, ++ first2; + return (make_pair (first1, first2)); +} + +/// \brief Returns true if two ranges are equal. +/// This is an extension, present in uSTL and SGI STL. +/// \ingroup SearchingAlgorithms +/// +template <typename InputIterator> +inline bool equal (InputIterator first1, InputIterator last1, InputIterator first2) +{ + return (mismatch (first1, last1, first2).first == last1); +} + +/// Count finds the number of elements in [first, last) that are equal +/// to value. More precisely, the first version of count returns the +/// number of iterators i in [first, last) such that *i == value. +/// \ingroup SearchingAlgorithms +/// +template <typename InputIterator, typename EqualityComparable> +inline size_t count (InputIterator first, InputIterator last, const EqualityComparable& value) +{ + size_t total = 0; + for (; first != last; ++first) + if (*first == value) + ++ total; + return (total); +} + +/// +/// The first version of transform performs the operation op(*i) for each +/// iterator i in the range [first, last), and assigns the result of that +/// operation to *o, where o is the corresponding output iterator. That is, +/// for each n such that 0 <= n < last - first, it performs the assignment +/// *(result + n) = op(*(first + n)). +/// The return value is result + (last - first). +/// \ingroup MutatingAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename InputIterator, typename OutputIterator, typename UnaryFunction> +inline OutputIterator transform (InputIterator first, InputIterator last, OutputIterator result, UnaryFunction op) +{ + for (; first != last; ++result, ++first) + *result = op (*first); + return (result); +} + +/// +/// The second version of transform is very similar, except that it uses a +/// Binary Function instead of a Unary Function: it performs the operation +/// op(*i1, *i2) for each iterator i1 in the range [first1, last1) and assigns +/// the result to *o, where i2 is the corresponding iterator in the second +/// input range and where o is the corresponding output iterator. That is, +/// for each n such that 0 <= n < last1 - first1, it performs the assignment +/// *(result + n) = op(*(first1 + n), *(first2 + n). +/// The return value is result + (last1 - first1). +/// \ingroup MutatingAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename BinaryFunction> +inline OutputIterator transform (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator result, BinaryFunction op) +{ + for (; first1 != last1; ++result, ++first1, ++first2) + *result = op (*first1, *first2); + return (result); +} + +/// Replace replaces every element in the range [first, last) equal to +/// old_value with new_value. That is: for every iterator i, +/// if *i == old_value then it performs the assignment *i = new_value. +/// \ingroup MutatingAlgorithms +/// +template <typename ForwardIterator, typename T> +inline void replace (ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value) +{ + for (; first != last; ++first) + if (*first == old_value) + *first = new_value; +} + +/// Replace_copy copies elements from the range [first, last) to the range +/// [result, result + (last-first)), except that any element equal to old_value +/// is not copied; new_value is copied instead. More precisely, for every +/// integer n such that 0 <= n < last-first, replace_copy performs the +/// assignment *(result+n) = new_value if *(first+n) == old_value, and +/// *(result+n) = *(first+n) otherwise. +/// \ingroup MutatingAlgorithms +/// +template <typename InputIterator, typename OutputIterator, typename T> +inline OutputIterator replace_copy (InputIterator first, InputIterator last, OutputIterator result, const T& old_value, const T& new_value) +{ + for (; first != last; ++result, ++first) + *result = (*first == old_value) ? new_value : *first; +} + +/// Generate assigns the result of invoking gen, a function object that +/// takes no arguments, to each element in the range [first, last). +/// \ingroup GeneratorAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename ForwardIterator, typename Generator> +inline void generate (ForwardIterator first, ForwardIterator last, Generator gen) +{ + for (; first != last; ++first) + *first = gen(); +} + +/// Generate_n assigns the result of invoking gen, a function object that +/// takes no arguments, to each element in the range [first, first+n). +/// The return value is first + n. +/// \ingroup GeneratorAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename OutputIterator, typename Generator> +inline OutputIterator generate_n (OutputIterator first, size_t n, Generator gen) +{ + for (uoff_t i = 0; i != n; ++i, ++first) + *first = gen(); + return (first); +} + +/// \brief Reverse reverses a range. +/// That is: for every i such that 0 <= i <= (last - first) / 2), +/// it exchanges *(first + i) and *(last - (i + 1)). +/// \ingroup MutatingAlgorithms +/// +template <typename BidirectionalIterator> +inline void reverse (BidirectionalIterator first, BidirectionalIterator last) +{ + for (; distance (first, --last) > 0; ++first) + iter_swap (first, last); +} + +/// \brief Reverses [first,last) and writes it to \p output. +/// \ingroup MutatingAlgorithms +/// +template <typename BidirectionalIterator, typename OutputIterator> +inline OutputIterator reverse_copy (BidirectionalIterator first, BidirectionalIterator last, OutputIterator result) +{ + for (; first != last; ++result) + *result = *--last; + return (result); +} + +/// \brief Exchanges ranges [first, middle) and [middle, last) +/// \ingroup MutatingAlgorithms +/// +template <typename ForwardIterator> +ForwardIterator rotate (ForwardIterator first, ForwardIterator middle, ForwardIterator last) +{ + if (first == middle || middle == last) + return (first); + reverse (first, middle); + reverse (middle, last); + for (;first != middle && middle != last; ++first) + iter_swap (first, --last); + reverse (first, (first == middle ? last : middle)); + return (first); +} + +/// Specialization for pointers, which can be treated identically. +template <typename T> +inline T* rotate (T* first, T* middle, T* last) +{ + rotate_fast (first, middle, last); + return (first); +} + + +/// \brief Exchanges ranges [first, middle) and [middle, last) into \p result. +/// \ingroup MutatingAlgorithms +/// +template <typename ForwardIterator, typename OutputIterator> +inline OutputIterator rotate_copy (ForwardIterator first, ForwardIterator middle, ForwardIterator last, OutputIterator result) +{ + return (copy (first, middle, copy (middle, last, result))); +} + +/// \brief Combines two sorted ranges. +/// \ingroup SortingAlgorithms +/// +template <typename InputIterator1, typename InputIterator2, typename OutputIterator> +OutputIterator merge (InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, OutputIterator result) +{ + for (; first1 != last1 && first2 != last2; ++result) { + if (*first1 < *first2) + *result = *first1++; + else + *result = *first2++; + } + if (first1 < last1) + return (copy (first1, last1, result)); + else + return (copy (first2, last2, result)); +} + +/// Combines two sorted ranges from the same container. +/// \ingroup SortingAlgorithms +/// +template <typename InputIterator> +void inplace_merge (InputIterator first, InputIterator middle, InputIterator last) +{ + for (; middle != last; ++first) { + while (*first < *middle) + ++ first; + reverse (first, middle); + reverse (first, ++middle); + } +} + +/// Remove_copy copies elements that are not equal to value from the range +/// [first, last) to a range beginning at result. The return value is the +/// end of the resulting range. This operation is stable, meaning that the +/// relative order of the elements that are copied is the same as in the +/// range [first, last). +/// \ingroup MutatingAlgorithms +/// +template <typename InputIterator, typename OutputIterator, typename T> +OutputIterator remove_copy (InputIterator first, InputIterator last, OutputIterator result, const T& value) +{ + for (; first != last; ++first) { + if (!(*first == value)) { + *result = *first; + ++ result; + } + } + return (result); +} + +/// Remove_copy copies elements pointed to by iterators in [rfirst, rlast) +/// from the range [first, last) to a range beginning at result. The return +/// value is the end of the resulting range. This operation is stable, meaning +/// that the relative order of the elements that are copied is the same as in the +/// range [first, last). Range [rfirst, rlast) is assumed to be sorted. +/// This algorithm is a uSTL extension. +/// \ingroup MutatingAlgorithms +/// +template <typename InputIterator, typename OutputIterator, typename RInputIterator> +OutputIterator remove_copy (InputIterator first, InputIterator last, OutputIterator result, RInputIterator rfirst, RInputIterator rlast) +{ + for (; first != last; ++first) { + while (rfirst != rlast && *rfirst < first) + ++ rfirst; + if (rfirst == rlast || first != *rfirst) { + *result = *first; + ++ result; + } + } + return (result); +} + +/// Remove removes from the range [first, last) all elements that are equal to +/// value. That is, remove returns an iterator new_last such that the range +/// [first, new_last) contains no elements equal to value. [1] The iterators +/// in the range [new_last, last) are all still dereferenceable, but the +/// elements that they point to are unspecified. Remove is stable, meaning +/// that the relative order of elements that are not equal to value is +/// unchanged. +/// \ingroup MutatingAlgorithms +/// +template <typename ForwardIterator, typename T> +inline ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& value) +{ + return (remove_copy (first, last, first, value)); +} + +/// Unique_copy copies elements from the range [first, last) to a range +/// beginning with result, except that in a consecutive group of duplicate +/// elements only the first one is copied. The return value is the end of +/// the range to which the elements are copied. This behavior is similar +/// to the Unix filter uniq. +/// \ingroup MutatingAlgorithms +/// +template <typename InputIterator, typename OutputIterator> +OutputIterator unique_copy (InputIterator first, InputIterator last, OutputIterator result) +{ + if (first != last) { + *result = *first; + while (++first != last) + if (!(*first == *result)) + *++result = *first; + ++ result; + } + return (result); +} + +/// Every time a consecutive group of duplicate elements appears in the range +/// [first, last), the algorithm unique removes all but the first element. +/// That is, unique returns an iterator new_last such that the range [first, +/// new_last) contains no two consecutive elements that are duplicates. +/// The iterators in the range [new_last, last) are all still dereferenceable, +/// but the elements that they point to are unspecified. Unique is stable, +/// meaning that the relative order of elements that are not removed is +/// unchanged. +/// \ingroup MutatingAlgorithms +/// +template <typename ForwardIterator> +inline ForwardIterator unique (ForwardIterator first, ForwardIterator last) +{ + return (unique_copy (first, last, first)); +} + +/// Returns the furthermost iterator i in [first, last) such that, +/// for every iterator j in [first, i), *j < value +/// Assumes the range is sorted. +/// \ingroup SearchingAlgorithms +/// +template <typename ForwardIterator, typename LessThanComparable> +ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const LessThanComparable& value) +{ + ForwardIterator mid; + while (first != last) { + mid = advance (first, distance (first,last) / 2); + if (*mid < value) + first = mid + 1; + else + last = mid; + } + return (first); +} + +/// Performs a binary search inside the sorted range. +/// \ingroup SearchingAlgorithms +/// +template <typename ForwardIterator, typename LessThanComparable> +inline bool binary_search (ForwardIterator first, ForwardIterator last, const LessThanComparable& value) +{ + ForwardIterator found = lower_bound (first, last, value); + return (found != last && !(value < *found)); +} + +/// Returns the furthermost iterator i in [first,last) such that for +/// every iterator j in [first,i), value < *j is false. +/// \ingroup SearchingAlgorithms +/// +template <typename ForwardIterator, typename LessThanComparable> +ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last, const LessThanComparable& value) +{ + ForwardIterator mid; + while (first != last) { + mid = advance (first, distance (first,last) / 2); + if (value < *mid) + last = mid; + else + first = mid + 1; + } + return (last); +} + +/// Returns pair<lower_bound,upper_bound> +/// \ingroup SearchingAlgorithms +/// +template <typename ForwardIterator, typename LessThanComparable> +inline pair<ForwardIterator,ForwardIterator> equal_range (ForwardIterator first, ForwardIterator last, const LessThanComparable& value) +{ + pair<ForwardIterator,ForwardIterator> rv; + rv.second = rv.first = lower_bound (first, last, value); + while (rv.second != last && !(value < *(rv.second))) + ++ rv.second; + return (rv); +} + +/// Randomly permute the elements of the container. +/// \ingroup GeneratorAlgorithms +/// +template <typename RandomAccessIterator> +void random_shuffle (RandomAccessIterator first, RandomAccessIterator last) +{ + for (; first != last; ++ first) + iter_swap (first, first + (rand() % distance (first, last))); +} + +/// \brief Generic compare function adaptor to pass to qsort +/// \ingroup FunctorObjects +template <typename ConstPointer, typename Compare> +int qsort_adapter (const void* p1, const void* p2) +{ + ConstPointer i1 = reinterpret_cast<ConstPointer>(p1); + ConstPointer i2 = reinterpret_cast<ConstPointer>(p2); + Compare comp; + return (comp (*i1, *i2) ? -1 : (comp (*i2, *i1) ? 1 : 0)); +} + +/// Sorts the container +/// \ingroup SortingAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename RandomAccessIterator, typename Compare> +void sort (RandomAccessIterator first, RandomAccessIterator last, Compare) +{ + typedef typename iterator_traits<RandomAccessIterator>::value_type value_type; + typedef typename iterator_traits<RandomAccessIterator>::const_pointer const_pointer; + qsort (first, distance (first, last), sizeof(value_type), + &qsort_adapter<const_pointer, Compare>); +} + +/// Sorts the container +/// \ingroup SortingAlgorithms +/// +template <typename RandomAccessIterator> +inline void sort (RandomAccessIterator first, RandomAccessIterator last) +{ + typedef typename iterator_traits<RandomAccessIterator>::value_type value_type; + sort (first, last, less<value_type>()); +} + +/// Sorts the container preserving order of equal elements. +/// \ingroup SortingAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename RandomAccessIterator, typename Compare> +void stable_sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp) +{ + for (RandomAccessIterator j, i = first; ++i < last;) { // Insertion sort + for (j = i; j-- > first && comp(*i, *j);) ; + if (++j != i) rotate (j, i, i + 1); + } +} + +/// Sorts the container +/// \ingroup SortingAlgorithms +/// +template <typename RandomAccessIterator> +inline void stable_sort (RandomAccessIterator first, RandomAccessIterator last) +{ + typedef typename iterator_traits<RandomAccessIterator>::value_type value_type; + stable_sort (first, last, less<value_type>()); +} + +/// \brief Searches for the first subsequence [first2,last2) in [first1,last1) +/// \ingroup SearchingAlgorithms +template <typename ForwardIterator1, typename ForwardIterator2> +inline ForwardIterator1 search (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2) +{ + typedef typename iterator_traits<ForwardIterator1>::value_type value_type; + return (search (first1, last1, first2, last2, equal_to<value_type>())); +} + +/// \brief Searches for the last subsequence [first2,last2) in [first1,last1) +/// \ingroup SearchingAlgorithms +template <typename ForwardIterator1, typename ForwardIterator2> +inline ForwardIterator1 find_end (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2) +{ + typedef typename iterator_traits<ForwardIterator1>::value_type value_type; + return (find_end (first1, last1, first2, last2, equal_to<value_type>())); +} + +/// \brief Searches for the first occurence of \p count \p values in [first, last) +/// \ingroup SearchingAlgorithms +template <typename Iterator, typename T> +inline Iterator search_n (Iterator first, Iterator last, size_t count, const T& value) +{ + typedef typename iterator_traits<Iterator>::value_type value_type; + return (search_n (first, last, count, value, equal_to<value_type>())); +} + +/// \brief Searches [first1,last1) for the first occurrence of an element from [first2,last2) +/// \ingroup SearchingAlgorithms +template <typename InputIterator, typename ForwardIterator> +inline InputIterator find_first_of (InputIterator first1, InputIterator last1, ForwardIterator first2, ForwardIterator last2) +{ + typedef typename iterator_traits<InputIterator>::value_type value_type; + return (find_first_of (first1, last1, first2, last2, equal_to<value_type>())); +} + +/// \brief Returns true if [first2,last2) is a subset of [first1,last1) +/// \ingroup ConditionAlgorithms +/// \ingroup SetAlgorithms +template <typename InputIterator1, typename InputIterator2> +inline bool includes (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) +{ + typedef typename iterator_traits<InputIterator1>::value_type value_type; + return (includes (first1, last1, first2, last2, less<value_type>())); +} + +/// \brief Merges [first1,last1) with [first2,last2) +/// +/// Result will contain every element that is in either set. If duplicate +/// elements are present, max(n,m) is placed in the result. +/// +/// \ingroup SetAlgorithms +template <typename InputIterator1, typename InputIterator2, typename OutputIterator> +inline OutputIterator set_union (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result) +{ + typedef typename iterator_traits<InputIterator1>::value_type value_type; + return (set_union (first1, last1, first2, last2, result, less<value_type>())); +} + +/// \brief Creates a set containing elements shared by the given ranges. +/// \ingroup SetAlgorithms +template <typename InputIterator1, typename InputIterator2, typename OutputIterator> +inline OutputIterator set_intersection (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result) +{ + typedef typename iterator_traits<InputIterator1>::value_type value_type; + return (set_intersection (first1, last1, first2, last2, result, less<value_type>())); +} + +/// \brief Removes from [first1,last1) elements present in [first2,last2) +/// \ingroup SetAlgorithms +template <typename InputIterator1, typename InputIterator2, typename OutputIterator> +inline OutputIterator set_difference (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result) +{ + typedef typename iterator_traits<InputIterator1>::value_type value_type; + return (set_difference (first1, last1, first2, last2, result, less<value_type>())); +} + +/// \brief Performs union of sets A-B and B-A. +/// \ingroup SetAlgorithms +template <typename InputIterator1, typename InputIterator2, typename OutputIterator> +inline OutputIterator set_symmetric_difference (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result) +{ + typedef typename iterator_traits<InputIterator1>::value_type value_type; + return (set_symmetric_difference (first1, last1, first2, last2, result, less<value_type>())); +} + +/// \brief Returns true if the given range is sorted. +/// \ingroup ConditionAlgorithms +template <typename ForwardIterator> +inline bool is_sorted (ForwardIterator first, ForwardIterator last) +{ + typedef typename iterator_traits<ForwardIterator>::value_type value_type; + return (is_sorted (first, last, less<value_type>())); +} + +/// \brief Compares two given containers like strcmp compares strings. +/// \ingroup ConditionAlgorithms +template <typename InputIterator1, typename InputIterator2> +inline bool lexicographical_compare (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) +{ + typedef typename iterator_traits<InputIterator1>::value_type value_type; + return (lexicographical_compare (first1, last1, first2, last2, less<value_type>())); +} + +/// \brief Creates the next lexicographical permutation of [first,last). +/// Returns false if no further permutations can be created. +/// \ingroup GeneratorAlgorithms +template <typename BidirectionalIterator> +inline bool next_permutation (BidirectionalIterator first, BidirectionalIterator last) +{ + typedef typename iterator_traits<BidirectionalIterator>::value_type value_type; + return (next_permutation (first, last, less<value_type>())); +} + +/// \brief Creates the previous lexicographical permutation of [first,last). +/// Returns false if no further permutations can be created. +/// \ingroup GeneratorAlgorithms +template <typename BidirectionalIterator> +inline bool prev_permutation (BidirectionalIterator first, BidirectionalIterator last) +{ + typedef typename iterator_traits<BidirectionalIterator>::value_type value_type; + return (prev_permutation (first, last, less<value_type>())); +} + +/// \brief Returns iterator to the max element in [first,last) +/// \ingroup SearchingAlgorithms +template <typename ForwardIterator> +inline ForwardIterator max_element (ForwardIterator first, ForwardIterator last) +{ + typedef typename iterator_traits<ForwardIterator>::value_type value_type; + return (max_element (first, last, less<value_type>())); +} + +/// \brief Returns iterator to the min element in [first,last) +/// \ingroup SearchingAlgorithms +template <typename ForwardIterator> +inline ForwardIterator min_element (ForwardIterator first, ForwardIterator last) +{ + typedef typename iterator_traits<ForwardIterator>::value_type value_type; + return (min_element (first, last, less<value_type>())); +} + +/// \brief Makes [first,middle) a part of the sorted array. +/// Contents of [middle,last) is undefined. This implementation just calls stable_sort. +/// \ingroup SortingAlgorithms +template <typename RandomAccessIterator> +inline void partial_sort (RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last) +{ + typedef typename iterator_traits<RandomAccessIterator>::value_type value_type; + partial_sort (first, middle, last, less<value_type>()); +} + +/// \brief Puts \p nth element into its sorted position. +/// In this implementation, the entire array is sorted. I can't think of any +/// use for it where the time gained would be useful. +/// \ingroup SortingAlgorithms +/// \ingroup SearchingAlgorithms +/// +template <typename RandomAccessIterator> +inline void nth_element (RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last) +{ + partial_sort (first, nth, last); +} + +/// \brief Like partial_sort, but outputs to [result_first,result_last) +/// \ingroup SortingAlgorithms +template <typename InputIterator, typename RandomAccessIterator> +inline RandomAccessIterator partial_sort_copy (InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last) +{ + typedef typename iterator_traits<InputIterator>::value_type value_type; + return (partial_sort_copy (first, last, result_first, result_last, less<value_type>())); +} + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/ualgobase.h @@ -0,0 +1,321 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UALGOBASE_H_683A0BE77546133C4CE0E3622CFAA2EB +#define UALGOBASE_H_683A0BE77546133C4CE0E3622CFAA2EB + +#include "uutility.h" +#include <string.h> + +namespace ustl { + +/// Assigns the contents of a to b and the contents of b to a. +/// This is used as a primitive operation by many other algorithms. +/// \ingroup SwapAlgorithms +/// +template <typename Assignable> +inline void swap (Assignable& a, Assignable& b) +{ + Assignable tmp = a; + a = b; + b = tmp; +} + +/// Equivalent to swap (*a, *b) +/// \ingroup SwapAlgorithms +/// +template <typename Iterator> +inline void iter_swap (Iterator a, Iterator b) +{ + swap (*a, *b); +} + +/// Copy copies elements from the range [first, last) to the range +/// [result, result + (last - first)). That is, it performs the assignments +/// *result = *first, *(result + 1) = *(first + 1), and so on. [1] Generally, +/// for every integer n from 0 to last - first, copy performs the assignment +/// *(result + n) = *(first + n). Assignments are performed in forward order, +/// i.e. in order of increasing n. +/// \ingroup MutatingAlgorithms +/// +template <typename InputIterator, typename OutputIterator> +inline OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result) +{ + for (; first != last; ++result, ++first) + *result = *first; + return (result); +} + +/// Copy_n copies elements from the range [first, first + n) to the range +/// [result, result + n). That is, it performs the assignments +/// *result = *first, *(result + 1) = *(first + 1), and so on. Generally, +/// for every integer i from 0 up to (but not including) n, copy_n performs +/// the assignment *(result + i) = *(first + i). Assignments are performed +/// in forward order, i.e. in order of increasing n. +/// \ingroup MutatingAlgorithms +/// +template <typename InputIterator, typename OutputIterator> +inline OutputIterator copy_n (InputIterator first, size_t count, OutputIterator result) +{ + for (; count; --count, ++result, ++first) + *result = *first; + return (result); +} + +/// \brief Copy copies elements from the range (last, first] to result. +/// \ingroup MutatingAlgorithms +/// Copies elements starting at last, decrementing both last and result. +/// +template <typename InputIterator, typename OutputIterator> +inline OutputIterator copy_backward (InputIterator first, InputIterator last, OutputIterator result) +{ + while (first != last) + *--result = *--last; + return (result); +} + +/// For_each applies the function object f to each element in the range +/// [first, last); f's return value, if any, is ignored. Applications are +/// performed in forward order, i.e. from first to last. For_each returns +/// the function object after it has been applied to each element. +/// \ingroup MutatingAlgorithms +/// +template <typename InputIterator, typename UnaryFunction> +inline UnaryFunction for_each (InputIterator first, InputIterator last, UnaryFunction f) +{ + for (; first != last; ++first) + f (*first); + return (f); +} + +/// Fill assigns the value value to every element in the range [first, last). +/// That is, for every iterator i in [first, last), +/// it performs the assignment *i = value. +/// \ingroup GeneratorAlgorithms +/// +template <typename ForwardIterator, typename T> +inline void fill (ForwardIterator first, ForwardIterator last, const T& value) +{ + for (; first != last; ++first) + *first = value; +} + +/// Fill_n assigns the value value to every element in the range +/// [first, first+count). That is, for every iterator i in [first, first+count), +/// it performs the assignment *i = value. The return value is first + count. +/// \ingroup GeneratorAlgorithms +/// +template <typename OutputIterator, typename T> +inline OutputIterator fill_n (OutputIterator first, size_t count, const T& value) +{ + for (; count; --count, ++first) + *first = value; + return (first); +} + +#if CPU_HAS_MMX +extern "C" void copy_n_fast (const void* src, size_t count, void* dest) throw(); +#else +inline void copy_n_fast (const void* src, size_t count, void* dest) throw() + { memcpy (dest, src, count); } +#endif +#if __i386__ || __x86_64__ +extern "C" void copy_backward_fast (const void* first, const void* last, void* result) throw(); +#else +inline void copy_backward_fast (const void* first, const void* last, void* result) throw() +{ + const size_t nBytes (distance (first, last)); + memmove (advance (result, -nBytes), first, nBytes); +} +#endif +extern "C" void fill_n8_fast (uint8_t* dest, size_t count, uint8_t v) throw(); +extern "C" void fill_n16_fast (uint16_t* dest, size_t count, uint16_t v) throw(); +extern "C" void fill_n32_fast (uint32_t* dest, size_t count, uint32_t v) throw(); +extern "C" void rotate_fast (void* first, void* middle, void* last) throw(); + +#if __GNUC__ >= 4 +/// \brief Computes the number of 1 bits in a number. +/// \ingroup ConditionAlgorithms +inline size_t popcount (uint32_t v) { return (__builtin_popcount (v)); } +#if HAVE_INT64_T +inline size_t popcount (uint64_t v) { return (__builtin_popcountll (v)); } +#endif +#else +size_t popcount (uint32_t v); +#if HAVE_INT64_T +size_t popcount (uint64_t v); +#endif // HAVE_INT64_T +#endif // __GNUC__ + +//---------------------------------------------------------------------- +// Optimized versions for standard types +//---------------------------------------------------------------------- + +#if WANT_UNROLLED_COPY + +template <typename T> +inline T* unrolled_copy (const T* first, size_t count, T* result) +{ + copy_n_fast (first, count * sizeof(T), result); + return (advance (result, count)); +} + +template <> +inline uint8_t* copy_backward (const uint8_t* first, const uint8_t* last, uint8_t* result) +{ + copy_backward_fast (first, last, result); + return (result); +} + +template <typename T> +inline T* unrolled_fill (T* result, size_t count, T value) +{ + for (; count; --count, ++result) + *result = value; + return (result); +} +template <> inline uint8_t* unrolled_fill (uint8_t* result, size_t count, uint8_t value) + { fill_n8_fast (result, count, value); return (advance (result, count)); } +template <> inline uint16_t* unrolled_fill (uint16_t* result, size_t count, uint16_t value) + { fill_n16_fast (result, count, value); return (advance (result, count)); } +template <> inline uint32_t* unrolled_fill (uint32_t* result, size_t count, uint32_t value) + { fill_n32_fast (result, count, value); return (advance (result, count)); } +template <> inline float* unrolled_fill (float* result, size_t count, float value) + { fill_n32_fast ((uint32_t*) result, count, *noalias_cast<uint32_t*>(&value)); return (advance (result, count)); } + +#if CPU_HAS_MMX +#define UNROLLED_COPY_SPECIALIZATION(type) \ +template <> inline type* copy (const type* first, const type* last, type* result) \ +{ return (unrolled_copy (first, distance (first, last), result)); } \ +template <> inline type* copy_n (const type* first, size_t count, type* result) \ +{ return (unrolled_copy (first, count, result)); } +#define UNROLLED_FILL_SPECIALIZATION(type) \ +template <> inline void fill (type* first, type* last, const type& value) \ +{ unrolled_fill (first, distance (first, last), value); } \ +template <> inline type* fill_n (type* first, size_t count, const type& value) \ +{ return (unrolled_fill (first, count, value)); } +UNROLLED_COPY_SPECIALIZATION(uint8_t) +UNROLLED_FILL_SPECIALIZATION(uint8_t) +UNROLLED_COPY_SPECIALIZATION(uint16_t) +UNROLLED_FILL_SPECIALIZATION(uint16_t) +UNROLLED_COPY_SPECIALIZATION(uint32_t) +UNROLLED_FILL_SPECIALIZATION(uint32_t) +UNROLLED_COPY_SPECIALIZATION(float) +UNROLLED_FILL_SPECIALIZATION(float) +#undef UNROLLED_FILL_SPECIALIZATION +#undef UNROLLED_COPY_SPECIALIZATION +#endif // WANT_UNROLLED_COPY +#endif // CPU_HAS_MMX + +// Specializations for void* and char*, aliasing the above optimized versions. +// +// All these need duplication with const and non-const arguments, since +// otherwise the compiler will default to the unoptimized version for +// pointers not const in the caller's context, such as local variables. +// These are all inline, but they sure slow down compilation... :( +// +#define COPY_ALIAS_FUNC(ctype, type, alias_type) \ +template <> inline type* copy (ctype* first, ctype* last, type* result) \ +{ return ((type*) copy ((const alias_type*) first, (const alias_type*) last, (alias_type*) result)); } +#if WANT_UNROLLED_COPY +#if HAVE_THREE_CHAR_TYPES +COPY_ALIAS_FUNC(const char, char, uint8_t) +COPY_ALIAS_FUNC(char, char, uint8_t) +#endif +COPY_ALIAS_FUNC(const int8_t, int8_t, uint8_t) +COPY_ALIAS_FUNC(int8_t, int8_t, uint8_t) +COPY_ALIAS_FUNC(uint8_t, uint8_t, uint8_t) +COPY_ALIAS_FUNC(const int16_t, int16_t, uint16_t) +COPY_ALIAS_FUNC(int16_t, int16_t, uint16_t) +COPY_ALIAS_FUNC(uint16_t, uint16_t, uint16_t) +#if CPU_HAS_MMX || (SIZE_OF_LONG > 4) +COPY_ALIAS_FUNC(const int32_t, int32_t, uint32_t) +COPY_ALIAS_FUNC(int32_t, int32_t, uint32_t) +COPY_ALIAS_FUNC(uint32_t, uint32_t, uint32_t) +#endif +#endif +COPY_ALIAS_FUNC(const void, void, uint8_t) +COPY_ALIAS_FUNC(void, void, uint8_t) +#undef COPY_ALIAS_FUNC +#define COPY_BACKWARD_ALIAS_FUNC(ctype, type, alias_type) \ +template <> inline type* copy_backward (ctype* first, ctype* last, type* result) \ +{ return ((type*) copy_backward ((const alias_type*) first, (const alias_type*) last, (alias_type*) result)); } +#if WANT_UNROLLED_COPY +#if HAVE_THREE_CHAR_TYPES +COPY_BACKWARD_ALIAS_FUNC(char, char, uint8_t) +#endif +COPY_BACKWARD_ALIAS_FUNC(uint8_t, uint8_t, uint8_t) +COPY_BACKWARD_ALIAS_FUNC(int8_t, int8_t, uint8_t) +COPY_BACKWARD_ALIAS_FUNC(uint16_t, uint16_t, uint8_t) +COPY_BACKWARD_ALIAS_FUNC(const uint16_t, uint16_t, uint8_t) +COPY_BACKWARD_ALIAS_FUNC(int16_t, int16_t, uint8_t) +COPY_BACKWARD_ALIAS_FUNC(const int16_t, int16_t, uint8_t) +#endif +COPY_BACKWARD_ALIAS_FUNC(void, void, uint8_t) +COPY_BACKWARD_ALIAS_FUNC(const void, void, uint8_t) +#undef COPY_BACKWARD_ALIAS_FUNC +#define FILL_ALIAS_FUNC(type, alias_type, v_type) \ +template <> inline void fill (type* first, type* last, const v_type& value) \ +{ fill ((alias_type*) first, (alias_type*) last, (const alias_type&) value); } +FILL_ALIAS_FUNC(void, uint8_t, char) +FILL_ALIAS_FUNC(void, uint8_t, uint8_t) +#if WANT_UNROLLED_COPY +#if HAVE_THREE_CHAR_TYPES +FILL_ALIAS_FUNC(char, uint8_t, char) +FILL_ALIAS_FUNC(char, uint8_t, uint8_t) +#endif +FILL_ALIAS_FUNC(int8_t, uint8_t, int8_t) +FILL_ALIAS_FUNC(int16_t, uint16_t, int16_t) +#if CPU_HAS_MMX || (SIZE_OF_LONG > 4) +FILL_ALIAS_FUNC(int32_t, uint32_t, int32_t) +#endif +#endif +#undef FILL_ALIAS_FUNC +#define COPY_N_ALIAS_FUNC(ctype, type, alias_type) \ +template <> inline type* copy_n (ctype* first, size_t count, type* result) \ +{ return ((type*) copy_n ((const alias_type*) first, count, (alias_type*) result)); } +COPY_N_ALIAS_FUNC(const void, void, uint8_t) +COPY_N_ALIAS_FUNC(void, void, uint8_t) +#if WANT_UNROLLED_COPY +#if HAVE_THREE_CHAR_TYPES +COPY_N_ALIAS_FUNC(const char, char, uint8_t) +COPY_N_ALIAS_FUNC(char, char, uint8_t) +#endif +COPY_N_ALIAS_FUNC(int8_t, int8_t, uint8_t) +COPY_N_ALIAS_FUNC(uint8_t, uint8_t, uint8_t) +COPY_N_ALIAS_FUNC(const int8_t, int8_t, uint8_t) +COPY_N_ALIAS_FUNC(int16_t, int16_t, uint16_t) +COPY_N_ALIAS_FUNC(uint16_t, uint16_t, uint16_t) +COPY_N_ALIAS_FUNC(const int16_t, int16_t, uint16_t) +#if CPU_HAS_MMX || (SIZE_OF_LONG > 4) +COPY_N_ALIAS_FUNC(int32_t, int32_t, uint32_t) +COPY_N_ALIAS_FUNC(uint32_t, uint32_t, uint32_t) +COPY_N_ALIAS_FUNC(const int32_t, int32_t, uint32_t) +#endif +#endif +#undef COPY_N_ALIAS_FUNC +#define FILL_N_ALIAS_FUNC(type, alias_type, v_type) \ +template <> inline type* fill_n (type* first, size_t n, const v_type& value) \ +{ return ((type*) fill_n ((alias_type*) first, n, (const alias_type&) value)); } +FILL_N_ALIAS_FUNC(void, uint8_t, char) +FILL_N_ALIAS_FUNC(void, uint8_t, uint8_t) +#if WANT_UNROLLED_COPY +#if HAVE_THREE_CHAR_TYPES +FILL_N_ALIAS_FUNC(char, uint8_t, char) +FILL_N_ALIAS_FUNC(char, uint8_t, uint8_t) +#endif +FILL_N_ALIAS_FUNC(int8_t, uint8_t, int8_t) +FILL_N_ALIAS_FUNC(int16_t, uint16_t, int16_t) +#if CPU_HAS_MMX || (SIZE_OF_LONG > 4) +FILL_N_ALIAS_FUNC(int32_t, uint32_t, int32_t) +#endif +#endif +#undef FILL_N_ALIAS_FUNC + +extern const char _FmtPrtChr[2][8]; + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/ubitset.h @@ -0,0 +1,129 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UBITSET_H_7B6450EC1400CBA45DCE0127739F82EE +#define UBITSET_H_7B6450EC1400CBA45DCE0127739F82EE + +#include "ustring.h" +#include "ufunction.h" + +namespace ustl { + +typedef uint32_t bitset_value_type; + +void convert_to_bitstring (const bitset_value_type* v, size_t n, string& buf); +void convert_from_bitstring (const string& buf, bitset_value_type* v, size_t n); + +/// \class bitset ubitset.h ustl.h +/// \ingroup Sequences +/// +/// \brief bitset is a fixed-size block of memory with addressable bits. +/// +/// Normally used for state flags; allows setting and unsetting of individual +/// bits as well as bitwise operations on the entire set. The interface is +/// most like that of unsigned integers, and is intended to be used as such. +/// If you were using begin() and end() functions in STL's bitset, you would +/// not be able to do the same thing here, because those functions return +/// host type iterators, not bits. +/// +template <size_t Size> +class bitset { +public: + typedef bitset_value_type value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef pointer iterator; + typedef const_pointer const_iterator; + typedef size_t difference_type; + typedef size_t size_type; +private: + static const size_t s_WordBits = BitsInType (value_type); + static const size_t s_nWords = Size / s_WordBits + ((Size % s_WordBits) != 0); + static const size_t s_nBits = s_nWords * s_WordBits; +private: + inline value_type& BitRef (uoff_t n) { assert (n < Size); return (m_Bits [n / s_WordBits]); } + inline value_type BitRef (uoff_t n) const { assert (n < Size); return (m_Bits [n / s_WordBits]); } + inline value_type Mask (uoff_t n) const { assert (n < Size); return (1 << (n % s_WordBits)); } +public: + inline bitset (value_type v = 0) { fill_n (m_Bits, s_nWords, 0); m_Bits[0] = v; } + inline bitset (const string& buf) { convert_from_bitstring (buf, m_Bits, s_nWords); } + inline void flip (uoff_t n) { BitRef(n) ^= Mask(n); } + inline void reset (void) { fill_n (m_Bits, s_nWords, 0); } + inline void clear (void) { fill_n (m_Bits, s_nWords, 0); } + inline void set (void) { fill_n (m_Bits, s_nWords, -1); } + inline bitset operator~ (void) const { bitset rv (*this); rv.flip(); return (rv); } + inline size_type size (void) const { return (Size); } + inline size_type capacity (void) const { return (s_nBits); } + inline bool test (uoff_t n) const { return (BitRef(n) & Mask(n)); } + inline bool operator[] (uoff_t n) const { return (test(n)); } + inline const_iterator begin (void) const { return (m_Bits); } + inline iterator begin (void) { return (m_Bits); } + inline const_iterator end (void) const { return (m_Bits + s_nWords); } + inline iterator end (void) { return (m_Bits + s_nWords); } + /// Returns the value_type with the equivalent bits. If size() > 1, you'll get only the first BitsInType(value_type) bits. + inline value_type to_value (void) const { return (m_Bits[0]); } + /// Flips all the bits in the set. + inline void flip (void) { transform (begin(), end(), begin(), bitwise_not<value_type>()); } + /// Sets or clears bit \p n. + inline void set (uoff_t n, bool val = true) + { + value_type& br (BitRef (n)); + const value_type mask (Mask (n)); + const value_type bOn (br | mask), bOff (br & ~mask); + br = val ? bOn : bOff; + } + // Sets the value of the bitrange \p first through \p last to the equivalent number of bits from \p v. + inline void set (uoff_t first, uoff_t DebugArg(last), value_type v) + { + assert (size_t (distance (first, last)) <= s_WordBits && "Bit ranges must be 32 bits or smaller"); + assert (first / s_WordBits == last / s_WordBits && "Bit ranges can not cross dword (4 byte) boundary"); + assert ((v & BitMask(value_type,distance(first,last))) == v && "The value is too large to fit in the given bit range"); + BitRef(first) |= v << (first % s_WordBits); + } + /// Clears the bit \p n. + inline void reset (uoff_t n) { set (n, false); } + /// Returns a string with bits MSB "001101001..." LSB. + inline string to_string (void) const + { + string rv (Size, '0'); + convert_to_bitstring (m_Bits, s_nWords, rv); + return (rv); + } + inline value_type at (uoff_t n) const { return (test(n)); } + /// Returns the value in bits \p first through \p last. + inline value_type at (uoff_t first, uoff_t last) const + { + assert (size_t (distance (first, last)) <= s_WordBits && "Bit ranges must be 32 bits or smaller"); + assert (first / s_WordBits == last / s_WordBits && "Bit ranges can not cross dword (4 byte) boundary"); + return ((BitRef(first) >> (first % s_WordBits)) & BitMask(value_type,distance(first, last))); + } + inline bool any (void) const { value_type sum = 0; foreach (const_iterator, i, *this) sum |= *i; return (sum); } + inline bool none (void) const { return (!any()); } + inline size_t count (void) const { size_t sum = 0; foreach (const_iterator, i, *this) sum += popcount(*i); return (sum); } + inline bool operator== (const bitset<Size>& v) const + { return (s_nWords == 1 ? (m_Bits[0] == v.m_Bits[0]) : equal (begin(), end(), v.begin())); } + inline const bitset operator& (const bitset<Size>& v) + { bitset<Size> result; transform (begin(), end(), v.begin(), result.begin(), bitwise_and<value_type>()); return (result); } + inline const bitset operator| (const bitset<Size>& v) + { bitset<Size> result; transform (begin(), end(), v.begin(), result.begin(), bitwise_or<value_type>()); return (result); } + inline const bitset operator^ (const bitset<Size>& v) + { bitset<Size> result; transform (begin(), end(), v.begin(), result.begin(), bitwise_xor<value_type>()); return (result); } + inline const bitset& operator&= (const bitset<Size>& v) + { transform (begin(), end(), v.begin(), begin(), bitwise_and<value_type>()); return (*this); } + inline const bitset& operator|= (const bitset<Size>& v) + { transform (begin(), end(), v.begin(), begin(), bitwise_or<value_type>()); return (*this); } + inline const bitset& operator^= (const bitset<Size>& v) + { transform (begin(), end(), v.begin(), begin(), bitwise_xor<value_type>()); return (*this); } + inline void read (istream& is) { nr_container_read (is, *this); } + inline void write (ostream& os) const { nr_container_write (os, *this); } + inline void text_write (ostringstream& os) const { os << to_string(); } + inline size_t stream_size (void) const { return (sizeof(m_Bits)); } +private: + value_type m_Bits [s_nWords]; +}; + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/uctralgo.h @@ -0,0 +1,470 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UCTRALGO_H_0D1AEDFA74B09791489FE25B1EC644B0 +#define UCTRALGO_H_0D1AEDFA74B09791489FE25B1EC644B0 + +namespace ustl { + +/// Copy copies elements from the range [first, last) to the range +/// [result, result + (last - first)). That is, it performs the assignments +/// *result = *first, *(result + 1) = *(first + 1), and so on. [1] Generally, +/// for every integer n from 0 to last - first, copy performs the assignment +/// *(result + n) = *(first + n). Assignments are performed in forward order, +/// i.e. in order of increasing n. +/// \ingroup MutatingAlgorithms +/// +template <typename Container, typename OutputIterator> +inline OutputIterator copy (const Container& ctr, OutputIterator result) +{ + return (copy (ctr.begin(), ctr.end(), result)); +} + +/// Copy_if copies elements from the range [first, last) to the range +/// [result, result + (last - first)) if pred(*i) returns true. +/// \ingroup MutatingAlgorithms +/// +template <typename Container, typename OutputIterator, typename Predicate> +inline OutputIterator copy_if (Container& ctr, OutputIterator result, Predicate pred) +{ + return (copy_if (ctr.begin(), ctr.end(), result, pred)); +} + +/// For_each applies the function object f to each element in the range +/// [first, last); f's return value, if any, is ignored. Applications are +/// performed in forward order, i.e. from first to last. For_each returns +/// the function object after it has been applied to each element. +/// \ingroup MutatingAlgorithms +/// +template <typename Container, typename UnaryFunction> +inline UnaryFunction for_each (Container& ctr, UnaryFunction f) +{ + return (for_each (ctr.begin(), ctr.end(), f)); +} + +/// For_each applies the function object f to each element in the range +/// [first, last); f's return value, if any, is ignored. Applications are +/// performed in forward order, i.e. from first to last. For_each returns +/// the function object after it has been applied to each element. +/// \ingroup MutatingAlgorithms +/// +template <typename Container, typename UnaryFunction> +inline UnaryFunction for_each (const Container& ctr, UnaryFunction f) +{ + return (for_each (ctr.begin(), ctr.end(), f)); +} + +/// Returns the first iterator i in the range [first, last) such that +/// *i == value. Returns last if no such iterator exists. +/// \ingroup SearchingAlgorithms +/// +template <typename Container, typename EqualityComparable> +inline typename Container::const_iterator find (const Container& ctr, const EqualityComparable& value) +{ + return (find (ctr.begin(), ctr.end(), value)); +} +template <typename Container, typename EqualityComparable> +inline typename Container::iterator find (Container& ctr, const EqualityComparable& value) +{ + return (find (ctr.begin(), ctr.end(), value)); +} + +/// Returns the first iterator i in the range [first, last) such that +/// pred(*i) is true. Returns last if no such iterator exists. +/// \ingroup SearchingAlgorithms +/// +template <typename Container, typename Predicate> +inline typename Container::const_iterator find_if (const Container& ctr, Predicate pred) +{ + return (find_if (ctr.begin(), ctr.end(), pred)); +} +template <typename Container, typename Predicate> +inline typename Container::iterator find_if (Container& ctr, Predicate pred) +{ + return (find_if (ctr.begin(), ctr.end(), pred)); +} + +/// Count finds the number of elements in [first, last) that are equal +/// to value. More precisely, the first version of count returns the +/// number of iterators i in [first, last) such that *i == value. +/// \ingroup ConditionAlgorithms +/// +template <typename Container, typename EqualityComparable> +inline size_t count (const Container& ctr, const EqualityComparable& value) +{ + return (count (ctr.begin(), ctr.end(), value)); +} + +/// Count_if finds the number of elements in [first, last) that satisfy the +/// predicate pred. More precisely, the first version of count_if returns the +/// number of iterators i in [first, last) such that pred(*i) is true. +/// \ingroup ConditionAlgorithms +/// +template <typename Container, typename Predicate> +inline size_t count_if (const Container& ctr, Predicate pred) +{ + return (count_if (ctr.begin(), ctr.end(), pred)); +} + +/// The first version of transform performs the operation op(*i) for each +/// iterator i in the range [first, last), and assigns the result of that +/// operation to *o, where o is the corresponding output iterator. That is, +/// for each n such that 0 <= n < last - first, it performs the assignment +/// *(result + n) = op(*(first + n)). +/// The return value is result + (last - first). +/// \ingroup MutatingAlgorithms +/// +template <typename Container, typename UnaryFunction> +inline void transform (Container& ctr, UnaryFunction op) +{ + transform (ctr.begin(), ctr.end(), ctr.begin(), op); +} + +/// The first version of transform performs the operation op(*i) for each +/// iterator i in the range [first, last), and assigns the result of that +/// operation to *o, where o is the corresponding output iterator. That is, +/// for each n such that 0 <= n < last - first, it performs the assignment +/// *(result + n) = op(*(first + n)). +/// The return value is result + (last - first). +/// \ingroup MutatingAlgorithms +/// +template <typename Container, typename OutputIterator, typename UnaryFunction> +inline OutputIterator transform (Container& ctr, OutputIterator result, UnaryFunction op) +{ + return (transform (ctr.begin(), ctr.end(), result, op)); +} + +/// The second version of transform is very similar, except that it uses a +/// Binary Function instead of a Unary Function: it performs the operation +/// op(*i1, *i2) for each iterator i1 in the range [first1, last1) and assigns +/// the result to *o, where i2 is the corresponding iterator in the second +/// input range and where o is the corresponding output iterator. That is, +/// for each n such that 0 <= n < last1 - first1, it performs the assignment +/// *(result + n) = op(*(first1 + n), *(first2 + n). +/// The return value is result + (last1 - first1). +/// \ingroup MutatingAlgorithms +/// +template <typename Container, typename InputIterator, typename OutputIterator, typename BinaryFunction> +inline OutputIterator transform (Container& ctr, InputIterator first, OutputIterator result, BinaryFunction op) +{ + return (transform (ctr.begin(), ctr.end(), first, result, op)); +} + +/// Replace replaces every element in the range [first, last) equal to +/// old_value with new_value. That is: for every iterator i, +/// if *i == old_value then it performs the assignment *i = new_value. +/// \ingroup MutatingAlgorithms +/// +template <typename Container, typename T> +inline void replace (Container& ctr, const T& old_value, const T& new_value) +{ + replace (ctr.begin(), ctr.end(), old_value, new_value); +} + +/// Replace_if replaces every element in the range [first, last) for which +/// pred returns true with new_value. That is: for every iterator i, if +/// pred(*i) is true then it performs the assignment *i = new_value. +/// \ingroup MutatingAlgorithms +/// +template <typename Container, typename Predicate, typename T> +inline void replace_if (Container& ctr, Predicate pred, const T& new_value) +{ + replace_if (ctr.begin(), ctr.end(), pred, new_value); +} + +/// Replace_copy copies elements from the range [first, last) to the range +/// [result, result + (last-first)), except that any element equal to old_value +/// is not copied; new_value is copied instead. More precisely, for every +/// integer n such that 0 <= n < last-first, replace_copy performs the +/// assignment *(result+n) = new_value if *(first+n) == old_value, and +/// *(result+n) = *(first+n) otherwise. +/// \ingroup MutatingAlgorithms +/// +template <typename Container, typename OutputIterator, typename T> +inline OutputIterator replace_copy (const Container& ctr, OutputIterator result, const T& old_value, const T& new_value) +{ + return (replace_copy (ctr.begin(), ctr.end(), result, old_value, new_value)); +} + +/// Replace_copy_if copies elements from the range [first, last) to the range +/// [result, result + (last-first)), except that any element for which pred is +/// true is not copied; new_value is copied instead. More precisely, for every +/// integer n such that 0 <= n < last-first, replace_copy_if performs the +/// assignment *(result+n) = new_value if pred(*(first+n)), +/// and *(result+n) = *(first+n) otherwise. +/// \ingroup MutatingAlgorithms +/// +template <typename Container, typename OutputIterator, typename Predicate, typename T> +inline OutputIterator replace_copy_if (const Container& ctr, OutputIterator result, Predicate pred, const T& new_value) +{ + return (replace_copy_if (ctr.begin(), ctr.end(), result, pred, new_value)); +} + +/// Fill assigns the value value to every element in the range [first, last). +/// That is, for every iterator i in [first, last), +/// it performs the assignment *i = value. +/// \ingroup GeneratorAlgorithms +/// +template <typename Container, typename T> +inline void fill (Container& ctr, const T& value) +{ + fill (ctr.begin(), ctr.end(), value); +} + +/// Generate assigns the result of invoking gen, a function object that +/// takes no arguments, to each element in the range [first, last). +/// \ingroup GeneratorAlgorithms +/// +template <typename Container, typename Generator> +inline void generate (Container& ctr, Generator gen) +{ + generate (ctr.begin(), ctr.end(), gen); +} + +/// Randomly permute the elements of the container. +/// \ingroup GeneratorAlgorithms +/// +template <typename Container> +inline void random_shuffle (Container& ctr) +{ + random_shuffle (ctr.begin(), ctr.end()); +} + +/// Remove_copy copies elements that are not equal to value from the range +/// [first, last) to a range beginning at result. The return value is the +/// end of the resulting range. This operation is stable, meaning that the +/// relative order of the elements that are copied is the same as in the +/// range [first, last). +/// \ingroup MutatingAlgorithms +/// +template <typename Container, typename OutputIterator, typename T> +inline OutputIterator remove_copy (const Container& ctr, OutputIterator result, const T& value) +{ + return (remove_copy (ctr.begin(), ctr.end(), result, value)); +} + +/// Remove_copy_if copies elements from the range [first, last) to a range +/// beginning at result, except that elements for which pred is true are not +/// copied. The return value is the end of the resulting range. This operation +/// is stable, meaning that the relative order of the elements that are copied +/// is the same as in the range [first, last). +/// \ingroup MutatingAlgorithms +/// +template <typename Container, typename OutputIterator, typename Predicate> +inline OutputIterator remove_copy_if (const Container& ctr, OutputIterator result, Predicate pred) +{ + return (remove_copy_if (ctr.begin(), ctr.end(), result, pred)); +} + +/// Remove removes from the range [first, last) all elements that are equal to +/// value. That is, remove returns an iterator new_last such that the range +/// [first, new_last) contains no elements equal to value. Remove is stable, +/// meaning that the relative order of elements that are not equal to value is +/// unchanged. +/// \ingroup MutatingAlgorithms +/// +template <typename Container, typename T> +inline void remove (Container& ctr, const T& value) +{ + ctr.erase (remove_copy (ctr.begin(), ctr.end(), ctr.begin(), value), ctr.end()); +} + +/// Remove removes from the range [first, last) all elements that have an iterator +/// in range [rfirst, rlast). The range is assumed to be sorted. That is, remove +/// returns an iterator new_last such that the range [first, new_last) contains +/// no elements whose iterators are in [rfirst, rlast). Remove is stable, +/// meaning that the relative order of elements that are not equal to value is +/// unchanged. This version of the algorithm is a uSTL extension. +/// \ingroup MutatingAlgorithms +/// +template <typename Container, typename ForwardIterator> +inline void remove (Container& ctr, ForwardIterator rfirst, ForwardIterator rlast) +{ + ctr.erase (remove_copy (ctr.begin(), ctr.end(), ctr.begin(), rfirst, rlast), ctr.end()); +} + +/// Remove_if removes from the range [first, last) every element x such that +/// pred(x) is true. That is, remove_if returns an iterator new_last such that +/// the range [first, new_last) contains no elements for which pred is true. +/// The iterators in the range [new_last, last) are all still dereferenceable, +/// but the elements that they point to are unspecified. Remove_if is stable, +/// meaning that the relative order of elements that are not removed is +/// unchanged. +/// \ingroup MutatingAlgorithms +/// +template <typename Container, typename Predicate> +inline void remove_if (Container& ctr, Predicate pred) +{ + ctr.erase (remove_copy_if (ctr.begin(), ctr.end(), ctr.begin(), pred), ctr.end()); +} + +/// Unique_copy copies elements from the range [first, last) to a range +/// beginning with result, except that in a consecutive group of duplicate +/// elements only the first one is copied. The return value is the end of +/// the range to which the elements are copied. This behavior is similar +/// to the Unix filter uniq. +/// \ingroup MutatingAlgorithms +/// +template <typename Container, typename OutputIterator> +inline OutputIterator unique_copy (const Container& ctr, OutputIterator result) +{ + return (unique_copy (ctr.begin(), ctr.end(), result)); +} + +/// Every time a consecutive group of duplicate elements appears in the range +/// [first, last), the algorithm unique removes all but the first element. +/// That is, unique returns an iterator new_last such that the range [first, +/// new_last) contains no two consecutive elements that are duplicates. +/// The iterators in the range [new_last, last) are all still dereferenceable, +/// but the elements that they point to are unspecified. Unique is stable, +/// meaning that the relative order of elements that are not removed is +/// unchanged. +/// \ingroup MutatingAlgorithms +/// +template <typename Container> +inline void unique (Container& ctr) +{ + ctr.erase (unique_copy (ctr.begin(), ctr.end(), ctr.begin()), ctr.end()); +} + +/// Every time a consecutive group of duplicate elements appears in the range +/// [first, last), the algorithm unique removes all but the first element. +/// That is, unique returns an iterator new_last such that the range [first, +/// new_last) contains no two consecutive elements that are duplicates. +/// The iterators in the range [new_last, last) are all still dereferenceable, +/// but the elements that they point to are unspecified. Unique is stable, +/// meaning that the relative order of elements that are not removed is +/// unchanged. +/// \ingroup MutatingAlgorithms +/// +template <typename Container, typename BinaryPredicate> +inline void unique (Container& ctr, BinaryPredicate binary_pred) +{ + ctr.erase (unique_copy (ctr.begin(), ctr.end(), ctr.begin(), binary_pred), ctr.end()); +} + +/// Reverse reverses a range. +/// That is: for every i such that 0 <= i <= (last - first) / 2), +/// it exchanges *(first + i) and *(last - (i + 1)). +/// \ingroup MutatingAlgorithms +/// +template <typename Container> +inline void reverse (Container& ctr) +{ + reverse (ctr.begin(), ctr.end()); +} + +/// Exchanges ranges [first, middle) and [middle, last) +/// \ingroup MutatingAlgorithms +/// +template <typename Container> +inline void rotate (Container& ctr, off_t offset) +{ + assert (size_t(offset > 0 ? offset : -offset) < ctr.size()); + if (offset > 0) + rotate (ctr.begin(), ctr.end() - offset, ctr.end()); + else + rotate (ctr.begin(), ctr.begin() - offset, ctr.end()); +} + +/// Returns the furthermost iterator i in [first, last) such that, +/// for every iterator j in [first, i), *j < value +/// Assumes the range is sorted. +/// \ingroup SearchingAlgorithms +/// +template <typename Container, typename LessThanComparable> +inline typename Container::const_iterator lower_bound (const Container& ctr, const LessThanComparable& value) +{ + return (lower_bound (ctr.begin(), ctr.end(), value)); +} +template <typename Container, typename LessThanComparable> +inline typename Container::iterator lower_bound (Container& ctr, const LessThanComparable& value) +{ + return (lower_bound (ctr.begin(), ctr.end(), value)); +} + +/// Returns the furthermost iterator i in [first,last) such that for +/// every iterator j in [first,i), value < *j is false. +/// \ingroup SearchingAlgorithms +/// +template <typename Container, typename LessThanComparable> +inline typename Container::const_iterator upper_bound (const Container& ctr, const LessThanComparable& value) +{ + return (upper_bound (ctr.begin(), ctr.end(), value)); +} +template <typename Container, typename LessThanComparable> +inline typename Container::iterator upper_bound (Container& ctr, const LessThanComparable& value) +{ + return (upper_bound (ctr.begin(), ctr.end(), value)); +} + +/// Performs a binary search for \p value. +/// Assumes the range is sorted. +/// \ingroup SearchingAlgorithms +/// +template <typename Container> +inline bool binary_search (const Container& ctr, const typename Container::value_type& value) +{ + return (binary_search (ctr.begin(), ctr.end(), value)); +} +template <typename Container> +inline bool binary_search (Container& ctr, const typename Container::value_type& value) +{ + return (binary_search (ctr.begin(), ctr.end(), value)); +} + +/// Returns pair<lower_bound,upper_bound> +/// \ingroup SearchingAlgorithms +/// +template <typename Container, typename LessThanComparable> +inline pair<typename Container::const_iterator,typename Container::const_iterator> equal_range (const Container& ctr, const LessThanComparable& value) +{ + return (equal_range (ctr.begin(), ctr.end(), value)); +} +template <typename Container, typename LessThanComparable> +inline pair<typename Container::iterator,typename Container::iterator> equal_range (Container& ctr, const LessThanComparable& value) +{ + return (equal_range (ctr.begin(), ctr.end(), value)); +} + +/// Sorts the container +/// \ingroup SortingAlgorithms +/// +template <typename Container> +inline void sort (Container& ctr) +{ + sort (ctr.begin(), ctr.end()); +} + +/// Sorts the container +/// \ingroup SortingAlgorithms +/// +template <typename Container, typename Compare> +inline void sort (Container& ctr, Compare comp) +{ + sort (ctr.begin(), ctr.end(), comp); +} + +/// Sorts the container +/// \ingroup SortingAlgorithms +/// +template <typename Container> +inline void stable_sort (Container& ctr) +{ + stable_sort (ctr.begin(), ctr.end()); +} + +/// Sorts the container +/// \ingroup SortingAlgorithms +/// +template <typename Container, typename Compare> +inline void stable_sort (Container& ctr, Compare comp) +{ + stable_sort (ctr.begin(), ctr.end(), comp); +} + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/uctrstrm.h @@ -0,0 +1,181 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. +// +/// \file uctrstrm.h +/// +/// \brief Serialization templates for standard containers. +/// Because containers are templates, a single operator>> is impossible. +/// Making virtual read/write is also impossible because not all containers +/// contain serializable elements. Therefore, use the macros in this file. + +#ifndef UCTRSTRM_H_75B2C3EA4980DDDC6B6DFFF767A3B7AC +#define UCTRSTRM_H_75B2C3EA4980DDDC6B6DFFF767A3B7AC + +#include "mistream.h" +#include "sostream.h" +#include "uiosfunc.h" +#include <typeinfo> + +namespace ustl { + +//---------------------------------------------------------------------- +// Macros for easily declaring a container streamable. +//---------------------------------------------------------------------- + +/// \brief Declares container template \p type streamable. +/// +/// Use TEMPLATE_TYPE and TEMPLATE_DECL macros to pass in templated +/// type with commas and the template declaration. +/// +#define STD_TEMPLATE_CTR_STREAMABLE(type, template_decl) \ + template_decl \ + inline istream& operator>> (istream& is, type& v) \ + { return (container_read (is, v)); } \ + template_decl \ + inline ostream& operator<< (ostream& os, const type& v) \ + { return (container_write (os, v)); } \ + template_decl \ + inline ostringstream& operator<< (ostringstream& os, const type& v) \ + { return (container_text_write (os, v)); } \ + template_decl \ + struct object_stream_size<type > { \ + inline size_t operator()(const type& v) const \ + { return (container_stream_size (v)); } \ + }; + +/// \brief Declares non-resizable container template \p type streamable. +#define STD_TEMPLATE_NR_CTR_STREAMABLE(type, template_decl) \ + template_decl \ + inline istream& operator>> (istream& is, type& v) \ + { return (nr_container_read (is, v)); } \ + template_decl \ + inline ostream& operator<< (ostream& os, const type& v) \ + { return (nr_container_write (os, v)); } \ + template_decl \ + inline ostringstream& operator<< (ostringstream& os, const type& v) \ + { return (container_text_write (os, v)); } \ + template_decl \ + struct object_stream_size<type > { \ + inline size_t operator()(const type& v) const \ + { return (nr_container_stream_size (v)); } \ + }; + +//---------------------------------------------------------------------- +// Fixed size container serialization. +//---------------------------------------------------------------------- + +/// Reads fixed size container \p v from stream \p is. +template <typename Container> +inline istream& nr_container_read (istream& is, Container& v) +{ + foreach (typename Container::iterator, i, v) + is >> *i; + return (is); +} + +/// Writes fixed size container \p v into stream \p os. +template <typename Container> +inline ostream& nr_container_write (ostream& os, const Container& v) +{ + foreach (typename Container::const_iterator, i, v) + os << *i; + return (os); +} + +/// Computes the stream size of a fixed size standard container. +template <typename Container> +inline size_t nr_container_stream_size (const Container& v) +{ + typedef typename Container::const_iterator vciter_t; + typedef typename iterator_traits<vciter_t>::value_type value_type; + if (!v.size()) + return (0); + size_t s = 0, dvs; + vciter_t i = v.begin(); + do { + dvs = stream_size_of(*i); + s += dvs; + } while (++i != v.end() && !__builtin_constant_p(dvs)); + if (__builtin_constant_p(dvs)) + s *= v.size(); + return (s); +} + +//---------------------------------------------------------------------- +// Resizable container serialization. +//---------------------------------------------------------------------- + +/// Reads container \p v from stream \p is. +template <typename Container> +istream& container_read (istream& is, Container& v) +{ + typedef typename Container::value_type value_type; + typedef typename Container::iterator iterator; + typedef typename Container::written_size_type written_size_type; + written_size_type n = 0; + is >> n; + const size_t expectedSize = n * stream_size_of(value_type()); + if (!is.verify_remaining ("read", USTL_TYPENAME(v), expectedSize)) + return (is); + if (alignof(NullValue<value_type>()) > alignof(n)) + is >> ios::talign<value_type>(); + v.resize (n); + nr_container_read (is, v); + is >> ios::talign<written_size_type>(); + return (is); +} + +/// Writes the vector to stream \p os. +template <typename Container> +ostream& container_write (ostream& os, const Container& v) +{ + typedef typename Container::value_type value_type; + typedef typename Container::written_size_type written_size_type; + const written_size_type sz (v.size()); + os << sz; + if (alignof(NullValue<value_type>()) > alignof(sz)) + os << ios::talign<value_type>(); + nr_container_write (os, v); + os << ios::talign<written_size_type>(); + return (os); +} + +/// Computes the stream size of a standard container. +template <typename Container> +size_t container_stream_size (const Container& v) +{ + typedef typename Container::value_type value_type; + typedef typename Container::written_size_type written_size_type; + const written_size_type sz (v.size()); + size_t sizeSize = stream_size_of (sz); + if (alignof(NullValue<value_type>()) > alignof(sz)) + sizeSize = Align (sizeSize, alignof(NullValue<value_type>())); + return (Align (sizeSize + nr_container_stream_size (v), alignof(sz))); +} + +/// \brief Writes element \p v into stream \p os as text. +/// Specialize to custom print elements. +template <typename T> +inline ostringstream& container_element_text_write (ostringstream& os, const T& v) +{ return (os << v); } + +/// Writes container \p v into stream \p os as text. +template <typename Container> +ostringstream& container_text_write (ostringstream& os, const Container& v) +{ + typename Container::const_iterator i = v.begin(); + os << '('; + while (i < v.end()) { + container_element_text_write (os, *i); + os << ",)"[++i == v.end()]; + } + return (os); +} + +//---------------------------------------------------------------------- + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/uexception.h @@ -0,0 +1,186 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UEXCEPTION_H_18DE3EF55C4F00673268F0D66546AF5D +#define UEXCEPTION_H_18DE3EF55C4F00673268F0D66546AF5D + +#include "utypes.h" +#ifndef WITHOUT_LIBSTDCPP + #include <exception> + #include <new> +#endif +#include "bktrace.h" + +#if WITHOUT_LIBSTDCPP +namespace std { +/// If you write a replacement terminate handler, it must be of this type. +typedef void (*terminate_handler) (void); +/// If you write a replacement unexpected handler, it must be of this type. +typedef void (*unexpected_handler) (void); +/// Takes a new handler function as an argument, returns the old function. +terminate_handler set_terminate (terminate_handler pHandler) throw(); +/// The runtime will call this function if exception handling must be +/// abandoned for any reason. It can also be called by the user. +void terminate (void) __attribute__ ((__noreturn__)); +/// Takes a new handler function as an argument, returns the old function. +unexpected_handler set_unexpected (unexpected_handler pHandler) throw(); +/// The runtime will call this function if an exception is thrown which +/// violates the function's exception specification. +void unexpected (void) __attribute__ ((__noreturn__)); +/// Returns true when the caught exception violates the throw specification. +bool uncaught_exception() throw(); +} // namespace std +#endif + +namespace ustl { + +class string; + +typedef uint32_t xfmt_t; + +enum { + xfmt_Exception, + xfmt_BadAlloc, + xfmt_LibcException = 12, + xfmt_FileException = 13, + xfmt_StreamBoundsException = 14 +}; + +/// \class exception uexception.h ustl.h +/// \ingroup Exceptions +/// +/// \brief Base class for exceptions, equivalent to std::exception. +/// +#if WITHOUT_LIBSTDCPP +class exception { +#else +class exception : public std::exception { +#endif +public: + typedef const CBacktrace& rcbktrace_t; +public: + inline exception (void) throw() : m_Format (xfmt_Exception) {} + inline virtual ~exception (void) throw() {} + inline virtual const char* what (void) const throw() { return ("error"); } + virtual void info (string& msgbuf, const char* fmt = NULL) const throw(); + virtual void read (istream& is); + virtual void write (ostream& os) const; + void text_write (ostringstream& os) const; + inline virtual size_t stream_size (void) const { return (sizeof(m_Format) + sizeof(uint32_t) + m_Backtrace.stream_size()); } + /// Format of the exception is used to lookup exception::info format string. + /// Another common use is the instantiation of serialized exceptions, used + /// by the error handler node chain to troubleshoot specific errors. + inline xfmt_t format (void) const { return (m_Format); } + inline rcbktrace_t backtrace (void) const { return (m_Backtrace); } +protected: + inline void set_format (xfmt_t fmt) { m_Format = fmt; } +private: + CBacktrace m_Backtrace; ///< Backtrace of the throw point. + xfmt_t m_Format; ///< Format of the exception's data. +}; + +/// \class bad_cast uexception.h ustl.h +/// \ingroup Exceptions +/// +/// \brief Thrown to indicate a bad dynamic_cast usage. +/// +class bad_cast : public exception { +public: + inline explicit bad_cast (void) throw() : exception() {} + inline virtual const char* what (void) const throw() { return ("bad cast"); } +}; + +//---------------------------------------------------------------------- + +/// \class bad_alloc uexception.h ustl.h +/// \ingroup Exceptions +/// +/// \brief Exception thrown on memory allocation failure by memblock::reserve. +/// +#if WITHOUT_LIBSTDCPP +class bad_alloc : public exception { +#else +class bad_alloc : public std::bad_alloc, public exception { +#endif +public: + explicit bad_alloc (size_t nBytes = 0) throw(); + inline virtual const char* what (void) const throw() { return ("memory allocation failed"); } + virtual void info (string& msgbuf, const char* fmt = NULL) const throw(); + virtual void read (istream& is); + virtual void write (ostream& os) const; + virtual size_t stream_size (void) const; +protected: + size_t m_nBytesRequested; ///< Number of bytes requested by the failed allocation. +}; + +/// \class libc_exception uexception.h ustl.h +/// \ingroup Exceptions +/// +/// \brief Thrown when a libc function returns an error. +/// +/// Contains an errno and description. This is a uSTL extension. +/// +class libc_exception : public exception { +public: + explicit libc_exception (const char* operation) throw(); + libc_exception (const libc_exception& v) throw(); + const libc_exception& operator= (const libc_exception& v); + inline virtual const char* what (void) const throw() { return ("libc function failed"); } + virtual void info (string& msgbuf, const char* fmt = NULL) const throw(); + virtual void read (istream& is); + virtual void write (ostream& os) const; + virtual size_t stream_size (void) const; +protected: + intptr_t m_Errno; ///< Error code returned by the failed operation. + const char* m_Operation; ///< Name of the failed operation. +}; + +/// \class file_exception uexception.h ustl.h +/// \ingroup Exceptions +/// +/// \brief File-related exceptions. +/// +/// Contains the file name. This is a uSTL extension. +/// +class file_exception : public libc_exception { +public: + file_exception (const char* operation, const char* filename) throw(); + inline virtual const char* what (void) const throw() { return ("file error"); } + virtual void info (string& msgbuf, const char* fmt = NULL) const throw(); + virtual void read (istream& is); + virtual void write (ostream& os) const; + virtual size_t stream_size (void) const; +protected: + char m_Filename [PATH_MAX]; ///< Name of the file causing the error. +}; + +/// \class stream_bounds_exception uexception.h ustl.h +/// \ingroup Exceptions +/// +/// \brief Stream bounds checking. +/// +/// Only thrown in debug builds unless you say otherwise in config.h +/// This is a uSTL extension. +/// +class stream_bounds_exception : public libc_exception { +public: + stream_bounds_exception (const char* operation, const char* type, uoff_t offset, size_t expected, size_t remaining) throw(); + inline virtual const char* what (void) const throw() { return ("stream bounds exception"); } + virtual void info (string& msgbuf, const char* fmt = NULL) const throw(); + virtual void read (istream& is); + virtual void write (ostream& os) const; + virtual size_t stream_size (void) const; +protected: + const char* m_TypeName; + uoff_t m_Offset; + size_t m_Expected; + size_t m_Remaining; +}; + +const char* demangle_type_name (char* buf, size_t bufSize, size_t* pdmSize = NULL); + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/ufunction.h @@ -0,0 +1,465 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UFUNCTION_H_221ABA8551801799263C927234C085F3 +#define UFUNCTION_H_221ABA8551801799263C927234C085F3 + +namespace ustl { + +//---------------------------------------------------------------------- +// Standard functors +//---------------------------------------------------------------------- + +/// \brief void-returning function abstract interface. +/// \ingroup FunctorObjects +template <typename Result> +struct void_function { + typedef Result result_type; +}; + +/// \brief \p Result f (\p Arg) function abstract interface. +/// \ingroup FunctorObjects +template <typename Arg, typename Result> +struct unary_function { + typedef Arg argument_type; + typedef Result result_type; +}; + +/// \brief \p Result f (\p Arg1, \p Arg2) function abstract interface. +/// \ingroup FunctorObjects +template <typename Arg1, typename Arg2, typename Result> +struct binary_function { + typedef Arg1 first_argument_type; + typedef Arg2 second_argument_type; + typedef Result result_type; +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +#define STD_BINARY_FUNCTOR(name, rv, func) \ +template <class T> struct name : public binary_function<T,T,rv> \ +{ inline rv operator()(const T& a, const T& b) const { return func; } }; +#define STD_UNARY_FUNCTOR(name, rv, func) \ +template <class T> struct name : public unary_function<T,rv> \ +{ inline rv operator()(const T& a) const { return func; } }; +#define STD_CONVERSION_FUNCTOR(name, func) \ +template <class S, class D> struct name : public unary_function<S,D> \ +{ inline D operator()(const S& a) const { return func; } }; + +STD_BINARY_FUNCTOR (plus, T, (a + b)) +STD_BINARY_FUNCTOR (minus, T, (a - b)) +STD_BINARY_FUNCTOR (divides, T, (a / b)) +STD_BINARY_FUNCTOR (modulus, T, (a % b)) +STD_BINARY_FUNCTOR (multiplies, T, (a * b)) +STD_BINARY_FUNCTOR (logical_and, T, (a && b)) +STD_BINARY_FUNCTOR (logical_or, T, (a || b)) +STD_UNARY_FUNCTOR (logical_not, T, (!a)) +STD_BINARY_FUNCTOR (bitwise_or, T, (a | b)) +STD_BINARY_FUNCTOR (bitwise_and, T, (a & b)) +STD_BINARY_FUNCTOR (bitwise_xor, T, (a ^ b)) +STD_UNARY_FUNCTOR (bitwise_not, T, (~a)) +STD_UNARY_FUNCTOR (negate, T, (-a)) +STD_BINARY_FUNCTOR (equal_to, bool, (a == b)) +STD_BINARY_FUNCTOR (not_equal_to, bool, (!(a == b))) +STD_BINARY_FUNCTOR (greater, bool, (b < a)) +STD_BINARY_FUNCTOR (less, bool, (a < b)) +STD_BINARY_FUNCTOR (greater_equal, bool, (!(a < b))) +STD_BINARY_FUNCTOR (less_equal, bool, (!(b < a))) +STD_BINARY_FUNCTOR (compare, int, (a < b ? -1 : (b < a))) +STD_UNARY_FUNCTOR (identity, T, (a)) + +#endif // DOXYGEN_SHOULD_SKIP_THIS + +/// \brief Selects and returns the first argument. +/// \ingroup FunctorObjects +template <class T1, class T2> struct project1st : public binary_function<T1,T2,T1> { inline const T1& operator()(const T1& a, const T2&) const { return (a); } }; +/// \brief Selects and returns the second argument. +/// \ingroup FunctorObjects +template <class T1, class T2> struct project2nd : public binary_function<T1,T2,T2> { inline const T2& operator()(const T1&, const T2& a) const { return (a); } }; + +//---------------------------------------------------------------------- +// Generic function to functor converters. +//---------------------------------------------------------------------- + +/// \brief Wrapper object for unary function pointers. +/// Use the ptr_fun accessor to create this object. +/// \ingroup FunctorObjects +template <typename Arg, typename Result> +class pointer_to_unary_function : public unary_function<Arg,Result> { +public: + typedef Arg argument_type; + typedef Result result_type; + typedef Result (*pfunc_t)(Arg); +public: + explicit inline pointer_to_unary_function (pfunc_t pfn) : m_pfn (pfn) {} + inline result_type operator() (argument_type v) const { return (m_pfn(v)); } +private: + pfunc_t m_pfn; ///< Pointer to the wrapped function. +}; + +/// \brief Wrapper object for binary function pointers. +/// Use the ptr_fun accessor to create this object. +/// \ingroup FunctorObjects +template <typename Arg1, typename Arg2, typename Result> +class pointer_to_binary_function : public binary_function<Arg1,Arg2,Result> { +public: + typedef Arg1 first_argument_type; + typedef Arg2 second_argument_type; + typedef Result result_type; + typedef Result (*pfunc_t)(Arg1, Arg2); +public: + explicit inline pointer_to_binary_function (pfunc_t pfn) : m_pfn (pfn) {} + inline result_type operator() (first_argument_type v1, second_argument_type v2) const { return (m_pfn(v1, v2)); } +private: + pfunc_t m_pfn; ///< Pointer to the wrapped function. +}; + +/// ptr_fun(pfn) wraps function pointer pfn into a functor class that calls it. +/// \ingroup FunctorAccessors +template <typename Arg, typename Result> +inline pointer_to_unary_function<Arg,Result> ptr_fun (Result (*pfn)(Arg)) +{ + return (pointer_to_unary_function<Arg,Result> (pfn)); +} + +/// ptr_fun(pfn) wraps function pointer pfn into a functor class that calls it. +/// \ingroup FunctorAccessors +template <typename Arg1, typename Arg2, typename Result> +inline pointer_to_binary_function<Arg1,Arg2,Result> ptr_fun (Result (*pfn)(Arg1,Arg2)) +{ + return (pointer_to_binary_function<Arg1,Arg2,Result> (pfn)); +} + +//---------------------------------------------------------------------- +// Negators. +//---------------------------------------------------------------------- + +/// \brief Wraps a unary function to return its logical negative. +/// Use the unary_negator accessor to create this object. +/// \ingroup FunctorObjects +template <class UnaryFunction> +class unary_negate : public unary_function<typename UnaryFunction::argument_type, + typename UnaryFunction::result_type> { +public: + typedef typename UnaryFunction::argument_type argument_type; + typedef typename UnaryFunction::result_type result_type; +public: + explicit inline unary_negate (UnaryFunction pfn) : m_pfn (pfn) {} + inline result_type operator() (argument_type v) const { return (!m_pfn(v)); } +private: + UnaryFunction m_pfn; +}; + +/// Returns the functor that negates the result of *pfn(). +/// \ingroup FunctorAccessors +template <class UnaryFunction> +inline unary_negate<UnaryFunction> unary_negator (UnaryFunction pfn) +{ + return (unary_negate<UnaryFunction>(pfn)); +} + +//---------------------------------------------------------------------- +// Argument binders +//---------------------------------------------------------------------- + +/// \brief Converts a binary function to a unary function +/// by binding a constant value to the first argument. +/// Use the bind1st accessor to create this object. +/// \ingroup FunctorObjects +template <class BinaryFunction> +class binder1st : public unary_function<typename BinaryFunction::second_argument_type, + typename BinaryFunction::result_type> { +public: + typedef typename BinaryFunction::first_argument_type arg1_t; + typedef typename BinaryFunction::second_argument_type arg2_t; + typedef typename BinaryFunction::result_type result_t; +public: + inline binder1st (const BinaryFunction& pfn, const arg1_t& v) : m_pfn (pfn), m_Value(v) {} + inline result_t operator()(arg2_t v2) const { return (m_pfn (m_Value, v2)); } +protected: + BinaryFunction m_pfn; + arg1_t m_Value; +}; + +/// \brief Converts a binary function to a unary function +/// by binding a constant value to the second argument. +/// Use the bind2nd accessor to create this object. +/// \ingroup FunctorObjects +template <class BinaryFunction> +class binder2nd : public unary_function<typename BinaryFunction::first_argument_type, + typename BinaryFunction::result_type> { +public: + typedef typename BinaryFunction::first_argument_type arg1_t; + typedef typename BinaryFunction::second_argument_type arg2_t; + typedef typename BinaryFunction::result_type result_t; +public: + inline binder2nd (const BinaryFunction& pfn, const arg2_t& v) : m_pfn (pfn), m_Value(v) {} + inline result_t operator()(arg1_t v1) const { return (m_pfn (v1, m_Value)); } +protected: + BinaryFunction m_pfn; + arg2_t m_Value; +}; + +/// Converts \p pfn into a unary function by binding the first argument to \p v. +/// \ingroup FunctorAccessors +template <typename BinaryFunction> +inline binder1st<BinaryFunction> +bind1st (BinaryFunction pfn, typename BinaryFunction::first_argument_type v) +{ + return (binder1st<BinaryFunction> (pfn, v)); +} + +/// Converts \p pfn into a unary function by binding the second argument to \p v. +/// \ingroup FunctorAccessors +template <typename BinaryFunction> +inline binder2nd<BinaryFunction> +bind2nd (BinaryFunction pfn, typename BinaryFunction::second_argument_type v) +{ + return (binder2nd<BinaryFunction> (pfn, v)); +} + +//---------------------------------------------------------------------- +// Composition adapters +//---------------------------------------------------------------------- + +/// \brief Chains two unary functions together. +/// +/// When f(x) and g(x) are composed, the result is function c(x)=f(g(x)). +/// Use the \ref compose1 accessor to create this object. +/// This template is an extension, implemented by SGI STL and uSTL. +/// \ingroup FunctorObjects +/// +template <typename Operation1, typename Operation2> +class unary_compose : public unary_function<typename Operation2::argument_type, + typename Operation1::result_type> { +public: + typedef typename Operation2::argument_type arg_t; + typedef const arg_t& rcarg_t; + typedef typename Operation1::result_type result_t; +public: + inline unary_compose (const Operation1& f, const Operation2& g) : m_f(f), m_g(g) {} + inline result_t operator() (rcarg_t x) const { return m_f(m_g(x)); } +protected: + Operation1 m_f; ///< f(x), if c(x) = f(g(x)) + Operation2 m_g; ///< g(x), if c(x) = f(g(x)) +}; + +/// Creates a \ref unary_compose object whose function c(x)=f(g(x)) +/// \ingroup FunctorAccessors +template <typename Operation1, typename Operation2> +inline unary_compose<Operation1, Operation2> +compose1 (const Operation1& f, const Operation2& g) +{ return unary_compose<Operation1,Operation2>(f, g); } + +/// \brief Chains two unary functions through a binary function. +/// +/// When f(x,y), g(x), and h(x) are composed, the result is function +/// c(x)=f(g(x),h(x)). Use the \ref compose2 accessor to create this +/// object. This template is an extension, implemented by SGI STL and uSTL. +/// \ingroup FunctorObjects +/// +template <typename Operation1, typename Operation2, typename Operation3> +class binary_compose : public unary_function<typename Operation2::argument_type, + typename Operation1::result_type> { +public: + typedef typename Operation2::argument_type arg_t; + typedef const arg_t& rcarg_t; + typedef typename Operation1::result_type result_t; +public: + inline binary_compose (const Operation1& f, const Operation2& g, const Operation3& h) : m_f(f), m_g(g), m_h(h) {} + inline result_t operator() (rcarg_t x) const { return m_f(m_g(x), m_h(x)); } +protected: + Operation1 m_f; ///< f(x,y), if c(x) = f(g(x),h(x)) + Operation2 m_g; ///< g(x), if c(x) = f(g(x),h(x)) + Operation3 m_h; ///< h(x), if c(x) = f(g(x),h(x)) +}; + +/// Creates a \ref binary_compose object whose function c(x)=f(g(x),h(x)) +/// \ingroup FunctorAccessors +template <typename Operation1, typename Operation2, typename Operation3> +inline binary_compose<Operation1, Operation2, Operation3> +compose2 (const Operation1& f, const Operation2& g, const Operation3& h) +{ return binary_compose<Operation1, Operation2, Operation3> (f, g, h); } + +//---------------------------------------------------------------------- +// Member function adaptors +//---------------------------------------------------------------------- + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +#define MEM_FUN_T(WrapperName, ClassName, ArgType, FuncType, CallType) \ + template <typename Ret, class T> \ + class ClassName : public unary_function<ArgType,Ret> { \ + public: \ + typedef Ret (T::*func_t) FuncType; \ + public: \ + explicit inline ClassName (func_t pf) : m_pf (pf) {} \ + inline Ret operator() (ArgType p) const { return ((p CallType m_pf)()); } \ + private: \ + func_t m_pf; \ + }; \ + \ + template <class Ret, typename T> \ + inline ClassName<Ret,T> WrapperName (Ret (T::*pf) FuncType) \ + { \ + return (ClassName<Ret,T> (pf)); \ + } + +MEM_FUN_T(mem_fun, mem_fun_t, T*, (void), ->*) +MEM_FUN_T(mem_fun, const_mem_fun_t, const T*, (void) const, ->*) +MEM_FUN_T(mem_fun_ref, mem_fun_ref_t, T&, (void), .*) +MEM_FUN_T(mem_fun_ref, const_mem_fun_ref_t, const T&, (void) const, .*) + +#define EXT_MEM_FUN_T(ClassName, HostType, FuncType) \ + template <class T, typename Ret, typename V> \ + class ClassName : public unary_function<V,void> { \ + public: \ + typedef Ret (T::*func_t)(V) FuncType; \ + public: \ + inline ClassName (HostType t, func_t pf) : m_t (t), m_pf (pf) {} \ + inline Ret operator() (V v) const { return ((m_t->*m_pf)(v)); } \ + private: \ + HostType m_t; \ + func_t m_pf; \ + }; \ + \ + template <class T, typename Ret, typename V> \ + inline ClassName<T,Ret,V> mem_fun (HostType p, Ret (T::*pf)(V) FuncType) \ + { \ + return (ClassName<T,Ret,V> (p, pf)); \ + } + +EXT_MEM_FUN_T(ext_mem_fun_t, T*, ) +EXT_MEM_FUN_T(const_ext_mem_fun_t, const T*, const) + +#endif // DOXYGEN_SHOULD_SKIP_THIS + +//---------------------------------------------------------------------- +// Member variable adaptors (uSTL extension) +//---------------------------------------------------------------------- + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +#define MEM_VAR_T(FunctorName, ArgType, VarType, BaseClass, CallImpl) \ + template <typename Function, class T, typename VT> \ + class FunctorName##_t : public BaseClass { \ + public: \ + typedef ArgType argument_type; \ + typedef typename Function::result_type result_type; \ + typedef VarType mem_var_ptr_t; \ + public: \ + inline FunctorName##_t (mem_var_ptr_t pv, Function pfn) : m_pv(pv), m_pfn(pfn) {} \ + inline result_type operator() CallImpl \ + private: \ + mem_var_ptr_t m_pv; \ + Function m_pfn; \ + }; \ + \ + template <typename Function, class T, typename VT> \ + inline FunctorName##_t<Function, T, VT> \ + FunctorName (VT T::*mvp, Function pfn) \ + { \ + return (FunctorName##_t<Function,T,VT> (mvp, pfn)); \ + } + +#define FUNCTOR_UNARY_BASE(ArgType) unary_function<ArgType, typename Function::result_type> +#define FUNCTOR_BINARY_BASE(ArgType) binary_function<ArgType, ArgType, typename Function::result_type> + +#define MEM_VAR_UNARY_ARGS (argument_type p) const \ + { return (m_pfn(p.*m_pv)); } +#define MEM_VAR_BINARY_ARGS (argument_type p1, argument_type p2) const \ + { return (m_pfn(p1.*m_pv, p2.*m_pv)); } + +MEM_VAR_T(mem_var1, T&, VT T::*, FUNCTOR_UNARY_BASE(T&), MEM_VAR_UNARY_ARGS) +MEM_VAR_T(const_mem_var1, const T&, const VT T::*, FUNCTOR_UNARY_BASE(T&), MEM_VAR_UNARY_ARGS) +MEM_VAR_T(mem_var2, T&, VT T::*, FUNCTOR_BINARY_BASE(T&), MEM_VAR_BINARY_ARGS) +MEM_VAR_T(const_mem_var2, const T&, const VT T::*, FUNCTOR_BINARY_BASE(T&), MEM_VAR_BINARY_ARGS) + +#undef MEM_VAR_UNARY_ARGS +#undef MEM_VAR_BINARY_ARGS + +#endif // DOXYGEN_SHOULD_SKIP_THIS + +/// Returned functor passes member variable \p mvp reference of given object to equal\<VT\>. +/// \ingroup FunctorAccessors +template <class T, typename VT> +inline const_mem_var1_t<binder2nd<equal_to<VT> >, T, VT> +mem_var_equal_to (const VT T::*mvp, const VT& v) +{ + return (const_mem_var1_t<binder2nd<equal_to<VT> >,T,VT> (mvp, bind2nd(equal_to<VT>(), v))); +} + +/// Returned functor passes member variable \p mvp reference of given object to less\<VT\>. +/// \ingroup FunctorAccessors +template <class T, typename VT> +inline const_mem_var1_t<binder2nd<less<VT> >, T, VT> +mem_var_less (const VT T::*mvp, const VT& v) +{ + return (const_mem_var1_t<binder2nd<less<VT> >,T,VT> (mvp, bind2nd(less<VT>(), v))); +} + +/// Returned functor passes member variable \p mvp reference of given object to equal\<VT\>. +/// \ingroup FunctorAccessors +template <class T, typename VT> +inline const_mem_var2_t<equal_to<VT>, T, VT> +mem_var_equal_to (const VT T::*mvp) +{ + return (const_mem_var2_t<equal_to<VT>,T,VT> (mvp, equal_to<VT>())); +} + +/// Returned functor passes member variable \p mvp reference of given object to less\<VT\>. +/// \ingroup FunctorAccessors +template <class T, typename VT> +inline const_mem_var2_t<less<VT>, T, VT> +mem_var_less (const VT T::*mvp) +{ + return (const_mem_var2_t<less<VT>,T,VT> (mvp, less<VT>())); +} + +//---------------------------------------------------------------------- +// Dereference adaptors (uSTL extension) +//---------------------------------------------------------------------- + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +#define DEREFERENCER_T(ClassName, ArgType, BaseClass, CallImpl, FunctorKey) \ + template <typename T, typename Function> \ + class ClassName : public BaseClass { \ + public: \ + typedef ArgType* argument_type; \ + typedef typename Function::result_type result_type; \ + public: \ + inline ClassName (Function pfn) : m_pfn (pfn) {} \ + inline result_type operator() CallImpl \ + private: \ + Function m_pfn; \ + }; \ + \ + template <typename T, typename Function> \ + inline ClassName<T,Function> _dereference (Function pfn, FunctorKey) \ + { \ + return (ClassName<T,Function> (pfn)); \ + } + +#define DEREF_UNARY_ARGS (argument_type p) const \ + { return (m_pfn(*p)); } +#define DEREF_BINARY_ARGS (argument_type p1, argument_type p2) const \ + { return (m_pfn(*p1, *p2)); } + +DEREFERENCER_T(deref1_t, T, FUNCTOR_UNARY_BASE(T*), DEREF_UNARY_ARGS, FUNCTOR_UNARY_BASE(T)) +DEREFERENCER_T(const_deref1_t, const T, FUNCTOR_UNARY_BASE(const T*), DEREF_UNARY_ARGS, FUNCTOR_UNARY_BASE(const T)) +DEREFERENCER_T(deref2_t, T, FUNCTOR_BINARY_BASE(T*), DEREF_BINARY_ARGS, FUNCTOR_BINARY_BASE(T)) +DEREFERENCER_T(const_deref2_t, const T, FUNCTOR_BINARY_BASE(const T*), DEREF_BINARY_ARGS, FUNCTOR_BINARY_BASE(const T)) + +#define dereference(f) _dereference(f,f) + +#undef DEREF_UNARY_ARGS +#undef DEREF_BINARY_ARGS + +#endif + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/uheap.h @@ -0,0 +1,142 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UHEAP_H_574B9EAF271A1C107190B4D575A356C5 +#define UHEAP_H_574B9EAF271A1C107190B4D575A356C5 + +#include "ualgobase.h" + +namespace ustl { + +/// \brief Returns true if the given range is a heap under \p comp. +/// A heap is a sequentially encoded binary tree where for every node +/// comp(node,child1) is false and comp(node,child2) is false. +/// \ingroup HeapAlgorithms +/// \ingroup ConditionAlgorithms +/// +template <typename RandomAccessIterator, typename Compare> +bool is_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp) +{ + RandomAccessIterator iChild (first); + for (; ++iChild < last; ++first) + if (comp (*first, *iChild) || (++iChild < last && comp (*first, *iChild))) + return (false); + return (true); +} + +/// \brief make_heap turns the range [first, last) into a heap +/// At completion, is_heap (first, last, comp) is true. +/// The algorithm is adapted from "Classic Data Structures in C++" by Timothy Budd. +/// \ingroup HeapAlgorithms +/// \ingroup SortingAlgorithms +/// +template <typename RandomAccessIterator, typename Compare> +void make_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp) +{ + typedef typename iterator_traits<RandomAccessIterator>::value_type value_type; + const value_type v (*first); + uoff_t iChild, iHole = 0, iEnd (distance (first, last)); + while ((iChild = 2 * iHole + 1) < iEnd) { + if (iChild + 1 < iEnd) // Pick the greater child + iChild += comp (first[iChild], first[iChild + 1]); + if (comp (first[iChild], v)) + break; // Done when parent is greater than both children. + first[iHole] = first[iChild]; + iHole = iChild; + } + if (iHole < iEnd) + first[iHole] = v; +} + +/// \brief Inserts the *--last into the preceeding range assumed to be a heap. +/// \ingroup HeapAlgorithms +/// \ingroup MutatingAlgorithms +template <typename RandomAccessIterator, typename Compare> +void push_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp) +{ + if (last <= first) + return; + typedef typename iterator_traits<RandomAccessIterator>::value_type value_type; + const value_type v (*--last); + while (first < last) { + RandomAccessIterator iParent = first + (distance(first, last) - 1) / 2; + if (comp (v, *iParent)) + break; + *last = *iParent; + last = iParent; + } + *last = v; +} + +/// Removes the largest element from the heap (*first) and places it at *(last-1) +/// [first, last-1) is a heap after this operation. +/// \ingroup HeapAlgorithms +/// \ingroup MutatingAlgorithms +template <typename RandomAccessIterator, typename Compare> +void pop_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp) +{ + if (--last <= first) + return; + iter_swap (first, last); + make_heap (first, last, comp); +} + +/// Sorts heap [first, last) in descending order according to comp. +/// \ingroup HeapAlgorithms +/// \ingroup SortingAlgorithms +template <typename RandomAccessIterator, typename Compare> +void sort_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp) +{ + for (; first < last; --last) + pop_heap (first, last, comp); +} + +#define HEAP_FN_WITH_LESS(rtype, name) \ +template <typename RandomAccessIterator>\ +inline rtype name (RandomAccessIterator first, RandomAccessIterator last) \ +{ \ + typedef typename iterator_traits<RandomAccessIterator>::value_type value_type; \ + return (name (first, last, less<value_type>())); \ +} +HEAP_FN_WITH_LESS (bool, is_heap) +HEAP_FN_WITH_LESS (void, make_heap) +HEAP_FN_WITH_LESS (void, push_heap) +HEAP_FN_WITH_LESS (void, pop_heap) +HEAP_FN_WITH_LESS (void, sort_heap) +#undef HEAP_FN_WITH_LESS + +/// \class priority_queue uheap.h ustl.h +/// \ingroup Sequences +/// +/// \brief Sorted queue adapter to uSTL containers. +/// +/// Acts just like the queue adapter, but keeps the elements sorted by priority +/// specified by the given comparison operator. +/// +template <typename T, typename Ctr = vector<T>, typename Comp = less<typename Ctr::value_type> > +class priority_queue { +public: + typedef Ctr base_ctr; + typedef typename base_ctr::value_type value_type; + typedef typename base_ctr::size_type size_type; + typedef typename base_ctr::const_pointer const_pointer; + typedef typename base_ctr::const_reference reference; +public: + priority_queue (const Comp& c = Comp()) : m_v(), m_c (c) {} + priority_queue (const_pointer f, const_pointer l, const Comp& c = Comp()) + : m_v (f, l), m_c (c) { make_heap (m_v.begin(), m_v.end(), m_c); } + inline size_type size (void) const { return (m_v.size()); } + inline bool empty (void) const { return (m_v.empty()); } + inline reference top (void) const { return (m_v.at(0)); } + inline void push (reference v) { m_v.push_back (v); make_heap (m_v.begin(), m_v.end(), m_c); } + inline void pop (void) { pop_heap (m_v.begin(), m_v.end()); m_v.pop_back(); } +private: + base_ctr m_v; ///< Element container. + Comp m_c; ///< Comparison functor by value. +}; + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/uios.h @@ -0,0 +1,103 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UIOS_H_630C16E316F7650E3A02E1C6611B789A +#define UIOS_H_630C16E316F7650E3A02E1C6611B789A + +#include "utypes.h" + +namespace ustl { + +class file_exception; + +const char endl = '\n'; ///< End of line character. +const char ends = '\0'; ///< End of string character. + +/// Defines types and constants used by all stream classes. +class ios_base { +public: + /// Used to set parameters for stringstreams + enum fmtflags { + boolalpha = (1 << 0), ///< Boolean values printed as text. + dec = (1 << 1), ///< Decimal number output. + fixed = (1 << 2), ///< Fixed-point float output. + hex = (1 << 3), ///< Hexadecimal number output. + internal = (1 << 4), + left = (1 << 5), ///< Left alignment. + oct = (1 << 6), ///< Octal number output. + right = (1 << 7), ///< Right alignment. + scientific = (1 << 8), ///< Scientific float format. + showbase = (1 << 9), ///< Add 0x or 0 prefixes on hex and octal numbers. + showpoint = (1 << 10), ///< Print decimal point. + showpos = (1 << 11), + skipws = (1 << 12), ///< Skip whitespace when reading. + unitbuf = (1 << 13), + uppercase = (1 << 14), + adjustfield = (1 << 15), + basefield = (1 << 16), + floatfield = (1 << 17) + }; + /// For file-based streams, specifies fd mode. + enum openmode_bits { + in = (1 << 0), + out = (1 << 1), + app = (1 << 2), + ate = (1 << 3), + binary = (1 << 4), + trunc = (1 << 5), + #ifndef DOXYGEN_SHOULD_SKIP_THIS + nonblock= (1 << 6), + nocreate= (1 << 7), + noctty = (1 << 8), + nombits = 9 + #endif + }; + /// Seek directions, equivalent to SEEK_SET, SEEK_CUR, and SEEK_END. + enum seekdir { + beg, + cur, + end + }; + /// I/O state bitmasks. + enum iostate_bits { + goodbit = 0, + badbit = (1 << 0), + eofbit = (1 << 1), + failbit = (1 << 2), + #ifndef DOXYGEN_SHOULD_SKIP_THIS + nbadbits = 3, + allbadbits = 0x7 + #endif + }; + + typedef uint32_t openmode; ///< Holds openmode_bits. + typedef uint32_t iostate; ///< Holds iostate_bits for a file stream. + typedef file_exception failure; ///< Thrown by fstream on errors. + + static const char c_DefaultDelimiters [16]; ///< Default word delimiters for stringstreams. +public: + inline ios_base (void) : m_State (goodbit), m_Exceptions (allbadbits) {} + inline iostate rdstate (void) const { return (m_State); } + inline bool bad (void) const { return (rdstate() & badbit); } + inline bool good (void) const { return (rdstate() == goodbit); } + inline bool fail (void) const { return (rdstate() & (badbit | failbit)); } + inline bool eof (void) const { return (rdstate() & eofbit); } + inline bool operator! (void) const { return (fail()); } + inline operator void* (void) const { return (reinterpret_cast<void*>(!fail())); } + inline void clear (iostate v = goodbit) { m_State = v; } + inline void setstate (iostate v) { m_State |= v; } + inline iostate exceptions (void) const { return (m_Exceptions); } + inline iostate exceptions (iostate v) { return (m_Exceptions = v); } +protected: + inline bool set_and_throw (iostate v) { setstate(v); return (exceptions() & v); } + void overrun (const char* op, const char* type, uint32_t n, uint32_t p, uint32_t rem); +private: + uint16_t m_State; ///< Open state, using ios::iostate_bits. + uint16_t m_Exceptions; ///< Exception flags, using ios::iostate_bits. +}; + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/uiosfunc.h @@ -0,0 +1,96 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UIOSFUNC_H_730C16E316F7650E3A02E1C6611B789A +#define UIOSFUNC_H_730C16E316F7650E3A02E1C6611B789A + +#include "sostream.h" + +namespace ustl { + +class ios : public ios_base { +public: + /// \class align uiosfunc.h ustl.h + /// \ingroup StreamFunctors + /// \brief Stream functor to allow inline align() calls. + /// + /// Example: os << ios::align(sizeof(uint16_t)); + /// + class align { + public: + inline explicit align (size_t grain = c_DefaultAlignment) : m_Grain(grain) {} + inline istream& apply (istream& is) const { is.align (m_Grain); return (is); } + inline ostream& apply (ostream& os) const { os.align (m_Grain); return (os); } + inline void read (istream& is) const { apply (is); } + inline void write (ostream& os) const { apply (os); } + inline size_t stream_size (void) const { return (m_Grain - 1); } + private: + const size_t m_Grain; + }; + + /// \class talign uiosfunc.h ustl.h + /// \ingroup StreamFunctors + /// \brief Stream functor to allow type-based alignment. + template <typename T> + class talign : public align { + public: + inline explicit talign (void) : align (alignof (NullValue<T>())) {} + }; + + /// \class skip uiosfunc.h ustl.h + /// \ingroup StreamFunctors + /// \brief Stream functor to allow inline skip() calls. + /// + /// Example: os << ios::skip(sizeof(uint16_t)); + /// + class skip { + public: + inline explicit skip (size_t nBytes) : m_nBytes(nBytes) {} + inline istream& apply (istream& is) const { is.skip (m_nBytes); return (is); } + inline ostream& apply (ostream& os) const { os.skip (m_nBytes); return (os); } + inline void read (istream& is) const { apply (is); } + inline void write (ostream& os) const { apply (os); } + inline size_t stream_size (void) const { return (m_nBytes); } + private: + const size_t m_nBytes; + }; + + /// \class width uiosfunc.h ustl.h + /// \ingroup StreamFunctors + /// \brief Stream functor to allow inline set_width() calls. + /// + /// Example: os << ios::width(15); + /// + class width { + public: + inline explicit width (size_t nBytes) : m_nBytes(nBytes) {} + inline ostringstream& apply (ostringstream& os) const { os.set_width (m_nBytes); return (os); } + inline void text_write (ostringstream& os) const { apply (os); } + private: + const size_t m_nBytes; + }; + + /// \class base uiosfunc.h ustl.h + /// \ingroup StreamFunctors + /// \brief Stream functor to allow inline set_base() calls. + /// + /// Example: os << ios::base(15); + /// + class base { + public: + inline explicit base (size_t n) : m_Base(n) {} + inline ostringstream& apply (ostringstream& os) const { os.set_base (m_Base); return (os); } + inline void text_write (ostringstream& os) const { apply (os); } + private: + const size_t m_Base; + }; +}; + +} // namespace ustl + +CAST_STREAMABLE(ustl::ios::fmtflags, uint32_t) +NUMERIC_LIMITS(ustl::ios::fmtflags, ustl::ios::boolalpha, ustl::ios::floatfield, false, true, true) + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/uiterator.h @@ -0,0 +1,266 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. +// +/// \file uiterator.h +/// \brief Contains various iterator adapters. + +#ifndef UITERATOR_H_5BCA176C7214A30F2069E2614D2DC226 +#define UITERATOR_H_5BCA176C7214A30F2069E2614D2DC226 + +#include "utypes.h" + +namespace ustl { + +//---------------------------------------------------------------------- + +/// \struct iterator_traits uiterator.h ustl.h +/// \brief Contains the type traits of \p Iterator +/// +template <typename Iterator> +struct iterator_traits { + typedef typename Iterator::value_type value_type; + typedef typename Iterator::difference_type difference_type; + typedef typename Iterator::pointer pointer; + typedef typename Iterator::reference reference; +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +template <typename T> +struct iterator_traits<T*> { + typedef T value_type; + typedef ptrdiff_t difference_type; + typedef const T* const_pointer; + typedef T* pointer; + typedef const T& const_reference; + typedef T& reference; +}; + +template <typename T> +struct iterator_traits<const T*> { + typedef T value_type; + typedef ptrdiff_t difference_type; + typedef const T* const_pointer; + typedef const T* pointer; + typedef const T& const_reference; + typedef const T& reference; +}; + +template <> +struct iterator_traits<void*> { + typedef uint8_t value_type; + typedef ptrdiff_t difference_type; + typedef const void* const_pointer; + typedef void* pointer; + typedef const value_type& const_reference; + typedef value_type& reference; +}; + +template <> +struct iterator_traits<const void*> { + typedef uint8_t value_type; + typedef ptrdiff_t difference_type; + typedef const void* const_pointer; + typedef const void* pointer; + typedef const value_type& const_reference; + typedef const value_type& reference; +}; + +#endif + +//---------------------------------------------------------------------- + +/// \class reverse_iterator uiterator.h ustl.h +/// \ingroup IteratorAdaptors +/// \brief Wraps \p Iterator to behave in an exactly opposite manner. +/// +template <class Iterator> +class reverse_iterator { +public: + typedef typename iterator_traits<Iterator>::value_type value_type; + typedef typename iterator_traits<Iterator>::difference_type difference_type; + typedef typename iterator_traits<Iterator>::pointer pointer; + typedef typename iterator_traits<Iterator>::reference reference; +public: + reverse_iterator (void) : m_i() {} + explicit reverse_iterator (Iterator iter) : m_i (iter) {} + inline bool operator== (const reverse_iterator& iter) const { return (m_i == iter.m_i); } + inline bool operator< (const reverse_iterator& iter) const { return (iter.m_i < m_i); } + inline Iterator base (void) const { return (m_i); } + inline reference operator* (void) const { Iterator prev (m_i); --prev; return (*prev); } + inline pointer operator-> (void) const { return (&(operator*())); } + inline reverse_iterator& operator++ (void) { -- m_i; return (*this); } + inline reverse_iterator& operator-- (void) { ++ m_i; return (*this); } + inline reverse_iterator operator++ (int) { reverse_iterator prev (*this); -- m_i; return (prev); } + inline reverse_iterator operator-- (int) { reverse_iterator prev (*this); ++ m_i; return (prev); } + inline reverse_iterator& operator+= (size_t n) { m_i -= n; return (*this); } + inline reverse_iterator& operator-= (size_t n) { m_i += n; return (*this); } + inline reverse_iterator operator+ (size_t n) const { return (reverse_iterator (m_i - n)); } + inline reverse_iterator operator- (size_t n) const { return (reverse_iterator (m_i + n)); } + inline reference operator[] (uoff_t n) const { return (*(*this + n)); } + inline difference_type operator- (const reverse_iterator& i) const { return (distance (m_i, i.m_i)); } +protected: + Iterator m_i; +}; + +//---------------------------------------------------------------------- + +/// \class insert_iterator uiterator.h ustl.h +/// \ingroup IteratorAdaptors +/// \brief Calls insert on bound container for each assignment. +/// +template <class Container> +class insert_iterator { +public: + typedef typename Container::value_type value_type; + typedef typename Container::difference_type difference_type; + typedef typename Container::pointer pointer; + typedef typename Container::reference reference; + typedef typename Container::iterator iterator; +public: + explicit insert_iterator (Container& ctr, iterator ip) : m_rCtr (ctr), m_ip (ip) {} + inline insert_iterator& operator= (typename Container::const_reference v) + { m_ip = m_rCtr.insert (m_ip, v); return (*this); } + inline insert_iterator& operator* (void) { return (*this); } + inline insert_iterator& operator++ (void) { ++ m_ip; return (*this); } + inline insert_iterator operator++ (int) { insert_iterator prev (*this); ++ m_ip; return (*this); } +protected: + Container& m_rCtr; + iterator m_ip; +}; + +/// Returns the insert_iterator for \p ctr. +template <class Container> +inline insert_iterator<Container> inserter (Container& ctr, typename Container::iterator ip) +{ + return (insert_iterator<Container> (ctr, ip)); +} + +//---------------------------------------------------------------------- + +/// \class back_insert_iterator uiterator.h ustl.h +/// \ingroup IteratorAdaptors +/// \brief Calls push_back on bound container for each assignment. +/// +template <class Container> +class back_insert_iterator { +public: + typedef typename Container::value_type value_type; + typedef typename Container::difference_type difference_type; + typedef typename Container::pointer pointer; + typedef typename Container::reference reference; +public: + explicit back_insert_iterator (Container& ctr) : m_rCtr (ctr) {} + inline back_insert_iterator& operator= (typename Container::const_reference v) + { m_rCtr.push_back (v); return (*this); } + inline back_insert_iterator& operator* (void) { return (*this); } + inline back_insert_iterator& operator++ (void) { return (*this); } + inline back_insert_iterator operator++ (int) { return (*this); } +protected: + Container& m_rCtr; +}; + +/// Returns the back_insert_iterator for \p ctr. +template <class Container> +inline back_insert_iterator<Container> back_inserter (Container& ctr) +{ + return (back_insert_iterator<Container> (ctr)); +} + +//---------------------------------------------------------------------- + +/// \class index_iterate uiterator.h ustl.h +/// \ingroup IteratorAdaptors +/// +/// \brief Allows iteration through an index container. +/// +/// Converts an iterator into a container of uoff_t indexes to an +/// iterator of iterators into another container. +/// +template <typename RandomAccessIterator, typename IndexIterator> +class index_iterate { +public: + typedef RandomAccessIterator value_type; + typedef ptrdiff_t difference_type; + typedef RandomAccessIterator* pointer; + typedef RandomAccessIterator reference; +public: + index_iterate (void) : m_Base(), m_i() {} + index_iterate (RandomAccessIterator ibase, IndexIterator iindex) : m_Base (ibase), m_i (iindex) {} + inline bool operator== (const index_iterate& i) const { return (m_i == i.m_i); } + inline bool operator< (const index_iterate& i) const { return (m_i < i.m_i); } + inline bool operator== (const RandomAccessIterator& i) const { return (m_Base == i); } + inline bool operator< (const RandomAccessIterator& i) const { return (m_Base < i); } + inline IndexIterator base (void) const { return (m_i); } + inline reference operator* (void) const { return (advance(m_Base, *m_i)); } + inline pointer operator-> (void) const { return (&(operator*())); } + inline index_iterate& operator++ (void) { ++ m_i; return (*this); } + inline index_iterate& operator-- (void) { -- m_i; return (*this); } + inline index_iterate operator++ (int) { index_iterate prev (*this); ++ m_i; return (prev); } + inline index_iterate operator-- (int) { index_iterate prev (*this); -- m_i; return (prev); } + inline index_iterate& operator+= (size_t n) { m_i += n; return (*this); } + inline index_iterate& operator-= (size_t n) { m_i -= n; return (*this); } + inline index_iterate operator+ (size_t n) const { return (index_iterate (m_Base, m_i + n)); } + inline index_iterate operator- (size_t n) const { return (index_iterate (m_Base, m_i - n)); } + inline reference operator[] (uoff_t n) const { return (*(*this + n)); } + inline difference_type operator- (const index_iterate& i) const { return (distance (m_i, i.m_i)); } +private: + RandomAccessIterator m_Base; + IndexIterator m_i; +}; + +/// Returns an index_iterate for \p ibase over \p iindex. +template <typename RandomAccessIterator, typename IndexIterator> +inline index_iterate<RandomAccessIterator, IndexIterator> index_iterator (RandomAccessIterator ibase, IndexIterator iindex) +{ + return (index_iterate<RandomAccessIterator, IndexIterator> (ibase, iindex)); +} + +/// Converts the indexes in \p xc to iterators in \p ic of base \p ibase. +template <typename IndexContainer, typename IteratorContainer> +inline void indexv_to_iteratorv (typename IteratorContainer::value_type ibase, const IndexContainer& xc, IteratorContainer& ic) +{ + ic.resize (xc.size()); + copy_n (index_iterator (ibase, xc.begin()), xc.size(), ic.begin()); +} + +//---------------------------------------------------------------------- + +/// Converts the given const_iterator into an iterator. +/// +template <typename Container> +inline typename Container::iterator unconst (typename Container::const_iterator i, Container&) + { return (const_cast<typename Container::iterator>(i)); } + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +#define IBYI(Iter1, Iter2, Ctr1, Ctr2) \ +template <typename Container1, typename Container2> \ +inline typename Container2::Iter2 ibyi (typename Container1::Iter1 idx, Ctr1& ctr1, Ctr2& ctr2) \ +{ \ + assert (ctr1.size() == ctr2.size()); \ + return (ctr2.begin() + (idx - ctr1.begin())); \ +} + +IBYI(const_iterator, const_iterator, const Container1, const Container2) +IBYI(iterator, iterator, Container1, Container2) +IBYI(const_iterator, iterator, const Container1, Container2) +IBYI(iterator, const_iterator, Container1, const Container2) + +#else // DOXYGEN + +#error This declaration is for doxygen only; it is not compiled. + +/// Converts a const_iterator in one container into a const_iterator in another container. +template <typename Container1, typename Container2> +inline typename Container2::iterator ibyi (typename Container1::iterator idx, Container1& ctr1, Container2& ctr2) {} + +#endif // DOXYGEN + +//---------------------------------------------------------------------- + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/ulaalgo.h @@ -0,0 +1,221 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef ULAALGO_H_2E403D182E83FB596AFB800E68B255A1 +#define ULAALGO_H_2E403D182E83FB596AFB800E68B255A1 + +#include "umatrix.h" +#include "simd.h" + +namespace ustl { + +/// \brief Creates an identity matrix in \p m +/// \ingroup NumericAlgorithms +template <size_t NX, size_t NY, typename T> +void load_identity (matrix<NX,NY,T>& m) +{ + fill_n (m.begin(), NX * NY, 0); + for (typename matrix<NX,NY,T>::iterator i = m.begin(); i < m.end(); i += NX + 1) + *i = 1; +} + +/// \brief Multiplies two matrices +/// \ingroup NumericAlgorithms +template <size_t NX, size_t NY, typename T> +matrix<NY,NY,T> operator* (const matrix<NX,NY,T>& m1, const matrix<NY,NX,T>& m2) +{ + matrix<NY,NY,T> mr; + for (uoff_t ry = 0; ry < NY; ++ ry) { + for (uoff_t rx = 0; rx < NY; ++ rx) { + T dpv (0); + for (uoff_t x = 0; x < NX; ++ x) + dpv += m1[ry][x] * m2[x][rx]; + mr[ry][rx] = dpv; + } + } + return (mr); +} + +/// \brief Transforms vector \p t with matrix \p m +/// \ingroup NumericAlgorithms +template <size_t NX, size_t NY, typename T> +tuple<NX,T> operator* (const tuple<NY,T>& t, const matrix<NX,NY,T>& m) +{ + tuple<NX,T> tr; + for (uoff_t x = 0; x < NX; ++ x) { + T dpv (0); + for (uoff_t y = 0; y < NY; ++ y) + dpv += t[y] * m[y][x]; + tr[x] = dpv; + } + return (tr); +} + +/// \brief Transposes (exchanges rows and columns) matrix \p m. +/// \ingroup NumericAlgorithms +template <size_t N, typename T> +void transpose (matrix<N,N,T>& m) +{ + for (uoff_t x = 0; x < N; ++ x) + for (uoff_t y = x; y < N; ++ y) + swap (m[x][y], m[y][x]); +} + +#if WANT_UNROLLED_COPY + +#if CPU_HAS_SSE + +#if linux // Non-linux gcc versions (BSD, Solaris) can't handle "x" constraint and provide no alternative. +template <> +inline void load_identity (matrix<4,4,float>& m) +{ + asm ( + "movaps %4, %%xmm1 \n\t" // 1 0 0 0 + "movups %4, %0 \n\t" // 1 0 0 0 + "shufps $0xB1,%%xmm1,%%xmm1 \n\t" // 0 1 0 0 + "movups %%xmm1, %1 \n\t" // 0 1 0 0 + "shufps $0x4F,%4,%%xmm1 \n\t" // 0 0 1 0 + "shufps $0x1B,%4,%4 \n\t" // 0 0 0 1 + "movups %%xmm1, %2 \n\t" // 0 0 1 0 + "movups %4, %3" // 0 0 0 1 + : "=m"(m[0][0]), "=m"(m[1][0]), "=m"(m[2][0]), "=m"(m[3][0]) + : "x"(1.0f) + : "xmm1", "memory" + ); + asm ("":::"memory"); +} +#endif + +inline void _sse_load_matrix (const float* m) +{ + asm ( + "movups %0, %%xmm4 \n\t" // xmm4 = m[1 2 3 4] + "movups %1, %%xmm5 \n\t" // xmm5 = m[1 2 3 4] + "movups %2, %%xmm6 \n\t" // xmm6 = m[1 2 3 4] + "movups %3, %%xmm7" // xmm7 = m[1 2 3 4] + : : "m"(m[0]), "m"(m[4]), "m"(m[8]), "m"(m[12]) + : "xmm4", "xmm5", "xmm6", "xmm7", "memory" + ); +} + +inline void _sse_transform_to_vector (float* result) +{ + asm ( + "movaps %%xmm0, %%xmm1 \n\t" // xmm1 = t[0 1 2 3] + "movaps %%xmm0, %%xmm2 \n\t" // xmm1 = t[0 1 2 3] + "movaps %%xmm0, %%xmm3 \n\t" // xmm1 = t[0 1 2 3] + "shufps $0x00, %%xmm0, %%xmm0 \n\t" // xmm0 = t[0 0 0 0] + "shufps $0x66, %%xmm1, %%xmm1 \n\t" // xmm1 = t[1 1 1 1] + "shufps $0xAA, %%xmm2, %%xmm2 \n\t" // xmm2 = t[2 2 2 2] + "shufps $0xFF, %%xmm3, %%xmm3 \n\t" // xmm3 = t[3 3 3 3] + "mulps %%xmm4, %%xmm0 \n\t" // xmm0 = t[0 0 0 0] * m[0 1 2 3] + "mulps %%xmm5, %%xmm1 \n\t" // xmm1 = t[1 1 1 1] * m[0 1 2 3] + "addps %%xmm1, %%xmm0 \n\t" // xmm0 = xmm0 + xmm1 + "mulps %%xmm6, %%xmm2 \n\t" // xmm2 = t[2 2 2 2] * m[0 1 2 3] + "mulps %%xmm7, %%xmm3 \n\t" // xmm3 = t[3 3 3 3] * m[0 1 2 3] + "addps %%xmm3, %%xmm2 \n\t" // xmm2 = xmm2 + xmm3 + "addps %%xmm2, %%xmm0 \n\t" // xmm0 = result + "movups %%xmm0, %0" + : "=m"(result[0]), "=m"(result[1]), "=m"(result[2]), "=m"(result[3]) : + : "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "memory" + ); +} + +template <> +inline tuple<4,float> operator* (const tuple<4,float>& t, const matrix<4,4,float>& m) +{ + tuple<4,float> result; + _sse_load_matrix (m.begin()); + asm ("movups %0, %%xmm0" : : "m"(t[0]), "m"(t[1]), "m"(t[2]), "m"(t[3]) : "xmm0", "memory"); + _sse_transform_to_vector (result.begin()); + return (result); +} + +template <> +inline matrix<4,4,float> operator* (const matrix<4,4,float>& m1, const matrix<4,4,float>& m2) +{ + matrix<4,4,float> result; + _sse_load_matrix (m2.begin()); + for (uoff_t r = 0; r < 4; ++ r) { + asm ("movups %0, %%xmm0" : : "m"(m1[r][0]), "m"(m1[r][1]), "m"(m1[r][2]), "m"(m1[r][3]) : "xmm0", "memory"); + _sse_transform_to_vector (result[r]); + } + return (result); +} + +#elif CPU_HAS_3DNOW + +/// Specialization for 4-component vector transform, the slow part of 3D graphics. +template <> +static tuple<4,float> operator* (const tuple<4,float>& t, const matrix<4,4,float>& m) +{ + tuple<4,float> result; + // This is taken from "AMD Athlon Code Optimization Guide" from AMD. 18 cycles! + // If you are writing a 3D engine, you may want to copy it instead of calling it + // because of the femms instruction at the end, which takes 2 cycles. + asm ( + "movq %2, %%mm0 \n\t" // y | x + "movq %3, %%mm1 \n\t" // w | z + "movq %%mm0, %%mm2 \n\t" // y | x + "movq %4, %%mm3 \n\t" // m[0][1] | m[0][0] + "punpckldq %%mm0, %%mm0 \n\t" // x | x + "movq %6, %%mm4 \n\t" // m[1][1] | m[1][0] + "pfmul %%mm0, %%mm3 \n\t" // x*m[0][1] | x*m[0][0] + "punpckhdq %%mm2, %%mm2 \n\t" // y | y + "pfmul %%mm2, %%mm4 \n\t" // y*m[1][1] | y*m[1][0] + "movq %5, %%mm5 \n\t" // m[0][3] | m[0][2] + "movq %7, %%mm7 \n\t" // m[1][3] | m[1][2] + "movq %%mm1, %%mm6 \n\t" // w | z + "pfmul %%mm0, %%mm5 \n\t" // x*m[0][3] | v0>x*m[0][2] + "movq %8, %%mm0 \n\t" // m[2][1] | m[2][0] + "punpckldq %%mm1, %%mm1 \n\t" // z | z + "pfmul %%mm2, %%mm7 \n\t" // y*m[1][3] | y*m[1][2] + "movq %9, %%mm2 \n\t" // m[2][3] | m[2][2] + "pfmul %%mm1, %%mm0 \n\t" // z*m[2][1] | z*m[2][0] + "pfadd %%mm4, %%mm3 \n\t" // x*m[0][1]+y*m[1][1] | x*m[0][0]+y*m[1][0] + "movq %10, %%mm4 \n\t" // m[3][1] | m[3][0] + "pfmul %%mm1, %%mm2 \n\t" // z*m[2][3] | z*m[2][2] + "pfadd %%mm7, %%mm5 \n\t" // x*m[0][3]+y*m[1][3] | x*m[0][2]+y*m[1][2] + "movq %11, %%mm1 \n\t" // m[3][3] | m[3][2] + "punpckhdq %%mm6, %%mm6 \n\t" // w | w + "pfadd %%mm0, %%mm3 \n\t" // x*m[0][1]+y*m[1][1]+z*m[2][1] | x*m[0][0]+y*m[1][0]+z*m[2][0] + "pfmul %%mm6, %%mm4 \n\t" // w*m[3][1] | w*m[3][0] + "pfmul %%mm6, %%mm1 \n\t" // w*m[3][3] | w*m[3][2] + "pfadd %%mm2, %%mm5 \n\t" // x*m[0][3]+y*m[1][3]+z*m[2][3] | x*m[0][2]+y*m[1][2]+z*m[2][2] + "pfadd %%mm4, %%mm3 \n\t" // x*m[0][1]+y*m[1][1]+z*m[2][1]+w*m[3][1] | x*m[0][0]+y*m[1][0]+z*m[2][0]+w*m[3][0] + "movq %%mm3, %0 \n\t" // store result->y | result->x + "pfadd %%mm1, %%mm5 \n\t" // x*m[0][3]+y*m[1][3]+z*m[2][3]+w*m[3][3] | x*m[0][2]+y*m[1][2]+z*m[2][2]+w*m[3][2] + "movq %%mm5, %1" // store result->w | result->z + : "=m"(result[0]), "=m"(result[2]) + : "m"(t[0]), "m"(t[2]), + "m"(m[0][0]), "m"(m[0][2]), + "m"(m[1][0]), "m"(m[1][2]), + "m"(m[2][0]), "m"(m[2][2]), + "m"(m[3][0]), "m"(m[3][2]) + : ALL_MMX_REGS_CHANGELIST, "memory" + ); + asm ("":::"memory"); + simd::reset_mmx(); + return (result); +} + +#else // If no processor extensions, just unroll the multiplication + +/// Specialization for 4-component vector transform, the slow part of 3D graphics. +template <> +static tuple<4,float> operator* (const tuple<4,float>& t, const matrix<4,4,float>& m) +{ + tuple<4,float> tr; + for (uoff_t i = 0; i < 4; ++ i) + tr[i] = t[0] * m[0][i] + t[1] * m[1][i] + t[2] * m[2][i] + t[3] * m[3][i]; + return (tr); +} + +#endif // CPU_HAS_3DNOW +#endif // WANT_UNROLLED_COPY + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/ulimits.h @@ -0,0 +1,104 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef ULIMITS_H_1C2192EA3821E0811BBAF86B0F048364 +#define ULIMITS_H_1C2192EA3821E0811BBAF86B0F048364 + +#include "utypes.h" + +namespace ustl { + +#define __limits_digits(T) (sizeof(T)*8) +#define __limits_digits10(T) (sizeof(T)*8*643/2136+1) + +/// \class numeric_limits ulimits.h ustl.h +/// \brief Defines numeric limits for a type. +/// +template <typename T> +struct numeric_limits { + /// Returns the minimum value for type T. + static inline T min (void) { return (T(0)); } + /// Returns the minimum value for type T. + static inline T max (void) { return (T(0)); } + static const bool is_signed = false; ///< True if the type is signed. + static const bool is_integer = false; ///< True if stores an exact value. + static const bool is_integral = false; ///< True if fixed size and cast-copyable. + static const unsigned digits = __limits_digits(T); ///< Number of bits in T + static const unsigned digits10 = __limits_digits10(T); ///< Maximum number of decimal digits in printed version of T +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +template <typename T> +struct numeric_limits<T*> { + static inline T* min (void) { return (NULL); } + static inline T* max (void) { return (reinterpret_cast<T*>(UINTPTR_MAX)); } + static const bool is_signed = false; + static const bool is_integer = true; + static const bool is_integral = true; + static const unsigned digits = __limits_digits(T*); + static const unsigned digits10 = __limits_digits10(T*); +}; + +#define _NUMERIC_LIMITS(type, minVal, maxVal, bSigned, bInteger, bIntegral) \ +template <> \ +struct numeric_limits<type> { \ + static inline type min (void) { return (minVal); } \ + static inline type max (void) { return (maxVal); } \ + static const bool is_signed = bSigned; \ + static const bool is_integer = bInteger; \ + static const bool is_integral = bIntegral; \ + static const unsigned digits = __limits_digits(type); \ + static const unsigned digits10 = __limits_digits10(type); \ +} + +//-------------------------------------------------------------------------------------- +// type min max signed integer integral +//-------------------------------------------------------------------------------------- +_NUMERIC_LIMITS (bool, false, true, false, true, true); +_NUMERIC_LIMITS (char, CHAR_MIN, CHAR_MAX, true, true, true); +_NUMERIC_LIMITS (int, INT_MIN, INT_MAX, true, true, true); +_NUMERIC_LIMITS (short, SHRT_MIN, SHRT_MAX, true, true, true); +_NUMERIC_LIMITS (long, LONG_MIN, LONG_MAX, true, true, true); +#if HAVE_THREE_CHAR_TYPES +_NUMERIC_LIMITS (signed char, SCHAR_MIN, SCHAR_MAX, true, true, true); +#endif +_NUMERIC_LIMITS (unsigned char, 0, UCHAR_MAX, false, true, true); +_NUMERIC_LIMITS (unsigned int, 0, UINT_MAX, false, true, true); +_NUMERIC_LIMITS (unsigned short,0, USHRT_MAX, false, true, true); +_NUMERIC_LIMITS (unsigned long, 0, ULONG_MAX, false, true, true); +_NUMERIC_LIMITS (wchar_t, 0, WCHAR_MAX, false, true, true); +_NUMERIC_LIMITS (float, FLT_MIN, FLT_MAX, true, false, true); +_NUMERIC_LIMITS (double, DBL_MIN, DBL_MAX, true, false, true); +_NUMERIC_LIMITS (long double, LDBL_MIN, LDBL_MAX, true, false, true); +#if HAVE_LONG_LONG +_NUMERIC_LIMITS (long long, LLONG_MIN, LLONG_MAX, true, true, true); +_NUMERIC_LIMITS (unsigned long long, 0, ULLONG_MAX, false, true, true); +#endif +//-------------------------------------------------------------------------------------- + +#endif // DOXYGEN_SHOULD_SKIP_THIS + +/// Macro for defining numeric_limits specializations +#define NUMERIC_LIMITS(type, minVal, maxVal, bSigned, bInteger, bIntegral) \ +namespace ustl { _NUMERIC_LIMITS (type, minVal, maxVal, bSigned, bInteger, bIntegral); } + +/// \brief Returns the recommended stream alignment for type \p T. Override with ALIGNOF. +/// Because this is occasionally called with a null value, do not access the argument! +template <typename T> +inline size_t alignof (const T&) +{ + if (numeric_limits<T>::is_integral) + return (__alignof__(T)); + return (4); +} + +#define ALIGNOF(type,grain) \ +namespace ustl { \ + template <> inline size_t alignof (const type&) { return (grain); } } + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/ulist.h @@ -0,0 +1,74 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef ULIST_H_54E3B510498982C87A0A1E1932E6729D +#define ULIST_H_54E3B510498982C87A0A1E1932E6729D + +#include "uvector.h" +#include "uctralgo.h" + +namespace ustl { + +/// \class list ulist.h ustl.h +/// \ingroup Sequences +/// +/// \brief Linked list, defined as an alias to vector. +/// +template <typename T> +class list : public vector<T> { +public: + typedef typename vector<T>::size_type size_type; + typedef typename vector<T>::iterator iterator; + typedef typename vector<T>::const_iterator const_iterator; + typedef typename vector<T>::reference reference; + typedef typename vector<T>::const_reference const_reference; +public: + inline list (void) : vector<T> () {} + inline explicit list (size_type n) : vector<T> (n) {} + inline list (size_type n, const T& v) : vector<T> (n, v) {} + inline list (const list<T>& v) : vector<T> (v) {} + inline list (const_iterator i1, const_iterator i2) : vector<T> (i1, i2) {} + inline size_type size (void) const { return (vector<T>::size()); } + inline iterator begin (void) { return (vector<T>::begin()); } + inline const_iterator begin (void) const { return (vector<T>::begin()); } + inline iterator end (void) { return (vector<T>::end()); } + inline const_iterator end (void) const { return (vector<T>::end()); } + inline void push_front (const T& v) { insert (begin(), v); } + inline void pop_front (void) { erase (begin()); } + inline const_reference front (void) const { return (*begin()); } + inline reference front (void) { return (*begin()); } + inline void remove (const T& v) { ::ustl::remove (*this, v); } + inline void unique (void) { ::ustl::unique (*this); } + inline void sort (void) { ::ustl::sort (*this); } + void merge (list<T>& l); + void splice (iterator ip, list<T>& l, iterator first = NULL, iterator last = NULL); +}; + +/// Merges the contents with \p l. Assumes both lists are sorted. +template <typename T> +void list<T>::merge (list& l) +{ + list<T>::resize (size() + l.size()); + iterator me = merge (begin(), end(), l.begin(), l.end(), begin()); + list<T>::resize (distance (begin(), me)); +} + +/// Moves the range [first, last) from \p l to this list at \p ip. +template <typename T> +void list<T>::splice (iterator ip, list<T>& l, iterator first, iterator last) +{ + if (!first) + first = l.begin(); + if (!last) + last = l.end(); + insert (ip, first, last); + l.erase (first, last); +} + +#define deque list ///< list has all the functionality provided by deque + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/umap.h @@ -0,0 +1,160 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UMAP_H_45643F516E02A87A3DCEA5024052A6F5 +#define UMAP_H_45643F516E02A87A3DCEA5024052A6F5 + +#include "uvector.h" +#include "ufunction.h" + +namespace ustl { + +/// \class map umap.h ustl.h +/// \ingroup AssociativeContainers +/// +/// \brief A sorted associative container of pair<K,V> +/// +template <typename K, typename V> +class map : public vector<pair<K,V> > { +public: + typedef K key_type; + typedef V data_type; + typedef const K& const_key_ref; + typedef const V& const_data_ref; + typedef const map<K,V>& rcself_t; + typedef vector<pair<K,V> > base_class; + typedef typename base_class::value_type value_type; + typedef typename base_class::size_type size_type; + typedef typename base_class::pointer pointer; + typedef typename base_class::const_pointer const_pointer; + typedef typename base_class::reference reference; + typedef typename base_class::const_reference const_reference; + typedef typename base_class::const_iterator const_iterator; + typedef typename base_class::iterator iterator; + typedef typename base_class::reverse_iterator reverse_iterator; + typedef typename base_class::const_reverse_iterator const_reverse_iterator; + typedef pair<const_iterator,const_iterator> const_range_t; + typedef pair<iterator,iterator> range_t; + typedef pair<iterator,bool> insertrv_t; +public: + inline map (void) : vector<pair<K,V> > () {} + explicit inline map (size_type n) : vector<pair<K,V> > (n) {} + inline map (rcself_t v) : vector<pair<K,V> > (v) {} + inline map (const_iterator i1, const_iterator i2) : vector<pair<K,V> >() { insert (i1, i2); } + inline rcself_t operator= (rcself_t v) { base_class::operator= (v); return (*this); } + inline const_data_ref operator[] (const_key_ref i) const; + data_type& operator[] (const_key_ref i); + inline size_type size (void) const { return (base_class::size()); } + inline iterator begin (void) { return (base_class::begin()); } + inline const_iterator begin (void) const { return (base_class::begin()); } + inline iterator end (void) { return (base_class::end()); } + inline const_iterator end (void) const { return (base_class::end()); } + inline void assign (const_iterator i1, const_iterator i2) { clear(); insert (i1, i2); } + inline void push_back (const_reference v) { insert (v); } + inline const_iterator find (const_key_ref k) const; + inline iterator find (const_key_ref k) { return (const_cast<iterator> (const_cast<rcself_t>(*this).find (k))); } + inline const_iterator find_data (const_data_ref v, const_iterator first = NULL, const_iterator last = NULL) const; + inline iterator find_data (const_data_ref v, iterator first = NULL, iterator last = NULL); + insertrv_t insert (const_reference v); + void insert (const_iterator i1, const_iterator i2); + inline void erase (const_key_ref k); + inline iterator erase (iterator ep) { return (base_class::erase (ep)); } + inline iterator erase (iterator ep1, iterator ep2) { return (base_class::erase (ep1, ep2)); } + inline void clear (void) { base_class::clear(); } +private: + const_iterator lower_bound (const_key_ref k) const; + inline iterator lower_bound (const_key_ref k) { return (const_cast<iterator>(const_cast<rcself_t>(*this).lower_bound (k))); } +}; + +template <typename K, typename V> +typename map<K,V>::const_iterator map<K,V>::lower_bound (const_key_ref k) const +{ + const_iterator first (begin()), last (end()); + while (first != last) { + const_iterator mid = advance (first, distance (first,last) / 2); + if (mid->first < k) + first = advance (mid, 1); + else + last = mid; + } + return (first); +} + +/// Returns the pair<K,V> where K = \p k. +template <typename K, typename V> +inline typename map<K,V>::const_iterator map<K,V>::find (const_key_ref k) const +{ + const_iterator i = lower_bound (k); + return ((i < end() && k < i->first) ? end() : i); +} + +/// Returns the pair<K,V> where V = \p v, occuring in range [first,last). +template <typename K, typename V> +inline typename map<K,V>::const_iterator map<K,V>::find_data (const_data_ref v, const_iterator first, const_iterator last) const +{ + if (!first) first = begin(); + if (!last) last = end(); + for (; first != last && first->second != v; ++first) ; + return (first); +} + +/// Returns the pair<K,V> where V = \p v, occuring in range [first,last). +template <typename K, typename V> +inline typename map<K,V>::iterator map<K,V>::find_data (const_data_ref v, iterator first, iterator last) +{ + return (const_cast<iterator> (find_data (v, const_cast<const_iterator>(first), const_cast<const_iterator>(last)))); +} + +/// Returns data associated with key \p k. +template <typename K, typename V> +inline const typename map<K,V>::data_type& map<K,V>::operator[] (const_key_ref k) const +{ + assert (find(k) != end() && "operator[] const can not insert non-existent keys"); + return (find(k)->second); +} + +/// Returns data associated with key \p k. +template <typename K, typename V> +typename map<K,V>::data_type& map<K,V>::operator[] (const_key_ref k) +{ + iterator ip = lower_bound (k); + if (ip == end() || k < ip->first) + ip = base_class::insert (ip, make_pair (k, V())); + return (ip->second); +} + +/// Inserts the pair into the container. +template <typename K, typename V> +typename map<K,V>::insertrv_t map<K,V>::insert (const_reference v) +{ + iterator ip = lower_bound (v.first); + bool bInserted = ip == end() || v.first < ip->first; + if (bInserted) + ip = base_class::insert (ip, v); + return (make_pair (ip, bInserted)); +} + +/// Inserts elements from range [i1,i2) into the container. +template <typename K, typename V> +void map<K,V>::insert (const_iterator i1, const_iterator i2) +{ + assert (i1 <= i2); + reserve (size() + distance (i1, i2)); + for (; i1 != i2; ++i1) + insert (*i1); +} + +/// Erases the element with key value \p k. +template <typename K, typename V> +inline void map<K,V>::erase (const_key_ref k) +{ + iterator ip = find (k); + if (ip != end()) + erase (ip); +} + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/umatrix.h @@ -0,0 +1,121 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UMATRIX_H_740EBFEF554E833645E0FD72419A8185 +#define UMATRIX_H_740EBFEF554E833645E0FD72419A8185 + +#include "utuple.h" + +namespace ustl { + +/// \class matrix umatrix.h ustl.h +/// \ingroup Sequences +/// +/// \brief A two-dimensional array of NX*NY elements of type T. +/// +template <size_t NX, size_t NY, typename T> +class matrix : public tuple<NX*NY,T> { +public: + typedef tuple<NX,T> row_type; + typedef tuple<NY,T> column_type; + typedef tuple<NX*NY,T> tuple_type; + typedef typename tuple_type::value_type value_type; + typedef typename tuple_type::size_type size_type; + typedef typename tuple_type::pointer pointer; + typedef typename tuple_type::const_pointer const_pointer; + typedef typename tuple_type::reference reference; + typedef typename tuple_type::const_reference const_reference; + typedef typename tuple_type::iterator iterator; + typedef typename tuple_type::const_iterator const_iterator; + typedef typename tuple_type::range_t range_t; + typedef typename tuple_type::const_range_t const_range_t; + typedef typename tuple_type::reverse_iterator reverse_iterator; + typedef typename tuple_type::const_reverse_iterator const_reverse_iterator; +public: + inline matrix (void) { } + inline size_type columns (void) const { return (NX); } + inline size_type rows (void) const { return (NY); } + inline const_iterator at (size_type i) const { return (matrix::begin() + i * NX); } + inline iterator at (size_type i) { return (matrix::begin() + i * NX); } + inline const_iterator operator[] (size_type i) const { return (at (i)); } + inline iterator operator[] (size_type i) { return (at (i)); } + inline row_type row (size_type r) const { return (row_type (at (r))); } + inline column_type column (size_type c) const; + template <typename T2> + inline const matrix& operator= (const matrix<NX,NY,T2>& src) { tuple_type::operator= (src); return (*this); } + inline const matrix& operator= (const matrix<NX,NY,T>& src) { tuple_type::operator= (src); return (*this); } + inline const matrix& operator+= (const_reference v) { tuple_type::operator+= (v); return (*this); } + inline const matrix& operator-= (const_reference v) { tuple_type::operator-= (v); return (*this); } + inline const matrix& operator*= (const_reference v) { tuple_type::operator*= (v); return (*this); } + inline const matrix& operator/= (const_reference v) { tuple_type::operator/= (v); return (*this); } + inline const matrix operator+ (const_reference v) const + { matrix result (*this); result += v; return (result); } + inline const matrix operator- (const_reference v) const + { matrix result (*this); result -= v; return (result); } + inline const matrix operator* (const_reference v) const + { matrix result (*this); result *= v; return (result); } + inline const matrix operator/ (const_reference v) const + { matrix result (*this); result /= v; return (result); } +}; + +template <size_t NX, size_t NY, typename T> +inline typename matrix<NX,NY,T>::column_type matrix<NX,NY,T>::column (size_type c) const +{ + column_type result; + const_iterator src (matrix::begin() + c); + iterator dest (result.begin()); + for (uoff_t i = 0; i < NY; ++ i, ++ dest, src += NX) + *dest = *src; + return (result); +} + +//---------------------------------------------------------------------- +// Define SIMD specializations for member functions. + +#if CPU_HAS_SSE +#define MATRIX_R(v) "m"(v[0]),"m"(v[4]),"m"(v[8]),"m"(v[12]) +#define MATRIX_W(v) "=m"(v[0]),"=m"(v[4]),"=m"(v[8]),"=m"(v[12]) +#define SSE_TUPLE_SPECS(n,type) \ +template <> inline tuple<n,type>::tuple (void) \ +{ asm volatile ("xorps %%xmm0, %%xmm0\n\t" \ + "movups %%xmm0, %0\n\t" \ + "movups %%xmm0, %1\n\t" \ + "movups %%xmm0, %2\n\t" \ + "movups %%xmm0, %3" \ + : "=m"(m_v[0]),"=m"(m_v[4]),"=m"(m_v[8]),"=m"(m_v[12]) \ + ::"xmm0","memory"); \ +} \ +namespace simd { \ +SIMD_PASSIGN_SPEC(n,type) \ +{ \ + asm volatile ("movups %2, %%xmm0\n\t" \ + "movups %3, %%xmm1\n\t" \ + "movups %%xmm0, %0\n\t" \ + "movups %%xmm1, %1" \ + : "=m"(oout[0]),"=m"(oout[4]) \ + : "m"(oin[0]),"m"(oin[4]) \ + : "xmm0", "xmm1", "memory"); \ + asm volatile ("movups %2, %%xmm0\n\t" \ + "movups %3, %%xmm1\n\t" \ + "movups %%xmm0, %0\n\t" \ + "movups %%xmm1, %1" \ + : "=m"(oout[8]),"=m"(oout[12]) \ + : "m"(oin[8]),"m"(oin[12]) \ + : "xmm0", "xmm1", "memory"); \ +} \ +} +SSE_TUPLE_SPECS(16,float) +SSE_TUPLE_SPECS(16,int32_t) +SSE_TUPLE_SPECS(16,uint32_t) +#undef SSE_TUPLE_SPECS +#undef TOUCH_MATRIX_R +#undef TOUCH_MATRIX_W +#undef MATRIX_R +#undef MATRIX_W +#endif + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/umemory.h @@ -0,0 +1,193 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UMEMORY_H_4AB5B0DB5BF09140541409CC47BCD17A +#define UMEMORY_H_4AB5B0DB5BF09140541409CC47BCD17A + +#include "unew.h" +#if HAVE_ALLOCA_H + #include <alloca.h> +#else + #include <stdlib.h> +#endif +#include "upair.h" +#include "uiterator.h" +#include "ulimits.h" + +namespace ustl { + +/// \class auto_ptr umemory.h ustl.h +/// \ingroup MemoryManagement +/// +/// \brief A smart pointer. +/// +/// Calls delete in the destructor; assignment transfers ownership. +/// This class does not work with void pointers due to the absence +/// of the required dereference operator. +/// +template <typename T> +class auto_ptr { +public: + typedef T value_type; + typedef T* pointer; + typedef T& reference; +public: + /// Takes ownership of \p p. + inline explicit auto_ptr (pointer p = NULL) : m_p (p) {} + /// Takes ownership of pointer in \p p. \p p relinquishes ownership. + inline auto_ptr (auto_ptr<T>& p) : m_p (p.release()) {} + /// Deletes the owned pointer. + inline ~auto_ptr (void) { delete m_p; } + /// Returns the pointer without relinquishing ownership. + inline pointer get (void) const { return (m_p); } + /// Returns the pointer and gives up ownership. + inline pointer release (void) { pointer rv (m_p); m_p = NULL; return (rv); } + /// Deletes the pointer and sets it equal to \p p. + inline void reset (pointer p) { if (p != m_p) { delete m_p; m_p = p; } } + /// Takes ownership of \p p. + inline auto_ptr<T>& operator= (pointer p) { reset (p); return (*this); } + /// Takes ownership of pointer in \p p. \p p relinquishes ownership. + inline auto_ptr<T>& operator= (auto_ptr<T>& p) { reset (p.release()); return (*this); } + inline reference operator* (void) const { return (*m_p); } + inline pointer operator-> (void) const { return (m_p); } + inline bool operator== (const pointer p) const { return (m_p == p); } + inline bool operator== (const auto_ptr<T>& p) const { return (m_p == p.m_p); } + inline bool operator< (const auto_ptr<T>& p) const { return (p.m_p < m_p); } +private: + pointer m_p; +}; + +/// Calls the placement new on \p p. +/// \ingroup RawStorageAlgorithms +/// +template <typename T> +inline void construct (T* p) +{ + new (p) T; +} + +/// Calls the placement new on \p p. +/// \ingroup RawStorageAlgorithms +/// +template <typename ForwardIterator> +inline void construct (ForwardIterator first, ForwardIterator last) +{ + typedef typename iterator_traits<ForwardIterator>::value_type value_type; + if (!numeric_limits<value_type>::is_integral && first) + for (--last; first <= last; ++first) + construct (&*first); +} + +/// Calls the placement new on \p p. +/// \ingroup RawStorageAlgorithms +/// +template <typename T> +inline void construct (T* p, const T& value) +{ + new (p) T (value); +} + +/// Calls the destructor of \p p without calling delete. +/// \ingroup RawStorageAlgorithms +/// +template <typename T> +inline void destroy (T* p) throw() +{ + p->~T(); +} + +// Helper templates to not instantiate anything for integral types. +template <typename T> +void dtors (T first, T last) throw() + { for (--last; first <= last; ++first) destroy (&*first); } +template <typename T, bool bIntegral> +struct Sdtorsr { + inline void operator()(T first, T last) throw() { dtors (first, last); } +}; +template <typename T> +struct Sdtorsr<T,true> { + inline void operator()(T, T) throw() {} +}; + +/// Calls the destructor on elements in range [first, last) without calling delete. +/// \ingroup RawStorageAlgorithms +/// +template <typename ForwardIterator> +inline void destroy (ForwardIterator first, ForwardIterator last) throw() +{ + typedef typename iterator_traits<ForwardIterator>::value_type value_type; + Sdtorsr<ForwardIterator,numeric_limits<value_type>::is_integral>()(first, last); +} + +/// Casts \p p to the type of the second pointer argument. +template <typename T> inline T* cast_to_type (void* p, const T*) { return ((T*) p); } + +/// \brief Creates a temporary buffer pair from \p p and \p n +/// This is intended to be used with alloca to create temporary buffers. +/// The size in the returned pair is set to 0 if the allocation is unsuccessful. +/// \ingroup RawStorageAlgorithms +/// +template <typename T> +inline pair<T*, ptrdiff_t> make_temporary_buffer (void* p, size_t n, const T* ptype) +{ + return (make_pair (cast_to_type(p,ptype), ptrdiff_t(p ? n : 0))); +} + +#if HAVE_ALLOCA_H + /// \brief Allocates a temporary buffer, if possible. + /// \ingroup RawStorageAlgorithms + #define get_temporary_buffer(size, ptype) make_temporary_buffer (alloca(size_of_elements(size, ptype)), size, ptype) + #define return_temporary_buffer(p) +#else + #define get_temporary_buffer(size, ptype) make_temporary_buffer (malloc(size_of_elements(size, ptype)), size, ptype) + #define return_temporary_buffer(p) if (p) free (p), p = NULL +#endif + +/// Copies [first, last) into result by calling copy constructors in result. +/// \ingroup RawStorageAlgorithms +/// +template <typename InputIterator, typename ForwardIterator> +ForwardIterator uninitialized_copy (InputIterator first, InputIterator last, ForwardIterator result) +{ + for (; first < last; ++result, ++first) + construct (&*result, *first); + return (result); +} + +/// Copies [first, first + n) into result by calling copy constructors in result. +/// \ingroup RawStorageAlgorithms +/// +template <typename InputIterator, typename ForwardIterator> +ForwardIterator uninitialized_copy_n (InputIterator first, size_t n, ForwardIterator result) +{ + for (++n; --n; ++result, ++first) + construct (&*result, *first); + return (result); +} + +/// Calls construct on all elements in [first, last) with value \p v. +/// \ingroup RawStorageAlgorithms +/// +template <typename ForwardIterator, typename T> +void uninitialized_fill (ForwardIterator first, ForwardIterator last, const T& v) +{ + for (; first < last; ++first) + construct (&*first, v); +} + +/// Calls construct on all elements in [first, first + n) with value \p v. +/// \ingroup RawStorageAlgorithms +/// +template <typename ForwardIterator, typename T> +ForwardIterator uninitialized_fill_n (ForwardIterator first, size_t n, const T& v) +{ + for (++n; --n; ++first) + construct (&*first, v); + return (first); +} + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/umultimap.h @@ -0,0 +1,116 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UMULTIMAP_H_45743F516E02A87A3FCEA5024052A6F5 +#define UMULTIMAP_H_45743F516E02A87A3FCEA5024052A6F5 + +#include "uvector.h" +#include "ufunction.h" + +namespace ustl { + +/// \class multimap umultimap.h ustl.h +/// \ingroup AssociativeContainers +/// +/// \brief A sorted associative container that may container multiple entries for each key. +/// +template <typename K, typename V> +class multimap : public vector<pair<K,V> > { +public: + typedef K key_type; + typedef V data_type; + typedef const K& const_key_ref; + typedef const V& const_data_ref; + typedef const multimap<K,V>& rcself_t; + typedef vector<pair<K,V> > base_class; + typedef typename base_class::value_type value_type; + typedef typename base_class::size_type size_type; + typedef typename base_class::pointer pointer; + typedef typename base_class::const_pointer const_pointer; + typedef typename base_class::reference reference; + typedef typename base_class::const_reference const_reference; + typedef typename base_class::const_iterator const_iterator; + typedef typename base_class::iterator iterator; + typedef typename base_class::reverse_iterator reverse_iterator; + typedef typename base_class::const_reverse_iterator const_reverse_iterator; + typedef pair<const_iterator,const_iterator> const_range_t; + typedef pair<iterator,iterator> range_t; +public: + inline multimap (void) : vector<pair<K,V> > () {} + explicit inline multimap (size_type n) : vector<pair<K,V> > (n) {} + inline multimap (rcself_t v) : vector<pair<K,V> > (v) {} + inline multimap (const_iterator i1, const_iterator i2) : vector<pair<K,V> > () { insert (i1, i2); } + inline rcself_t operator= (rcself_t v) { base_class::operator= (v); return (*this); } + inline size_type size (void) const { return (base_class::size()); } + inline iterator begin (void) { return (base_class::begin()); } + inline const_iterator begin (void) const { return (base_class::begin()); } + inline iterator end (void) { return (base_class::end()); } + inline const_iterator end (void) const { return (base_class::end()); } + inline void assign (const_iterator i1, const_iterator i2) { clear(); insert (i1, i2); } + inline size_type count (const_key_ref k) const { return (upper_bound(k) - lower_bound(k)); } + inline void push_back (const_reference v) { insert (v); } + inline const_range_t equal_range (const_key_ref k) const { return (make_pair (lower_bound(k), upper_bound(k))); } + inline range_t equal_range (const_key_ref k) { return (make_pair (const_cast<iterator>(lower_bound(k)), const_cast<iterator>(upper_bound(k)))); } + const_iterator lower_bound (const_key_ref k) const; + const_iterator upper_bound (const_key_ref k) const; + inline iterator insert (const_reference v); + void insert (const_iterator i1, const_iterator i2); + inline void erase (const_key_ref k) { erase (const_cast<iterator>(lower_bound(k)), const_cast<iterator>(upper_bound(k))); } + inline iterator erase (iterator ep) { return (base_class::erase (ep)); } + inline iterator erase (iterator ep1, iterator ep2) { return (base_class::erase (ep1, ep2)); } + inline void clear (void) { base_class::clear(); } +}; + +/// Returns an iterator to the first element with key value \p k. +template <typename K, typename V> +typename multimap<K,V>::const_iterator multimap<K,V>::lower_bound (const_key_ref k) const +{ + const_iterator first (begin()), last (end()); + while (first != last) { + const_iterator mid = advance (first, distance (first,last) / 2); + if (mid->first < k) + first = advance (mid, 1); + else + last = mid; + } + return (first); +} + +/// Returns an iterator to the first element with key value \p k. +template <typename K, typename V> +typename multimap<K,V>::const_iterator multimap<K,V>::upper_bound (const_key_ref k) const +{ + const_iterator first (begin()), last (end()); + while (first != last) { + const_iterator mid = advance (first, distance (first,last) / 2); + if (k < mid->first) + last = mid; + else + first = advance (mid, 1); + } + return (last); +} + +/// Inserts the pair into the container. +template <typename K, typename V> +inline typename multimap<K,V>::iterator multimap<K,V>::insert (const_reference v) +{ + iterator ip = const_cast<iterator> (upper_bound (v.first)); + return (base_class::insert (ip, v)); +} + +/// Inserts elements from range [i1,i2) into the container. +template <typename K, typename V> +void multimap<K,V>::insert (const_iterator i1, const_iterator i2) +{ + assert (i1 <= i2); + reserve (size() + distance (i1, i2)); + for (; i1 != i2; ++i1) + insert (*i1); +} + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/umultiset.h @@ -0,0 +1,101 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UMULTISET_H_446AEDBB7F61C6994DC228C25D5FA3A1 +#define UMULTISET_H_446AEDBB7F61C6994DC228C25D5FA3A1 + +#include "uvector.h" +#include "ualgo.h" + +namespace ustl { + +/// \class multiset umultiset.h ustl.h +/// \ingroup AssociativeContainers +/// +/// \brief Multiple sorted container. +/// Unlike set, it may contain multiple copies of each element. +/// +template <typename T> +class multiset : public vector<T> { +public: + typedef const multiset<T>& rcself_t; + typedef vector<T> base_class; + typedef typename base_class::value_type value_type; + typedef typename base_class::size_type size_type; + typedef typename base_class::pointer pointer; + typedef typename base_class::const_pointer const_pointer; + typedef typename base_class::reference reference; + typedef typename base_class::const_reference const_reference; + typedef typename base_class::const_iterator const_iterator; + typedef typename base_class::iterator iterator; + typedef typename base_class::reverse_iterator reverse_iterator; + typedef typename base_class::const_reverse_iterator const_reverse_iterator; +public: + inline multiset (void) : vector<T> () {} + explicit inline multiset (size_type n) : vector<T> (n) {} + inline multiset (rcself_t v) : vector<T> (v) {} + inline multiset (const_iterator i1, const_iterator i2) : vector<T> () { insert (i1, i2); } + inline rcself_t operator= (rcself_t v) { base_class::operator= (v); return (*this); } + inline size_type size (void) const { return (base_class::size()); } + inline iterator begin (void) { return (base_class::begin()); } + inline const_iterator begin (void) const { return (base_class::begin()); } + inline iterator end (void) { return (base_class::end()); } + inline const_iterator end (void) const { return (base_class::end()); } + inline void assign (const_iterator i1, const_iterator i2); + size_type count (const_reference v) const; + inline void push_back (const_reference v) { insert (v); } + inline iterator insert (const_reference v); + void insert (const_iterator i1, const_iterator i2); + void erase (const_reference v); + inline iterator erase (iterator ep) { return (base_class::erase (ep)); } + inline iterator erase (iterator ep1, iterator ep2) { return (base_class::erase (ep1, ep2)); } + inline void clear (void) { base_class::clear(); } +}; + +/// Copies contents of range [i1,i2) +template <typename T> +inline void multiset<T>::assign (const_iterator i1, const_iterator i2) +{ + base_class::clear(); + insert (i1, i2); +} + +/// Returns the number of elements of value \p v. +template <typename T> +typename multiset<T>::size_type multiset<T>::count (const_reference v) const +{ + const pair<const_iterator,const_iterator> fr = equal_range (begin(), end(), v); + return (distance (fr.first, fr.second)); +} + +/// Inserts \p v. +template <typename T> +inline typename multiset<T>::iterator multiset<T>::insert (const_reference v) +{ + iterator ip = upper_bound (begin(), end(), v); + return (base_class::insert (ip, v)); +} + +/// Inserts all elements from range [i1,i2). +template <typename T> +void multiset<T>::insert (const_iterator i1, const_iterator i2) +{ + assert (i1 <= i2); + reserve (size() + distance (i1, i2)); + for (; i1 < i2; ++i1) + push_back (*i1); +} + +/// Erases all elements with value \p v. +template <typename T> +void multiset<T>::erase (const_reference v) +{ + pair<iterator,iterator> epr = equal_range (begin(), end(), v); + erase (epr.first, epr.second); +} + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/unew.h @@ -0,0 +1,47 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UNEW_H_11D237512B324C9C05A55DAF1BF086F1 +#define UNEW_H_11D237512B324C9C05A55DAF1BF086F1 + +#include "uexception.h" +#include <stdlib.h> + +/// Just like malloc, but throws on failure. +void* tmalloc (size_t n) throw (ustl::bad_alloc) __attribute__((malloc)); +/// Just like free, but doesn't crash when given a NULL. +inline void nfree (void* p) throw() { if (p) free (p); } + +#if WITHOUT_LIBSTDCPP + +// +// These are replaceable signatures: +// - normal single new and delete (no arguments, throw @c bad_alloc on error) +// - normal array new and delete (same) +// - @c nothrow single new and delete (take a @c nothrow argument, return +// @c NULL on error) +// - @c nothrow array new and delete (same) +// +// Placement new and delete signatures (take a memory address argument, +// does nothing) may not be replaced by a user's program. +// +inline void* operator new (size_t n) throw (ustl::bad_alloc) { return (tmalloc (n)); } +inline void* operator new[] (size_t n) throw (ustl::bad_alloc) { return (tmalloc (n)); } +inline void operator delete (void* p) throw() { nfree (p); } +inline void operator delete[] (void* p) throw() { nfree (p); } + +// Default placement versions of operator new. +inline void* operator new (size_t, void* p) throw() { return (p); } +inline void* operator new[] (size_t, void* p) throw() { return (p); } + +// Default placement versions of operator delete. +inline void operator delete (void*, void*) throw() { } +inline void operator delete[](void*, void*) throw() { } + +#else +#include <new> +#endif // WITHOUT_LIBSTDCPP + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/unumeric.h @@ -0,0 +1,154 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UNUMERIC_H_6C99D6F6363832C644A6FFF336E84E18 +#define UNUMERIC_H_6C99D6F6363832C644A6FFF336E84E18 + +namespace ustl { + +/// Returns the sum of all elements in [first, last) added to \p init. +/// \ingroup NumericAlgorithms +/// +template <typename InputIterator, typename T> +inline T accumulate (InputIterator first, InputIterator last, T init) +{ + while (first < last) + init += *first++; + return (init); +} + +/// Returns the sum of all elements in [first, last) via \p op, added to \p init. +/// \ingroup NumericAlgorithms +/// +template <typename InputIterator, typename T, typename BinaryFunction> +inline T accumulate (InputIterator first, InputIterator last, T init, BinaryFunction binary_op) +{ + while (first < last) + init = binary_op (init, *first++); + return (init); +} + +/// Assigns range [value, value + (last - first)) to [first, last) +/// \ingroup NumericAlgorithms +/// +template <typename ForwardIterator, typename T> +inline void iota (ForwardIterator first, ForwardIterator last, T value) +{ + while (first < last) + *first++ = value++; +} + +/// Returns the sum of products of respective elements in the given ranges. +/// \ingroup NumericAlgorithms +/// +template <typename InputIterator1, typename InputIterator2, typename T> +inline T inner_product (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init) +{ + while (first1 < last1) + init += *first1++ * *first2++; + return (init); +} + +/// Returns the sum of products of respective elements in the given ranges. +/// \ingroup NumericAlgorithms +/// +template <typename InputIterator1, typename InputIterator2, typename T, + typename BinaryOperation1, typename BinaryOperation2> +inline T inner_product +(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, + BinaryOperation1 sumOp, BinaryOperation2 productOp) +{ + while (first1 < last1) + init = sumOp (init, productOp (*first1++, *first2++)); + return (init); +} + +/// Writes result such that result[i] = sum (first...first+i) +/// \ingroup NumericAlgorithms +/// +template <typename InputIterator, typename OutputIterator> +inline OutputIterator partial_sum (InputIterator first, InputIterator last, OutputIterator result) +{ + if (first < last) + *result = *first++; + while (first < last) + *++result = *first++ + *result; + return (result); +} + +/// Writes result such that result[i] = sumOp (first...first+i) +/// \ingroup NumericAlgorithms +/// +template <typename InputIterator, typename OutputIterator, typename BinaryOperation> +inline OutputIterator partial_sum (InputIterator first, InputIterator last, OutputIterator result, BinaryOperation sumOp) +{ + if (first < last) + *result = *first++; + while (first < last) + *++result = sumOp (*first++, *result); + return (result); +} + +/// Writes result such that result[i] = first[i] - first[i - 1] +/// \ingroup NumericAlgorithms +/// +template <typename InputIterator, typename OutputIterator> +inline OutputIterator adjacent_difference (InputIterator first, InputIterator last, OutputIterator result) +{ + if (first < last) + *result++ = *first++; + while (first < last) + *result++ = *first - *(first - 1); + return (result); +} + +/// Writes result such that result[i] = differenceOp (first[i], first[i - 1]) +/// \ingroup NumericAlgorithms +/// +template <typename InputIterator, typename OutputIterator, typename BinaryOperation> +inline OutputIterator adjacent_difference (InputIterator first, InputIterator last, OutputIterator result, BinaryOperation differenceOp) +{ + if (first < last) + *result++ = *first++; + while (first < last) + *result++ = differenceOp (*first, *(first - 1)); + return (result); +} + +/// \brief Returns x^n. +/// Donald Knuth's Russian Peasant algorithm. +/// \ingroup NumericAlgorithms +/// +template <typename T> +inline T power (T x, unsigned n) +{ + T result (n % 2 ? x : 1); + while (n /= 2) { + x *= x; + if (n % 2) + result *= x; + } + return (result); +} + +/// \brief Returns x^n, using \p op instead of multiplication. +/// Donald Knuth's Russian Peasant algorithm. +/// \ingroup NumericAlgorithms +/// +template <typename T, typename BinaryOperation> +inline T power (T x, unsigned n, BinaryOperation op) +{ + T result (n % 2 ? x : 1); + while (n /= 2) { + x = op (x, x); + if (n % 2) + result = op (result, x); + } + return (result); +} + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/upair.h @@ -0,0 +1,59 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UPAIR_H_7DC08F1B7FECF8AE6856D84C3B617A75 +#define UPAIR_H_7DC08F1B7FECF8AE6856D84C3B617A75 + +#include "utypes.h" + +namespace ustl { + +/// \class pair upair.h ustl.h +/// \ingroup AssociativeContainers +/// +/// \brief Container for two values. +/// +template <typename T1, typename T2> +class pair { +public: + typedef T1 first_type; + typedef T2 second_type; +public: + /// Default constructor. + inline pair (void) : first (T1()), second (T2()) {} + /// Initializes members with \p a, and \p b. + inline pair (const T1& a, const T2& b) : first (a), second (b) {} + inline pair& operator= (const pair<T1, T2>& p2) { first = p2.first; second = p2.second; return (*this); } + template <typename T3, typename T4> + inline pair& operator= (const pair<T3, T4>& p2) { first = p2.first; second = p2.second; return (*this); } +public: + first_type first; + second_type second; +}; + +/// Compares both values of \p p1 to those of \p p2. +template <typename T1, typename T2> +inline bool operator== (const pair<T1,T2>& p1, const pair<T1,T2>& p2) +{ + return (p1.first == p2.first && p1.second == p2.second); +} + +/// Compares both values of \p p1 to those of \p p2. +template <typename T1, typename T2> +bool operator< (const pair<T1,T2>& p1, const pair<T1,T2>& p2) +{ + return (p1.first < p2.first || (p1.first == p2.first && p1.second < p2.second)); +} + +/// Returns a pair object with (a,b) +template <typename T1, typename T2> +inline pair<T1,T2> make_pair (const T1& a, const T2& b) +{ + return (pair<T1,T2> (a, b)); +} + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/upredalgo.h @@ -0,0 +1,587 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UPREDALGO_H_2CB058AE0807A01A2F6A51BA5D5820A5 +#define UPREDALGO_H_2CB058AE0807A01A2F6A51BA5D5820A5 + +namespace ustl { + +/// Copy_if copies elements from the range [first, last) to the range +/// [result, result + (last - first)) if pred(*i) returns true. +/// \ingroup MutatingAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename InputIterator, typename OutputIterator, typename Predicate> +inline OutputIterator copy_if (InputIterator first, InputIterator last, OutputIterator result, Predicate pred) +{ + for (; first != last; ++first) { + if (pred(*first)) { + *result = *first; + ++ result; + } + } + return (result); +} + +/// Returns the first iterator i in the range [first, last) such that +/// pred(*i) is true. Returns last if no such iterator exists. +/// \ingroup SearchingAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename InputIterator, typename Predicate> +inline InputIterator find_if (InputIterator first, InputIterator last, Predicate pred) +{ + while (first != last && !pred (*first)) + ++ first; + return (first); +} + +/// Returns the first iterator such that p(*i, *(i + 1)) == true. +/// \ingroup SearchingAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename ForwardIterator, typename BinaryPredicate> +inline ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last, BinaryPredicate p) +{ + if (first != last) + for (ForwardIterator prev = first; ++first != last; ++ prev) + if (p (*prev, *first)) + return (prev); + return (last); +} + +/// Returns the pointer to the first pair of unequal elements. +/// \ingroup SearchingAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename InputIterator, typename BinaryPredicate> +inline pair<InputIterator,InputIterator> +mismatch (InputIterator first1, InputIterator last1, InputIterator first2, BinaryPredicate comp) +{ + while (first1 != last1 && comp(*first1, *first2)) + ++ first1, ++ first2; + return (make_pair (first1, first2)); +} + +/// Returns true if two ranges are equal. +/// This is an extension, present in uSTL and SGI STL. +/// \ingroup ConditionAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename InputIterator, typename BinaryPredicate> +inline bool equal (InputIterator first1, InputIterator last1, InputIterator first2, BinaryPredicate comp) +{ + return (mismatch (first1, last1, first2, comp).first == last1); +} + +/// Count_if finds the number of elements in [first, last) that satisfy the +/// predicate pred. More precisely, the first version of count_if returns the +/// number of iterators i in [first, last) such that pred(*i) is true. +/// \ingroup ConditionAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename InputIterator, typename Predicate> +inline size_t count_if (InputIterator first, InputIterator last, Predicate pred) +{ + size_t total = 0; + for (; first != last; ++first) + if (pred (*first)) + ++ total; + return (total); +} + +/// Replace_if replaces every element in the range [first, last) for which +/// pred returns true with new_value. That is: for every iterator i, if +/// pred(*i) is true then it performs the assignment *i = new_value. +/// \ingroup MutatingAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename ForwardIterator, typename Predicate, typename T> +inline void replace_if (ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value) +{ + for (; first != last; ++first) + if (pred (*first)) + *first = new_value; +} + +/// Replace_copy_if copies elements from the range [first, last) to the range +/// [result, result + (last-first)), except that any element for which pred is +/// true is not copied; new_value is copied instead. More precisely, for every +/// integer n such that 0 <= n < last-first, replace_copy_if performs the +/// assignment *(result+n) = new_value if pred(*(first+n)), +/// and *(result+n) = *(first+n) otherwise. +/// \ingroup MutatingAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename InputIterator, typename OutputIterator, typename Predicate, typename T> +inline OutputIterator replace_copy_if (InputIterator first, InputIterator last, OutputIterator result, Predicate pred, const T& new_value) +{ + for (; first != last; ++result, ++first) + *result = pred(*first) ? new_value : *first; +} + +/// Remove_copy_if copies elements from the range [first, last) to a range +/// beginning at result, except that elements for which pred is true are not +/// copied. The return value is the end of the resulting range. This operation +/// is stable, meaning that the relative order of the elements that are copied +/// is the same as in the range [first, last). +/// \ingroup MutatingAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename InputIterator, typename OutputIterator, typename Predicate> +inline OutputIterator remove_copy_if (InputIterator first, InputIterator last, OutputIterator result, Predicate pred) +{ + for (; first != last; ++first) + if (pred (*first)) + *result++ = *first; + return (result); +} + +/// Remove_if removes from the range [first, last) every element x such that +/// pred(x) is true. That is, remove_if returns an iterator new_last such that +/// the range [first, new_last) contains no elements for which pred is true. +/// The iterators in the range [new_last, last) are all still dereferenceable, +/// but the elements that they point to are unspecified. Remove_if is stable, +/// meaning that the relative order of elements that are not removed is +/// unchanged. +/// \ingroup MutatingAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename ForwardIterator, typename Predicate> +inline ForwardIterator remove_if (ForwardIterator first, ForwardIterator last, Predicate pred) +{ + return (remove_copy_if (first, last, first, pred)); +} + +/// The reason there are two different versions of unique_copy is that there +/// are two different definitions of what it means for a consecutive group of +/// elements to be duplicates. In the first version, the test is simple +/// equality: the elements in a range [f, l) are duplicates if, for every +/// iterator i in the range, either i == f or else *i == *(i-1). In the second, +/// the test is an arbitrary Binary Predicate binary_pred: the elements in +/// [f, l) are duplicates if, for every iterator i in the range, either +/// i == f or else binary_pred(*i, *(i-1)) is true. +/// \ingroup MutatingAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename InputIterator, typename OutputIterator, typename BinaryPredicate> +OutputIterator unique_copy (InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate binary_pred) +{ + if (first != last) { + *result = *first; + while (++first != last) + if (!binary_pred (*first, *result)) + *++result = *first; + ++ result; + } + return (result); +} + +/// Every time a consecutive group of duplicate elements appears in the range +/// [first, last), the algorithm unique removes all but the first element. +/// That is, unique returns an iterator new_last such that the range [first, +/// new_last) contains no two consecutive elements that are duplicates. +/// The iterators in the range [new_last, last) are all still dereferenceable, +/// but the elements that they point to are unspecified. Unique is stable, +/// meaning that the relative order of elements that are not removed is +/// unchanged. +/// \ingroup MutatingAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename ForwardIterator, typename BinaryPredicate> +inline ForwardIterator unique (ForwardIterator first, ForwardIterator last, BinaryPredicate binary_pred) +{ + return (unique_copy (first, last, first, binary_pred)); +} + +/// Returns the furthermost iterator i in [first, last) such that, +/// for every iterator j in [first, i), comp(*j, value) is true. +/// Assumes the range is sorted. +/// \ingroup SearchingAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename ForwardIterator, typename T, typename StrictWeakOrdering> +ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering comp) +{ + ForwardIterator mid; + while (first != last) { + mid = advance (first, distance (first,last) / 2); + if (comp (*mid, value)) + first = mid + 1; + else + last = mid; + } + return (first); +} + +/// Performs a binary search inside the sorted range. +/// \ingroup SearchingAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename ForwardIterator, typename T, typename StrictWeakOrdering> +inline bool binary_search (ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering comp) +{ + ForwardIterator found = lower_bound (first, last, value, comp); + return (found != last && !comp(*found, value)); +} + +/// Returns the furthermost iterator i in [first,last) such that for +/// every iterator j in [first,i), comp(value,*j) is false. +/// \ingroup SearchingAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename ForwardIterator, typename T, typename StrictWeakOrdering> +ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering comp) +{ + ForwardIterator mid; + while (first != last) { + mid = advance (first, distance (first,last) / 2); + if (comp (value, *mid)) + last = mid; + else + first = mid + 1; + } + return (last); +} + +/// Returns pair<lower_bound,upper_bound> +/// \ingroup SearchingAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename ForwardIterator, typename T, typename StrictWeakOrdering> +inline pair<ForwardIterator,ForwardIterator> equal_range (ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering comp) +{ + pair<ForwardIterator,ForwardIterator> rv; + rv.second = rv.first = lower_bound (first, last, value, comp); + while (rv.second != last && !comp(value, *(rv.second))) + ++ rv.second; + return (rv); +} + +/// \brief Puts \p nth element into its sorted position. +/// In this implementation, the entire array is sorted. The performance difference is +/// so small and the function use is so rare, there is no need to have code for it. +/// \ingroup SortingAlgorithms +/// \ingroup SearchingAlgorithms +/// \ingroup PredicateAlgorithms +/// +template <typename RandomAccessIterator, typename Compare> +inline void nth_element (RandomAccessIterator first, RandomAccessIterator, RandomAccessIterator last, Compare comp) +{ + sort (first, last, comp); +} + +/// \brief Searches for the first subsequence [first2,last2) in [first1,last1) +/// \ingroup SearchingAlgorithms +/// \ingroup PredicateAlgorithms +template <typename ForwardIterator1, typename ForwardIterator2, typename BinaryPredicate> +ForwardIterator1 search (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate comp) +{ + const ForwardIterator1 slast = last1 - distance(first2, last2) + 1; + for (; first1 < slast; ++first1) { + ForwardIterator2 i = first2; + ForwardIterator1 j = first1; + for (; i != last2 && comp(*j, *i); ++i, ++j) ; + if (i == last2) + return (first1); + } + return (last1); +} + +/// \brief Searches for the last subsequence [first2,last2) in [first1,last1) +/// \ingroup SearchingAlgorithms +/// \ingroup PredicateAlgorithms +template <typename ForwardIterator1, typename ForwardIterator2, typename BinaryPredicate> +ForwardIterator1 find_end (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate comp) +{ + ForwardIterator1 s = last1 - distance(first2, last2); + for (; first1 < s; --s) { + ForwardIterator2 i = first2, j = s; + for (; i != last2 && comp(*j, *i); ++i, ++j) ; + if (i == last2) + return (s); + } + return (last1); +} + +/// \brief Searches for the first occurence of \p count \p values in [first, last) +/// \ingroup SearchingAlgorithms +/// \ingroup PredicateAlgorithms +template <typename Iterator, typename T, typename BinaryPredicate> +Iterator search_n (Iterator first, Iterator last, size_t count, const T& value, BinaryPredicate comp) +{ + size_t n = 0; + for (; first != last; ++first) { + if (!comp (*first, value)) + n = 0; + else if (++n == count) + return (first - --n); + } + return (last); +} + +/// \brief Searches [first1,last1) for the first occurrence of an element from [first2,last2) +/// \ingroup SearchingAlgorithms +/// \ingroup PredicateAlgorithms +template <typename InputIterator, typename ForwardIterator, typename BinaryPredicate> +InputIterator find_first_of (InputIterator first1, InputIterator last1, ForwardIterator first2, ForwardIterator last2, BinaryPredicate comp) +{ + for (; first1 != last1; ++first1) + for (ForwardIterator i = first2; i != last2; ++i) + if (comp (*first1, *i)) + return (first1); + return (first1); +} + +/// \brief Returns true if [first2,last2) is a subset of [first1,last1) +/// \ingroup ConditionAlgorithms +/// \ingroup SetAlgorithms +/// \ingroup PredicateAlgorithms +template <typename InputIterator1, typename InputIterator2, typename StrictWeakOrdering> +bool includes (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, StrictWeakOrdering comp) +{ + for (; (first1 != last1) & (first2 != last2); ++first1) { + if (comp (*first2, *first1)) + return (false); + first2 += !comp (*first1, *first2); + } + return (first2 == last2); +} + +/// \brief Merges [first1,last1) with [first2,last2) +/// +/// Result will contain every element that is in either set. If duplicate +/// elements are present, max(n,m) is placed in the result. +/// +/// \ingroup SetAlgorithms +/// \ingroup PredicateAlgorithms +template <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename StrictWeakOrdering> +OutputIterator set_union (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering comp) +{ + for (; (first1 != last1) & (first2 != last2); ++result) { + if (comp (*first2, *first1)) + *result = *first2++; + else { + first2 += !comp (*first1, *first2); + *result = *first1++; + } + } + return (copy (first2, last2, copy (first1, last1, result))); +} + +/// \brief Creates a set containing elements shared by the given ranges. +/// \ingroup SetAlgorithms +/// \ingroup PredicateAlgorithms +template <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename StrictWeakOrdering> +OutputIterator set_intersection (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering comp) +{ + while ((first1 != last1) & (first2 != last2)) { + bool b1ge2 = !comp (*first1, *first2), b2ge1 = !comp (*first2, *first1); + if (b1ge2 & b2ge1) + *result++ = *first1; + first1 += b2ge1; + first2 += b1ge2; + } + return (result); +} + +/// \brief Removes from [first1,last1) elements present in [first2,last2) +/// \ingroup SetAlgorithms +/// \ingroup PredicateAlgorithms +template <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename StrictWeakOrdering> +OutputIterator set_difference (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering comp) +{ + while ((first1 != last1) & (first2 != last2)) { + bool b1ge2 = !comp (*first1, *first2), b2ge1 = !comp (*first2, *first1); + if (!b1ge2) + *result++ = *first1; + first1 += b2ge1; + first2 += b1ge2; + } + return (copy (first1, last1, result)); +} + +/// \brief Performs union of sets A-B and B-A. +/// \ingroup SetAlgorithms +/// \ingroup PredicateAlgorithms +template <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename StrictWeakOrdering> +OutputIterator set_symmetric_difference (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering comp) +{ + while ((first1 != last1) & (first2 != last2)) { + bool b1l2 = comp (*first1, *first2), b2l1 = comp (*first2, *first1); + if (b1l2) + *result++ = *first1; + else if (b2l1) + *result++ = *first2; + first1 += !b2l1; + first2 += !b1l2; + } + return (copy (first2, last2, copy (first1, last1, result))); +} + +/// \brief Returns true if the given range is sorted. +/// \ingroup ConditionAlgorithms +/// \ingroup PredicateAlgorithms +template <typename ForwardIterator, typename StrictWeakOrdering> +bool is_sorted (ForwardIterator first, ForwardIterator last, StrictWeakOrdering comp) +{ + for (ForwardIterator i = first; ++i < last; ++first) + if (comp (*i, *first)) + return (false); + return (true); +} + +/// \brief Compares two given containers like strcmp compares strings. +/// \ingroup ConditionAlgorithms +/// \ingroup PredicateAlgorithms +template <typename InputIterator1, typename InputIterator2, typename BinaryPredicate> +bool lexicographical_compare (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, BinaryPredicate comp) +{ + for (; (first1 != last1) & (first2 != last2); ++first1, ++first2) { + if (comp (*first1, *first2)) + return (true); + if (comp (*first2, *first1)) + return (false); + } + return ((first1 == last1) & (first2 != last2)); +} + +/// \brief Creates the next lexicographical permutation of [first,last). +/// Returns false if no further permutations can be created. +/// \ingroup GeneratorAlgorithms +/// \ingroup PredicateAlgorithms +template <typename BidirectionalIterator, typename StrictWeakOrdering> +bool next_permutation (BidirectionalIterator first, BidirectionalIterator last, StrictWeakOrdering comp) +{ + if (distance (first, last) < 2) + return (false); + BidirectionalIterator i = last; + for (--i; i != first; ) { + --i; + if (comp (i[0], i[1])) { + BidirectionalIterator j = last; + while (!comp (*i, *--j)) ; + iter_swap (i, j); + reverse (i + 1, last); + return (true); + } + } + reverse (first, last); + return (false); +} + +/// \brief Creates the previous lexicographical permutation of [first,last). +/// Returns false if no further permutations can be created. +/// \ingroup GeneratorAlgorithms +/// \ingroup PredicateAlgorithms +template <typename BidirectionalIterator, typename StrictWeakOrdering> +bool prev_permutation (BidirectionalIterator first, BidirectionalIterator last, StrictWeakOrdering comp) +{ + if (distance (first, last) < 2) + return (false); + BidirectionalIterator i = last; + for (--i; i != first; ) { + --i; + if (comp(i[1], i[0])) { + BidirectionalIterator j = last; + while (!comp (*--j, *i)) ; + iter_swap (i, j); + reverse (i + 1, last); + return (true); + } + } + reverse (first, last); + return (false); +} + +/// \brief Returns iterator to the max element in [first,last) +/// \ingroup SearchingAlgorithms +/// \ingroup PredicateAlgorithms +template <typename ForwardIterator, typename BinaryPredicate> +inline ForwardIterator max_element (ForwardIterator first, ForwardIterator last, BinaryPredicate comp) +{ + ForwardIterator result = first; + for (; first != last; ++first) + if (comp (*result, *first)) + result = first; + return (result); +} + +/// \brief Returns iterator to the min element in [first,last) +/// \ingroup SearchingAlgorithms +/// \ingroup PredicateAlgorithms +template <typename ForwardIterator, typename BinaryPredicate> +inline ForwardIterator min_element (ForwardIterator first, ForwardIterator last, BinaryPredicate comp) +{ + ForwardIterator result = first; + for (; first != last; ++first) + if (comp (*first, *result)) + result = first; + return (result); +} + +/// \brief Makes [first,middle) a part of the sorted array. +/// Contents of [middle,last) is undefined. This implementation just calls stable_sort. +/// \ingroup SortingAlgorithms +/// \ingroup PredicateAlgorithms +template <typename RandomAccessIterator, typename StrictWeakOrdering> +inline void partial_sort (RandomAccessIterator first, RandomAccessIterator, RandomAccessIterator last, StrictWeakOrdering comp) +{ + stable_sort (first, last, comp); +} + +/// \brief Like partial_sort, but outputs to [result_first,result_last) +/// \ingroup SortingAlgorithms +/// \ingroup PredicateAlgorithms +template <typename InputIterator, typename RandomAccessIterator, typename StrictWeakOrdering> +RandomAccessIterator partial_sort_copy (InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last, StrictWeakOrdering comp) +{ + RandomAccessIterator rend = result_first; + for (; first != last; ++first) { + RandomAccessIterator i = result_first; + for (; i != rend && comp (*i, *first); ++i) ; + if (i == result_last) + continue; + rend += (rend < result_last); + copy_backward (i, rend - 1, rend); + *i = *first; + } + return (rend); +} + +/// \brief Like partition, but preserves equal element order. +/// \ingroup SortingAlgorithms +/// \ingroup PredicateAlgorithms +template <typename ForwardIterator, typename Predicate> +ForwardIterator stable_partition (ForwardIterator first, ForwardIterator last, Predicate pred) +{ + if (first == last) + return (first); + ForwardIterator l, r, m = advance (first, distance (first, last) / 2); + if (first == m) + return (pred(*first) ? last : first); + l = stable_partition (first, m, pred); + r = stable_partition (m, last, pred); + rotate (l, m, r); + return (advance (l, distance (m, r))); +} + +/// \brief Splits [first,last) in two by \p pred. +/// +/// Creates two ranges [first,middle) and [middle,last), where every element +/// in the former is less than every element in the latter. +/// The return value is middle. +/// +/// \ingroup SortingAlgorithms +/// \ingroup PredicateAlgorithms +template <typename ForwardIterator, typename Predicate> +inline ForwardIterator partition (ForwardIterator first, ForwardIterator last, Predicate pred) +{ + return (stable_partition (first, last, pred)); +} + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/uqueue.h @@ -0,0 +1,69 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UQUEUE_H_27F01FDB0D59B75277E0E5C41ABC6B5B +#define UQUEUE_H_27F01FDB0D59B75277E0E5C41ABC6B5B + +namespace ustl { + +/// \class queue uqueue.h ustl.h +/// \ingroup Sequences +/// +/// \brief Queue adapter to uSTL containers. +/// +/// The most efficient way to use this implementation is to fill the queue +/// and the completely empty it before filling again. +/// +template <typename T> +class queue { +public: + typedef T value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; +public: + inline queue (void) : m_Storage (), m_Front (0) { } + explicit inline queue (const vector<T>& s) : m_Storage (s), m_Front (0) { } + explicit inline queue (const queue& s) : m_Storage (s.m_Storage), m_Front (0) { } + inline size_type size (void) const { return (m_Storage.size() - m_Front); } + inline bool empty (void) const { return (!size()); } + inline reference front (void) { return (m_Storage [m_Front]); } + inline const_reference front (void) const { return (m_Storage [m_Front]); } + inline reference back (void) { return (m_Storage.back()); } + inline const_reference back (void) const { return (m_Storage.back()); } + inline void push (const value_type& v); + inline void pop (void); + inline bool operator== (const queue& s) const { return (m_Storage == s.m_Storage && m_Front == s.m_Front); } + inline bool operator< (const queue& s) const { return (size() < s.size()); } +private: + vector<T> m_Storage; ///< Where the data actually is. + size_type m_Front; ///< Index of the element returned by next pop. +}; + +/// Pushes \p v on the queue. +template <typename T> +inline void queue<T>::push (const value_type& v) +{ + if (m_Front) { + m_Storage.erase (m_Storage.begin(), m_Front); + m_Front = 0; + } + m_Storage.push_back (v); +} + +/// Pops the topmost element from the queue. +template <typename T> +inline void queue<T>::pop (void) +{ + if (++m_Front >= m_Storage.size()) + m_Storage.resize (m_Front = 0); +} + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/uset.h @@ -0,0 +1,91 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef USET_H_45543F516E02A87A3FCEA5024052A6F5 +#define USET_H_45543F516E02A87A3FCEA5024052A6F5 + +#include "uvector.h" + +namespace ustl { + +/// \class set uset.h ustl.h +/// \ingroup Sequences +/// +/// \brief Unique sorted container. Sorted vector with all values unique. +/// +template <typename T> +class set : public vector<T> { +public: + typedef const set<T>& rcself_t; + typedef vector<T> base_class; + typedef typename base_class::value_type key_type; + typedef typename base_class::value_type data_type; + typedef typename base_class::value_type value_type; + typedef typename base_class::size_type size_type; + typedef typename base_class::pointer pointer; + typedef typename base_class::const_pointer const_pointer; + typedef typename base_class::reference reference; + typedef typename base_class::const_reference const_reference; + typedef typename base_class::const_iterator const_iterator; + typedef typename base_class::iterator iterator; + typedef typename base_class::reverse_iterator reverse_iterator; + typedef typename base_class::const_reverse_iterator const_reverse_iterator; + typedef pair<iterator,bool> insertrv_t; +public: + inline set (void) : vector<T> () { } + explicit inline set (size_type n) : vector<T> (n) { } + inline set (rcself_t v) : vector<T> (v) { } + inline set (const_iterator i1, const_iterator i2) : vector<T> () { insert (i1, i2); } + inline rcself_t operator= (rcself_t v) { base_class::operator= (v); return (*this); } + inline size_type size (void) const { return (base_class::size()); } + inline iterator begin (void) { return (base_class::begin()); } + inline const_iterator begin (void) const { return (base_class::begin()); } + inline iterator end (void) { return (base_class::end()); } + inline const_iterator end (void) const { return (base_class::end()); } + inline void assign (const_iterator i1, const_iterator i2) { clear(); insert (i1, i2); } + inline void push_back (const_reference v) { insert (v); } + inline const_iterator find (const_reference v) const { const_iterator i = lower_bound (begin(), end(), v); return ((i != end() && *i == v) ? i : end()); } + inline iterator find (const_reference v) { return (const_cast<iterator>(const_cast<rcself_t>(*this).find (v))); } + insertrv_t insert (const_reference v); + inline void insert (const_iterator i1, const_iterator i2); + inline void erase (const_reference v); + inline iterator erase (iterator ep) { return (base_class::erase (ep)); } + inline iterator erase (iterator ep1, iterator ep2) { return (base_class::erase (ep1, ep2)); } + inline void clear (void) { base_class::clear(); } +}; + +/// Inserts \p v into the container, maintaining the sort order. +template <typename T> +typename set<T>::insertrv_t set<T>::insert (const_reference v) +{ + iterator ip = lower_bound (begin(), end(), v); + bool bInserted = (ip == end() || v < *ip); + if (bInserted) + ip = base_class::insert (ip, v); + return (make_pair (ip, bInserted)); +} + +/// Inserts the contents of range [i1,i2) +template <typename T> +void set<T>::insert (const_iterator i1, const_iterator i2) +{ + assert (i1 <= i2); + reserve (size() + distance (i1, i2)); + for (; i1 < i2; ++i1) + push_back (*i1); +} + +/// Erases the element with value \p v. +template <typename T> +inline void set<T>::erase (const_reference v) +{ + iterator ip = find (v); + if (ip != end()) + erase (ip); +} + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/uspecial.h @@ -0,0 +1,260 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef USPECIAL_H_947ADYOU0ARE3YOU2REALLY8ARE44CE0 +#define USPECIAL_H_947ADYOU0ARE3YOU2REALLY8ARE44CE0 + +#include "uvector.h" +#include "ustring.h" +#include "uset.h" +#include "umultiset.h" +#include "ubitset.h" +#include "ulaalgo.h" +#include "uctralgo.h" +#include "ufunction.h" +#include "uctrstrm.h" +#include "sistream.h" +#include <ctype.h> + +namespace ustl { + +//---------------------------------------------------------------------- +// Alogrithm specializations not in use by the library code. +//---------------------------------------------------------------------- + +template <> inline void swap (cmemlink& a, cmemlink& b) { a.swap (b); } +template <> inline void swap (memlink& a, memlink& b) { a.swap (b); } +template <> inline void swap (memblock& a, memblock& b) { a.swap (b); } +template <> inline void swap (string& a, string& b) { a.swap (b); } +#define TEMPLATE_SWAP_PSPEC(type, template_decl) \ +template_decl inline void swap (type& a, type& b) { a.swap (b); } +TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE1 (vector,T), TEMPLATE_DECL1 (T)) +TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE1 (set,T), TEMPLATE_DECL1 (T)) +TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE1 (multiset,T), TEMPLATE_DECL1 (T)) +TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE2 (tuple,N,T), TEMPLATE_FULL_DECL2 (size_t,N,typename,T)) + +//---------------------------------------------------------------------- +// Streamable definitions. Not used in the library and require streams. +//---------------------------------------------------------------------- + +//----{ pair }---------------------------------------------------------- + +/// \brief Reads pair \p p from stream \p is. +template <typename T1, typename T2> +istream& operator>> (istream& is, pair<T1,T2>& p) +{ + is >> p.first; + is.align (alignof(p.second)); + is >> p.second; + is.align (alignof(p.first)); + return (is); +} + +/// Writes pair \p p to stream \p os. +template <typename T1, typename T2> +ostream& operator<< (ostream& os, const pair<T1,T2>& p) +{ + os << p.first; + os.align (alignof(p.second)); + os << p.second; + os.align (alignof(p.first)); + return (os); +} + +/// Writes pair \p p to stream \p os. +template <typename T1, typename T2> +ostringstream& operator<< (ostringstream& os, const pair<T1,T2>& p) +{ + os << '(' << p.first << ',' << p.second << ')'; + return (os); +} + +/// Returns the written size of the object. +template <typename T1, typename T2> +struct object_stream_size<pair<T1,T2> > { + inline size_t operator()(const pair<T1,T2>& v) const + { + return (Align (stream_size_of(v.first), alignof(v.second)) + + Align (stream_size_of(v.second), alignof(v.first))); + } +}; + +/// \brief Takes a pair and returns pair.first +/// This is an extension, available in uSTL and the SGI STL. +template <typename Pair> struct select1st : public unary_function<Pair,typename Pair::first_type> { + typedef typename Pair::first_type result_type; + inline const result_type& operator()(const Pair& a) const { return (a.first); } + inline result_type& operator()(Pair& a) const { return (a.first); } +}; + +/// \brief Takes a pair and returns pair.second +/// This is an extension, available in uSTL and the SGI STL. +template <typename Pair> struct select2nd : public unary_function<Pair,typename Pair::second_type> { + typedef typename Pair::second_type result_type; + inline const result_type& operator()(const Pair& a) const { return (a.second); } + inline result_type& operator()(Pair& a) const { return (a.second); } +}; + +/// \brief Converts a const_iterator pair into an iterator pair +/// Useful for converting pair ranges returned by equal_range, for instance. +/// This is an extension, available in uSTL. +template <typename Container> +inline pair<typename Container::iterator, typename Container::iterator> +unconst (const pair<typename Container::const_iterator, typename Container::const_iterator>& i, Container&) +{ + typedef pair<typename Container::iterator, typename Container::iterator> unconst_pair_t; + return (*noalias_cast<unconst_pair_t*>(&i)); +} + +//----{ vector }-------------------------------------------------------- + +template <typename T> +inline size_t alignof (const vector<T>&) +{ + typedef typename vector<T>::written_size_type written_size_type; + return (alignof (written_size_type())); +} + +//----{ bitset }-------------------------------------------------------- + +/// Writes bitset \p v into stream \p os. +template <size_t Size> +istringstream& operator>> (istringstream& is, bitset<Size>& v) +{ + char c; + for (int i = Size; --i >= 0 && (is >> c).good();) + v.set (i, c == '1'); + return (is); +} + +//----{ tuple }--------------------------------------------------------- + +template <size_t N, typename T> +inline istream& operator>> (istream& is, tuple<N,T>& v) + { v.read (is); return (is); } +template <size_t N, typename T> +inline ostream& operator<< (ostream& os, const tuple<N,T>& v) + { v.write (os); return (os); } +template <size_t N, typename T> +inline ostringstream& operator<< (ostringstream& os, const tuple<N,T>& v) + { v.text_write (os); return (os); } + +template <size_t N, typename T> +struct numeric_limits<tuple<N,T> > { + typedef numeric_limits<T> value_limits; + static inline tuple<N,T> min (void) { tuple<N,T> v; fill (v, value_limits::min()); return (v); } + static inline tuple<N,T> max (void) { tuple<N,T> v; fill (v, value_limits::max()); return (v); } + static const bool is_signed = value_limits::is_signed; + static const bool is_integer = value_limits::is_integer; + static const bool is_integral = value_limits::is_integral; +}; + +template <size_t N, typename T> +inline size_t alignof (const tuple<N,T>&) { return (alignof (NullValue<T>())); } + +template <typename T, typename IntT> +inline ostringstream& chartype_text_write (ostringstream& os, const T& v) +{ + os.format (_FmtPrtChr[!isprint(v)], v); + return (os); +} + +template <> +inline ostringstream& container_element_text_write (ostringstream& os, const uint8_t& v) +{ return (chartype_text_write<uint8_t, unsigned int> (os, v)); } +template <> +inline ostringstream& container_element_text_write (ostringstream& os, const int8_t& v) +{ return (chartype_text_write<int8_t, int> (os, v)); } + +//----{ matrix }-------------------------------------------------------- + +/// Writes tuple \p v into stream \p os. +template <size_t NX, size_t NY, typename T> +ostringstream& operator<< (ostringstream& os, const matrix<NX,NY,T>& v) +{ + os << '('; + for (uoff_t row = 0; row < NY; ++ row) { + os << '('; + for (uoff_t column = 0; column < NX; ++column) + os << v[row][column] << ",)"[column == NX-1]; + } + os << ')'; + return (os); +} + +//----{ long4grain }---------------------------------------------------- + +#if SIZE_OF_LONG == 8 && HAVE_INT64_T +// Helper class for long4grain and ptr4grain wrappers. +class _long4grain { +public: + inline _long4grain (uint64_t v) : m_v (v) {} +#if __x86_64__ + inline void read (istream& is) + { + assert (is.aligned(4)); + #if WANT_STREAM_BOUNDS_CHECKING + if (!is.verify_remaining ("read", "long4grain", sizeof(m_v))) return; + #else + assert (is.remaining() >= sizeof(m_v)); + #endif + m_v = *reinterpret_cast<const uint64_t*>(is.ipos()); + is.skip (sizeof(m_v)); + } + inline void write (ostream& os) const + { + assert (os.aligned(4)); + #if WANT_STREAM_BOUNDS_CHECKING + if (!os.verify_remaining ("write", "long4grain", sizeof(m_v))) return; + #else + assert (os.remaining() >= sizeof(m_v)); + #endif + *reinterpret_cast<uint64_t*>(os.ipos()) = m_v; + os.skip (sizeof(m_v)); + } +#elif USTL_BYTE_ORDER == USTL_BIG_ENDIAN + inline void read (istream& is) { uint32_t vl, vh; is >> vh >> vl; m_v = (uint64_t(vh) << 32) | uint64_t(vl); } + inline void write (ostream& os) const { os << uint32_t(m_v >> 32) << uint32_t(m_v); } +#else + inline void read (istream& is) { uint32_t vl, vh; is >> vl >> vh; m_v = (uint64_t(vh) << 32) | uint64_t(vl); } + inline void write (ostream& os) const { os << uint32_t(m_v) << uint32_t(m_v >> 32); } +#endif + inline size_t stream_size (void) const { return (stream_size_of(m_v)); } +private: + uint64_t m_v; +}; + +/// Wrap long values to allow writing them on 4-grain even on 64bit platforms. +inline _long4grain& long4grain (unsigned long& v) { asm("":"+m"(v)); return (*noalias_cast<_long4grain*>(&v)); } +/// Wrap long values to allow writing them on 4-grain even on 64bit platforms. +inline const _long4grain long4grain (const unsigned long& v) { return (_long4grain(v)); } +/// Wrap pointer values to allow writing them on 4-grain even on 64bit platforms. +template <typename T> +inline _long4grain& ptr4grain (T*& p) { asm("":"+m"(p)); return (*noalias_cast<_long4grain*>(&p)); } +/// Wrap pointer values to allow writing them on 4-grain even on 64bit platforms. +template <typename T> +inline const _long4grain ptr4grain (const T* const& p) { return (_long4grain(uintptr_t(p))); } +#else // if not SIZE_OF_LONG == 8 && HAVE_INT64_T +inline unsigned long& long4grain (unsigned long& v) { return (v); } +inline const unsigned long& long4grain (const unsigned long& v) { return (v); } +template <typename T> inline T*& ptr4grain (T*& p) { return (p); } +template <typename T> inline const T* const& ptr4grain (const T* const& p) { return (p); } +#endif // SIZE_OF_LONG == 8 + +//---------------------------------------------------------------------- + +} // namespace ustl + +// This is here because there really is no other place to put it. +#if SIZE_OF_BOOL != SIZE_OF_CHAR +// bool is a big type on some machines (like DEC Alpha), so it's written as a byte. +ALIGNOF(bool, sizeof(uint8_t)) +CAST_STREAMABLE(bool, uint8_t) +#endif +#if SIZE_OF_LONG == 8 && HAVE_INT64_T +ALIGNOF (_long4grain, 4) +#endif + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/ustack.h @@ -0,0 +1,44 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef USTACK_H_5242F5635322B2EC44A9AEE73022C6E9 +#define USTACK_H_5242F5635322B2EC44A9AEE73022C6E9 + +namespace ustl { + +/// \class stack ustack.h ustl.h +/// \ingroup Sequences +/// +/// \brief Stack adapter to uSTL containers. +/// +template <typename T> +class stack { +public: + typedef T value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; +public: + inline stack (void) : m_Storage () { } + explicit inline stack (const vector<T>& s) : m_Storage (s) { } + explicit inline stack (const stack& s) : m_Storage (s.m_Storage) { } + inline bool empty (void) const { return (m_Storage.empty()); } + inline size_type size (void) const { return (m_Storage.size()); } + inline reference top (void) { return (m_Storage.back()); } + inline const_reference top (void) const { return (m_Storage.back()); } + inline void push (const value_type& v) { m_Storage.push_back (v); } + inline void pop (void) { m_Storage.pop_back(); } + inline bool operator== (const stack& s) const { return (m_Storage == s.m_Storage); } + inline bool operator< (const stack& s) const { return (m_Storage.size() < s.m_Storage.size()); } +private: + vector<T> m_Storage; ///< Where the data actually is. +}; + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/ustdxept.h @@ -0,0 +1,140 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef USTDXEPT_H_46F7AE967738B588038F95E41158D7FF +#define USTDXEPT_H_46F7AE967738B588038F95E41158D7FF + +#include "uexception.h" +#include "ustring.h" + +namespace ustl { + +enum { + xfmt_ErrorMessage = 2, + xfmt_LogicError = xfmt_ErrorMessage, + xfmt_RuntimeError = xfmt_ErrorMessage +}; + +/// \class logic_error ustdxept.h ustl.h +/// \ingroup Exceptions +/// +/// \brief Logic errors represent problems in the internal logic of the program. +/// +class error_message : public exception { +public: + explicit error_message (const char* arg) throw(); + virtual ~error_message (void) throw(); + inline virtual const char* what (void) const throw() { return (m_Arg.c_str()); } + inline virtual const char* name (void) const throw() { return ("error"); } + virtual void info (string& msgbuf, const char* fmt = NULL) const throw(); + virtual void read (istream& is); + virtual void write (ostream& os) const; + virtual size_t stream_size (void) const; +protected: + string m_Arg; +}; + +/// \class logic_error ustdxept.h ustl.h +/// \ingroup Exceptions +/// +/// \brief Logic errors represent problems in the internal logic of the program. +/// +class logic_error : public error_message { +public: + inline explicit logic_error (const char* arg) throw() : error_message (arg) {} + inline virtual const char* name (void) const throw() { return ("logic error"); } +}; + +/// \class domain_error ustdxept.h ustl.h +/// \ingroup Exceptions +/// +/// \brief Reports domain errors ("domain" is in the mathematical sense) +/// +class domain_error : public logic_error { +public: + inline explicit domain_error (const char* arg) throw() : logic_error (arg) {} + inline virtual const char* name (void) const throw() { return ("domain error"); } +}; + +/// \class invalid_argument ustdxept.h ustl.h +/// \ingroup Exceptions +/// +/// \brief Reports an invalid argument to a function. +/// +class invalid_argument : public logic_error { +public: + inline explicit invalid_argument (const char* arg) throw() : logic_error (arg) {} + inline virtual const char* name (void) const throw() { return ("invalid argument"); } +}; + +/// \class length_error ustdxept.h ustl.h +/// \ingroup Exceptions +/// +/// \brief Reports when an object exceeds its allowed size. +/// +class length_error : public logic_error { +public: + inline explicit length_error (const char* arg) throw() : logic_error (arg) {} + inline virtual const char* name (void) const throw() { return ("length error"); } +}; + +/// \class out_of_range ustdxept.h ustl.h +/// \ingroup Exceptions +/// +/// \brief Reports arguments with values out of allowed range. +/// +class out_of_range : public logic_error { +public: + inline explicit out_of_range (const char* arg) throw() : logic_error (arg) {} + inline virtual const char* name (void) const throw() { return ("out of range"); } +}; + +/// \class runtime_error ustdxept.h ustl.h +/// \ingroup Exceptions +/// +/// \brief Reports errors that are dependent on the data being processed. +/// +class runtime_error : public error_message { +public: + inline explicit runtime_error (const char* arg) throw() : error_message (arg) {} + inline virtual const char* name (void) const throw() { return ("runtime error"); } +}; + +/// \class range_error ustdxept.h ustl.h +/// \ingroup Exceptions +/// +/// \brief Reports data that does not fall within the permitted range. +/// +class range_error : public runtime_error { +public: + inline explicit range_error (const char* arg) throw() : runtime_error (arg) {} + inline virtual const char* name (void) const throw() { return ("range error"); } +}; + +/// \class overflow_error ustdxept.h ustl.h +/// \ingroup Exceptions +/// +/// \brief Reports arithmetic overflow. +/// +class overflow_error : public runtime_error { +public: + inline explicit overflow_error (const char* arg) throw() : runtime_error (arg) {} + inline virtual const char* name (void) const throw() { return ("overflow error"); } +}; + +/// \class underflow_error ustdxept.h ustl.h +/// \ingroup Exceptions +/// +/// \brief Reports arithmetic underflow. +/// +class underflow_error : public runtime_error { +public: + inline explicit underflow_error (const char* arg) throw() : runtime_error (arg) {} + inline virtual const char* name (void) const throw() { return ("underflow error"); } +}; + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/ustl.h @@ -0,0 +1,191 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef USTL_H_6A5A10410D2CD7FC2D78FE470F045EB7 +#define USTL_H_6A5A10410D2CD7FC2D78FE470F045EB7 + +#include "uspecial.h" +#include "umap.h" +#include "umultimap.h" +#include "ustack.h" +#include "uqueue.h" +#ifdef CYGCLS_USTL_FSTREAMS +#include "ofstream.h" +#endif +#include "unumeric.h" +#include "ulist.h" +#include "uheap.h" +#include "ustdxept.h" +#include "ustlecos.h" + +#endif + +/// \mainpage +/// +/// \section intro Introduction +/// +/// uSTL is a partial implementation of the STL specification intended to +/// reduce code size of the derivative programs. Usually, the STL containers +/// manage their own storage with new[] and delete[] operators, which create +/// strongly typed storage. That is the standard way of allocating C++ object +/// vectors, allowing appropriate constructors and destructors to be called on +/// the allocated storage and ensuring that objects are copied via their copy +/// operators. Although type safety is a good thing, placing memory management +/// code into a template necessitates its reinstantiation for every template +/// instance used by the derivative program. This produces substantial code +/// bloat, that is frequently derided by C developers and used by them as +/// an argument that C is better than C++. The uSTL implementation solves +/// this problem by factoring memory management code into a non-template base +/// class, ustl::memblock, which performs unstructured memory allocation. STL +/// containers are then implemented as template wrappers for memblock to +/// provide a measure of type safety. The result is that each template +/// instantiation contains less code, and although it does not completely +/// "disappear", due to the requirement for calling placement constructors +/// on the allocated memory, most of it does, being replaced by calls to +/// memblock methods. The base classes for unstructured storage management +/// (cmemlink - link to constant memory, memlink - link to mutable memory, +/// and memblock - owner of mutable memory) are, of course, also available +/// for use as data buffers wherever those are needed, and streams that +/// efficiently read and write binary data into them are also available. +// +/// \defgroup Containers Containers +/// Here you'll find all the containers for your objects and data. +// +/// \defgroup MemoryManagement Memory Management +/// \ingroup Containers +/// Classes that implement low-level memory management and form the base for +/// all containers in the library. Almost all functionality in the containers +/// is reduced to calls to these base classes through a great deal of inline +/// crunching by the compiler, and thus you end up storing all your data in +/// ustl::memblock objects with the container templates as mere syntactic sugar. +// +/// \defgroup Sequences Sequence Containers +/// \ingroup Containers +/// Containers containing sequences of objects. +// +/// \defgroup AssociativeContainers Associative Containers +/// \ingroup Containers +/// Containers containing associations of objects. +// +/// \defgroup Streams Streams +/// Streams convert objects into flat data. +// +/// \defgroup BinaryStreams Binary Streams +/// \ingroup Streams +/// Unlike the C++ standard library, +/// the default behaviour is very strongly biased toward binary streams. I +/// believe that text formats should be used very sparingly due to numerous +/// problems they cause, such as total lack of structure, buffer overflows, +/// the great multitude of formats and encodings for even the most +/// trivial of things like integers, and the utter lack of readability +/// despite ardent claims to the contrary. Binary formats are well-structured, +/// are simpler to define exhaustively, are aggregates of basic types which +/// are universal to all architectures (with the exception of two types of +/// byte ordering, which I hope to be an issue that will go away soon), and +/// are much more readable (through an appropriate formatting tool equipped +/// to read binary format specifications). +// +/// \defgroup BinaryStreamIterators Binary Stream Iterators +/// \ingroup BinaryStreams +/// \ingroup Iterators +/// Iterators for using STL algorithms with binary streams. +// +/// \defgroup TextStreams TextStreams +/// \ingroup Streams +/// Streams converting objects into streams of text. +// +/// \defgroup DeviceStreams Device Streams +/// \ingroup Streams +/// Standard cout, cerr, and cin implementations for reading +/// and writing text through standard file descriptors. +// +/// \defgroup Iterators Iterators +/// Generalizations of the pointer concept, allowing algorithms to treat +/// all containers in a unified fashion. +// +/// \defgroup IteratorAdaptors Iterator Adaptors +/// \ingroup Iterators +/// Iterators made out of other iterators. +// +/// \defgroup Algorithms Algorithms +/// STL algorithms are the heart of generic programming. The idea is to +/// separate algorithms from containers to take advantage of the fact that +/// there are fewer distinct algorithms than typed containers. This is +/// diametrically opposed to object oriented programming, where each object +/// must contain all functionality related to its internal data. You will +/// find, I think, that in practice, generic programming is not terribly +/// convenient because it prevents you from encapsulating all your data. +/// The best approach is to compromise and have raw data classes that will +/// be manipulated by algorithms and to treat the rest of the objects as +/// stateful data transformers. +// +/// \defgroup MutatingAlgorithms Mutating Algorithms +/// \ingroup Algorithms +/// Algorithms for modifying your data in some way. +// +/// \defgroup SortingAlgorithms Sorting Algorithms +/// \ingroup MutatingAlgorithms +/// Algorithms for sorting containers. +// +/// \defgroup GeneratorAlgorithms Generator Algorithms +/// \ingroup MutatingAlgorithms +/// Algorithms for generating data. +// +/// \defgroup NumericAlgorithms Numeric Algorithms +/// \ingroup MutatingAlgorithms +/// Algorithms generalizing mathematical operations. +// +/// \defgroup SetAlgorithms Set Algorithms +/// \ingroup MutatingAlgorithms +/// Algorithms for working with sorted sets. +// +/// \defgroup HeapAlgorithms Heap Algorithms +/// \ingroup MutatingAlgorithms +/// Algorithms for generating and manipulating heaps. +// +/// \defgroup SwapAlgorithms Swap Algorithms +/// \ingroup MutatingAlgorithms +/// Algorithms for swapping elements. +// +/// \defgroup RawStorageAlgorithms Raw Storage Algorithms +/// \ingroup MutatingAlgorithms +/// Algorithms for manipulating unstructured memory. +// +/// \defgroup ConditionAlgorithms Condition Algorithms +/// \ingroup Algorithms +/// Algorithms for obtaining information about data. +// +/// \defgroup SearchingAlgorithms Searching Algorithms +/// \ingroup ConditionAlgorithms +/// Algorithms for searching through containers. +// +/// \defgroup PredicateAlgorithms Predicate Algorithms +/// \ingroup Algorithms +/// Algorithms that take a functor object. Avoid these if you can, +/// and carefully check the generated assembly if you can't. These +/// algorithms can and will generate prodigious amounts of bloat +/// if you are not very very careful about writing your functors. +// +/// \defgroup Functors Functors +/// Functors are inteded to be passed as arguments to \link PredicateAlgorithms +/// predicate algorithms\endlink. Ivory tower academics make much of this capability, +/// no doubt happy that C++ can now be made to look just like their precious lisp. +/// In practice, however, functors and predicate algorithms are mostly useless. +/// An iterative solution using \ref foreach is usually far simpler to write +/// and to maintain. Furthermore, functional programming in C++ often +/// generates much bloat and slowness, which is difficult to avoid with any +/// but the most primitive functors. Try them if you wish, now and then, but +/// compare with an iterative solution to see if the compiler really can see +/// through all your functional trickery. +// +/// \defgroup FunctorObjects Functor Objects +/// \ingroup Functors +/// Objects that wrap other functors to provide new functionality. +// +/// \defgroup FunctorAccessors Functor Object Accessors +/// \ingroup Functors +/// Because C++ is so very unsuited to functional programming, trying +/// to do so may require a lot of typing. These accessor functions +/// are somewhat helpful in making functional constructs more readable.
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/ustlecos.h @@ -0,0 +1,78 @@ +#ifndef CYGONCE_USTLECOS_H +#define CYGONCE_USTLECOS_H +// ========================================================================== +// +// ustlecos.h +// +// eCos specific implementations and additions to uSTL library +// +// =========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2009 Free Software Foundation, Inc. +// +// eCos 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 or (at your option) any later +// version. +// +// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +// =========================================================================== +// =========================================================================== +// #####DESCRIPTIONBEGIN#### +// +// Author(s): Uwe Kindler +// Contributors: +// Date: 2009-07-28 +// Purpose: eCos specific additions to uSTL library +// Description: +// Usage: Do not include directly #include <ustl.h> +// +// ####DESCRIPTIONEND#### +// +// ========================================================================*/ + + +// +// If exception handling is disabled then we provide a low level and +// lightwight "exeption handler" +// +#ifndef __EXCEPTIONS +namespace ustl +{ + +typedef void (*app_exception_handler_t)(const exception& ex); + + +// allow an application to register its own ustl exception handler +void set_app_exception_handler(app_exception_handler_t func); + +// an application exception handler may use this function to print the +// exception to diagnostic output +void diag_print_exception(const exception& ex); +} // namespace ustl +#endif + +// --------------------------------------------------------------------------- +#endif // CYGONCE_USTLECOS_H
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/ustring.h @@ -0,0 +1,268 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef USTRING_H_1249CB7A098A9010763AAC6D37B133CF +#define USTRING_H_1249CB7A098A9010763AAC6D37B133CF + +#include "memblock.h" +#include "utf8.h" +#include <stdarg.h> // for va_list, va_start, and va_end (in string::format) + +namespace ustl { + +/// \class string ustring.h ustl.h +/// \ingroup Sequences +/// +/// \brief STL basic_string<char> equivalent. +/// +/// An STL container for text string manipulation. +/// Differences from C++ standard: +/// - string is a class, not a template. Wide characters are assumed to be +/// encoded with utf8 at all times except when rendering or editing, +/// where you would use a utf8 iterator. +/// - format member function - you can, of course use an \ref ostringstream, +/// which also have format functions, but most of the time this way +/// is more convenient. Because uSTL does not implement locales, +/// format is the only way to create localized strings. +/// - const char* cast operator. It is much clearer to use this than having +/// to type .c_str() every time. +/// - length returns the number of _characters_, not bytes. +/// This function is O(N), so use wisely. +/// +/// An additional note is in order regarding the use of indexes. All indexes +/// passed in as arguments or returned by find are byte offsets, not character +/// offsets. Likewise, sizes are specified in bytes, not characters. The +/// rationale is that there is no way for you to know what is in the string. +/// There is no way for you to know how many characters are needed to express +/// one thing or another. The only thing you can do to a localized string is +/// search for delimiters and modify text between them as opaque blocks. If you +/// do anything else, you are hardcoding yourself into a locale! So stop it! +/// +class string : public memblock { +public: + typedef char value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef wchar_t wvalue_type; + typedef wvalue_type* wpointer; + typedef const wvalue_type* const_wpointer; + typedef pointer iterator; + typedef const_pointer const_iterator; + typedef value_type& reference; + typedef value_type const_reference; + typedef ::ustl::reverse_iterator<iterator> reverse_iterator; + typedef ::ustl::reverse_iterator<const_iterator> const_reverse_iterator; + typedef utf8in_iterator<const_iterator> utf8_iterator; + static const uoff_t npos = static_cast<uoff_t>(-1); ///< Value that means the end of string. +public: + inline string (void) : memblock () { relink ("",0); } + string (const string& s); + inline string (const string& s, uoff_t o, size_type n); + inline explicit string (const cmemlink& l); + string (const_pointer s); + inline string (const_pointer s, size_type len); + inline string (const_pointer s1, const_pointer s2); + explicit string (size_type n, value_type c = 0); + inline pointer data (void) { return (string::pointer (memblock::data())); } + inline const_pointer c_str (void) const { return (string::const_pointer (memblock::cdata())); } + inline size_type max_size (void) const { size_type s (memblock::max_size()); return (s - !!s); } + inline size_type capacity (void) const { size_type c (memblock::capacity()); return (c - !!c); } + void resize (size_type n); + inline void resize (size_type n, value_type c); + inline void clear (void) { resize (0); } + inline const_iterator begin (void) const { return (const_iterator (memblock::begin())); } + inline iterator begin (void) { return (iterator (memblock::begin())); } + inline const_iterator end (void) const { return (const_iterator (memblock::end())); } + inline iterator end (void) { return (iterator (memblock::end())); } + inline const_reverse_iterator rbegin (void) const { return (const_reverse_iterator (end())); } + inline reverse_iterator rbegin (void) { return (reverse_iterator (end())); } + inline const_reverse_iterator rend (void) const { return (const_reverse_iterator (begin())); } + inline reverse_iterator rend (void) { return (reverse_iterator (begin())); } + inline utf8_iterator utf8_begin (void) const { return (utf8_iterator (begin())); } + inline utf8_iterator utf8_end (void) const { return (utf8_iterator (end())); } + inline const_reference at (uoff_t pos) const { assert (pos <= size() && begin()); return (begin()[pos]); } + inline reference at (uoff_t pos) { assert (pos <= size() && begin()); return (begin()[pos]); } + inline const_iterator iat (uoff_t pos) const { return (begin() + min (pos, size())); } + inline iterator iat (uoff_t pos) { return (begin() + min (pos, size())); } + const_iterator wiat (uoff_t i) const; + inline iterator wiat (uoff_t i) { return (const_cast<iterator>(const_cast<const string*>(this)->wiat(i))); } + inline const_reference back (void) const { return (at(size()-1)); } + inline reference back (void) { return (at(size()-1)); } + inline size_type length (void) const { return (distance (utf8_begin(), utf8_end())); } + inline void append (const_iterator i1, const_iterator i2) { append (i1, distance (i1, i2)); } + void append (const_pointer s, size_type len); + void append (const_pointer s); + void append (size_type n, const_reference c); + inline void append (size_type n, wvalue_type c) { insert (size(), c, n); } + inline void append (const_wpointer s1, const_wpointer s2) { insert (size(), s1, s2); } + inline void append (const_wpointer s) { const_wpointer se (s); for (;se&&*se;++se) ; append (s, se); } + inline void append (const string& s) { append (s.begin(), s.end()); } + inline void append (const string& s, uoff_t o, size_type n) { append (s.iat(o), s.iat(o+n)); } + inline void assign (const_iterator i1, const_iterator i2) { assign (i1, distance (i1, i2)); } + void assign (const_pointer s, size_type len); + void assign (const_pointer s); + inline void assign (const_wpointer s1, const_wpointer s2) { clear(); append (s1, s2); } + inline void assign (const_wpointer s1) { clear(); append (s1); } + inline void assign (const string& s) { assign (s.begin(), s.end()); } + inline void assign (const string& s, uoff_t o, size_type n) { assign (s.iat(o), s.iat(o+n)); } + size_type copyto (pointer p, size_type n, const_iterator start = NULL) const; + inline int compare (const string& s) const { return (compare (begin(), end(), s.begin(), s.end())); } + inline int compare (const_pointer s) const { return (compare (begin(), end(), s, s + strlen(s))); } + static int compare (const_iterator first1, const_iterator last1, const_iterator first2, const_iterator last2); + inline operator const value_type* (void) const; + inline operator value_type* (void); + inline const string& operator= (const string& s) { assign (s.begin(), s.end()); return (*this); } + inline const string& operator= (const_reference c) { assign (&c, 1); return (*this); } + inline const string& operator= (const_pointer s) { assign (s); return (*this); } + inline const string& operator= (const_wpointer s) { assign (s); return (*this); } + inline const string& operator+= (const string& s) { append (s.begin(), s.size()); return (*this); } + inline const string& operator+= (const_reference c) { append (1, c); return (*this); } + inline const string& operator+= (const_pointer s) { append (s); return (*this); } + inline const string& operator+= (wvalue_type c) { append (1, c); return (*this); } + inline const string& operator+= (const_wpointer s) { append (s); return (*this); } + inline string operator+ (const string& s) const; + inline bool operator== (const string& s) const { return (memblock::operator== (s)); } + bool operator== (const_pointer s) const; + inline bool operator== (const_reference c) const { return (size() == 1 && c == at(0)); } + inline bool operator!= (const string& s) const { return (!operator== (s)); } + inline bool operator!= (const_pointer s) const { return (!operator== (s)); } + inline bool operator!= (const_reference c) const { return (!operator== (c)); } + inline bool operator< (const string& s) const { return (0 > compare (s)); } + inline bool operator< (const_pointer s) const { return (0 > compare (s)); } + inline bool operator< (const_reference c) const { return (0 > compare (begin(), end(), &c, &c + 1)); } + inline bool operator> (const_pointer s) const { return (0 < compare (s)); } + void insert (const uoff_t ip, wvalue_type c, size_type n = 1); + void insert (const uoff_t ip, const_wpointer first, const_wpointer last, const size_type n = 1); + iterator insert (iterator start, const_reference c, size_type n = 1); + iterator insert (iterator start, const_pointer s, size_type n = 1); + iterator insert (iterator start, const_pointer first, const_iterator last, size_type n = 1); + inline void insert (uoff_t ip, const_pointer s, size_type nlen) { insert (iat(ip), s, s + nlen); } + inline void insert (uoff_t ip, size_type n, value_type c) { insert (iat(ip), c, n); } + inline void insert (uoff_t ip, const string& s, uoff_t sp, size_type slen) { insert (iat(ip), s.iat(sp), s.iat(sp + slen)); } + iterator erase (iterator epo, size_type n = 1); + void erase (uoff_t epo, size_type n = 1); + inline iterator erase (iterator first, const_iterator last) { return (erase (first, size_type(distance(first,last)))); } + inline void eraser (uoff_t first, uoff_t last) { erase (iat(first), iat(last)); } + inline void push_back (const_reference c) { append (1, c); } + inline void push_back (wvalue_type c) { append (1, c); } + inline void pop_back (void) { resize (size() - 1); } + void replace (iterator first, iterator last, const_pointer s); + void replace (iterator first, iterator last, const_pointer i1, const_pointer i2, size_type n = 1); + inline void replace (iterator first, iterator last, const string& s) { replace (first, last, s.begin(), s.end()); } + inline void replace (iterator first, iterator last, const_pointer s, size_type slen) { replace (first, last, s, s + slen); } + inline void replace (iterator first, iterator last, size_type n, value_type c) { replace (first, last, &c, &c + 1, n); } + inline void replace (uoff_t rp, size_type n, const string& s) { replace (iat(rp), iat(rp + n), s); } + inline void replace (uoff_t rp, size_type n, const string& s, uoff_t sp, size_type slen) { replace (iat(rp), iat(rp + n), s.iat(sp), s.iat(sp + slen)); } + inline void replace (uoff_t rp, size_type n, const_pointer s, size_type slen) { replace (iat(rp), iat(rp + n), s, s + slen); } + inline void replace (uoff_t rp, size_type n, const_pointer s) { replace (iat(rp), iat(rp + n), string(s)); } + inline void replace (uoff_t rp, size_type n, size_type count, value_type c) { replace (iat(rp), iat(rp + n), count, c); } + inline string substr (uoff_t o, size_type n = npos) const { return (string (*this, o, n)); } + uoff_t find (const_reference c, uoff_t pos = 0) const; + uoff_t find (const string& s, uoff_t pos = 0) const; + uoff_t rfind (const_reference c, uoff_t pos = npos) const; + uoff_t rfind (const string& s, uoff_t pos = npos) const; + uoff_t find_first_of (const string& s, uoff_t pos = 0) const; + uoff_t find_first_not_of (const string& s, uoff_t pos = 0) const; + uoff_t find_last_of (const string& s, uoff_t pos = npos) const; + uoff_t find_last_not_of (const string& s, uoff_t pos = npos) const; + int vformat (const char* fmt, va_list args); + int format (const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))); + void read (istream&); + void write (ostream& os) const; + size_t stream_size (void) const; + static hashvalue_t hash (const char* f1, const char* l1); +protected: + virtual size_type minimumFreeCapacity (void) const throw() __attribute__((const)); +}; + +//---------------------------------------------------------------------- + +/// Assigns itself the value of string \p s +inline string::string (const cmemlink& s) +: memblock () +{ + assign (const_iterator (s.begin()), s.size()); +} + +/// Assigns itself a [o,o+n) substring of \p s. +inline string::string (const string& s, uoff_t o, size_type n) +: memblock() +{ + assign (s, o, n); +} + +/// Copies the value of \p s of length \p len into itself. +inline string::string (const_pointer s, size_type len) +: memblock () +{ + assign (s, len); +} + +/// Copies into itself the string data between \p s1 and \p s2 +inline string::string (const_pointer s1, const_pointer s2) +: memblock () +{ + assert (s1 <= s2 && "Negative ranges result in memory allocation errors."); + assign (s1, s2); +} + +/// Returns the pointer to the first character. +inline string::operator const string::value_type* (void) const +{ + assert ((!end() || !*end()) && "This string is linked to data that is not 0-terminated. This may cause serious security problems. Please assign the data instead of linking."); + return (begin()); +} + +/// Returns the pointer to the first character. +inline string::operator string::value_type* (void) +{ + assert ((end() && !*end()) && "This string is linked to data that is not 0-terminated. This may cause serious security problems. Please assign the data instead of linking."); + return (begin()); +} + +/// Concatenates itself with \p s +inline string string::operator+ (const string& s) const +{ + string result (*this); + result += s; + return (result); +} + +/// Resize to \p n and fill new entries with \p c +inline void string::resize (size_type n, value_type c) +{ + const size_type oldn = size(); + resize (n); + fill_n (iat(oldn), max(ssize_t(n-oldn),0), c); +} + +//---------------------------------------------------------------------- +// Operators needed to avoid comparing pointer to pointer + +#define PTR_STRING_CMP(op, impl) \ +inline bool op (const char* s1, const string& s2) { return impl; } +PTR_STRING_CMP (operator==, (s2 == s1)) +PTR_STRING_CMP (operator!=, (s2 != s1)) +PTR_STRING_CMP (operator<, (s2 > s1)) +PTR_STRING_CMP (operator<=, (s2 >= s1)) +PTR_STRING_CMP (operator>, (s2 < s1)) +PTR_STRING_CMP (operator>=, (s2 <= s1)) +#undef PTR_STRING_CMP + +//---------------------------------------------------------------------- + +inline hashvalue_t hash_value (const char* first, const char* last) +{ return (string::hash (first, last)); } +inline hashvalue_t hash_value (const char* v) +{ return (hash_value (v, v + strlen(v))); } + +//---------------------------------------------------------------------- + +} // namespace ustl + +// Specialization for stream alignment +ALIGNOF (ustl::string, alignof (string::value_type())) + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/utf8.h @@ -0,0 +1,215 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. +// +// This file contains stream iterators that read and write UTF-8 encoded +// characters. The encoding is defined as follows: +// +// U-00000000 - U-0000007F: 0xxxxxxx +// U-00000080 - U-000007FF: 110xxxxx 10xxxxxx +// U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx +// U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx +// U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx +// U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx +// U-80000000 - U-FFFFFFFF: 11111110 100000xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + +#ifndef UTF8_H_3D7AEEEB3A88928D4D280B785F78B6F4 +#define UTF8_H_3D7AEEEB3A88928D4D280B785F78B6F4 + +#include "uiterator.h" + +namespace ustl { + +//---------------------------------------------------------------------- + +typedef uint8_t utf8subchar_t; ///< Type for the encoding subcharacters. + +//---------------------------------------------------------------------- + +inline size_t Utf8Bytes (wchar_t v) __attribute__((const)); +inline size_t Utf8Bytes (const wchar_t* first, const wchar_t* last) __attribute__((pure)); +inline size_t Utf8SequenceBytes (wchar_t c) __attribute__((const)); + +//---------------------------------------------------------------------- + +/// Returns the number of bytes required to UTF-8 encode \p v. +inline size_t Utf8Bytes (wchar_t v) +{ + if ((uint32_t) v < 128) + return (1); + size_t n; + #if __i386__ || __x86_64__ + uint32_t r = 0; + asm ("bsr\t%2, %%eax\n\t" + "add\t$4, %0\n\t" + "div\t%3":"=a"(n),"+d"(r):"r"(v),"c"(5)); + #else + static const uint32_t c_Bounds[7] = { 0x0000007F, 0x000007FF, 0x0000FFFF, 0x001FFFFF, 0x03FFFFFF, 0x7FFFFFFF, 0xFFFFFFFF }; + for (n = 0; c_Bounds[n++] < uint32_t(v);); + #endif + return (n); +} + +/// Measures the size of a wchar_t array in UTF-8 encoding. +inline size_t Utf8Bytes (const wchar_t* first, const wchar_t* last) +{ + size_t bc = 0; + for (; first < last; ++first) + bc += Utf8Bytes(*first); + return (bc); +} + +/// Returns the number of bytes in a UTF-8 sequence that starts with \p c. +inline size_t Utf8SequenceBytes (wchar_t c) // a wchar_t to keep c in a full register +{ + // Count the leading bits. Header bits are 1 * nBytes followed by a 0. + // 0 - single byte character. Take 7 bits (0xFF >> 1) + // 1 - error, in the middle of the character. Take 6 bits (0xFF >> 2) + // so you will keep reading invalid entries until you hit the next character. + // >2 - multibyte character. Take remaining bits, and get the next bytes. + // All errors are ignored, since the user can not correct them. + // + wchar_t mask = 0x80; + size_t nBytes = 0; + for (; c & mask; ++nBytes) + mask >>= 1; + return (nBytes ? nBytes : 1); // A sequence is always at least 1 byte. +} + +//---------------------------------------------------------------------- + +/// \class utf8in_iterator utf8.h ustl.h +/// \ingroup IteratorAdaptors +/// +/// \brief An iterator adaptor to character containers for reading UTF-8 encoded text. +/// +/// For example, you can copy from ustl::string to ustl::vector<wchar_t> with +/// copy (utf8in (str.begin()), utf8in (str.end()), back_inserter(wvect)); +/// There is no error handling; if the reading frame slips you'll get extra +/// characters, one for every misaligned byte. Although it is possible to skip +/// to the start of the next character, that would result in omitting the +/// misformatted character and the one after it, making it very difficult to +/// detect by the user. It is better to write some strange characters and let +/// the user know his file is corrupted. Another problem is overflow on bad +/// encodings (like a 0xFF on the end of a string). This is checked through +/// the end-of-string nul character, which will always be there as long as +/// you are using the string class. +/// +template <typename Iterator, typename WChar = wchar_t> +class utf8in_iterator { +public: + typedef typename iterator_traits<Iterator>::value_type value_type; + typedef typename iterator_traits<Iterator>::difference_type difference_type; + typedef typename iterator_traits<Iterator>::pointer pointer; + typedef typename iterator_traits<Iterator>::reference reference; +public: + explicit utf8in_iterator (const Iterator& is) : m_i (is), m_v (0) { Read(); } + utf8in_iterator (const utf8in_iterator& i) : m_i (i.m_i), m_v (i.m_v) {} + inline const utf8in_iterator& operator= (const utf8in_iterator& i) { m_i = i.m_i; m_v = i.m_v; return (*this); } + inline Iterator base (void) const { return (m_i - (Utf8Bytes(m_v) - 1)); } + /// Reads and returns the next value. + inline WChar operator* (void) const { return (m_v); } + inline utf8in_iterator& operator++ (void) { ++m_i; Read(); return (*this); } + inline utf8in_iterator operator++ (int) { utf8in_iterator old (*this); operator++(); return (old); } + inline utf8in_iterator& operator+= (uoff_t n) { while (n--) operator++(); return (*this); } + inline utf8in_iterator operator+ (uoff_t n) { utf8in_iterator v (*this); return (v += n); } + inline bool operator== (const utf8in_iterator& i) const { return (m_i == i.m_i); } + inline bool operator< (const utf8in_iterator& i) const { return (m_i < i.m_i); } + difference_type operator- (const utf8in_iterator& i) const; +private: + void Read (void); +private: + Iterator m_i; + WChar m_v; +}; + +/// Steps to the next character and updates current returnable value. +template <typename Iterator, typename WChar> +void utf8in_iterator<Iterator,WChar>::Read (void) +{ + const utf8subchar_t c = *m_i; + size_t nBytes = Utf8SequenceBytes (c); + m_v = c & (0xFF >> nBytes); // First byte contains bits after the header. + while (--nBytes && *++m_i) // Each subsequent byte has 6 bits. + m_v = (m_v << 6) | (*m_i & 0x3F); +} + +/// Returns the distance in characters (as opposed to the distance in bytes). +template <typename Iterator, typename WChar> +typename utf8in_iterator<Iterator,WChar>::difference_type +utf8in_iterator<Iterator,WChar>::operator- (const utf8in_iterator<Iterator,WChar>& last) const +{ + difference_type dist = 0; + for (Iterator first (last.m_i); first < m_i; ++dist) + first = advance (first, Utf8SequenceBytes (*first)); + return (dist); +} + +//---------------------------------------------------------------------- + +/// \class utf8out_iterator utf8.h ustl.h +/// \ingroup IteratorAdaptors +/// +/// \brief An iterator adaptor to character containers for writing UTF-8 encoded text. +/// +template <typename Iterator, typename WChar = wchar_t> +class utf8out_iterator { +public: + typedef typename iterator_traits<Iterator>::value_type value_type; + typedef typename iterator_traits<Iterator>::difference_type difference_type; + typedef typename iterator_traits<Iterator>::pointer pointer; + typedef typename iterator_traits<Iterator>::reference reference; +public: + explicit utf8out_iterator (const Iterator& os) : m_i (os) {} + utf8out_iterator (const utf8out_iterator& i) : m_i (i.m_i) {} + inline const Iterator& base (void) const { return (m_i); } + /// Writes \p v into the stream. + utf8out_iterator& operator= (WChar v); + inline utf8out_iterator& operator* (void) { return (*this); } + inline utf8out_iterator& operator++ (void) { return (*this); } + inline utf8out_iterator operator++ (int) { return (*this); } + inline bool operator== (const utf8out_iterator& i) const { return (m_i == i.m_i); } + inline bool operator< (const utf8out_iterator& i) const { return (m_i < i.m_i); } +private: + Iterator m_i; +}; + +/// Writes \p v into the stream. +template <typename Iterator, typename WChar> +utf8out_iterator<Iterator,WChar>& utf8out_iterator<Iterator,WChar>::operator= (WChar v) +{ + const size_t nBytes = Utf8Bytes (v); + if (nBytes > 1) { + // Write the bits 6 bits at a time, except for the first one, + // which may be less than 6 bits. + register wchar_t shift = nBytes * 6; + *m_i++ = ((v >> (shift -= 6)) & 0x3F) | (0xFF << (8 - nBytes)); + while (shift) + *m_i++ = ((v >> (shift -= 6)) & 0x3F) | 0x80; + } else // If only one byte, there is no header. + *m_i++ = v; + return (*this); +} + +//---------------------------------------------------------------------- + +/// Returns a UTF-8 adaptor writing to \p i. Useful in conjuction with back_insert_iterator. +template <typename Iterator> +inline utf8out_iterator<Iterator> utf8out (Iterator i) +{ + return (utf8out_iterator<Iterator> (i)); +} + +/// Returns a UTF-8 adaptor reading from \p i. +template <typename Iterator> +inline utf8in_iterator<Iterator> utf8in (Iterator i) +{ + return (utf8in_iterator<Iterator> (i)); +} + +//---------------------------------------------------------------------- + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/utuple.h @@ -0,0 +1,332 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UTUPLE_H_7324ADEC49B397CA74A56F6050FD5A6B +#define UTUPLE_H_7324ADEC49B397CA74A56F6050FD5A6B + +#include "ualgo.h" +#include "metamac.h" + +namespace ustl { + +/// \class tuple utuple.h ustl.h +/// \ingroup Sequences +/// +/// \brief A fixed-size array of \p N \p Ts. +/// +template <size_t N, typename T> +class tuple { +public: + typedef T value_type; + typedef size_t size_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef pointer iterator; + typedef const_pointer const_iterator; + typedef ::ustl::reverse_iterator<iterator> reverse_iterator; + typedef ::ustl::reverse_iterator<const_iterator> const_reverse_iterator; + typedef pair<iterator,iterator> range_t; + typedef pair<const_iterator,const_iterator> const_range_t; +public: + template <typename T2> + inline tuple (const tuple<N,T2>& t); + inline tuple (const tuple<N,T>& t); + inline tuple (const_pointer v); + inline tuple (void); + explicit inline tuple (const_reference v0, const_reference v1 = T(), const_reference v2 = T(), const_reference v3 = T()); + inline iterator begin (void) { return (m_v); } + inline const_iterator begin (void) const { return (m_v); } + inline iterator end (void) { return (begin() + N); } + inline const_iterator end (void) const { return (begin() + N); } + inline size_type size (void) const { return (N); } + inline size_type max_size (void) const { return (N); } + inline bool empty (void) const { return (N == 0); } + inline const_reference at (size_type i) const { return (m_v[i]); } + inline reference at (size_type i) { return (m_v[i]); } + inline const_reference operator[] (size_type i) const { return (m_v[i]); } + inline reference operator[] (size_type i) { return (m_v[i]); } + template <typename T2> + inline const tuple& operator= (const tuple<N,T2>& src); + inline const tuple& operator= (const tuple<N,T>& src); + inline const tuple& operator+= (const_reference v) + { for (uoff_t i = 0; i < N; ++ i) m_v[i] += v; return (*this); } + inline const tuple& operator-= (const_reference v) + { for (uoff_t i = 0; i < N; ++ i) m_v[i] -= v; return (*this); } + inline const tuple& operator*= (const_reference v) + { for (uoff_t i = 0; i < N; ++ i) m_v[i] *= v; return (*this); } + inline const tuple& operator/= (const_reference v) + { for (uoff_t i = 0; i < N; ++ i) m_v[i] /= v; return (*this); } + inline const tuple operator+ (const_reference v) const + { tuple result; for (uoff_t i = 0; i < N; ++ i) result[i] = m_v[i] + v; return (result); } + inline const tuple operator- (const_reference v) const + { tuple result; for (uoff_t i = 0; i < N; ++ i) result[i] = m_v[i] - v; return (result); } + inline const tuple operator* (const_reference v) const + { tuple result; for (uoff_t i = 0; i < N; ++ i) result[i] = m_v[i] * v; return (result); } + inline const tuple operator/ (const_reference v) const + { tuple result; for (uoff_t i = 0; i < N; ++ i) result[i] = m_v[i] / v; return (result); } + inline void swap (tuple<N,T>& v) + { for (uoff_t i = 0; i < N; ++ i) ::ustl::swap (m_v[i], v.m_v[i]); } + inline void read (istream& is) { nr_container_read (is, *this); } + inline void write (ostream& os) const { nr_container_write (os, *this); } + inline void text_write (ostringstream& os) const { container_text_write (os, *this); } + inline size_t stream_size (void) const { return (nr_container_stream_size (*this)); } +private: + T m_v [N]; +}; + +} // namespace ustl + +#include "simd.h" + +namespace ustl { + +template <size_t N, typename T> +template <typename T2> +inline tuple<N,T>::tuple (const tuple<N,T2>& t) +{ simd::pconvert (t, *this, simd::fcast<T2,T>()); } + +template <size_t N, typename T> +inline tuple<N,T>::tuple (const tuple<N,T>& t) +{ simd::passign (t, *this); } + +template <size_t N, typename T> +inline tuple<N,T>::tuple (const_pointer v) +{ simd::ipassign (v, *this); } + +template <size_t N, typename T> +inline tuple<N,T>::tuple (void) +{ + const T v = T(); + if (N > 4 || !numeric_limits<T>::is_integral) + fill_n (m_v, N, v); + else { + m_v[0] = v; + if (N > 1) m_v[1] = v; + if (N > 2) m_v[2] = v; + if (N > 3) m_v[3] = v; + } +} + +template <size_t N, typename T> +inline tuple<N,T>::tuple (const_reference v0, const_reference v1, const_reference v2, const_reference v3) +{ + m_v[0] = v0; + if (N > 1) m_v[1] = v1; + if (N > 2) m_v[2] = v2; + if (N > 3) m_v[3] = v3; + if (N > 4) fill_n (m_v + 4, N - 4, T()); +} + +template <size_t N, typename T> +template <typename T2> +inline const tuple<N,T>& tuple<N,T>::operator= (const tuple<N,T2>& src) +{ simd::pconvert (src, *this, simd::fcast<T2,T>()); return (*this); } + +template <size_t N, typename T> +inline const tuple<N,T>& tuple<N,T>::operator= (const tuple<N,T>& src) +{ simd::passign (src, *this); return (*this); } + +template <size_t N, typename T1, typename T2> +inline bool operator== (const tuple<N,T1>& t1, const tuple<N,T2>& t2) +{ + for (uoff_t i = 0; i < N; ++ i) + if (t1[i] != t2[i]) + return (false); + return (true); +} + +template <size_t N, typename T1, typename T2> +inline bool operator< (const tuple<N,T1>& t1, const tuple<N,T2>& t2) +{ + for (uoff_t i = 0; i < N && t1[i] <= t2[i]; ++ i) + if (t1[i] < t2[i]) + return (true); + return (false); +} + +template <size_t N, typename T1, typename T2> +inline const tuple<N,T1>& operator+= (tuple<N,T1>& t1, const tuple<N,T2>& t2) + { for (uoff_t i = 0; i < N; ++ i) t1[i] = T1(t1[i] + t2[i]); return (t1); } + +template <size_t N, typename T1, typename T2> +inline const tuple<N,T1>& operator-= (tuple<N,T1>& t1, const tuple<N,T2>& t2) + { for (uoff_t i = 0; i < N; ++ i) t1[i] = T1(t1[i] - t2[i]); return (t1); } + +template <size_t N, typename T1, typename T2> +inline const tuple<N,T1>& operator*= (tuple<N,T1>& t1, const tuple<N,T2>& t2) + { for (uoff_t i = 0; i < N; ++ i) t1[i] = T1(t1[i] * t2[i]); return (t1); } + +template <size_t N, typename T1, typename T2> +inline const tuple<N,T1>& operator/= (tuple<N,T1>& t1, const tuple<N,T2>& t2) + { for (uoff_t i = 0; i < N; ++ i) t1[i] = T1(t1[i] / t2[i]); return (t1); } + +template <size_t N, typename T1, typename T2> +inline const tuple<N,T1> operator+ (const tuple<N,T1>& t1, const tuple<N,T2>& t2) +{ + tuple<N,T1> result; + for (uoff_t i = 0; i < N; ++ i) result[i] = T1(t1[i] + t2[i]); + return (result); +} + +template <size_t N, typename T1, typename T2> +inline const tuple<N,T1> operator- (const tuple<N,T1>& t1, const tuple<N,T2>& t2) +{ + tuple<N,T1> result; + for (uoff_t i = 0; i < N; ++ i) result[i] = T1(t1[i] - t2[i]); + return (result); +} + +template <size_t N, typename T1, typename T2> +inline const tuple<N,T1> operator* (const tuple<N,T1>& t1, const tuple<N,T2>& t2) +{ + tuple<N,T1> result; + for (uoff_t i = 0; i < N; ++ i) result[i] = T1(t1[i] * t2[i]); + return (result); +} + +template <size_t N, typename T1, typename T2> +inline const tuple<N,T1> operator/ (const tuple<N,T1>& t1, const tuple<N,T2>& t2) +{ + tuple<N,T1> result; + for (uoff_t i = 0; i < N; ++ i) result[i] = T1(t1[i] / t2[i]); + return (result); +} + +//---------------------------------------------------------------------- +// Define SIMD specializations for member functions. + +#if CPU_HAS_SSE +#define SSE_TUPLE_SPECS(n,type) \ +template <> inline tuple<n,type>::tuple (void) \ +{ asm("xorps %%xmm0, %%xmm0\n\tmovups %%xmm0, %0":"+m"(m_v[0])::"xmm0","memory"); } \ +template<> inline void tuple<n,type>::swap (tuple<n,type>& v) \ +{ \ + asm ("movups %0,%%xmm0\n\tmovups %1,%%xmm1\n\t" \ + "movups %%xmm0,%1\n\tmovups %%xmm1,%0" \ + : "+m"(m_v[0]), "+m"(v.m_v[0]) :: "xmm0","xmm1","memory"); \ +} +SSE_TUPLE_SPECS(4,float) +SSE_TUPLE_SPECS(4,int32_t) +SSE_TUPLE_SPECS(4,uint32_t) +#undef SSE_TUPLE_SPECS +#endif +#if SIZE_OF_LONG == 8 && __GNUC__ +#define LONG_TUPLE_SPECS(n,type) \ +template <> inline tuple<n,type>::tuple (void) \ +{ asm("":"+m"(m_v[0])::"memory"); \ + *noalias_cast<long*>(m_v) = 0; } \ +template<> inline void tuple<n,type>::swap (tuple<n,type>& v) \ +{ asm("":"+m"(m_v[0]),"+m"(v.m_v[0])::"memory"); \ + iter_swap (noalias_cast<long*>(m_v), noalias_cast<long*>(v.m_v)); \ + asm("":"+m"(m_v[0]),"+m"(v.m_v[0])::"memory"); \ +} +LONG_TUPLE_SPECS(2,float) +LONG_TUPLE_SPECS(4,int16_t) +LONG_TUPLE_SPECS(4,uint16_t) +LONG_TUPLE_SPECS(2,int32_t) +LONG_TUPLE_SPECS(2,uint32_t) +LONG_TUPLE_SPECS(8,int8_t) +LONG_TUPLE_SPECS(8,uint8_t) +#undef LONG_TUPLE_SPECS +#elif CPU_HAS_MMX +#define MMX_TUPLE_SPECS(n,type) \ +template <> inline tuple<n,type>::tuple (void) \ +{ asm ("pxor %%mm0, %%mm0\n\tmovq %%mm0, %0" \ + :"=m"(m_v[0])::"mm0","st","memory"); simd::reset_mmx(); } \ +template<> inline void tuple<n,type>::swap (tuple<n,type>& v) \ +{ asm ("movq %2,%%mm0\n\tmovq %3,%%mm1\n\t" \ + "movq %%mm0,%1\n\tmovq %%mm1,%0" \ + :"=m"(m_v[0]),"=m"(v.m_v[0]):"m"(m_v[0]),"m"(v.m_v[0]):"mm0","mm1","st","st(1)","memory"); \ + simd::reset_mmx(); \ +} +MMX_TUPLE_SPECS(2,float) +MMX_TUPLE_SPECS(4,int16_t) +MMX_TUPLE_SPECS(4,uint16_t) +MMX_TUPLE_SPECS(2,int32_t) +MMX_TUPLE_SPECS(2,uint32_t) +MMX_TUPLE_SPECS(8,int8_t) +MMX_TUPLE_SPECS(8,uint8_t) +#undef MMX_TUPLE_SPECS +#endif + +#if __i386__ || __x86_64__ +#define UINT32_TUPLE_SPECS(type,otype) \ +template <> inline tuple<2,type>::tuple (void) \ +{ asm("":"+m"(m_v[0]),"+m"(m_v[1])::"memory"); \ + *noalias_cast<uint32_t*>(m_v) = 0; \ + asm("":"+m"(m_v[0]),"+m"(m_v[1])::"memory"); }\ +template <> inline const tuple<2,type>& tuple<2,type>::operator= (const tuple<2,type>& v)\ +{ asm ("mov %3, %0" \ + :"=m"(*noalias_cast<uint32_t*>(m_v)),"=m"(m_v[0]),"=m"(m_v[1]) \ + :"r"(*noalias_cast<const uint32_t*>(v.begin())),"m"(v[0]),"m"(v[1]):"memory"); \ + return (*this); } \ +template <> template <> \ +inline const tuple<2,type>& tuple<2,type>::operator= (const tuple<2,otype>& v)\ +{ asm ("mov %3, %0" \ + :"=m"(*noalias_cast<uint32_t*>(m_v)),"=m"(m_v[0]),"=m"(m_v[1]) \ + :"r"(*noalias_cast<const uint32_t*>(v.begin())),"m"(v[0]),"m"(v[1]):"memory"); \ + return (*this); } \ +template <> inline tuple<2,type>::tuple (const tuple<2,type>& v) \ +{ operator= (v); } \ +template <> template <> \ +inline tuple<2,type>::tuple (const tuple<2,otype>& v) \ +{ operator= (v); } \ +template<> inline void tuple<2,type>::swap (tuple<2,type>& v) \ +{ asm(""::"m"(m_v[0]),"m"(m_v[1]),"m"(v.m_v[0]),"m"(v.m_v[1]):"memory");\ + iter_swap (noalias_cast<uint32_t*>(m_v), noalias_cast<uint32_t*>(v.m_v)); \ + asm("":"=m"(m_v[0]),"=m"(m_v[1]),"=m"(v.m_v[0]),"=m"(v.m_v[1])::"memory"); } \ +template <> inline const tuple<2,type>& operator+= (tuple<2,type>& t1, const tuple<2,type>& t2) \ + { t1[0] += t2[0]; t1[1] += t2[1]; return (t1); } \ +template <> inline const tuple<2,type>& operator-= (tuple<2,type>& t1, const tuple<2,type>& t2) \ + { t1[0] -= t2[0]; t1[1] -= t2[1]; return (t1); } \ +template <> inline const tuple<2,type> operator+ (const tuple<2,type>& t1, const tuple<2,type>& t2) \ + { return (tuple<2,type> (t1[0] + t2[0], t1[1] + t2[1])); } \ +template <> inline const tuple<2,type> operator- (const tuple<2,type>& t1, const tuple<2,type>& t2) \ + { return (tuple<2,type> (t1[0] - t2[0], t1[1] - t2[1])); } +UINT32_TUPLE_SPECS(int16_t,uint16_t) +UINT32_TUPLE_SPECS(uint16_t,int16_t) +#undef UINT32_TUPLE_SPECS +#endif + +#undef TUPLEV_R1 +#undef TUPLEV_R2 +#undef TUPLEV_W1 +#undef TUPLEV_W2 + +#define SIMD_TUPLE_PACKOP(N,T) \ +template <> inline const tuple<N,T>& operator+= (tuple<N,T>& t1, const tuple<N,T>& t2) \ + { simd::padd (t2, t1); return (t1); } \ +template <> inline const tuple<N,T>& operator-= (tuple<N,T>& t1, const tuple<N,T>& t2) \ + { simd::psub (t2, t1); return (t1); } \ +template <> inline const tuple<N,T>& operator*= (tuple<N,T>& t1, const tuple<N,T>& t2) \ + { simd::pmul (t2, t1); return (t1); } \ +template <> inline const tuple<N,T>& operator/= (tuple<N,T>& t1, const tuple<N,T>& t2) \ + { simd::pdiv (t2, t1); return (t1); } \ +template <> inline const tuple<N,T> operator+ (const tuple<N,T>& t1, const tuple<N,T>& t2) \ + { tuple<N,T> result (t1); simd::padd (t2, result); return (result); } \ +template <> inline const tuple<N,T> operator- (const tuple<N,T>& t1, const tuple<N,T>& t2) \ + { tuple<N,T> result (t1); simd::psub (t2, result); return (result); } \ +template <> inline const tuple<N,T> operator* (const tuple<N,T>& t1, const tuple<N,T>& t2) \ + { tuple<N,T> result (t1); simd::pmul (t2, result); return (result); } \ +template <> inline const tuple<N,T> operator/ (const tuple<N,T>& t1, const tuple<N,T>& t2) \ + { tuple<N,T> result (t1); simd::pdiv (t2, result); return (result); } +SIMD_TUPLE_PACKOP(4,float) +SIMD_TUPLE_PACKOP(2,float) +SIMD_TUPLE_PACKOP(2,double) +SIMD_TUPLE_PACKOP(4,int32_t) +SIMD_TUPLE_PACKOP(4,uint32_t) +SIMD_TUPLE_PACKOP(4,int16_t) +SIMD_TUPLE_PACKOP(4,uint16_t) +SIMD_TUPLE_PACKOP(2,int32_t) +SIMD_TUPLE_PACKOP(2,uint32_t) +SIMD_TUPLE_PACKOP(8,int8_t) +SIMD_TUPLE_PACKOP(8,uint8_t) +#undef SIMD_TUPLE_PACKOP + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/utypes.h @@ -0,0 +1,67 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UTYPES_H_118BBB3B50B7DBF22F5460C52E515C83 +#define UTYPES_H_118BBB3B50B7DBF22F5460C52E515C83 + +#include "config.h" +#ifndef STDC_HEADERS + #error "This library requires standard C and C++ headers to compile." +#endif +#ifndef STDUNIX_HEADERS + #error "This library compiles only on UNIX systems." +#endif +#define __STDC_LIMIT_MACROS // For WCHAR_MIN and WCHAR_MAX in stdint. +#define __STDC_CONSTANT_MACROS // For UINT??_C macros to avoid using L and UL suffixes on constants. +#if HAVE_STDINT_H + #include <stdint.h> +#elif HAVE_INTTYPES_H + #include <inttypes.h> +#else + #error "Need standard integer types definitions, usually in stdint.h" +#endif +#include <stddef.h> // For ptrdiff_t, size_t +#include <limits.h> +#include <float.h> +#if HAVE_SYS_TYPES_H + #include <sys/types.h> +#endif +#ifndef SIZE_MAX + #define SIZE_MAX UINT_MAX +#endif +#if sun || __sun // Solaris defines UINTPTR_MAX as empty. + #undef UINTPTR_MAX + #define UINTPTR_MAX ULONG_MAX +#endif +#ifndef WCHAR_MAX + #ifdef __WCHAR_MAX__ + #define WCHAR_MAX __WCHAR_MAX__ + #else + #define WCHAR_MAX CHAR_MAX + #endif +#endif +#if HAVE_LONG_LONG + #ifndef LLONG_MAX + #define ULLONG_MAX UINT64_C(0xFFFFFFFFFFFFFFFF) + #define LLONG_MAX INT64_C(0x7FFFFFFFFFFFFFFF) + #define LLONG_MIN ULLONG_MAX + #endif +#endif +#ifndef BYTE_ORDER + #define LITTLE_ENDIAN USTL_LITTLE_ENDIAN + #define BIG_ENDIAN USTL_BIG_ENDIAN + #define BYTE_ORDER USTL_BYTE_ORDER +#endif + +typedef size_t uoff_t; ///< A type for storing offsets into blocks measured by size_t. +typedef uint32_t hashvalue_t; ///< Value type returned by the hash functions. +typedef size_t streamsize; ///< Size of stream data +typedef uoff_t streamoff; ///< Offset into a stream + + +#if !defined(UINTPTR_MAX) || !defined(UINT32_C) + #error "If you include stdint.h before ustl.h, define __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS first" +#endif +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/uutility.h @@ -0,0 +1,383 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. +// +/// \file uutility.h +/// \brief Utility templates. + +#ifndef UUTILITY_H_6A58BD296269A82A4AAAA4FD19FDB3AC +#define UUTILITY_H_6A58BD296269A82A4AAAA4FD19FDB3AC + +#include "utypes.h" +#include "traits.h" +#include "ulimits.h" +#include <assert.h> + +namespace ustl { + +#ifdef __GNUC__ + /// Returns the number of elements in a static vector + #define VectorSize(v) (sizeof(v) / sizeof(*v)) +#else + // Old compilers will not be able to evaluate *v on an empty vector. + // The tradeoff here is that VectorSize will not be able to measure arrays of local structs. + #define VectorSize(v) (sizeof(v) / ustl::size_of_elements(1, v)) +#endif + +/// Expands into a ptr,size expression for the given static vector; useful as link arguments. +#define VectorBlock(v) (v)+0, VectorSize(v) // +0 makes it work under gcc 2.95 +/// Expands into a begin,end expression for the given static vector; useful for algorithm arguments. +#define VectorRange(v) VectorBlock(v)+(v) + +/// Indexes into a static array with bounds limit +#define VectorElement(v,i) v[min(uoff_t(i),uoff_t(VectorSize(v)-1))] + +/// Returns the number of bits in the given type +#define BitsInType(t) (sizeof(t) * CHAR_BIT) + +/// Returns the mask of type \p t with the lowest \p n bits set. +#define BitMask(t,n) (t(~t(0)) >> ((sizeof(t) * CHAR_BIT) - (n))) + +/// Argument that is used only in debug builds (as in an assert) +#ifndef NDEBUG + #define DebugArg(x) x +#else + #define DebugArg(x) +#endif + +/// Shorthand for container iteration. +#define foreach(type,i,ctr) for (type i = (ctr).begin(); i != (ctr).end(); ++ i) +/// Shorthand for container reverse iteration. +#define eachfor(type,i,ctr) for (type i = (ctr).rbegin(); i != (ctr).rend(); ++ i) + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +// Macro for passing template types as macro arguments. +// These are deprecated. Use metamac macros instead. Will remove by next release. +#define TEMPLATE_FULL_DECL1(d1,t1) template <d1 t1> +#define TEMPLATE_FULL_DECL2(d1,t1,d2,t2) template <d1 t1, d2 t2> +#define TEMPLATE_FULL_DECL3(d1,t1,d2,t2,d3,t3) template <d1 t1, d2 t2, d3 t3> +#define TEMPLATE_DECL1(t1) TEMPLATE_FULL_DECL1(typename,t1) +#define TEMPLATE_DECL2(t1,t2) TEMPLATE_FULL_DECL2(typename,t1,typename,t2) +#define TEMPLATE_DECL3(t1,t2,t3) TEMPLATE_FULL_DECL3(typename,t1,typename,t2,typename,t3) +#define TEMPLATE_TYPE1(type,a1) type<a1> +#define TEMPLATE_TYPE2(type,a1,a2) type<a1,a2> +#define TEMPLATE_TYPE3(type,a1,a2,a3) type<a1,a2,a3> +#endif + +/// Returns the minimum of \p a and \p b +template <typename T1, typename T2> +inline T1 min (const T1& a, const T2& b) +{ + return (a < b ? a : b); +} + +/// Returns the maximum of \p a and \p b +template <typename T1, typename T2> +inline T1 max (const T1& a, const T2& b) +{ + return (b < a ? a : b); +} + +/// The alignment performed by default. +const size_t c_DefaultAlignment = __alignof__(void*); + +/// \brief Rounds \p n up to be divisible by \p grain +template <typename T> +inline T Align (T n, size_t grain = c_DefaultAlignment) +{ + n += grain - 1; + return (n - n % grain); +} + +/// Returns a NULL pointer cast to T. +template <typename T> +inline T* NullPointer (void) + { return ((T*) NULL); } + +/// \brief Returns a non-dereferentiable value reference. +/// This is useful for passing to alignof or the like which need a value but +/// don't need to actually use it. +template <typename T> +inline T& NullValue (void) + { return (*NullPointer<T>()); } + +/// Offsets an iterator +template <typename T> +inline T advance (T i, ssize_t offset) +{ + return (i + offset); +} + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +/// Offsets a void pointer +template <> +inline const void* advance (const void* p, ssize_t offset) +{ + assert (p || !offset); + return (reinterpret_cast<const uint8_t*>(p) + offset); +} + +/// Offsets a void pointer +template <> +inline void* advance (void* p, ssize_t offset) +{ + assert (p || !offset); + return (reinterpret_cast<uint8_t*>(p) + offset); +} +#endif + +/// Returns the difference \p p1 - \p p2 +template <typename T1, typename T2> +inline ptrdiff_t distance (T1 i1, T2 i2) +{ + return (i2 - i1); +} + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +#define UNVOID_DISTANCE(T1const,T2const) \ +template <> inline ptrdiff_t distance (T1const void* p1, T2const void* p2) \ +{ return ((T2const uint8_t*)(p2) - (T1const uint8_t*)(p1)); } +UNVOID_DISTANCE(,) +UNVOID_DISTANCE(const,const) +UNVOID_DISTANCE(,const) +UNVOID_DISTANCE(const,) +#undef UNVOID_DISTANCE +#endif + +// The compiler issues a warning if an unsigned type is compared to 0. +template <typename T, bool IsSigned> struct __is_negative { inline bool operator()(const T& v) { return (v < 0); } }; +template <typename T> struct __is_negative<T,false> { inline bool operator()(const T&) { return (false); } }; +/// Warning-free way to check if \p v is negative, even if for unsigned types. +template <typename T> inline bool is_negative (const T& v) { return (__is_negative<T,numeric_limits<T>::is_signed>()(v)); } + +/// \brief Returns the absolute value of \p v +/// Unlike the stdlib functions, this is inline and works with all types. +template <typename T> +inline T absv (T v) +{ + return (is_negative(v) ? -v : v); +} + +/// \brief Returns -1 for negative values, 1 for positive, and 0 for 0 +template <typename T> +inline T sign (T v) +{ + return ((0 < v) - is_negative(v)); +} + +/// Returns the absolute value of the distance i1 and i2 +template <typename T1, typename T2> +inline size_t abs_distance (T1 i1, T2 i2) +{ + return (absv (distance(i1, i2))); +} + +/// Returns the size of \p n elements of size \p T +template <typename T> +inline size_t size_of_elements (size_t n, const T*) +{ + return (n * sizeof(T)); +} + +// Defined in byteswap.h, which is usually unusable. +#undef bswap_16 +#undef bswap_32 +#undef bswap_64 + +inline uint16_t bswap_16 (uint16_t v) +{ +#if CPU_HAS_CMPXCHG8 // If it has that, it has bswap. + if (!__builtin_constant_p(v)) asm ("rorw $8, %0":"+r"(v)); else +#endif + v = v << 8 | v >> 8; + return (v); +} +inline uint32_t bswap_32 (uint32_t v) +{ +#if CPU_HAS_CMPXCHG8 + if (!__builtin_constant_p(v)) asm ("bswap %0":"+r"(v)); else +#endif + v = v << 24 | (v & 0xFF00) << 8 | ((v >> 8) & 0xFF00) | v >> 24; + return (v); +} +#if HAVE_INT64_T +inline uint64_t bswap_64 (uint64_t v) +{ +#if x86_64 + if (!__builtin_constant_p(v)) asm ("bswap %0":"+r"(v)); else +#endif + v = (uint64_t(bswap_32(v)) << 32) | bswap_32(v >> 32); + return (v); +} +#endif + +/// \brief Swaps the byteorder of \p v. +template <typename T> +inline T bswap (const T& v) +{ + switch (BitsInType(T)) { + default: return (v); + case 16: return (T (bswap_16 (uint16_t (v)))); + case 32: return (T (bswap_32 (uint32_t (v)))); +#if HAVE_INT64_T + case 64: return (T (bswap_64 (uint64_t (v)))); +#endif + } +} + +#if BYTE_ORDER == BIG_ENDIAN +template <typename T> inline T le_to_native (const T& v) { return (bswap (v)); } +template <typename T> inline T be_to_native (const T& v) { return (v); } +template <typename T> inline T native_to_le (const T& v) { return (bswap (v)); } +template <typename T> inline T native_to_be (const T& v) { return (v); } +#elif BYTE_ORDER == LITTLE_ENDIAN +template <typename T> inline T le_to_native (const T& v) { return (v); } +template <typename T> inline T be_to_native (const T& v) { return (bswap (v)); } +template <typename T> inline T native_to_le (const T& v) { return (v); } +template <typename T> inline T native_to_be (const T& v) { return (bswap (v)); } +#endif // BYTE_ORDER + +/// Deletes \p p and sets it to NULL +template <typename T> +inline void Delete (T*& p) +{ + delete p; + p = NULL; +} + +/// Deletes \p p as an array and sets it to NULL +template <typename T> +inline void DeleteVector (T*& p) +{ + delete [] p; + p = NULL; +} + +/// Template of making != from ! and == +template <typename T> +inline bool operator!= (const T& x, const T& y) +{ + return (!(x == y)); +} + +/// Template of making > from < +template <typename T> +inline bool operator> (const T& x, const T& y) +{ + return (y < x); +} + +/// Template of making <= from < and == +template <typename T> +inline bool operator<= (const T& x, const T& y) +{ + return (!(y < x)); +} + +/// Template of making >= from < and == +template <typename T> +inline bool operator>= (const T& x, const T& y) +{ + return (!(x < y)); +} + +/// Packs \p s multiple times into \p b. Useful for loop unrolling. +template <typename TSmall, typename TBig> +inline void pack_type (TSmall s, TBig& b) +{ + const size_t n = sizeof(TBig) / sizeof(TSmall); + b = s; + // Calls to min are here to avoid warnings for shifts bigger than the type. min will be gone when optimized. + if (n < 2) return; + b = (b << min (BitsInType(TSmall), BitsInType(TBig))) | b; + if (n < 4) return; + b = (b << min (BitsInType(TSmall) * 2, BitsInType(TBig))) | b; + if (n < 8) return; + b = (b << min (BitsInType(TSmall) * 4, BitsInType(TBig))) | b; +} + +/// \brief Divides \p n1 by \p n2 and rounds the result up. +/// This is in contrast to regular division, which rounds down. +template <typename T1, typename T2> +inline T1 DivRU (T1 n1, T2 n2) +{ + T2 adj = n2 - 1; + if (is_negative (n1)) + adj = -adj; + return ((n1 + adj) / n2); +} + +#if __GNUC__ >= 3 +inline bool TestAndSet (int* pm) INLINE; +#endif +/// Sets the contents of \p pm to 1 and returns true if the previous value was 0. +inline bool TestAndSet (int* pm) +{ +#if CPU_HAS_CMPXCHG8 + bool rv; + int oldVal (1); + asm volatile ( // cmpxchg compares to %eax and swaps if equal + "cmpxchgl %3, %1\n\t" + "sete %0" + : "=a" (rv), "=m" (*pm), "=r" (oldVal) + : "2" (oldVal), "a" (0) + : "memory"); + return (rv); +#elif __i386__ || __x86_64__ + int oldVal (1); + asm volatile ("xchgl %0, %1" : "=r"(oldVal), "=m"(*pm) : "0"(oldVal), "m"(*pm) : "memory"); + return (!oldVal); +#elif __sparc32__ // This has not been tested + int rv; + asm volatile ("ldstub %1, %0" : "=r"(rv), "=m"(*pm) : "m"(pm)); + return (!rv); +#else + const int oldVal (*pm); + *pm = 1; + return (!oldVal); +#endif +} + +/// \brief This template is to be used for dereferencing a type-punned pointer without a warning. +/// +/// When casting a local variable to an unrelated type through a pointer (for +/// example, casting a float to a uint32_t without conversion), the resulting +/// memory location can be accessed through either pointer, which violates the +/// strict aliasing rule. While -fno-strict-aliasing option can be given to +/// the compiler, eliminating this warning, inefficient code may result in +/// some instances, because aliasing inhibits some optimizations. By using +/// this template, and by ensuring the memory is accessed in one way only, +/// efficient code can be produced without the warning. For gcc 4.1.0+. +/// +template <typename DEST, typename SRC> +inline DEST noalias (const DEST&, SRC* s) +{ + asm("":"+g"(s)::"memory"); + union UPun { SRC s; DEST d; }; + return (((UPun*)(s))->d); +} + +template <typename DEST, typename SRC> +inline DEST noalias_cast (SRC s) +{ + asm("":"+g"(s)::"memory"); + union { SRC s; DEST d; } u = {s}; + return (u.d); +} + +namespace simd { + /// Call after you are done using SIMD algorithms for 64 bit tuples. + inline void reset_mmx (void) INLINE; + #define ALL_MMX_REGS_CHANGELIST "mm0","mm1","mm2","mm3","mm4","mm5","mm6","mm7","st","st(1)","st(2)","st(3)","st(4)","st(5)","st(6)","st(7)" +#if CPU_HAS_3DNOW + inline void reset_mmx (void) { asm ("femms":::ALL_MMX_REGS_CHANGELIST); } +#elif CPU_HAS_MMX + inline void reset_mmx (void) { asm ("emms":::ALL_MMX_REGS_CHANGELIST); } +#else + inline void reset_mmx (void) {} +#endif +} // namespace simd +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/include/uvector.h @@ -0,0 +1,272 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef UVECTOR_H_00BB13AF082BEB7829C031B265518169 +#define UVECTOR_H_00BB13AF082BEB7829C031B265518169 + +#include "memblock.h" +#include "umemory.h" + +namespace ustl { + +/// \class vector uvector.h ustl.h +/// \ingroup Sequences +/// +/// \brief STL vector equivalent. +/// +/// Provides a typed array-like interface to a managed memory block, including +/// element access, iteration, modification, resizing, and serialization. In +/// this design elements frequently undergo bitwise move, so don't put it in +/// here if it doesn't support it. This mostly means having no self-pointers. +/// +template <typename T> +class vector { +public: + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef pointer iterator; + typedef const_pointer const_iterator; + typedef memblock::size_type size_type; + typedef memblock::written_size_type written_size_type; + typedef memblock::difference_type difference_type; + typedef ::ustl::reverse_iterator<iterator> reverse_iterator; + typedef ::ustl::reverse_iterator<const_iterator> const_reverse_iterator; +public: + inline vector (void); + inline explicit vector (size_type n); + vector (size_type n, const T& v); + vector (const vector<T>& v); + vector (const_iterator i1, const_iterator i2); + inline ~vector (void) throw(); + inline const vector<T>& operator= (const vector<T>& v); + inline bool operator== (const vector<T>& v) const { return (m_Data == v.m_Data); } + inline operator cmemlink (void) const { return (cmemlink (m_Data)); } + inline operator cmemlink (void) { return (cmemlink (m_Data)); } + inline operator memlink (void) { return (memlink (m_Data)); } + inline void reserve (size_type n, bool bExact = true); + inline void resize (size_type n, bool bExact = true); + inline size_type capacity (void) const { return (m_Data.capacity() / sizeof(T)); } + inline size_type size (void) const { return (m_Data.size() / sizeof(T)); } + inline size_type max_size (void) const { return (m_Data.max_size() / sizeof(T)); } + inline bool empty (void) const { return (m_Data.empty()); } + inline iterator begin (void) { return (iterator (m_Data.begin())); } + inline const_iterator begin (void) const { return (const_iterator (m_Data.begin())); } + inline iterator end (void) { return (iterator (m_Data.end())); } + inline const_iterator end (void) const { return (const_iterator (m_Data.end())); } + inline reverse_iterator rbegin (void) { return (reverse_iterator (end())); } + inline const_reverse_iterator rbegin (void) const { return (const_reverse_iterator (end())); } + inline reverse_iterator rend (void) { return (reverse_iterator (begin())); } + inline const_reverse_iterator rend (void) const { return (const_reverse_iterator (begin())); } + inline iterator iat (size_type i) { assert (i <= size()); return (begin() + i); } + inline const_iterator iat (size_type i) const { assert (i <= size()); return (begin() + i); } + inline reference at (size_type i) { assert (i < size()); return (begin()[i]); } + inline const_reference at (size_type i) const { assert (i < size()); return (begin()[i]); } + inline reference operator[] (size_type i) { return (at (i)); } + inline const_reference operator[] (size_type i) const { return (at (i)); } + inline reference front (void) { return (at(0)); } + inline const_reference front (void) const { return (at(0)); } + inline reference back (void) { assert (!empty()); return (end()[-1]); } + inline const_reference back (void) const { assert (!empty()); return (end()[-1]); } + inline void push_back (const T& v = T()); + inline void pop_back (void) { m_Data.memlink::resize (m_Data.size() - sizeof(T)); } + inline void clear (void) { m_Data.clear(); } + inline void deallocate (void) throw(); + inline void assign (const_iterator i1, const_iterator i2); + inline void assign (size_type n, const T& v); + inline void swap (vector<T>& v) { m_Data.swap (v.m_Data); } + inline iterator insert (iterator ip, const T& v = T()); + inline iterator insert (iterator ip, size_type n, const T& v); + inline iterator insert (iterator ip, const_iterator i1, const_iterator i2); + inline iterator erase (iterator ep, size_type n = 1); + inline iterator erase (iterator ep1, iterator ep2); + inline void manage (pointer p, size_type n) { m_Data.manage (p, n * sizeof(T)); } + inline bool is_linked (void) const { return (m_Data.is_linked()); } + inline void unlink (void) { m_Data.unlink(); } + inline void copy_link (void) { m_Data.copy_link(); } + inline void link (const_pointer p, size_type n) { m_Data.link (p, n * sizeof(T)); } + inline void link (pointer p, size_type n) { m_Data.link (p, n * sizeof(T)); } + inline void link (const vector<T>& v) { m_Data.link (v); } + inline void link (vector<T>& v) { m_Data.link (v); } + inline void link (const_pointer first, const_pointer last) { m_Data.link (first, last); } + inline void link (pointer first, pointer last) { m_Data.link (first, last); } + inline void read (istream& is) { container_read (is, *this); } + inline void write (ostream& os) const { container_write (os, *this); } + inline void text_write (ostringstream& os) const { container_text_write (os, *this); } + inline size_t stream_size (void) const { return (container_stream_size (*this)); } +private: + inline iterator insert_space (iterator ip, size_type n); +private: + memblock m_Data; ///< Raw element data, consecutively stored. +}; + +/// Allocates space for at least \p n elements. +template <typename T> +inline void vector<T>::reserve (size_type n, bool bExact) +{ + const size_type oldCapacity = m_Data.capacity() - m_Data.capacity() % sizeof(T); + m_Data.reserve (n * sizeof(T), bExact); + construct (iterator (m_Data.begin() + oldCapacity), iterator (m_Data.begin() + m_Data.capacity())); +} + +/// Resizes the vector to contain \p n elements. +template <typename T> +inline void vector<T>::resize (size_type n, bool bExact) +{ + const size_type nb = n * sizeof(T); + if (m_Data.capacity() < nb) + reserve (n, bExact); + m_Data.memlink::resize (nb); +} + +/// Calls element destructors and frees storage. +template <typename T> +inline void vector<T>::deallocate (void) throw() +{ + destroy (begin(), iterator (m_Data.begin() + m_Data.capacity())); + m_Data.deallocate(); +} + +/// Initializes empty vector. +template <typename T> +inline vector<T>::vector (void) +: m_Data () +{ +} + +/// Initializes a vector of size \p n. +template <typename T> +inline vector<T>::vector (size_type n) +: m_Data () +{ + resize (n); +} + +/// Copies \p n elements from \p v. +template <typename T> +vector<T>::vector (size_type n, const T& v) +: m_Data () +{ + resize (n); + ::ustl::fill (begin(), end(), v); +} + +/// Copies \p v. +template <typename T> +vector<T>::vector (const vector<T>& v) +: m_Data () +{ + resize (v.size()); + ::ustl::copy (v.begin(), v.end(), begin()); +} + +/// Copies range [\p i1, \p i2] +template <typename T> +vector<T>::vector (const_iterator i1, const_iterator i2) +: m_Data () +{ + resize (distance (i1, i2)); + ::ustl::copy (i1, i2, begin()); +} + +/// Destructor +template <typename T> +inline vector<T>::~vector (void) throw() +{ + destroy (begin(), iterator (m_Data.begin() + m_Data.capacity())); +} + +/// Copies the range [\p i1, \p i2] +template <typename T> +inline void vector<T>::assign (const_iterator i1, const_iterator i2) +{ + assert (i1 <= i2); + resize (distance (i1, i2)); + ::ustl::copy (i1, i2, begin()); +} + +/// Copies \p n elements with value \p v. +template <typename T> +inline void vector<T>::assign (size_type n, const T& v) +{ + resize (n); + ::ustl::fill (begin(), end(), v); +} + +/// Copies contents of \p v. +template <typename T> +inline const vector<T>& vector<T>::operator= (const vector<T>& v) +{ + assign (v.begin(), v.end()); + return (*this); +} + +/// Inserts \p n uninitialized elements at \p ip. +template <typename T> +inline typename vector<T>::iterator vector<T>::insert_space (iterator ip, size_type n) +{ + const uoff_t ipmi = distance (m_Data.begin(), memblock::iterator(ip)); + reserve (size() + n, false); + return (iterator (m_Data.insert (m_Data.iat(ipmi), n * sizeof(T)))); +} + +/// Inserts \p n elements with value \p v at offsets \p ip. +template <typename T> +inline typename vector<T>::iterator vector<T>::insert (iterator ip, size_type n, const T& v) +{ + ip = insert_space (ip, n); + ::ustl::fill (ip, ip + n, v); + return (ip); +} + +/// Inserts value \p v at offset \p ip. +template <typename T> +inline typename vector<T>::iterator vector<T>::insert (iterator ip, const T& v) +{ + *(ip = insert_space (ip, 1)) = v; + return (ip); +} + +/// Inserts range [\p i1, \p i2] at offset \p ip. +template <typename T> +inline typename vector<T>::iterator vector<T>::insert (iterator ip, const_iterator i1, const_iterator i2) +{ + assert (i1 <= i2); + ip = insert_space (ip, distance (i1, i2)); + ::ustl::copy (i1, i2, ip); + return (ip); +} + +/// Removes \p count elements at offset \p ep. +template <typename T> +inline typename vector<T>::iterator vector<T>::erase (iterator ep, size_type n) +{ + return (iterator (m_Data.erase (memblock::iterator(ep), n * sizeof(T)))); +} + +/// Removes elements from \p ep1 to \p ep2. +template <typename T> +inline typename vector<T>::iterator vector<T>::erase (iterator ep1, iterator ep2) +{ + assert (ep1 <= ep2); + return (erase (ep1, distance(ep1, ep2))); +} + +/// Inserts value \p v at the end of the vector. +template <typename T> +inline void vector<T>::push_back (const T& v) +{ + resize (size() + 1, false); + back() = v; +} + +/// Use with vector classes to allocate and link to stack space. \p n is in elements. +#define typed_alloca_link(m,T,n) (m).link ((T*) alloca ((n) * sizeof(T)), (n)) + +} // namespace ustl + +#endif
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/src/bktrace.cpp @@ -0,0 +1,141 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2006-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "bktrace.h" +#include "sostream.h" +#include "mistream.h" +#if linux && __GNUC__ + #include <execinfo.h> +#else + static inline int backtrace (void**, int) { return (0); } + static inline char** backtrace_symbols (void* const*, int) { return (NULL); } +#endif + +namespace ustl { + +/// Default constructor. The backtrace is obtained here. +CBacktrace::CBacktrace (void) throw() +: m_Symbols (NULL), + m_nFrames (0), + m_SymbolsSize (0) +{ + m_nFrames = backtrace (VectorBlock (m_Addresses)); + GetSymbols(); +} + +/// Copy constructor. +CBacktrace::CBacktrace (const CBacktrace& v) throw() +: m_Symbols (NULL), + m_nFrames (0), + m_SymbolsSize (0) +{ + operator= (v); +} + +/// Copy operator. +const CBacktrace& CBacktrace::operator= (const CBacktrace& v) throw() +{ + memcpy (m_Addresses, v.m_Addresses, sizeof(m_Addresses)); + m_Symbols = strdup (v.m_Symbols); + m_nFrames = v.m_nFrames; + m_SymbolsSize = v.m_SymbolsSize; + return (*this); +} + +/// Converts a string returned by backtrace_symbols into readable form. +static size_t ExtractAbiName (const char* isym, char* nmbuf) throw() +{ + // Prepare the demangled name, if possible + size_t nmSize = 0; + if (isym) { + // Copy out the name; the strings are: "file(function+0x42) [0xAddress]" + const char* mnStart = strchr (isym, '('); + if (++mnStart == (const char*)(1)) + mnStart = isym; + const char* mnEnd = strchr (isym, '+'); + const char* isymEnd = isym + strlen (isym); + if (!mnEnd) + mnEnd = isymEnd; + nmSize = min (size_t (distance (mnStart, mnEnd)), 255U); + memcpy (nmbuf, mnStart, nmSize); + } + nmbuf[nmSize] = 0; + // Demangle + demangle_type_name (nmbuf, 255U, &nmSize); + return (nmSize); +} + +/// Tries to get symbol information for the addresses. +void CBacktrace::GetSymbols (void) throw() +{ + char** symbols = backtrace_symbols (m_Addresses, m_nFrames); + if (!symbols) + return; + char nmbuf [256]; + size_t symSize = 1; + for (uoff_t i = 0; i < m_nFrames; ++ i) + symSize += ExtractAbiName (symbols[i], nmbuf) + 1; + if ((m_Symbols = (char*) calloc (symSize, 1))) { + for (uoff_t i = 0; m_SymbolsSize < symSize - 1; ++ i) { + size_t sz = ExtractAbiName (symbols[i], nmbuf); + memcpy (m_Symbols + m_SymbolsSize, nmbuf, sz); + m_SymbolsSize += sz + 1; + m_Symbols [m_SymbolsSize - 1] = '\n'; + } + } + free (symbols); +} + +#if SIZE_OF_LONG == 8 + #define ADDRESS_FMT "%16p " +#else + #define ADDRESS_FMT "%8p " +#endif + +/// Prints the backtrace to \p os. +void CBacktrace::text_write (ostringstream& os) const +{ + const char *ss = m_Symbols, *se; + for (uoff_t i = 0; i < m_nFrames; ++ i) { + os.format (ADDRESS_FMT, m_Addresses[i]); + se = strchr (ss, '\n') + 1; + os.write (ss, distance (ss, se)); + ss = se; + } +} + +/// Reads the object from stream \p is. +void CBacktrace::read (istream& is) +{ + assert (is.aligned (alignof (m_Addresses[0])) && "Backtrace object contains pointers and must be void* aligned"); + is >> m_nFrames >> m_SymbolsSize; + nfree (m_Symbols); + m_Symbols = (char*) malloc (m_SymbolsSize + 1); + is.read (m_Symbols, m_SymbolsSize); + m_Symbols [m_SymbolsSize] = 0; + is.align(); + is.read (m_Addresses, m_nFrames * sizeof(void*)); +} + +/// Writes the object to stream \p os. +void CBacktrace::write (ostream& os) const +{ + assert (os.aligned (alignof (m_Addresses[0])) && "Backtrace object contains pointers and must be void* aligned"); + os << m_nFrames << m_SymbolsSize; + os.write (m_Symbols, m_SymbolsSize); + os.align(); + os.write (m_Addresses, m_nFrames * sizeof(void*)); +} + +/// Returns the size of the written object. +size_t CBacktrace::stream_size (void) const +{ + return (Align (stream_size_of (m_nFrames) + + stream_size_of (m_SymbolsSize) + + m_nFrames * sizeof(void*) + + m_SymbolsSize)); +} + +} // namespace ustl
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/src/cmemlink.cpp @@ -0,0 +1,78 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "cmemlink.h" +#ifdef CYGCLS_USTL_FSTREAMS +#include "ofstream.h" +#else +#include "sostream.h" +#endif +#include "strmsize.h" +#include "ualgo.h" +#include "config.h" + +namespace ustl { + +/// \brief Attaches the object to pointer \p p of size \p n. +/// +/// If \p p is NULL and \p n is non-zero, bad_alloc is thrown and current +/// state remains unchanged. +/// +void cmemlink::link (const void* p, size_type n) +{ + if (!p && n) + USTL_THROW(bad_alloc (n)); + unlink(); + relink (p, n); +} + +void cmemlink::unlink (void) throw() +{ + m_Data = NULL; m_Size = 0; +} + +/// Writes the object to stream \p os +void cmemlink::write (ostream& os) const +{ + const written_size_type sz (size()); + assert (sz == size() && "No support for writing memblocks larger than 4G"); + os << sz; + os.write (cdata(), sz); + os.align (alignof (sz)); +} + +/// Writes the object to stream \p os +void cmemlink::text_write (ostringstream& os) const +{ + os.write (begin(), readable_size()); +} + +/// Returns the number of bytes required to write this object to a stream. +cmemlink::size_type cmemlink::stream_size (void) const +{ + const written_size_type sz (size()); + return (Align (stream_size_of (sz) + sz, alignof(sz))); +} + +#ifdef CYGCLS_USTL_FSTREAMS +/// Writes the data to file \p "filename". +void cmemlink::write_file (const char* filename, int mode) const +{ + fstream f; + f.exceptions (fstream::allbadbits); + f.open (filename, fstream::out | fstream::trunc, mode); + f.write (cdata(), readable_size()); + f.close(); +} +#endif + +/// Compares to memory block pointed by l. Size is compared first. +bool cmemlink::operator== (const cmemlink& l) const +{ + return (l.m_Size == m_Size && + (l.m_Data == m_Data || 0 == memcmp (l.m_Data, m_Data, m_Size))); +} + +} // namespace ustl
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/src/fstream.cpp @@ -0,0 +1,264 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "fstream.h" +#include "uexception.h" +#include "uutility.h" +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <sys/stat.h> +#if 0 // both header files does not exist in eCos +#include <sys/mman.h> +#include <sys/ioctl.h> +#endif +#include "config.h" + +namespace ustl { + +/// Default constructor. +fstream::fstream (void) +: ios_base (), + m_fd (-1), + m_Filename () +{ + exceptions (goodbit); +} + +/// Opens \p filename in \p mode. +fstream::fstream (const char* filename, openmode mode) +: ios_base (), + m_fd (-1), + m_Filename () +{ + exceptions (goodbit); + open (filename, mode); +} + +/// Attaches to \p nfd of \p filename. +fstream::fstream (int nfd, const char* filename) +: ios_base (), + m_fd (-1), + m_Filename () +{ + exceptions (goodbit); + attach (nfd, filename); +} + +/// Destructor. Closes if still open, but without throwing. +fstream::~fstream (void) throw() +{ + clear (goodbit); + exceptions (goodbit); + close(); + assert (!(rdstate() & badbit) && "close failed in the destructor! This may lead to loss of user data. Please call close() manually and either enable exceptions or check the badbit."); +} + +/// Sets state \p s and throws depending on the exception setting. +void fstream::set_and_throw (iostate s, const char* op) +{ + if (ios_base::set_and_throw (s)) + USTL_THROW(file_exception (op, name())); +} + +/// Attaches to the given \p nfd. +void fstream::attach (int nfd, const char* filename) +{ + assert (filename && "Don't do that"); + m_Filename = filename; + clear (goodbit); + if (nfd < 0) + set_and_throw (badbit, "open"); + close(); + m_fd = nfd; +} + +/// Detaches from the current fd. +void fstream::detach (void) +{ + m_fd = -1; + m_Filename.clear(); +} + +/// Converts openmode bits into libc open flags. +/*static*/ int fstream::om_to_flags (openmode m) +{ + static const int s_OMFlags [nombits] = { + 0, // in + O_CREAT, // out + O_APPEND, // app + O_APPEND, // ate + 0, // binary + O_TRUNC, // trunc + O_NONBLOCK, // nonblock + 0, // nocreate + O_NOCTTY // noctty + }; + int flags = (m - 1) & O_ACCMODE; // in and out + for (uoff_t i = 0; i < VectorSize(s_OMFlags); ++ i) + flags |= s_OMFlags[i] & (!(m & (1 << i)) - 1); + if (m & nocreate) + flags &= ~O_CREAT; + return (flags); +} + +/// \brief Opens \p filename in the given mode. +/// \warning The string at \p filename must exist until the object is closed. +void fstream::open (const char* filename, openmode mode, mode_t perms) +{ + int nfd = ::open (filename, om_to_flags(mode), perms); + attach (nfd, filename); +} + +/// Closes the file and throws on error. +void fstream::close (void) +{ + if (m_fd < 0) + return; // already closed + while (::close(m_fd)) { + if (errno != EINTR) { + set_and_throw (badbit | failbit, "close"); + break; + } + } + detach(); +} + +/// Moves the current file position to \p n. +off_t fstream::seek (off_t n, seekdir whence) +{ + off_t p = lseek (m_fd, n, whence); + if (p < 0) + set_and_throw (failbit, "seek"); + return (p); +} + +/// Returns the current file position. +off_t fstream::pos (void) const +{ + return (lseek (m_fd, 0, SEEK_CUR)); +} + +/// Reads \p n bytes into \p p. +off_t fstream::read (void* p, off_t n) +{ + off_t br (0); + while ((br < n) & good()) + br += readsome (advance (p, br), n - br); + return (br); +} + +/// Reads at most \p n bytes into \p p, stopping when it feels like it. +off_t fstream::readsome (void* p, off_t n) +{ + ssize_t brn; + do { brn = ::read (m_fd, p, n); } while ((brn < 0) & (errno == EINTR)); + if (brn > 0) + return (brn); + else if ((brn < 0) & (errno != EAGAIN)) + set_and_throw (failbit, "read"); + else if (!brn && ios_base::set_and_throw (eofbit | failbit)) + USTL_THROW(stream_bounds_exception ("read", name(), pos(), n, 0)); + return (0); +} + +/// Writes \p n bytes from \p p. +off_t fstream::write (const void* p, off_t n) +{ + off_t btw (n); + while (btw) { + const off_t bw (n - btw); + ssize_t bwn = ::write (m_fd, advance(p,bw), btw); + if (bwn > 0) + btw -= bwn; + else if (!bwn) { + if (ios_base::set_and_throw (eofbit | failbit)) + USTL_THROW(stream_bounds_exception ("write", name(), pos() - bw, n, bw)); + break; + } else if (errno != EINTR) { + if (errno != EAGAIN) + set_and_throw (failbit, "write"); + break; + } + } + return (n - btw); +} + +/// Returns the file size. +off_t fstream::size (void) const +{ + struct stat st; + st.st_size = 0; + stat (st); + return (st.st_size); +} + +/// Synchronizes the file's data and status with the disk. +void fstream::sync (void) +{ + if (fsync (m_fd)) + set_and_throw (badbit | failbit, "sync"); +} + +/// Get the stat structure. +void fstream::stat (struct stat& rs) const +{ + if (fstat (m_fd, &rs)) + USTL_THROW(file_exception ("stat", name())); +} + +/// Calls the given ioctl. Use IOCTLID macro to pass in both \p name and \p request. +int fstream::ioctl (const char* rname, int request, long argument) +{ + int rv = ::ioctl (m_fd, request, argument); + if (rv < 0) + set_and_throw (failbit, rname); + return (rv); +} + +/// Calls the given fcntl. Use FCNTLID macro to pass in both \p name and \p request. +int fstream::fcntl (const char* rname, int request, long argument) +{ + int rv = ::fcntl (m_fd, request, argument); + if (rv < 0) + set_and_throw (failbit, rname); + return (rv); +} + +#if 0 // memory mapped files are not supported in eCos +/// Memory-maps the file and returns a link to it. +memlink fstream::mmap (off_t n, off_t offset) +{ + void* result = ::mmap (NULL, n, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, offset); + if (result == MAP_FAILED) + set_and_throw (failbit, "mmap"); + return (memlink (result, n)); +} + +/// Unmaps a memory-mapped area. +void fstream::munmap (memlink& l) +{ + if (::munmap (l.data(), l.size())) + set_and_throw (failbit, "munmap"); + l.unlink(); +} + +/// Synchronizes a memory-mapped area. +void fstream::msync (memlink& l) +{ + if (::msync (l.data(), l.size(), MS_ASYNC | MS_INVALIDATE)) + set_and_throw (failbit, "msync"); +} +#endif // #if 0 + +void fstream::set_nonblock (bool v) +{ + int curf = max (0, fcntl (FCNTLID (F_GETFL))); + if (v) curf |= O_NONBLOCK; + else curf &= ~O_NONBLOCK; + fcntl (FCNTLID (F_SETFL), curf); +} + +} // namespace ustl
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/src/memblock.cpp @@ -0,0 +1,155 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "mistream.h" +#include "memblock.h" +#include "ualgo.h" +#include "umemory.h" +#ifdef CYGCLS_USTL_FSTREAMS +#include "fstream.h" +#endif +#include <errno.h> +#include "config.h" + +namespace ustl { + +memblock::memblock (void) : memlink (), m_Capacity (0) { } +memblock::memblock (const void* p, size_type n) : memlink (), m_Capacity (0) { assign (p, n); } +memblock::memblock (size_type n) : memlink (), m_Capacity (0) { resize (n); } +memblock::memblock (const cmemlink& b) : memlink (), m_Capacity (0) { assign (b); } +memblock::memblock (const memlink& b) : memlink (), m_Capacity (0) { assign (b); } +memblock::memblock (const memblock& b) : memlink (), m_Capacity (0) { assign (b); } +memblock::~memblock (void) throw() { deallocate(); } + +void memblock::unlink (void) throw() +{ + m_Capacity = 0; + memlink::unlink(); +} + +/// resizes the block to \p newSize bytes, reallocating if necessary. +void memblock::resize (size_type newSize, bool bExact) +{ + if (m_Capacity < newSize + minimumFreeCapacity()) + reserve (newSize, bExact); + memlink::resize (newSize); +} + +/// Frees internal data. +void memblock::deallocate (void) throw() +{ + if (m_Capacity) { + assert (cdata() && "Internal error: space allocated, but the pointer is NULL"); + assert (data() && "Internal error: read-only block is marked as allocated space"); + free (data()); + } + unlink(); +} + +/// Assumes control of the memory block \p p of size \p n. +/// The block assigned using this function will be freed in the destructor. +void memblock::manage (void* p, size_type n) +{ + assert (p || !n); + assert (!m_Capacity && "Already managing something. deallocate or unlink first."); + link (p, n); + m_Capacity = n; +} + +/// "Instantiate" a linked block by allocating and copying the linked data. +void memblock::copy_link (void) +{ + const pointer p (begin()); + const size_t sz (size()); + if (is_linked()) + unlink(); + assign (p, sz); +} + +/// Copies data from \p p, \p n. +void memblock::assign (const void* p, size_type n) +{ + assert ((p != (const void*) cdata() || size() == n) && "Self-assignment can not resize"); + resize (n); + copy (p, n); +} + +/// \brief Reallocates internal block to hold at least \p newSize bytes. +/// +/// Additional memory may be allocated, but for efficiency it is a very +/// good idea to call reserve before doing byte-by-byte edit operations. +/// The block size as returned by size() is not altered. reserve will not +/// reduce allocated memory. If you think you are wasting space, call +/// deallocate and start over. To avoid wasting space, use the block for +/// only one purpose, and try to get that purpose to use similar amounts +/// of memory on each iteration. +/// +void memblock::reserve (size_type newSize, bool bExact) +{ + if ((newSize += minimumFreeCapacity()) <= m_Capacity) + return; + pointer oldBlock (is_linked() ? NULL : data()); + const size_t alignedSize (Align (newSize, 64)); + if (!bExact) + newSize = alignedSize; + pointer newBlock = (pointer) realloc (oldBlock, newSize); + if (!newBlock) + USTL_THROW(bad_alloc (newSize)); + if (!oldBlock & (cdata() != NULL)) + copy_n (cdata(), min (size() + 1, newSize), newBlock); + link (newBlock, size()); + m_Capacity = newSize; +} + +/// Shifts the data in the linked block from \p start to \p start + \p n. +memblock::iterator memblock::insert (iterator start, size_type n) +{ + const uoff_t ip = start - begin(); + assert (ip <= size()); + resize (size() + n, false); + memlink::insert (iat(ip), n); + return (iat (ip)); +} + +/// Shifts the data in the linked block from \p start + \p n to \p start. +memblock::iterator memblock::erase (iterator start, size_type n) +{ + const uoff_t ep = start - begin(); + assert (ep + n <= size()); + memlink::erase (start, n); + memlink::resize (size() - n); + return (iat (ep)); +} + +/// Reads the object from stream \p s +void memblock::read (istream& is) +{ + written_size_type n = 0; + is >> n; + if (!is.verify_remaining ("read", "ustl::memblock", n)) + return; + resize (n); + is.read (data(), writable_size()); + is.align (alignof (n)); +} + +#ifdef CYGCLS_USTL_FSTREAMS +/// Reads the entire file \p "filename". +void memblock::read_file (const char* filename) +{ + fstream f; + f.exceptions (fstream::allbadbits); + f.open (filename, fstream::in); + const off_t fsize (f.size()); + reserve (fsize); + f.read (data(), fsize); + f.close(); + resize (fsize); +} +#endif // CYGCLS_USTL_FSTREAMS + +memblock::size_type memblock::minimumFreeCapacity (void) const throw() { return (0); } + +} // namespace ustl
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/src/memlink.cpp @@ -0,0 +1,52 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "mistream.h" +#include "ustdxept.h" + +namespace ustl { + +/// Reads the object from stream \p s +void memlink::read (istream& is) +{ + written_size_type n = 0; + is >> n; + if (!is.verify_remaining ("read", "ustl::memlink", n)) + return; + if (n > size()) + USTL_THROW(length_error ("memlink can not increase the size of the linked storage for reading")); + resize (n); + is.read (data(), n); + is.align (alignof (n)); +} + +/// Copies data from \p p, \p n to the linked block starting at \p start. +void memlink::copy (iterator start, const void* p, size_type n) +{ + assert (data() || !n); + assert (p || !n); + assert (start >= begin() && start + n <= end()); + if (p) + copy_n (const_iterator(p), n, start); +} + +/// Fills the linked block with the given pattern. +/// \arg start Offset at which to start filling the linked block +/// \arg p Pointer to the pattern. +/// \arg elSize Size of the pattern. +/// \arg elCount Number of times to write the pattern. +/// Total number of bytes written is \p elSize * \p elCount. +/// +void memlink::fill (iterator start, const void* p, size_type elSize, size_type elCount) +{ + assert (data() || !elCount || !elSize); + assert (start >= begin() && start + elSize * elCount <= end()); + if (elSize == 1) + fill_n (start, elCount, *reinterpret_cast<const uint8_t*>(p)); + else while (elCount--) + start = copy_n (const_iterator(p), elSize, start); +} + +} // namespace ustl
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/src/mistream.cpp @@ -0,0 +1,121 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "mistream.h" +#include "sostream.h" +#include "ustring.h" +#include "ualgo.h" + +namespace ustl { + +//-------------------------------------------------------------------- + +/// Checks that \p n bytes are available in the stream, or else throws. +void ios_base::overrun (const char* op, const char* type, uint32_t n, uint32_t pos, uint32_t rem) +{ + if (set_and_throw (rem ? failbit : (failbit | eofbit))) + USTL_THROW(stream_bounds_exception (op, type, pos, n, rem)); +} + +//-------------------------------------------------------------------- + +/// Attaches to the block pointed to by source of size source.pos() +istream::istream (const ostream& source) +: cmemlink (source.begin(), source.pos()), + m_Pos (0) +{ +} + +void istream::unlink (void) throw() { cmemlink::unlink(); m_Pos = 0; } +void ostream::unlink (void) throw() { memlink::unlink(); m_Pos = 0; } + +/// Writes all unread bytes into \p os. +void istream::write (ostream& os) const +{ + os.write (ipos(), remaining()); +} + +/// Writes the object to stream \p os. +void istream::text_write (ostringstream& os) const +{ + os.write (ipos(), remaining()); +} + +/// Reads a null-terminated string into \p str. +void istream::read_strz (string& str) +{ + const_iterator zp = find (ipos(), end(), '\0'); + if (zp == end()) + zp = ipos(); + const size_type strl = distance (ipos(), zp); + str.assign (ipos(), strl); + m_Pos += strl + 1; +} + +/// Reads at most \p n bytes into \p s. +istream::size_type istream::readsome (void* s, size_type n) +{ + if (remaining() < n) + underflow (n); + const size_type ntr (min (n, remaining())); + read (s, ntr); + return (ntr); +} + +//-------------------------------------------------------------------- + +/// Aligns the write pointer on \p grain. The skipped bytes are zeroed. +void ostream::align (size_type grain) +{ + assert (!((grain-1)&grain) && "grain must be a power of 2"); + iterator ip = ipos(); + iterator ipa = iterator((uintptr_t(ip) + (grain-1)) & ~(grain-1)); + size_t nb = distance (ip, ipa); +#if WANT_STREAM_BOUNDS_CHECKING + if (!verify_remaining ("align", "padding", nb)) + return; +#else + assert (remaining() >= nb && "Buffer overrun. Check your stream size calculations."); +#endif + memset (ip, '\x0', nb); + m_Pos += nb; +} + +/// Writes \p str as a null-terminated string. +void ostream::write_strz (const char* str) +{ + write (str, strlen(str)+1); +} + +/// Writes all available data from \p is. +void ostream::read (istream& is) +{ + write (is.ipos(), is.remaining()); + is.seek (is.size()); +} + +/// Writes all written data to \p os. +void ostream::text_write (ostringstream& os) const +{ + os.write (begin(), pos()); +} + +/// Inserts an empty area of \p size, at \p start. +void ostream::insert (iterator start, size_type s) +{ + m_Pos += s; + memlink::insert (start, s); +} + +/// Erases an area of \p size, at \p start. +void ostream::erase (iterator start, size_type s) +{ + m_Pos -= s; + memlink::erase (start, s); +} + +//-------------------------------------------------------------------- + +} // namespace ustl
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/src/ofstream.cpp @@ -0,0 +1,169 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "ofstream.h" +#include "ustring.h" +#include "uexception.h" +#include <unistd.h> +#include <errno.h> +#include <stdio.h> +#include <stdarg.h> + +namespace ustl { + +//---------------------------------------------------------------------- +#ifdef CYGVAR_USTL_CIN_COUT_CERR +ifstream cin (STDIN_FILENO); +ofstream cout (STDOUT_FILENO); +ofstream cerr (STDERR_FILENO); +#endif +//---------------------------------------------------------------------- + +/// Default constructor. +ofstream::ofstream (void) +: ostringstream (), + m_File () +{ + reserve (255); +} + +/// Constructs a stream for writing to \p Fd. +ofstream::ofstream (int Fd) +: ostringstream (), + m_File (Fd) +{ + clear (m_File.rdstate()); + reserve (255); +} + +/// Constructs a stream for writing to \p filename. +ofstream::ofstream (const char* filename, openmode mode) +: ostringstream (), + m_File (filename, mode) +{ + clear (m_File.rdstate()); +} + +/// Default destructor. +ofstream::~ofstream (void) throw() +{ + USTL_TRY { flush(); } USTL_CATCH_ALL; +} + +/// Flushes the buffer and closes the file. +void ofstream::close (void) +{ + clear (m_File.rdstate()); + flush(); + m_File.close(); +} + +/// Flushes the buffer to the file. +ofstream& ofstream::flush (void) +{ + clear(); + while (good() && pos() && overflow (remaining())) ; + m_File.sync(); + clear (m_File.rdstate()); + return (*this); +} + +/// Seeks to \p p based on \p d. +ofstream& ofstream::seekp (off_t p, seekdir d) +{ + flush(); + m_File.seekp (p, d); + clear (m_File.rdstate()); + return (*this); +} + +/// Called when more buffer space (\p n bytes) is needed. +ofstream::size_type ofstream::overflow (size_type n) +{ + if (eof() || (n > remaining() && n < capacity() - pos())) + return (ostringstream::overflow (n)); + size_type bw = m_File.write (cdata(), pos()); + clear (m_File.rdstate()); + erase (begin(), bw); + if (remaining() < n) + ostringstream::overflow (n); + return (remaining()); +} + +//---------------------------------------------------------------------- + +/// Constructs a stream to read from \p Fd. +ifstream::ifstream (int Fd) +: istringstream (), + m_Buffer (255), + m_File (Fd) +{ + link (m_Buffer.data(), streamsize(0)); +} + +/// Constructs a stream to read from \p filename. +ifstream::ifstream (const char* filename, openmode mode) +: istringstream (), + m_Buffer (255), + m_File (filename, mode) +{ + clear (m_File.rdstate()); + link (m_Buffer.data(), streamsize(0)); +} + +/// Reads at least \p n more bytes and returns available bytes. +ifstream::size_type ifstream::underflow (size_type n) +{ + if (eof()) + return (istringstream::underflow (n)); + + const ssize_t freeSpace = m_Buffer.size() - pos(); + const ssize_t neededFreeSpace = max (n, m_Buffer.size() / 2); + const size_t oughtToErase = Align (max (0, neededFreeSpace - freeSpace)); + const size_type nToErase = min (pos(), oughtToErase); + m_Buffer.memlink::erase (m_Buffer.begin(), nToErase); + const uoff_t oldPos (pos() - nToErase); + + size_type br = oldPos; + if (m_Buffer.size() - br < n) { + m_Buffer.resize (br + neededFreeSpace); + link (m_Buffer.data(), streamsize(0)); + } + cout.flush(); + + size_type brn = 1; + for (; br < oldPos + n && brn && m_File.good(); br += brn) + brn = m_File.readsome (m_Buffer.begin() + br, m_Buffer.size() - br); + clear (m_File.rdstate()); + + m_Buffer[br] = 0; + link (m_Buffer.data(), br); + seek (oldPos); + return (remaining()); +} + +/// Flushes the input. +int ifstream::sync (void) +{ + istringstream::sync(); + underflow (0U); + m_File.sync(); + clear (m_File.rdstate()); + return (-good()); +} + +/// Seeks to \p p based on \p d. +ifstream& ifstream::seekg (off_t p, seekdir d) +{ + m_Buffer.clear(); + link (m_Buffer); + m_File.seekg (p, d); + clear (m_File.rdstate()); + return (*this); +} + +//---------------------------------------------------------------------- + +} // namespace ustl
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/src/sistream.cpp @@ -0,0 +1,216 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "sistream.h" +#include "sostream.h" +#include "ustring.h" + +namespace ustl { + +#define DEFAULT_DELIMITERS " \t\n\r;:,.?" +const char ios_base::c_DefaultDelimiters [istringstream::c_MaxDelimiters] = DEFAULT_DELIMITERS; + +/// Default constructor. +istringstream::istringstream (void) +: istream (), + m_Base (0) +{ + exceptions (goodbit); + set_delimiters (DEFAULT_DELIMITERS); +} + +istringstream::istringstream (const void* p, size_type n) +: istream (), + m_Base (0) +{ + exceptions (goodbit); + relink (p, n); + set_delimiters (DEFAULT_DELIMITERS); +} + +istringstream::istringstream (const cmemlink& source) +: istream (), + m_Base (0) +{ + exceptions (goodbit); + relink (source); + set_delimiters (DEFAULT_DELIMITERS); +} + +inline bool istringstream::is_delimiter (char c) const +{ + return (memchr (m_Delimiters, c, VectorSize(m_Delimiters)-1)); +} + +char istringstream::skip_delimiters (void) +{ + char c = m_Delimiters[0]; + while (is_delimiter(c)) { + if (!remaining() && !underflow()) { + verify_remaining ("read", "", 1); + return (0); + } + istream::iread (c); + } + return (c); +} + +typedef istringstream::iterator issiter_t; +template <typename T> +inline void str_to_num (issiter_t i, issiter_t* iend, uint8_t base, T& v) + { v = strtol (i, const_cast<char**>(iend), base); } +template <> inline void str_to_num (issiter_t i, issiter_t* iend, uint8_t, double& v) + { v = strtod (i, const_cast<char**>(iend)); } +#if HAVE_LONG_LONG +template <> inline void str_to_num (issiter_t i, issiter_t* iend, uint8_t base, long long& v) + { v = strtoll (i, const_cast<char**>(iend), base); } +#endif + +template <typename T> +inline void istringstream::read_number (T& v) +{ + v = 0; + if (!skip_delimiters()) + return; + ungetc(); + iterator ilast; + do { + str_to_num<T> (ipos(), &ilast, m_Base, v); + } while (ilast == end() && underflow()); + skip (distance (ipos(), ilast)); +} + +void istringstream::iread (int32_t& v) { read_number (v); } +void istringstream::iread (double& v) { read_number (v); } +#if HAVE_INT64_T +void istringstream::iread (int64_t& v) { read_number (v); } +#endif +#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8) +void istringstream::iread (long long& v) { read_number (v); } +#endif + +void istringstream::iread (wchar_t& v) +{ + if (!(v = skip_delimiters())) + return; + ungetc(); + size_t cs = Utf8SequenceBytes (v); + if (remaining() < cs && underflow(cs) < cs) + verify_remaining ("read", "wchar_t", cs); + else { + v = *utf8in (ipos()); + skip (cs); + } +} + +void istringstream::iread (bool& v) +{ + static const char tf[2][8] = { "false", "true" }; + char c = skip_delimiters(); + v = (c == 't' || c == '1'); + if (c != tf[v][0]) + return; + for (const char* tv = tf[v]; c == *tv && (remaining() || underflow()); ++tv) + istream::iread (c); + ungetc(); +} + +void istringstream::iread (string& v) +{ + v.clear(); + char prevc, quoteChar = 0, c = skip_delimiters(); + if (!c) + return; + if (c == '\"' || c == '\'') + quoteChar = c; + else + v += c; + while (remaining() || underflow()) { + prevc = c; + istream::iread (c); + if (!quoteChar && is_delimiter(c)) + break; + if (prevc == '\\') { + switch (c) { + case 't': c = '\t'; break; + case 'n': c = '\n'; break; + case 'r': c = '\r'; break; + case 'b': c = '\b'; break; + case 'E': c = 27; break; // ESC sequence + case '\"': c = '\"'; break; + case '\'': c = '\''; break; + case '\\': c = '\\'; break; + }; + v.end()[-1] = c; + } else { + if (c == quoteChar) + break; + v += c; + } + } +} + +istringstream& istringstream::read (void* buffer, size_type sz) +{ + if (remaining() < sz && underflow(sz) < sz) + verify_remaining ("read", "", sz); + else + istream::read (buffer, sz); + return (*this); +} + +/// Reads characters into \p s until \p delim is found (but not stored or extracted) +istringstream& istringstream::get (string& s, char delim) +{ + getline (s, delim); + if (!s.empty() && pos() > 0 && ipos()[-1] == delim) + ungetc(); + return (*this); +} + +/// Reads characters into \p p,n until \p delim is found (but not stored or extracted) +istringstream& istringstream::get (char* p, size_type n, char delim) +{ + assert (p && !n && "A non-empty buffer is required by this implementation"); + string s; + get (s, delim); + const size_t ntc (min (n - 1, s.size())); + memcpy (p, s.data(), ntc); + p[ntc] = 0; + return (*this); +} + +/// Reads characters into \p s until \p delim is extracted (but not stored) +istringstream& istringstream::getline (string& s, char delim) +{ + char oldDelim [VectorSize(m_Delimiters)]; + copy (VectorRange (m_Delimiters), oldDelim); + fill (VectorRange (m_Delimiters), '\0'); + m_Delimiters[0] = delim; + iread (s); + copy (VectorRange (oldDelim), m_Delimiters); + return (*this); +} + +/// Reads characters into \p p,n until \p delim is extracted (but not stored) +istringstream& istringstream::getline (char* p, size_type n, char delim) +{ + assert (p && !n && "A non-empty buffer is required by this implementation"); + string s; + getline (s, delim); + const size_t ntc (min (n - 1, s.size())); + memcpy (p, s.data(), ntc); + p[ntc] = 0; + return (*this); +} + +/// Extract until \p delim or \p n chars have been read. +istringstream& istringstream::ignore (size_type n, char delim) +{ + while (n-- && (remaining() || underflow()) && get() != delim) ; + return (*this); +} + +} // namespace ustl
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/src/sostream.cpp @@ -0,0 +1,168 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "mistream.h" // for istream_iterator, referenced in utf8.h +#include "sostream.h" +#include "ustring.h" +#include "ulimits.h" +#include <stdio.h> + +namespace ustl { + +/// Creates an output string stream linked to the given memory area. +ostringstream::ostringstream (void* p, size_t n) +: ostream (), + m_Buffer (), + m_Flags (0), + m_Width (0), + m_Base (10), + m_Precision (2) +{ + exceptions (goodbit); + link (p, n); +} + +/// Creates an output string stream, initializing the buffer with v. +ostringstream::ostringstream (const string& v) +: ostream (), + m_Buffer (v), + m_Flags (0), + m_Width (0), + m_Base (10), + m_Precision (2) +{ + exceptions (goodbit); + ostream::link (m_Buffer); +} + +/// Copies \p s to the internal buffer. +void ostringstream::str (const string& s) +{ + m_Buffer = s; + ostream::link (m_Buffer); + SetPos (m_Buffer.size()); +} + +/// Writes a single character into the stream. +void ostringstream::iwrite (uint8_t v) +{ + if (remaining() >= 1 || overflow() >= 1) + ostream::iwrite (v); +} + +/// Writes the contents of \p buffer of \p size into the stream. +ostringstream& ostringstream::write (const void* buffer, size_type sz) +{ + const char* buf = (const char*) buffer; + for (size_type bw = 0; (bw = min(sz, remaining() ? remaining() : overflow(sz))); buf += bw, sz -= bw) + ostream::write (buf, bw); + return (*this); +} + +/// Simple decimal encoding of \p n into \p fmt. +inline char* ostringstream::encode_dec (char* fmt, uint32_t n) const +{ + do { + *fmt++ = '0' + n % 10; + } while (n /= 10); + return (fmt); +} + +/// Generates a sprintf format string for the given type. +void ostringstream::fmtstring (char* fmt, const char* typestr, bool bInteger) const +{ + *fmt++ = '%'; + if (m_Width) + fmt = encode_dec (fmt, m_Width); + if (m_Flags & left) + *fmt++ = '-'; + if (!bInteger) { + *fmt++ = '.'; + fmt = encode_dec (fmt, m_Precision); + } + while (*typestr) + *fmt++ = *typestr++; + if (bInteger) { + if (m_Base == 16) + fmt[-1] = 'X'; + else if (m_Base == 8) + fmt[-1] = 'o'; + } else { + if (m_Flags & scientific) + fmt[-1] = 'E'; + } + *fmt = 0; +} + +/// Writes \p v into the stream as utf8 +void ostringstream::iwrite (wchar_t v) +{ + char buffer [8]; + *utf8out(buffer) = v; + write (buffer, Utf8Bytes(v)); +} + +/// Writes value \p v into the stream as text. +void ostringstream::iwrite (bool v) +{ + static const char tf[2][8] = { "false", "true" }; + write (tf[v], 5 - v); +} + +/// Equivalent to a vsprintf on the string. +int ostringstream::vformat (const char* fmt, va_list args) +{ +#if HAVE_VA_COPY + va_list args2; +#else + #define args2 args + #undef __va_copy + #define __va_copy(x,y) +#endif + size_t rv, space; + do { + space = remaining(); + __va_copy (args2, args); + rv = vsnprintf (ipos(), space, fmt, args2); + if (ssize_t(rv) < 0) + rv = space; + } while (rv >= space && rv < overflow(rv + 1)); + SetPos (pos() + min (rv, space)); + return (rv); +} + +/// Equivalent to a sprintf on the string. +int ostringstream::format (const char* fmt, ...) +{ + va_list args; + va_start (args, fmt); + const int rv = vformat (fmt, args); + va_end (args); + return (rv); +} + +/// Links to string \p l as resizable. +void ostringstream::link (void* p, size_type n) +{ + assert ((p || !n) && "The output string buffer must not be read-only"); + ostream::link (p, n); + m_Buffer.link (p, n); +} + +/// Attempts to create more output space. Returns remaining(). +ostringstream::size_type ostringstream::overflow (size_type n) +{ + if (n > remaining()) { + const uoff_t oldPos (pos()); + m_Buffer.reserve (oldPos + n, false); + m_Buffer.resize (oldPos + n); + ostream::link (m_Buffer); + SetPos (oldPos); + } + verify_remaining ("write", "text", n); + return (remaining()); +} + +} // namespace ustl
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/src/ualgobase.cpp @@ -0,0 +1,295 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#ifndef NDEBUG // Optimized code here. asserts slow it down, and are checked elsewhere. +#define NDEBUG +#endif + +#include "ualgo.h" + +namespace ustl { + +// Generic version for implementing fill_nX_fast on non-i386 architectures. +template <typename T> static inline void stosv (T*& p, size_t n, T v) + { while (n--) *p++ = v; } + +#if defined(__i386__) || defined(__x86_64__) + +//---------------------------------------------------------------------- +// Copy functions +//---------------------------------------------------------------------- + +#if __GNUC__ >= 3 +static inline void movsb_dir_up (void) INLINE; +static inline void movsb_dir_down (void) INLINE; +static inline void movsb (const void*& src, size_t nBytes, void*& dest) INLINE; +static inline void movsd (const void*& src, size_t nWords, void*& dest) INLINE; +#endif + +static inline void movsb_dir_up (void) { asm volatile ("cld"); } +static inline void movsb_dir_down (void) { asm volatile ("std"); } + +static inline void movsb (const void*& src, size_t nBytes, void*& dest) +{ + asm volatile ("rep;\n\tmovsb" + : "=&S"(src), "=&D"(dest), "=&c"(nBytes) + : "0"(src), "1"(dest), "2"(nBytes) + : "memory"); +} + +static inline void movsd (const void*& src, size_t nWords, void*& dest) +{ + asm volatile ("rep;\n\tmovsl" + : "=&S"(src), "=&D"(dest), "=&c"(nWords) + : "0"(src), "1"(dest), "2"(nWords) + : "memory"); +} + +template <> inline void stosv (uint8_t*& p, size_t n, uint8_t v) +{ asm volatile ("rep;\n\tstosb" : "=&D"(p), "=c"(n) : "0"(p), "1"(n), "a"(v) : "memory"); } +template <> inline void stosv (uint16_t*& p, size_t n, uint16_t v) +{ asm volatile ("rep;\n\tstosw" : "=&D"(p), "=c"(n) : "0"(p), "1"(n), "a"(v) : "memory"); } +template <> inline void stosv (uint32_t*& p, size_t n, uint32_t v) +{ asm volatile ("rep;\n\tstosl" : "=&D"(p), "=c"(n) : "0"(p), "1"(n), "a"(v) : "memory"); } + +#if CPU_HAS_MMX +#define MMX_ALIGN 16U // Data must be aligned on this grain +#define MMX_BS 32U // Assembly routines copy data this many bytes at a time. + +static inline void simd_block_copy (const void* src, void* dest) INLINE; +static inline void simd_block_store (uint8_t* dest) INLINE; +static inline void simd_block_cleanup (void) INLINE; + +static inline void simd_block_copy (const void* src, void* dest) +{ + const char* csrc ((const char*) src); + char* cdest ((char*) dest); + #if CPU_HAS_SSE + asm ( + "movaps\t%2, %%xmm0 \n\t" + "movaps\t%3, %%xmm1 \n\t" + "movntps\t%%xmm0, %0 \n\t" + "movntps\t%%xmm1, %1" + : "=m"(cdest[0]), "=m"(cdest[16]) + : "m"(csrc[0]), "m"(csrc[16]) + : "xmm0", "xmm1", "memory"); + #else + asm ( + "movq %4, %%mm0 \n\t" + "movq %5, %%mm1 \n\t" + "movq %6, %%mm2 \n\t" + "movq %7, %%mm3 \n\t" + "movq %%mm0, %0 \n\t" + "movq %%mm1, %1 \n\t" + "movq %%mm2, %2 \n\t" + "movq %%mm3, %3" + : "=m"(cdest[0]), "=m"(cdest[8]), "=m"(cdest[16]), "=m"(cdest[24]) + : "m"(csrc[0]), "m"(csrc[8]), "m"(csrc[16]), "m"(csrc[24]) + : "mm0", "mm1", "mm2", "mm3", "st", "st(1)", "st(2)", "st(3)", "memory"); + #endif +} + +static inline void simd_block_store (uint8_t* dest) +{ + #if CPU_HAS_SSE + asm volatile ( + "movntq %%mm0, %0\n\t" + "movntq %%mm0, %1\n\t" + "movntq %%mm0, %2\n\t" + "movntq %%mm0, %3" + : "=m"(dest[0]), "=m"(dest[8]), "=m"(dest[16]), "=m"(dest[24]) + :: "memory"); + #else + asm volatile ( + "movq %%mm0, %0 \n\t" + "movq %%mm0, %1 \n\t" + "movq %%mm0, %2 \n\t" + "movq %%mm0, %3" + : "=m"(dest[0]), "=m"(dest[8]), "=m"(dest[16]), "=m"(dest[24]) + :: "memory"); + #endif +} + +static inline void simd_block_cleanup (void) +{ + #if !CPU_HAS_SSE + simd::reset_mmx(); + #endif + asm volatile ("sfence"); +} + +/// The fastest optimized raw memory copy. +void copy_n_fast (const void* src, size_t nBytes, void* dest) throw() +{ + movsb_dir_up(); + size_t nHeadBytes = Align(uintptr_t(src), MMX_ALIGN) - uintptr_t(src); + nHeadBytes = min (nHeadBytes, nBytes); + movsb (src, nHeadBytes, dest); + nBytes -= nHeadBytes; + if (!(uintptr_t(dest) % MMX_ALIGN)) { + const size_t nMiddleBlocks = nBytes / MMX_BS; + for (uoff_t i = 0; i < nMiddleBlocks; ++ i) { + prefetch (advance (src, 512), 0, 0); + simd_block_copy (src, dest); + src = advance (src, MMX_BS); + dest = advance (dest, MMX_BS); + } + simd_block_cleanup(); + nBytes %= MMX_BS; + } + movsb (src, nBytes, dest); +} +#endif // CPU_HAS_MMX + +/// The fastest optimized backwards raw memory copy. +void copy_backward_fast (const void* first, const void* last, void* result) throw() +{ + prefetch (first, 0, 0); + prefetch (result, 1, 0); + size_t nBytes (distance (first, last)); + movsb_dir_down(); + size_t nHeadBytes = uintptr_t(last) % 4; + last = advance (last, -1); + result = advance (result, -1); + movsb (last, nHeadBytes, result); + nBytes -= nHeadBytes; + if (uintptr_t(result) % 4 == 3) { + const size_t nMiddleBlocks = nBytes / 4; + last = advance (last, -3); + result = advance (result, -3); + movsd (last, nMiddleBlocks, result); + nBytes %= 4; + } + movsb (last, nBytes, result); + movsb_dir_up(); +} +#endif // __i386__ + +//---------------------------------------------------------------------- +// Fill functions +//---------------------------------------------------------------------- + +#if CPU_HAS_MMX +template <typename T> static inline void build_block (T) {} +template <> inline void build_block (uint8_t v) +{ + asm volatile ( + "movd %0, %%mm0\n\tpunpcklbw %%mm0, %%mm0\n\tpshufw $0, %%mm0, %%mm0" + : : "g"(uint32_t(v)) : "mm0"); +} +template <> inline void build_block (uint16_t v) +{ + asm volatile ( + "movd %0, %%mm0\n\tpshufw $0, %%mm0, %%mm0" + : : "g"(uint32_t(v)) : "mm0"); +} +template <> inline void build_block (uint32_t v) +{ + asm volatile ( + "movd %0, %%mm0\n\tpunpckldq %%mm0, %%mm0" + : : "g"(uint32_t(v)) : "mm0"); +} + +static inline void simd_block_fill_loop (uint8_t*& dest, size_t count) +{ + prefetch (advance (dest, 512), 1, 0); + for (const uint8_t* destEnd = dest + count * MMX_BS; dest < destEnd; dest += MMX_BS) + simd_block_store (dest); + simd_block_cleanup(); + simd::reset_mmx(); +} + +template <typename T> +static inline void fill_n_fast (T* dest, size_t count, T v) +{ + size_t nHead = Align(uintptr_t(dest), MMX_ALIGN) - uintptr_t(dest) / sizeof(T); + nHead = min (nHead, count); + stosv (dest, nHead, v); + count -= nHead; + build_block (v); + uint8_t* bdest = (uint8_t*) dest; + simd_block_fill_loop (bdest, count * sizeof(T) / MMX_BS); + count %= MMX_BS; + dest = (T*) bdest; + stosv (dest, count, v); +} + +void fill_n8_fast (uint8_t* dest, size_t count, uint8_t v) throw() + { fill_n_fast (dest, count, v); } +void fill_n16_fast (uint16_t* dest, size_t count, uint16_t v) throw() + { fill_n_fast (dest, count, v); } +void fill_n32_fast (uint32_t* dest, size_t count, uint32_t v) throw() + { fill_n_fast (dest, count, v); } +#else +void fill_n8_fast (uint8_t* dest, size_t count, uint8_t v) throw() { memset (dest, v, count); } +void fill_n16_fast (uint16_t* dest, size_t count, uint16_t v) throw() { stosv (dest, count, v); } +void fill_n32_fast (uint32_t* dest, size_t count, uint32_t v) throw() { stosv (dest, count, v); } +#endif // CPU_HAS_MMX + +/// Exchanges ranges [first, middle) and [middle, last) +void rotate_fast (void* first, void* middle, void* last) throw() +{ +#if HAVE_ALLOCA_H + const size_t half1 (distance (first, middle)), half2 (distance (middle, last)); + const size_t hmin (min (half1, half2)); + if (!hmin) + return; + void* buf = alloca (hmin); + if (buf) { + if (half2 < half1) { + copy_n_fast (middle, half2, buf); + copy_backward_fast (first, middle, last); + copy_n_fast (buf, half2, first); + } else { + copy_n_fast (first, half1, buf); + copy_n_fast (middle, half2, first); + copy_n_fast (buf, half1, advance (first, half2)); + } + } else +#else + if (first == middle || middle == last) + return; +#endif + { + char* f = (char*) first; + char* m = (char*) middle; + char* l = (char*) last; + reverse (f, m); + reverse (m, l); + while (f != m && m != l) + iter_swap (f++, --l); + reverse (f, (f == m ? l : m)); + } +} + +#if __GNUC__ < 4 +size_t popcount (uint32_t v) +{ + const uint32_t w = v - ((v >> 1) & 0x55555555); // Algorithm from AMD optimization guide + const uint32_t x = (w & 0x33333333) + ((w >> 2) & 0x33333333); + return (((x + (x >> 4) & 0x0F0F0F0F) * 0x01010101) >> 24); +} + +#if HAVE_INT64_T +/// \brief Returns the number of 1s in \p v in binary. +size_t popcount (uint64_t v) +{ + v -= (v >> 1) & UINT64_C(0x5555555555555555); // Algorithm from Wikipedia + v = (v & UINT64_C(0x3333333333333333)) + ((v >> 2) & UINT64_C(0x3333333333333333)); + v = (v + (v >> 4)) & UINT64_C(0x0F0F0F0F0F0F0F0F); + return ((v * UINT64_C(0x0101010101010101)) >> 56); +} +#endif // HAVE_INT64_T +#endif // !__GNUC__ + +//---------------------------------------------------------------------- +// Miscellaneous instantiated stuff from headers which don't have enough +// to warrant creation of a separate file.cc +//---------------------------------------------------------------------- + +// Used in uspecial to print printable characters +const char _FmtPrtChr[2][8]={"'%c'","%d"}; + +} // namespace ustl
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/src/ubitset.cpp @@ -0,0 +1,34 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "ubitset.h" + +namespace ustl { + +/// Copies bits from \p v of size \p n into \p buf as MSB "1011001..." LSB +/// If \p buf is too small, MSB bits will be truncated. +void convert_to_bitstring (const bitset_value_type* v, size_t n, string& buf) +{ + string::iterator stri = buf.end(); + for (size_t i = 0; i < n && stri > buf.begin(); ++ i) + for (bitset_value_type b = 1; b && stri > buf.begin(); b <<= 1) + *--stri = (v[i] & b) ? '1' : '0'; +} + +/// Copies bits from \p buf as MSB "1011001..." LSB into \p v of size \p n. +void convert_from_bitstring (const string& buf, bitset_value_type* v, size_t n) +{ + string::const_iterator stri = buf.end(); + for (size_t i = 0; i < n; ++ i) { + for (bitset_value_type b = 1; b; b <<= 1) { + if (stri == buf.begin() || *--stri == '0') + v[i] &= ~b; + else + v[i] |= b; + } + } +} + +} // namespace ustl
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/src/uexception.cpp @@ -0,0 +1,276 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "uexception.h" +#include "ustring.h" +#include "mistream.h" +#include "sostream.h" +#include "strmsize.h" +#include "uspecial.h" +#include <errno.h> +#if HAVE_CXXABI_H && WANT_NAME_DEMANGLING + #include <cxxabi.h> +#endif + +namespace ustl { + +//---------------------------------------------------------------------- + +/// \brief Returns a descriptive error message. fmt="%s" +/// Overloads of this functions must set NULL as the default fmt +/// argument and handle that case to provide a default format string +/// in case the user does not have a localized one. The format +/// string should be shown in the documentation to not require +/// translators to look through code. Also, this function must +/// not throw anything, so you must wrap memory allocation routines +/// (like string::format, for instance) in a try{}catch(...){} block. +/// +void exception::info (string& msgbuf, const char*) const throw() +{ + USTL_TRY { msgbuf.format ("%s", what()); } USTL_CATCH_ALL; +} + +/// Reads the exception from stream \p is. +void exception::read (istream& is) +{ + uint32_t stmSize; + xfmt_t fmt = xfmt_Exception; + is >> fmt >> stmSize >> m_Backtrace; + assert (fmt == m_Format && "The saved exception is of a different type."); + assert ((stmSize + 8) - exception::stream_size() <= is.remaining() && "The saved exception data is corrupt."); + m_Format = fmt; +} + +/// Writes the exception into stream \p os as an IFF chunk. +void exception::write (ostream& os) const +{ + os << m_Format << uint32_t(stream_size() - 8) << m_Backtrace; +} + +/// Writes the exception as text into stream \p os. +void exception::text_write (ostringstream& os) const +{ + USTL_TRY { + string buf; + info (buf); + os << buf; + } USTL_CATCH_ALL +} + +//---------------------------------------------------------------------- + +/// Initializes the empty object. \p nBytes is the size of the attempted allocation. +bad_alloc::bad_alloc (size_t nBytes) throw() +: ustl::exception(), + m_nBytesRequested (nBytes) +{ + set_format (xfmt_BadAlloc); +} + +/// Returns a descriptive error message. fmt="failed to allocate %d bytes" +void bad_alloc::info (string& msgbuf, const char* fmt) const throw() +{ + if (!fmt) fmt = "failed to allocate %d bytes"; + USTL_TRY { msgbuf.format (fmt, m_nBytesRequested); } USTL_CATCH_ALL +} + +/// Reads the exception from stream \p is. +void bad_alloc::read (istream& is) +{ + ustl::exception::read (is); + is >> m_nBytesRequested; +} + +/// Writes the exception into stream \p os. +void bad_alloc::write (ostream& os) const +{ + ustl::exception::write (os); + os << m_nBytesRequested; +} + +/// Returns the size of the written exception. +size_t bad_alloc::stream_size (void) const +{ + return (ustl::exception::stream_size() + stream_size_of(m_nBytesRequested)); +} + +//---------------------------------------------------------------------- + +/// Initializes the empty object. \p operation is the function that returned the error code. +libc_exception::libc_exception (const char* operation) throw() +: exception(), + m_Errno (errno), + m_Operation (operation) +{ + set_format (xfmt_LibcException); +} + +/// Copies object \p v. +libc_exception::libc_exception (const libc_exception& v) throw() +: exception (v), + m_Errno (v.m_Errno), + m_Operation (v.m_Operation) +{ +} + +/// Copies object \p v. +const libc_exception& libc_exception::operator= (const libc_exception& v) +{ + m_Errno = v.m_Errno; + m_Operation = v.m_Operation; + return (*this); +} + +/// Returns a descriptive error message. fmt="%s: %m" +void libc_exception::info (string& msgbuf, const char* fmt) const throw() +{ + if (!fmt) fmt = "%s: %d %s"; + USTL_TRY { msgbuf.format (fmt, m_Operation, m_Errno, strerror(m_Errno)); } USTL_CATCH_ALL +} + +/// Reads the exception from stream \p is. +void libc_exception::read (istream& is) +{ + exception::read (is); + is >> m_Errno >> m_Operation; +} + +/// Writes the exception into stream \p os. +void libc_exception::write (ostream& os) const +{ + exception::write (os); + os << m_Errno << m_Operation; +} + +/// Returns the size of the written exception. +size_t libc_exception::stream_size (void) const +{ + return (exception::stream_size() + + stream_size_of(m_Errno) + + stream_size_of(m_Operation)); +} + +//---------------------------------------------------------------------- + +/// Initializes the empty object. \p operation is the function that returned the error code. +file_exception::file_exception (const char* operation, const char* filename) throw() +: libc_exception (operation) +{ + memset (m_Filename, 0, VectorSize(m_Filename)); + set_format (xfmt_FileException); + if (filename) { + strncpy (m_Filename, filename, VectorSize(m_Filename)); + m_Filename [VectorSize(m_Filename) - 1] = 0; + } +} + +/// Returns a descriptive error message. fmt="%s %s: %m" +void file_exception::info (string& msgbuf, const char* fmt) const throw() +{ + if (!fmt) fmt = "%s %s: %d %s"; + USTL_TRY { msgbuf.format (fmt, m_Operation, m_Filename, m_Errno, strerror(m_Errno)); } USTL_CATCH_ALL +} + +/// Reads the exception from stream \p is. +void file_exception::read (istream& is) +{ + libc_exception::read (is); + string filename; + is >> filename; + is.align (8); + filename.copyto (filename, VectorSize(m_Filename)); +} + +/// Writes the exception into stream \p os. +void file_exception::write (ostream& os) const +{ + libc_exception::write (os); + os << string (m_Filename); + os.align (8); +} + +/// Returns the size of the written exception. +size_t file_exception::stream_size (void) const +{ + return (libc_exception::stream_size() + + Align (stream_size_of (string (m_Filename)), 8)); +} + +//---------------------------------------------------------------------- + +/// \brief Uses C++ ABI call, if available to demangle the contents of \p buf. +/// +/// The result is written to \p buf, with the maximum size of \p bufSize, and +/// is zero-terminated. The return value is \p buf. +/// +const char* demangle_type_name (char* buf, size_t bufSize, size_t* pdmSize) +{ + size_t bl = strlen (buf); +#if HAVE_CXXABI_H && WANT_NAME_DEMANGLING + char dmname [256]; + size_t sz = VectorSize(dmname); + int bFailed; + abi::__cxa_demangle (buf, dmname, &sz, &bFailed); + if (!bFailed) { + bl = min (strlen (dmname), bufSize - 1); + memcpy (buf, dmname, bl); + buf[bl] = 0; + } +#else + bl = min (bl, bufSize); +#endif + if (pdmSize) + *pdmSize = bl; + return (buf); +} + +//---------------------------------------------------------------------- + +/// Initializes the empty object. \p operation is the function that returned the error code. +stream_bounds_exception::stream_bounds_exception (const char* operation, const char* type, uoff_t offset, size_t expected, size_t remaining) throw() +: libc_exception (operation), + m_TypeName (type), + m_Offset (offset), + m_Expected (expected), + m_Remaining (remaining) +{ + set_format (xfmt_StreamBoundsException); +} + +/// Returns a descriptive error message. fmt="%s stream %s: @%u: expected %u, available %u"; +void stream_bounds_exception::info (string& msgbuf, const char* fmt) const throw() +{ + char typeName [256]; + strncpy (typeName, m_TypeName, VectorSize(typeName)); + typeName[VectorSize(typeName)-1] = 0; + if (!fmt) fmt = "%s stream %s: @0x%X: need %u bytes, have %u"; + USTL_TRY { msgbuf.format (fmt, demangle_type_name (VectorBlock(typeName)), m_Operation, m_Offset, m_Expected, m_Remaining); } USTL_CATCH_ALL +} + +/// Reads the exception from stream \p is. +void stream_bounds_exception::read (istream& is) +{ + libc_exception::read (is); + is >> m_TypeName >> m_Offset >> m_Expected >> m_Remaining; +} + +/// Writes the exception into stream \p os. +void stream_bounds_exception::write (ostream& os) const +{ + libc_exception::write (os); + os << m_TypeName << m_Offset << m_Expected << m_Remaining; +} + +/// Returns the size of the written exception. +size_t stream_bounds_exception::stream_size (void) const +{ + return (libc_exception::stream_size() + + stream_size_of(m_TypeName) + + stream_size_of(m_Offset) + + stream_size_of(m_Expected) + + stream_size_of(m_Remaining)); +} + +} // namespace ustl
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/src/unew.cpp @@ -0,0 +1,14 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "unew.h" + +void* tmalloc (size_t n) throw (ustl::bad_alloc) +{ + void* p = malloc (n); + if (!p) + USTL_THROW(ustl::bad_alloc (n)); + return (p); +}
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/src/ustdxept.cpp @@ -0,0 +1,57 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "ustdxept.h" +#include "mistream.h" +#include "mostream.h" +#include "strmsize.h" +#include "uiosfunc.h" +#include "uspecial.h" + +namespace ustl { + +//---------------------------------------------------------------------- + +/// \p arg contains a description of the error. +error_message::error_message (const char* arg) throw() +: m_Arg () +{ + USTL_TRY { m_Arg = arg; } USTL_CATCH_ALL + set_format (xfmt_ErrorMessage); +} + +/// Virtual destructor +error_message::~error_message (void) throw() +{ +} + +/// Returns a descriptive error message. fmt="%s: %s" +void error_message::info (string& msgbuf, const char* fmt) const throw() +{ + if (!fmt) fmt = "%s: %s"; + USTL_TRY { msgbuf.format (fmt, name(), m_Arg.cdata()); } USTL_CATCH_ALL +} + +/// Reads the object from stream \p is. +void error_message::read (istream& is) +{ + exception::read (is); + is >> m_Arg >> ios::align(); +} + +/// Writes the object to stream \p os. +void error_message::write (ostream& os) const +{ + exception::write (os); + os << m_Arg << ios::align(); +} + +/// Returns the size of the written object. +size_t error_message::stream_size (void) const +{ + return (exception::stream_size() + Align (stream_size_of (m_Arg))); +} + +} // namespace ustl
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/src/ustlecos.cpp @@ -0,0 +1,115 @@ +// ========================================================================== +// +// ustlecos.cpp +// +// eCos specific implementations and additions to uSTL library +// +// =========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2009 Free Software Foundation, Inc. +// +// eCos 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 or (at your option) any later +// version. +// +// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +// =========================================================================== +// =========================================================================== +// #####DESCRIPTIONBEGIN#### +// +// Author(s): Uwe Kindler +// Contributors: +// Date: 2009-07-28 +// Purpose: eCos specific additions to uSTL library +// Description: +// +// ####DESCRIPTIONEND#### +// +// ========================================================================*/ +#include <cyg/infra/diag.h> +#include <cyg/infra/cyg_trac.h> +#include <ustl.h> +#include <config.h> +#include <ustlecos.h> + +// if exceptions are disabled provide a low level and lightweight +// "exception handler" +#ifndef __EXCEPTIONS +namespace ustl +{ + +// global application specific exception handler +static app_exception_handler_t app_exception_handler = 0; + + +// allow an eCos application to register its own ustl exception handler +void set_app_exception_handler(app_exception_handler_t func) +{ + //app_exception_handler = func; +} + + +// print ustl exception to diagnostic output channel +void diag_print_exception(const exception& ex) +{ + string exstr(64); + ex.info(exstr); + + string failstr = "Exception: "; + failstr += ex.what(); + failstr += "\n"; + failstr += exstr; + failstr += "\n"; + + diag_printf(failstr.c_str()); +} + + +// normally eCos is build with -fno-rtti and -fno-exceptions and does not +// provide C++ exception handling. To detect exceptions in debug builds this +// exception handler prints all exception information to diagnostic channel +// If application registerd an exception handler then exception handling will +// be passed to application exception handler +void exception_handler(const exception& ex) +{ + if (app_exception_handler) + { + app_exception_handler(ex); + } + else + { + diag_print_exception(ex); +#ifdef CYGDBG_USE_ASSERTS + CYG_FAIL("uSTL exception occured"); +#endif + } +} + +} // namespace ustl +#endif // #ifndef __EXCEPTIONS +// --------------------------------------------------------------------------- +// EOF ustlecos.cpp +
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/src/ustring.cpp @@ -0,0 +1,395 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "ustring.h" +#include "mistream.h" +#include "mostream.h" +#include "ualgo.h" +#include <stdio.h> // for vsnprintf (in string::format) + +namespace ustl { + +//---------------------------------------------------------------------- + +const uoff_t string::npos; + +//---------------------------------------------------------------------- + +/// Assigns itself the value of string \p s +string::string (const string& s) +: memblock ((s.size()+1) & (s.is_linked()-1)) // Allocate with terminator if not linked (can't call virtuals from base ctor) +{ + if (s.is_linked()) + relink (s.c_str(), s.size()); + else { + copy_n (s.begin(), size(), begin()); + relink (begin(), size()-1); // --m_Size + } +} + +/// Links to \p s +string::string (const_pointer s) +: memblock () +{ + if (!s) s = ""; + relink (s, strlen(s)); +} + +/// Creates a string of length \p n filled with character \p c. +string::string (size_type n, value_type c) +: memblock (n+1) // because base ctor can't call virtuals of this class +{ + relink (begin(), size()-1); // --m_Size + fill_n (begin(), n, c); + at(n) = 0; +} + +/// Resize the string to \p n characters. New space contents is undefined. +void string::resize (size_type n) +{ + if (!(n | memblock::capacity())) + return (relink ("",0)); + memblock::resize (n); + at(n) = 0; +} + +/// Assigns itself the value of string \p s +void string::assign (const_pointer s) +{ + if (!s) s = ""; + assign (s, strlen (s)); +} + +/// Assigns itself the value of string \p s of length \p len. +void string::assign (const_pointer s, size_type len) +{ + while (len && s[len - 1] == 0) + -- len; + resize (len); + copy (s, len); +} + +/// Appends to itself the value of string \p s of length \p len. +void string::append (const_pointer s) +{ + if (!s) s = ""; + append (s, strlen (s)); +} + +/// Appends to itself the value of string \p s of length \p len. +void string::append (const_pointer s, size_type len) +{ + while (len && s[len - 1] == 0) + -- len; + resize (size() + len); + copy_n (s, len, end() - len); +} + +/// Appends to itself \p n characters of value \p c. +void string::append (size_type n, value_type c) +{ + resize (size() + n); + fill_n (end() - n, n, c); +} + +/// Copies into itself at offset \p start, the value of string \p p of length \p n. +string::size_type string::copyto (pointer p, size_type n, const_iterator start) const +{ + assert (p && n); + if (!start) + start = begin(); + const size_type btc = min(n-1, size()); + copy_n (start, btc, p); + p[btc] = 0; + return (btc+1); +} + +/// Returns comparison value regarding string \p s. +/// The return value is: +/// \li 1 if this string is greater (by value, not length) than string \p s +/// \li 0 if this string is equal to string \p s +/// \li -1 if this string is less than string \p s +/// +/*static*/ int string::compare (const_iterator first1, const_iterator last1, const_iterator first2, const_iterator last2) +{ + assert (first1 <= last1 && (first2 <= last2 || !last2) && "Negative ranges result in memory allocation errors."); + const size_type len1 = distance (first1, last1), len2 = distance (first2, last2); + const int rvbylen = sign (int(len1 - len2)); + int rv = memcmp (first1, first2, min (len1, len2)); + return (rv ? rv : rvbylen); +} + +/// Returns true if this string is equal to string \p s. +bool string::operator== (const_pointer s) const +{ + if (!s) s = ""; + return (size() == strlen(s) && 0 == memcmp (c_str(), s, size())); +} + +/// Returns the beginning of character \p i. +string::const_iterator string::wiat (uoff_t i) const +{ + utf8in_iterator<string::const_iterator> cfinder (begin()); + cfinder += i; + return (cfinder.base()); +} + +/// Inserts wide character \p c at \p ipo \p n times as a UTF-8 string. +/// +/// \p ipo is a byte position, not a character position, and is intended +/// to be obtained from one of the find functions. Generally you are not +/// able to know the character position in a localized string; different +/// languages will have different character counts, so use find instead. +/// +void string::insert (const uoff_t ipo, wchar_t c, size_type n) +{ + iterator ip (iat(ipo)); + ip = iterator (memblock::insert (memblock::iterator(ip), n * Utf8Bytes(c))); + fill_n (utf8out (ip), n, c); + *end() = 0; +} + +/// Inserts sequence of wide characters at \p ipo (byte position from a find call) +void string::insert (const uoff_t ipo, const wchar_t* first, const wchar_t* last, const size_type n) +{ + iterator ip (iat(ipo)); + size_type nti = distance (first, last), bti = 0; + for (uoff_t i = 0; i < nti; ++ i) + bti += Utf8Bytes(first[i]); + ip = iterator (memblock::insert (memblock::iterator(ip), n * bti)); + utf8out_iterator<string::iterator> uout (utf8out (ip)); + for (uoff_t j = 0; j < n; ++ j) + for (uoff_t k = 0; k < nti; ++ k, ++ uout) + *uout = first[k]; + *end() = 0; +} + +/// Inserts character \p c into this string at \p start. +string::iterator string::insert (iterator start, const_reference c, size_type n) +{ + start = iterator (memblock::insert (memblock::iterator(start), n)); + fill_n (start, n, c); + *end() = 0; + return (start); +} + +/// Inserts \p count instances of string \p s at offset \p start. +string::iterator string::insert (iterator start, const_pointer s, size_type n) +{ + if (!s) s = ""; + return (insert (start, s, s + strlen(s), n)); +} + +/// Inserts [first,last] \p n times. +string::iterator string::insert (iterator start, const_pointer first, const_pointer last, size_type n) +{ + assert (first <= last); + assert (begin() <= start && end() >= start); + assert ((first < begin() || first >= end() || size() + abs_distance(first,last) < capacity()) && "Insertion of self with autoresize is not supported"); + start = iterator (memblock::insert (memblock::iterator(start), distance(first, last) * n)); + fill (memblock::iterator(start), first, distance(first, last), n); + *end() = 0; + return (start); +} + +/// Erases \p size bytes at \p ep. +string::iterator string::erase (iterator ep, size_type n) +{ + string::iterator rv = memblock::erase (memblock::iterator(ep), n); + *end() = 0; + return (rv); +} + +/// Erases \p n bytes at byte offset \p epo. +void string::erase (uoff_t epo, size_type n) +{ + erase (iat(epo), n); +} + +/// Replaces range [\p start, \p start + \p len] with string \p s. +void string::replace (iterator first, iterator last, const_pointer s) +{ + if (!s) s = ""; + replace (first, last, s, s + strlen(s)); +} + +/// Replaces range [\p start, \p start + \p len] with \p count instances of string \p s. +void string::replace (iterator first, iterator last, const_pointer i1, const_pointer i2, size_type n) +{ + assert (first <= last); + assert (n || distance(first, last)); + assert (first >= begin() && first <= end() && last >= first && last <= end()); + assert ((i1 < begin() || i1 >= end() || abs_distance(i1,i2) * n + size() < capacity()) && "Replacement by self can not autoresize"); + const size_type bte = distance(first, last), bti = distance(i1, i2) * n; + if (bti < bte) + first = iterator (memblock::erase (memblock::iterator(first), bte - bti)); + else if (bte < bti) + first = iterator (memblock::insert (memblock::iterator(first), bti - bte)); + fill (memblock::iterator(first), i1, distance(i1, i2), n); + *end() = 0; +} + +/// Returns the offset of the first occurence of \p c after \p pos. +uoff_t string::find (const_reference c, uoff_t pos) const +{ + const_iterator found = ::ustl::find (iat(pos), end(), c); + return (found < end() ? distance(begin(),found) : npos); +} + +/// Returns the offset of the first occurence of substring \p s of length \p n after \p pos. +uoff_t string::find (const string& s, uoff_t pos) const +{ + if (s.empty() || s.size() > size() - pos) + return (npos); + const uoff_t endi = s.size() - 1; + const_reference endchar = s[endi]; + uoff_t lastPos = endi; + while (lastPos-- && s[lastPos] != endchar) ; + const size_type skip = endi - lastPos; + const_iterator i = iat(pos) + endi; + for (; i < end() && (i = ::ustl::find (i, end(), endchar)) < end(); i += skip) + if (memcmp (i - endi, s.c_str(), s.size()) == 0) + return (distance (begin(), i) - endi); + return (npos); +} + +/// Returns the offset of the last occurence of character \p c before \p pos. +uoff_t string::rfind (const_reference c, uoff_t pos) const +{ + for (int i = min(pos,size()-1); i >= 0; --i) + if (at(i) == c) + return (i); + return (npos); +} + +/// Returns the offset of the last occurence of substring \p s of size \p n before \p pos. +uoff_t string::rfind (const string& s, uoff_t pos) const +{ + const_iterator d = iat(pos) - 1; + const_iterator sp = begin() + s.size() - 1; + const_iterator m = s.end() - 1; + for (long int i = 0; d > sp && size_type(i) < s.size(); -- d) + for (i = 0; size_type(i) < s.size(); ++ i) + if (m[-i] != d[-i]) + break; + return (d > sp ? distance (begin(), d + 2 - s.size()) : npos); +} + +/// Returns the offset of the first occurence of one of characters in \p s of size \p n after \p pos. +uoff_t string::find_first_of (const string& s, uoff_t pos) const +{ + for (uoff_t i = min(pos,size()); i < size(); ++ i) + if (s.find (at(i)) != npos) + return (i); + return (npos); +} + +/// Returns the offset of the first occurence of one of characters not in \p s of size \p n after \p pos. +uoff_t string::find_first_not_of (const string& s, uoff_t pos) const +{ + for (uoff_t i = min(pos,size()); i < size(); ++ i) + if (s.find (at(i)) == npos) + return (i); + return (npos); +} + +/// Returns the offset of the last occurence of one of characters in \p s of size \p n before \p pos. +uoff_t string::find_last_of (const string& s, uoff_t pos) const +{ + for (int i = min(pos,size()-1); i >= 0; -- i) + if (s.find (at(i)) != npos) + return (i); + return (npos); +} + +/// Returns the offset of the last occurence of one of characters not in \p s of size \p n before \p pos. +uoff_t string::find_last_not_of (const string& s, uoff_t pos) const +{ + for (int i = min(pos,size()-1); i >= 0; -- i) + if (s.find (at(i)) == npos) + return (i); + return (npos); +} + +/// Equivalent to a vsprintf on the string. +int string::vformat (const char* fmt, va_list args) +{ +#if HAVE_VA_COPY + va_list args2; +#else + #define args2 args + #undef __va_copy + #define __va_copy(x,y) +#endif + size_t rv = size(); + do { + reserve (rv); + __va_copy (args2, args); + rv = vsnprintf (data(), memblock::capacity(), fmt, args2); + rv = min (rv, memblock::capacity()); + } while (rv > capacity()); + resize (min (rv, capacity())); + return (rv); +} + +/// Equivalent to a sprintf on the string. +int string::format (const char* fmt, ...) +{ + va_list args; + va_start (args, fmt); + const int rv = vformat (fmt, args); + va_end (args); + return (rv); +} + +/// Returns the number of bytes required to write this object to a stream. +size_t string::stream_size (void) const +{ + return (Utf8Bytes(size()) + size()); +} + +/// Reads the object from stream \p os +void string::read (istream& is) +{ + char szbuf [8]; + is >> szbuf[0]; + size_t szsz (Utf8SequenceBytes (szbuf[0]) - 1), n = 0; + if (!is.verify_remaining ("read", "ustl::string", szsz)) return; + is.read (szbuf + 1, szsz); + n = *utf8in(szbuf); + if (!is.verify_remaining ("read", "ustl::string", n)) return; + resize (n); + is.read (data(), size()); +} + +/// Writes the object to stream \p os +void string::write (ostream& os) const +{ + const written_size_type sz (size()); + assert (sz == size() && "No support for writing strings larger than 4G"); + + char szbuf [8]; + utf8out_iterator<char*> szout (szbuf); + *szout = sz; + size_t szsz = distance (szbuf, szout.base()); + + if (!os.verify_remaining ("write", "ustl::string", szsz + sz)) return; + os.write (szbuf, szsz); + os.write (cdata(), sz); +} + +/// Returns a hash value for [first, last) +/*static*/ hashvalue_t string::hash (const char* first, const char* last) +{ + hashvalue_t h = 0; + // This has the bits flowing into each other from both sides of the number + for (; first < last; ++ first) + h = *first + ((h << 7) | (h >> (BitsInType(hashvalue_t) - 7))); + return (h); +} + +string::size_type string::minimumFreeCapacity (void) const throw() { return (1); } + +} // namespace ustl
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/README @@ -0,0 +1,1 @@ +The *.std files contain the output that should be generated by each test. \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt00.cpp @@ -0,0 +1,46 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +void WriteCML (const cmemlink& l) +{ + cout.format ("cmemlink{%zu}: ", l.size()); + const void* pv = l.cdata(); + const char* pc = reinterpret_cast<const char*>(pv); + size_t nc = l.size(); + if (pc[nc - 1] == 0) + -- nc; + cout.write (l.begin(), nc); + cout << endl; +} + +void TestCML (void) +{ + const char hello[] = "Hello world!"; + const char* phello = hello; // const storage is sometimes copied on pointing + + cmemlink a, b; + a.link (phello, VectorSize(hello)); + if (a.begin() != phello) + cout.format ("a.begin() failed: %p != %p\n", a.begin(), phello); + a.link (VectorRange (hello)); + if (*(const char*)(a.begin() + 5) != hello[5]) + cout.format ("begin()[5] failed: %c != %c\n", *(const char*)(a.begin() + 5), VectorElement(hello,5)); + if (a.size() != VectorSize(hello)) + cout << "link to VectorRange doesn't work\n"; + if (0 != memcmp (a.begin(), hello, VectorSize(hello))) + cout << "memcmp failed on cmemlink\n"; + b.static_link (hello); + WriteCML (a); + WriteCML (b); + if (!(a == b)) + cout << "operator== failed on cmemlink\n"; + b.resize (VectorSize(hello) - 5); + a = b; + WriteCML (a); +} + +StdBvtMain (TestCML)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt00.std @@ -0,0 +1,3 @@ +cmemlink{13}: Hello world! +cmemlink{13}: Hello world! +cmemlink{8}: Hello wo
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt01.cpp @@ -0,0 +1,60 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +void WriteCML (const cmemlink& l) +{ + cout.format ("memlink{%zu}: ", l.size()); + const char* pc = reinterpret_cast<const char*>(l.cdata()); + size_t nc = l.size(); + if (pc[nc - 1] == 0) + -- nc; + cout.write (l.cdata(), nc); + cout << endl; +} + +void TestML (void) +{ + char str[] = "abcdefghijklmnopqrstuvwzyz"; + memlink::const_pointer cstr = str; + + memlink a, b; + a.static_link (str); + if (a.begin() != str) + cout << "begin() failed on memlink\n"; + a.link (VectorRange(str)); + if (a.begin() + 5 != &str[5]) + cout << "begin() + 5 failed on memlink\n"; + if (0 != memcmp (a.begin(), str, VectorSize(str))) + cout << "memcmp failed on memlink\n"; + WriteCML (a); + b.link (cstr, VectorSize(str)); + if (b.data() != cstr) + cout << "begin() of const failed on cmemlink\n"; + if (b.cmemlink::begin() != cstr) + cout << "begin() failed on cmemlink\n"; + WriteCML (b); + if (!(a == b)) + cout << "operator== failed on cmemlink\n"; + b.resize (VectorSize(str) - 2); + a = b; + if (a.data() != b.data()) + cout << "begin() after assignment failed on cmemlink\n"; + a.relink (str, VectorSize(str) - 1); + WriteCML (a); + a.insert (a.begin() + 5, 9); + a.fill (a.begin() + 5, "-", 1, 9); + WriteCML (a); + a.erase (a.begin() + 9, 7); + a.fill (a.end() - 7, "=", 1, 7); + WriteCML (a); + a.fill (a.begin() + 5, "TEST", 4, 3); + WriteCML (a); + a.copy (cstr, VectorSize(str) - 1); + WriteCML (a); +} + +StdBvtMain (TestML)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt01.std @@ -0,0 +1,7 @@ +memlink{27}: abcdefghijklmnopqrstuvwzyz +memlink{27}: abcdefghijklmnopqrstuvwzyz +memlink{26}: abcdefghijklmnopqrstuvwzyz +memlink{26}: abcde---------fghijklmnopq +memlink{26}: abcde----hijklmnopq======= +memlink{26}: abcdeTESTTESTTESTpq======= +memlink{26}: abcdeTESTTESTTESTpq=======
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt02.cpp @@ -0,0 +1,73 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +void WriteCML (const memblock& l) +{ + cout.format ("memblock{%zu}: ", l.size()); + const char* pc = reinterpret_cast<const char*>(l.cdata()); + size_t nc = l.size(); + while (nc && pc[nc - 1] == 0) + -- nc; + cout.write (l.cdata(), nc); + cout << endl; +} + +void TestMB (void) +{ + char strTest[] = "abcdefghijklmnopqrstuvwxyz"; + const size_t strTestLen = strlen(strTest); + const char* cstrTest = strTest; + + memblock a, b; + a.link (strTest, strTestLen); + if (a.begin() != strTest) + cout << "begin() failed on memblock\n"; + if (a.begin() + 5 != &strTest[5]) + cout << "begin() + 5 failed on memblock\n"; + if (0 != memcmp (a.begin(), strTest, strTestLen)) + cout << "memcmp failed on memblock\n"; + WriteCML (a); + b.link (cstrTest, strTestLen); + if (b.data() != cstrTest) + cout << "begin() of const failed on memblock\n"; + if (b.cmemlink::begin() != cstrTest) + cout << "cmemlink::begin() failed on memblock\n"; + WriteCML (b); + if (!(a == b)) + cout << "operator== failed on memblock\n"; + b.copy_link(); + if (b.data() == NULL || b.cdata() == cstrTest) + cout << "copy_link failed on memblock\n"; + if (!(a == b)) + cout << "copy_link didn't copy\n"; + b.resize (strTestLen - 2); + a = b; + if (a.begin() == b.begin()) + cout << "Assignment does not copy a link\n"; + a.deallocate(); + a.resize (strTestLen); + a.copy (strTest, strTestLen); + WriteCML (a); + a.insert (a.begin() + 5, 9); + a.fill (a.begin() + 5, "-", 1, 9); + WriteCML (a); + a.erase (a.begin() + 2, 7); + a.fill (a.end() - 7, "=", 1, 7); + WriteCML (a); + a.fill (a.begin() + 5, "TEST", 4, 3); + WriteCML (a); + + a.resize (26 + 24); + a.fill (a.begin() + 26, "-+=", 3, 24 / 3); + WriteCML (a); + a.resize (0); + WriteCML (a); + a.resize (strTestLen + strTestLen / 2); + WriteCML (a); +} + +StdBvtMain (TestMB)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt02.std @@ -0,0 +1,9 @@ +memblock{26}: abcdefghijklmnopqrstuvwxyz +memblock{26}: abcdefghijklmnopqrstuvwxyz +memblock{26}: abcdefghijklmnopqrstuvwxyz +memblock{35}: abcde---------fghijklmnopqrstuvwxyz +memblock{28}: ab-----fghijklmnopqrs======= +memblock{28}: ab---TESTTESTTESTpqrs======= +memblock{50}: ab---TESTTESTTESTpqrs=====-+=-+=-+=-+=-+=-+=-+=-+= +memblock{0}: +memblock{39}: ab---TESTTESTTESTpqrs=====-+=-+=-+=-+=-
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt03.cpp @@ -0,0 +1,117 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" +#include <unistd.h> + +void TestStreams (void) +{ + const uint8_t magic_Char = 0x12; + const uint16_t magic_Short = 0x1234; + const uint32_t magic_Int = 0x12345678; + const float magic_Float = 0.12345678; + const double magic_Double = 0.123456789123456789; + const bool magic_Bool = true; + + char c = magic_Char; + unsigned char uc = magic_Char; + int i = magic_Int; + short si = magic_Short; + long li = magic_Int; + unsigned int ui = magic_Int; + unsigned short usi = magic_Short; + unsigned long uli = magic_Int; + float f = magic_Float; + double d = magic_Double; + bool bv = magic_Bool; + + size_t totalSize = stream_size_of(c); + totalSize += stream_size_of(uc); + totalSize = Align (totalSize, alignof(bv)); + totalSize += stream_size_of(bv); + totalSize = Align (totalSize, alignof(i)); + totalSize += stream_size_of(i); + totalSize += stream_size_of(ui); + totalSize = Align (totalSize); + totalSize += stream_size_of(li); + totalSize += stream_size_of(uli); + totalSize = Align (totalSize, alignof(f)); + totalSize += stream_size_of(f); + totalSize = Align (totalSize, alignof(d)); + totalSize += stream_size_of(d); + totalSize += stream_size_of(si); + totalSize += stream_size_of(usi); + + memblock b; + b.resize (totalSize); + b.fill (b.begin(), "\xCD", 1, b.size()); + ostream os (b); + + os << c; + os << uc; + os << ios::talign<bool>() << bv; + os << ios::talign<int>() << i; + os << ui; + os << ios::align() << li; + os << uli; + os << ios::talign<float>() << f; + os << ios::talign<double>() << d; + os << si; + os << usi; + if (b.size() == os.pos()) + cout << "Correct number of bytes written\n"; + else + cout.format ("Incorrect (%zu of %zu) number of bytes written\n", os.pos(), b.size()); + cout.flush(); + + c = 0; + uc = 0; + bv = false; + i = ui = li = uli = 0; + f = 0; d = 0; + si = usi = 0; + + istream is (b); + is >> c; + is >> uc; + is >> ios::talign<bool>() >> bv; + is >> ios::talign<int>() >> i; + is >> ui; + is >> ios::align() >> li; + is >> uli; + is >> ios::talign<float>() >> f; + is >> ios::talign<double>() >> d; + is >> si; + is >> usi; + if (is.pos() != b.size()) + cout << "Positional error\n"; + + cout.format ("Values:\n" + "char: 0x%02X\n" + "u_char: 0x%02X\n" + "bool: %d\n" + "int: 0x%08X\n" + "u_int: 0x%08X\n" + "long: 0x%08lX\n" + "u_long: 0x%08lX\n" + "float: %.8f\n" + "double: %.16f\n" + "short: 0x%04X\n" + "u_short: 0x%04X\n", + static_cast<int>(c), static_cast<int>(uc), static_cast<int>(bv), + i, ui, li, uli, f, d, static_cast<int>(si), static_cast<int>(usi)); + + if (isatty (STDIN_FILENO)) { + cout << "\nBinary dump:\n"; + foreach (memblock::const_iterator, pc, b) { + if (pc > b.begin() && !(distance(b.begin(), pc) % 8)) + cout << endl; + cout.format ("%02X ", uint8_t(*pc)); + } + cout << endl; + } +} + +StdBvtMain (TestStreams)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt03.std @@ -0,0 +1,13 @@ +Correct number of bytes written +Values: +char: 0x12 +u_char: 0x12 +bool: 1 +int: 0x12345678 +u_int: 0x12345678 +long: 0x12345678 +u_long: 0x12345678 +float: 0.12345678 +double: 0.1234567891234568 +short: 0x1234 +u_short: 0x1234
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt04.cpp @@ -0,0 +1,68 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +class A { +public: + A (void) + { cout << "A::A\n"; } + A (const A&) + { cout << "Copy A::A\n"; } + const A& operator= (const A&) + { cout << "A::operator=\n"; return (*this); } + ~A (void) + { cout << "A::~A\n"; } +}; + +void TestVector (void) +{ + static const int c_TestNumbers[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 14, 15, 16, 17, 18 }; + vector<int> v; + v.push_back (1); + cout << v << endl; + v.reserve (20); + cout.format ("Reserved to capacity() == %zu (%zu used, ", v.capacity(), v.size()); + if (v.max_size() == SIZE_MAX / sizeof(int)) + cout << "SIZE_MAX/elsize"; + else + cout << v.max_size(); + cout << " max)\n"; + v.insert (v.begin() + 1, 1 + VectorRange(c_TestNumbers)); + cout << v << endl; + cout.format ("front() = %d, back() = %d\n", v.front(), v.back()); + v.erase (v.begin()); + v.pop_back(); + cout << v << endl; + v.insert (v.begin() + 10, 3, 666); + v.at(5) = 777; + cout << v << endl; + v.resize (v.size() - 5); + if (v.empty()) + cout << "v is now empty\n"; + cout << v << endl; + cout.format ("v[5] == %d\n", v[5]); + v.clear(); + if (v.empty()) + cout << "v is now empty\n"; + vector<int> v2 (20, 66); + cout << v2 << endl; + v2.assign (20, 33); + cout << v2 << endl; + v.assign (VectorRange (c_TestNumbers)); + cout << v << endl; + if (v == v2) + cout << "v == v2\n"; + v2 = v; + if (v == v2) + cout << "v == v2\n"; + vector<A> ctv; + A a; + ctv.assign (3, a); + ctv.pop_back(); + cout << "Class insertion testing successful\n"; +} + +StdBvtMain (TestVector)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt04.std @@ -0,0 +1,25 @@ +(1) +Reserved to capacity() == 20 (1 used, SIZE_MAX/elsize max) +(1,2,3,4,5,6,7,8,9,10,11,12,13,13,14,15,16,17,18) +front() = 1, back() = 18 +(2,3,4,5,6,7,8,9,10,11,12,13,13,14,15,16,17) +(2,3,4,5,6,777,8,9,10,11,666,666,666,12,13,13,14,15,16,17) +(2,3,4,5,6,777,8,9,10,11,666,666,666,12,13) +v[5] == 777 +v is now empty +(66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66) +(33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33) +(1,2,3,4,5,6,7,8,9,10,11,12,13,13,14,15,16,17,18) +v == v2 +A::A +A::A +A::A +A::A +A::operator= +A::operator= +A::operator= +Class insertion testing successful +A::~A +A::~A +A::~A +A::~A
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt05.cpp @@ -0,0 +1,399 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +typedef vector<int> intvec_t; +typedef const intvec_t& rcintvec_t; +typedef intvec_t::const_iterator intiter_t; + +static void printint (int i) +{ + cout.format ("%d ", i); +} + +static void PrintVector (rcintvec_t v) +{ + cout << "{ "; + foreach (intiter_t, i, v) + printint (*i); + cout << "}\n"; +} + +static bool is_even (int i) +{ + return (i % 2 == 0); +} + +static int sqr (int i) +{ + return (i * i); +} + +static int genint (void) +{ + static int counter = 0; + return (counter++); +} + +// In its own function because compilers differ in selecting const/nonconst +// members where no choice is needed. +// +static void TestEqualRange (rcintvec_t v) +{ + pair<intiter_t,intiter_t> rv; + rv = equal_range (v, 10); + cout.format ("Range of 10 is { %2zd, %2zd }\n", abs_distance (v.begin(), rv.first), abs_distance (v.begin(), rv.second)); + rv = equal_range (v, 0); + cout.format ("Range of 0 is { %2zd, %2zd }\n", abs_distance (v.begin(), rv.first), abs_distance (v.begin(), rv.second)); + rv = equal_range (v, 100); + cout.format ("Range of 100 is { %2zd, %2zd }\n", abs_distance (v.begin(), rv.first), abs_distance (v.begin(), rv.second)); +} + +template <typename T> +void TestBigFill (const size_t size, const T magic) +{ + vector<T> vbig (size); + fill (vbig.begin() + 1, vbig.end(), magic); // offset to test prealignment loop + typename vector<T>::const_iterator iMismatch; + iMismatch = find_if (vbig.begin() + 1, vbig.end(), bind1st (not_equal_to<T>(), magic)); + if (iMismatch == vbig.end()) + cout << "works\n"; + else + cout.format ("does not work: mismatch at %zd, =0x%lX\n", abs_distance (vbig.begin(), iMismatch), (unsigned long)(*iMismatch)); +} + +template <typename T> +void TestBigCopy (const size_t size, const T magic) +{ + vector<T> vbig1 (size), vbig2 (size); + fill (vbig1, magic); + copy (vbig1.begin() + 1, vbig1.end(), vbig2.begin() + 1); // offset to test prealignment loop + typedef typename vector<T>::const_iterator iter_t; + pair<iter_t, iter_t> iMismatch; + iMismatch = mismatch (vbig1.begin() + 1, vbig1.end(), vbig2.begin() + 1); + assert (iMismatch.second <= vbig2.end()); + if (iMismatch.first == vbig1.end()) + cout << "works\n"; + else + cout.format ("does not work: mismatch at %zd, 0x%lX != 0x%lX\n", abs_distance(vbig1.begin(), iMismatch.first), (unsigned long)(*iMismatch.first), (unsigned long)(*iMismatch.second)); +} + +static void TestAlgorithms (void) +{ + static const int c_TestNumbers[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, 13, 14, 15, 16, 17, 18 }; + const int* first = c_TestNumbers; + const int* last = first + VectorSize(c_TestNumbers); + intvec_t v, buf; + v.assign (first, last); + PrintVector (v); + + cout << "swap(1,2)\n"; + swap (v[0], v[1]); + PrintVector (v); + v.assign (first, last); + + cout << "copy(0,8,9)\n"; + copy (v.begin(), v.begin() + 8, v.begin() + 9); + PrintVector (v); + v.assign (first, last); + + cout << "copy with back_inserter\n"; + v.clear(); + copy (first, last, back_inserter(v)); + PrintVector (v); + v.assign (first, last); + + cout << "copy with inserter\n"; + v.clear(); + copy (first, first + 5, inserter(v, v.begin())); + copy (first, first + 5, inserter(v, v.begin() + 3)); + PrintVector (v); + v.assign (first, last); + + cout << "copy_n(0,8,9)\n"; + copy_n (v.begin(), 8, v.begin() + 9); + PrintVector (v); + v.assign (first, last); + + cout << "copy_if(is_even)\n"; + intvec_t v_even; + copy_if (v, back_inserter(v_even), &is_even); + PrintVector (v_even); + v.assign (first, last); + + cout << "for_each(printint)\n{ "; + for_each (v, &printint); + cout << "}\n"; + + cout << "for_each(reverse_iterator, printint)\n{ "; + for_each (v.rbegin(), v.rend(), &printint); + cout << "}\n"; + + cout << "find(10)\n"; + cout.format ("10 found at offset %zd\n", abs_distance (v.begin(), find (v, 10))); + + cout << "count(13)\n"; + cout.format ("%zu values of 13, %zu values of 18\n", count(v,13), count(v,18)); + + cout << "transform(sqr)\n"; + transform (v, &sqr); + PrintVector (v); + v.assign (first, last); + + cout << "replace(13,666)\n"; + replace (v, 13, 666); + PrintVector (v); + v.assign (first, last); + + cout << "fill(13)\n"; + fill (v, 13); + PrintVector (v); + v.assign (first, last); + + cout << "fill_n(5, 13)\n"; + fill_n (v.begin(), 5, 13); + PrintVector (v); + v.assign (first, last); + + cout << "fill 64083 uint8_t(0x41) "; + TestBigFill<uint8_t> (64083, 0x41); + cout << "fill 64083 uint16_t(0x4142) "; + TestBigFill<uint16_t> (64083, 0x4142); + cout << "fill 64083 uint32_t(0x41424344) "; + TestBigFill<uint32_t> (64083, 0x41424344); + cout << "fill 64083 float(0.4242) "; + TestBigFill<float> (64083, 0x4242f); +#if HAVE_INT64_T + cout << "fill 64083 uint64_t(0x4142434445464748) "; + TestBigFill<uint64_t> (64083, UINT64_C(0x4142434445464748)); +#else + cout << "No 64bit types available on this platform\n"; +#endif + + cout << "copy 64083 uint8_t(0x41) "; + TestBigCopy<uint8_t> (64083, 0x41); + cout << "copy 64083 uint16_t(0x4142) "; + TestBigCopy<uint16_t> (64083, 0x4142); + cout << "copy 64083 uint32_t(0x41424344) "; + TestBigCopy<uint32_t> (64083, 0x41424344); + cout << "copy 64083 float(0.4242) "; + TestBigCopy<float> (64083, 0.4242f); +#if HAVE_INT64_T + cout << "copy 64083 uint64_t(0x4142434445464748) "; + TestBigCopy<uint64_t> (64083, UINT64_C(0x4142434445464748)); +#else + cout << "No 64bit types available on this platform\n"; +#endif + + cout << "generate(genint)\n"; + generate (v, &genint); + PrintVector (v); + v.assign (first, last); + + cout << "rotate(4)\n"; + rotate (v, 7); + rotate (v, -3); + PrintVector (v); + v.assign (first, last); + + cout << "merge with (3,5,10,11,11,14)\n"; + const int c_MergeWith[] = { 3,5,10,11,11,14 }; + intvec_t vmerged; + merge (v.begin(), v.end(), VectorRange(c_MergeWith), back_inserter(vmerged)); + PrintVector (vmerged); + v.assign (first, last); + + cout << "inplace_merge with (3,5,10,11,11,14)\n"; + v.insert (v.end(), VectorRange(c_MergeWith)); + inplace_merge (v.begin(), v.end() - VectorSize(c_MergeWith), v.end()); + PrintVector (v); + v.assign (first, last); + + cout << "remove(13)\n"; + remove (v, 13); + PrintVector (v); + v.assign (first, last); + + cout << "remove (elements 3, 4, 6, 15, and 45)\n"; + vector<uoff_t> toRemove; + toRemove.push_back (3); + toRemove.push_back (4); + toRemove.push_back (6); + toRemove.push_back (15); + toRemove.push_back (45); + typedef index_iterate<intvec_t::iterator, vector<uoff_t>::iterator> riiter_t; + riiter_t rfirst = index_iterator (v.begin(), toRemove.begin()); + riiter_t rlast = index_iterator (v.begin(), toRemove.end()); + remove (v, rfirst, rlast); + PrintVector (v); + v.assign (first, last); + + cout << "unique\n"; + unique (v); + PrintVector (v); + v.assign (first, last); + + cout << "reverse\n"; + reverse (v); + PrintVector (v); + v.assign (first, last); + + cout << "lower_bound(10)\n"; + PrintVector (v); + cout.format ("10 begins at position %zd\n", abs_distance (v.begin(), lower_bound (v, 10))); + v.assign (first, last); + + cout << "upper_bound(10)\n"; + PrintVector (v); + cout.format ("10 ends at position %zd\n", abs_distance (v.begin(), upper_bound (v, 10))); + v.assign (first, last); + + cout << "equal_range(10)\n"; + PrintVector (v); + TestEqualRange (v); + v.assign (first, last); + + cout << "sort\n"; + reverse (v); + PrintVector (v); + random_shuffle (v); + sort (v); + PrintVector (v); + v.assign (first, last); + + cout << "stable_sort\n"; + reverse (v); + PrintVector (v); + random_shuffle (v); + stable_sort (v); + PrintVector (v); + v.assign (first, last); + + cout << "is_sorted\n"; + random_shuffle (v); + const bool bNotSorted = is_sorted (v.begin(), v.end()); + sort (v); + const bool bSorted = is_sorted (v.begin(), v.end()); + cout << "unsorted=" << bNotSorted << ", sorted=" << bSorted << endl; + v.assign (first, last); + + cout << "find_first_of\n"; + static const int c_FFO[] = { 10000, -34, 14, 27 }; + cout.format ("found 14 at position %zd\n", abs_distance (v.begin(), find_first_of (v.begin(), v.end(), VectorRange(c_FFO)))); + v.assign (first, last); + + static const int LC1[] = { 3, 1, 4, 1, 5, 9, 3 }; + static const int LC2[] = { 3, 1, 4, 2, 8, 5, 7 }; + static const int LC3[] = { 1, 2, 3, 4 }; + static const int LC4[] = { 1, 2, 3, 4, 5 }; + cout << "lexicographical_compare"; + cout << "\nLC1 < LC2 == " << lexicographical_compare (VectorRange(LC1), VectorRange(LC2)); + cout << "\nLC2 < LC2 == " << lexicographical_compare (VectorRange(LC2), VectorRange(LC2)); + cout << "\nLC3 < LC4 == " << lexicographical_compare (VectorRange(LC3), VectorRange(LC4)); + cout << "\nLC4 < LC1 == " << lexicographical_compare (VectorRange(LC4), VectorRange(LC1)); + cout << "\nLC1 < LC4 == " << lexicographical_compare (VectorRange(LC1), VectorRange(LC4)); + + cout << "\nmax_element\n"; + cout.format ("max element is %d\n", *max_element (v.begin(), v.end())); + v.assign (first, last); + + cout << "min_element\n"; + cout.format ("min element is %d\n", *min_element (v.begin(), v.end())); + v.assign (first, last); + + cout << "partial_sort\n"; + reverse (v); + partial_sort (v.begin(), v.iat(v.size() / 2), v.end()); + PrintVector (v); + v.assign (first, last); + + cout << "partial_sort_copy\n"; + reverse (v); + buf.resize (v.size()); + partial_sort_copy (v.begin(), v.end(), buf.begin(), buf.end()); + PrintVector (buf); + v.assign (first, last); + + cout << "partition\n"; + partition (v.begin(), v.end(), &is_even); + PrintVector (v); + v.assign (first, last); + + cout << "stable_partition\n"; + stable_partition (v.begin(), v.end(), &is_even); + PrintVector (v); + v.assign (first, last); + + cout << "next_permutation\n"; + buf.resize (3); + iota (buf.begin(), buf.end(), 1); + PrintVector (buf); + while (next_permutation (buf.begin(), buf.end())) + PrintVector (buf); + cout << "prev_permutation\n"; + reverse (buf); + PrintVector (buf); + while (prev_permutation (buf.begin(), buf.end())) + PrintVector (buf); + v.assign (first, last); + + cout << "reverse_copy\n"; + buf.resize (v.size()); + reverse_copy (v.begin(), v.end(), buf.begin()); + PrintVector (buf); + v.assign (first, last); + + cout << "rotate_copy\n"; + buf.resize (v.size()); + rotate_copy (v.begin(), v.iat (v.size() / 3), v.end(), buf.begin()); + PrintVector (buf); + v.assign (first, last); + + static const int c_Search1[] = { 5, 6, 7, 8, 9 }, c_Search2[] = { 10, 10, 11, 14 }; + cout << "search\n"; + cout.format ("{5,6,7,8,9} at %zd\n", abs_distance (v.begin(), search (v.begin(), v.end(), VectorRange(c_Search1)))); + cout.format ("{10,10,11,14} at %zd\n", abs_distance (v.begin(), search (v.begin(), v.end(), VectorRange(c_Search2)))); + cout << "find_end\n"; + cout.format ("{5,6,7,8,9} at %zd\n", abs_distance (v.begin(), find_end (v.begin(), v.end(), VectorRange(c_Search1)))); + cout.format ("{10,10,11,14} at %zd\n", abs_distance (v.begin(), find_end (v.begin(), v.end(), VectorRange(c_Search2)))); + cout << "search_n\n"; + cout.format ("{14} at %zd\n", abs_distance (v.begin(), search_n (v.begin(), v.end(), 1, 14))); + cout.format ("{13,13} at %zd\n", abs_distance (v.begin(), search_n (v.begin(), v.end(), 2, 13))); + cout.format ("{10,10,10} at %zd\n", abs_distance (v.begin(), search_n (v.begin(), v.end(), 3, 10))); + v.assign (first, last); + + cout << "includes\n"; + static const int c_Includes[] = { 5, 14, 15, 18, 20 }; + cout << "includes=" << includes (v.begin(), v.end(), VectorRange(c_Includes)-1); + cout << ", not includes=" << includes (v.begin(), v.end(), VectorRange(c_Includes)); + cout << endl; + + static const int c_Set1[] = { 1, 2, 3, 4, 5, 6 }, c_Set2[] = { 4, 4, 6, 7, 8 }; + intvec_t::iterator setEnd; + cout << "set_difference\n"; + v.resize (4); + setEnd = set_difference (VectorRange(c_Set1), VectorRange(c_Set2), v.begin()); + PrintVector (v); + assert (setEnd == v.end()); + cout << "set_symmetric_difference\n"; + v.resize (7); + setEnd = set_symmetric_difference (VectorRange(c_Set1), VectorRange(c_Set2), v.begin()); + PrintVector (v); + assert (setEnd == v.end()); + cout << "set_intersection\n"; + v.resize (2); + setEnd = set_intersection (VectorRange(c_Set1), VectorRange(c_Set2), v.begin()); + PrintVector (v); + assert (setEnd == v.end()); + cout << "set_union\n"; + v.resize (9); + setEnd = set_union (VectorRange(c_Set1), VectorRange(c_Set2), v.begin()); + PrintVector (v); + assert (setEnd == v.end()); + v.assign (first, last); +} + +StdBvtMain (TestAlgorithms)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt05.std @@ -0,0 +1,132 @@ +{ 1 2 3 4 5 6 7 8 9 10 10 11 12 13 13 14 15 16 17 18 } +swap(1,2) +{ 2 1 3 4 5 6 7 8 9 10 10 11 12 13 13 14 15 16 17 18 } +copy(0,8,9) +{ 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 16 17 18 } +copy with back_inserter +{ 1 2 3 4 5 6 7 8 9 10 10 11 12 13 13 14 15 16 17 18 } +copy with inserter +{ 1 2 3 1 2 3 4 5 4 5 } +copy_n(0,8,9) +{ 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 16 17 18 } +copy_if(is_even) +{ 2 4 6 8 10 10 12 14 16 18 } +for_each(printint) +{ 1 2 3 4 5 6 7 8 9 10 10 11 12 13 13 14 15 16 17 18 } +for_each(reverse_iterator, printint) +{ 18 17 16 15 14 13 13 12 11 10 10 9 8 7 6 5 4 3 2 1 } +find(10) +10 found at offset 9 +count(13) +2 values of 13, 1 values of 18 +transform(sqr) +{ 1 4 9 16 25 36 49 64 81 100 100 121 144 169 169 196 225 256 289 324 } +replace(13,666) +{ 1 2 3 4 5 6 7 8 9 10 10 11 12 666 666 14 15 16 17 18 } +fill(13) +{ 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 } +fill_n(5, 13) +{ 13 13 13 13 13 6 7 8 9 10 10 11 12 13 13 14 15 16 17 18 } +fill 64083 uint8_t(0x41) works +fill 64083 uint16_t(0x4142) works +fill 64083 uint32_t(0x41424344) works +fill 64083 float(0.4242) works +fill 64083 uint64_t(0x4142434445464748) works +copy 64083 uint8_t(0x41) works +copy 64083 uint16_t(0x4142) works +copy 64083 uint32_t(0x41424344) works +copy 64083 float(0.4242) works +copy 64083 uint64_t(0x4142434445464748) works +generate(genint) +{ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 } +rotate(4) +{ 15 16 17 18 1 2 3 4 5 6 7 8 9 10 10 11 12 13 13 14 } +merge with (3,5,10,11,11,14) +{ 1 2 3 3 4 5 5 6 7 8 9 10 10 10 11 11 11 12 13 13 14 14 15 16 17 18 } +inplace_merge with (3,5,10,11,11,14) +{ 1 2 3 3 4 5 5 6 7 8 9 10 10 10 11 11 11 12 13 13 14 14 15 16 17 18 } +remove(13) +{ 1 2 3 4 5 6 7 8 9 10 10 11 12 14 15 16 17 18 } +remove (elements 3, 4, 6, 15, and 45) +{ 1 2 3 6 8 9 10 10 11 12 13 13 15 16 17 18 } +unique +{ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 } +reverse +{ 18 17 16 15 14 13 13 12 11 10 10 9 8 7 6 5 4 3 2 1 } +lower_bound(10) +{ 1 2 3 4 5 6 7 8 9 10 10 11 12 13 13 14 15 16 17 18 } +10 begins at position 9 +upper_bound(10) +{ 1 2 3 4 5 6 7 8 9 10 10 11 12 13 13 14 15 16 17 18 } +10 ends at position 11 +equal_range(10) +{ 1 2 3 4 5 6 7 8 9 10 10 11 12 13 13 14 15 16 17 18 } +Range of 10 is { 9, 11 } +Range of 0 is { 0, 0 } +Range of 100 is { 20, 20 } +sort +{ 18 17 16 15 14 13 13 12 11 10 10 9 8 7 6 5 4 3 2 1 } +{ 1 2 3 4 5 6 7 8 9 10 10 11 12 13 13 14 15 16 17 18 } +stable_sort +{ 18 17 16 15 14 13 13 12 11 10 10 9 8 7 6 5 4 3 2 1 } +{ 1 2 3 4 5 6 7 8 9 10 10 11 12 13 13 14 15 16 17 18 } +is_sorted +unsorted=false, sorted=true +find_first_of +found 14 at position 15 +lexicographical_compare +LC1 < LC2 == true +LC2 < LC2 == false +LC3 < LC4 == true +LC4 < LC1 == true +LC1 < LC4 == false +max_element +max element is 18 +min_element +min element is 1 +partial_sort +{ 1 2 3 4 5 6 7 8 9 10 10 11 12 13 13 14 15 16 17 18 } +partial_sort_copy +{ 1 2 3 4 5 6 7 8 9 10 10 11 12 13 13 14 15 16 17 18 } +partition +{ 2 4 6 8 10 10 12 14 16 18 1 3 5 7 9 11 13 13 15 17 } +stable_partition +{ 2 4 6 8 10 10 12 14 16 18 1 3 5 7 9 11 13 13 15 17 } +next_permutation +{ 1 2 3 } +{ 1 3 2 } +{ 2 1 3 } +{ 2 3 1 } +{ 3 1 2 } +{ 3 2 1 } +prev_permutation +{ 3 2 1 } +{ 3 1 2 } +{ 2 3 1 } +{ 2 1 3 } +{ 1 3 2 } +{ 1 2 3 } +reverse_copy +{ 18 17 16 15 14 13 13 12 11 10 10 9 8 7 6 5 4 3 2 1 } +rotate_copy +{ 7 8 9 10 10 11 12 13 13 14 15 16 17 18 1 2 3 4 5 6 } +search +{5,6,7,8,9} at 4 +{10,10,11,14} at 20 +find_end +{5,6,7,8,9} at 4 +{10,10,11,14} at 20 +search_n +{14} at 15 +{13,13} at 13 +{10,10,10} at 20 +includes +includes=true, not includes=false +set_difference +{ 1 2 3 5 } +set_symmetric_difference +{ 1 2 3 4 5 7 8 } +set_intersection +{ 4 6 } +set_union +{ 1 2 3 4 4 5 6 7 8 }
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt06.cpp @@ -0,0 +1,59 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +void PrintBlock (const cmemlink& l) +{ + const int* numbers = reinterpret_cast<const int*>(l.begin()); + const size_t nNumbers = l.size() / sizeof(int); + for (size_t i = 0; i < nNumbers; ++ i) + cout << numbers[i] << ' '; + cout << endl; +} + +void TestObjectVector (void) +{ + vector<memblock> v; + const size_t nNumbers = 1000; + int numbers [nNumbers]; + const size_t nLinks = 10; + cmemlink links [nLinks]; + for (size_t i = 0; i < nNumbers; ++ i) + numbers[i] = i; + uoff_t offset = 0; + for (size_t l = 0; l < nLinks; ++ l) { + links[l].link (numbers + offset, l * sizeof(int)); + offset += l; + v.push_back (memblock(links[l])); + } + cout.format ("---\nvector<memblock> of %zu elements:\n---\n", v.size()); + for_each (v.begin(), v.end(), &PrintBlock); + cout.format ("---\nsize() = %zu, max_size() = ", v.size()); + if (v.max_size() == SIZE_MAX / sizeof(memblock)) + cout << "SIZE_MAX/elsize"; + else + cout << v.max_size(); + static const char tf[2][6]={"false","true"}; + cout.format (", empty() = %s\n", tf[v.empty()]); + v.push_back (memblock(5)); + cout.format ("back()->size() = %zu\n", v.back().size()); + v.back().resize (40); + cout.format ("back()->size() = %zu\n", v.back().size()); + v.pop_back(); + PrintBlock (v.back()); + vector<memblock> cache; + cache.assign (v.begin(), v.end()); + v.clear(); + v.assign (cache.begin(), cache.end()); + v.erase (v.begin() + 5, 2); + v.erase (v.end() - 1, 1); + v.erase (v.end(), streamsize(0)); + cout.format ("---\nvector of %zu elements backwards:\n---\n", v.size()); + for_each (v.rbegin(), v.rend(), &PrintBlock); + cout << "---\n"; +} + +StdBvtMain (TestObjectVector)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt06.std @@ -0,0 +1,29 @@ +--- +vector<memblock> of 10 elements: +--- + +0 +1 2 +3 4 5 +6 7 8 9 +10 11 12 13 14 +15 16 17 18 19 20 +21 22 23 24 25 26 27 +28 29 30 31 32 33 34 35 +36 37 38 39 40 41 42 43 44 +--- +size() = 10, max_size() = SIZE_MAX/elsize, empty() = false +back()->size() = 5 +back()->size() = 40 +36 37 38 39 40 41 42 43 44 +--- +vector of 7 elements backwards: +--- +28 29 30 31 32 33 34 35 +21 22 23 24 25 26 27 +6 7 8 9 +3 4 5 +1 2 +0 + +---
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt07.cpp @@ -0,0 +1,138 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +void MyFormat (const char* fmt, ...) __attribute__((__format__(__printf__,1,2))); + +void TestString (void) +{ + static const char c_TestString1[] = "123456789012345678901234567890"; + static const char c_TestString2[] = "abcdefghijklmnopqrstuvwxyz"; + static const char c_TestString3[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + string s1 (c_TestString1); + string s2 (VectorRange (c_TestString2)); + string s3 (s1); + + cout << s1 << endl; + cout << s2 << endl; + cout << s3 << endl; + s3.reserve (48); + s3.resize (20); + + uoff_t i; + for (i = 0; i < s3.length(); ++ i) + s3.at(i) = s3.at(i); + for (i = 0; i < s3.length(); ++ i) + s3[i] = s3[i]; + cout.format ("%s\ns3.size() = %zu, max_size() = ", s3.c_str(), s3.size()); + if (s3.max_size() == SIZE_MAX - 1) + cout << "(SIZE_MAX/elsize)-1"; + else + cout << s3.max_size(); + cout.format (", capacity() = %zu\n", s3.capacity()); + + s1.unlink(); + s1 = c_TestString2; + s1 += c_TestString3; + s1 += '$'; + cout << s1 << endl; + + s1 = "Hello"; + s2.unlink(); + s2 = "World"; + s3 = s1 + s2; + cout << s3 << endl; + s3 = "Concatenated "; + s3 += s1.c_str(); + s3 += s2; + s3 += " string."; + cout << s3 << endl; + + if (s1 < s2) + cout << "s1 < s2\n"; + if (s1 == s1) + cout << "s1 == s1\n"; + if (s1[0] != s1[0]) + cout << "s1[0] != s1[0]\n"; + + string s4; + s4.link (s1); + if (s1 == s4) + cout << "s1 == s4\n"; + + s1 = c_TestString1; + string s5 (s1.begin() + 4, s1.begin() + 4 + 5); + string s6 (s1.begin() + 4, s1.begin() + 4 + 5); + if (s5 == s6) + cout.format ("%s == %s\n", s5.c_str(), s6.c_str()); + string tail (s1.begin() + 7, s1.end()); + cout.format ("&s1[7] = %s\n", tail.c_str()); + + cout.format ("initial:\t\t%s\n", s1.c_str()); + cout << "erase(5,find(9)-5)\t"; + s1.erase (5, s1.find ('9')-5); + cout << s1 << endl; + cout << "erase(5,5)\t\t"; + s1.erase (s1.begin() + 5, 2U); + s1.erase (5, 3); + assert (!*s1.end()); + cout << s1 << endl; + cout << "push_back('x')\t\t"; + s1.push_back ('x'); + assert (!*s1.end()); + cout << s1 << endl; + cout << "pop_back()\n"; + s1.pop_back(); + assert (!*s1.end()); + cout << "insert(10,#)\t\t"; + s1.insert (s1.begin() + 10, '#'); + assert (!*s1.end()); + cout << s1 << endl; + cout << "replace(0,5,@)\t\t"; + s1.replace (s1.begin(), s1.begin() + 5, 1, '@'); + assert (!*s1.end()); + cout << s1 << endl; + + s1 = c_TestString1; + cout.format ("8 found at %zu\n", s1.find ('8')); + cout.format ("9 found at %zu\n", s1.find ("9")); + cout.format ("7 rfound at %zu\n", s1.rfind ('7')); + cout.format ("7 rfound again at %zu\n", s1.rfind ('7', s1.rfind ('7') - 1)); + cout.format ("67 rfound at %zu\n", s1.rfind ("67")); + if (s1.rfind("X") == string::npos) + cout << "X was not rfound\n"; + else + cout.format ("X rfound at %zu\n", s1.rfind ("X")); + uoff_t poundfound = s1.find ("#"); + if (poundfound != string::npos) + cout.format ("# found at %zu\n", poundfound); + cout.format ("[456] found at %zu\n", s1.find_first_of ("456")); + cout.format ("[456] last found at %zu\n", s1.find_last_of ("456")); + + s2.clear(); + assert (!*s2.end()); + if (s2.empty()) + cout.format ("s2 is empty [%s], capacity %zu bytes\n", s2.c_str(), s2.capacity()); + + s2.format ("<const] %d, %s, 0x%08X", 42, "[rfile>", 0xDEADBEEF); + cout.format ("<%zu bytes of %zu> Format '%s'\n", s2.length(), s2.capacity(), s2.c_str()); + MyFormat ("'<const] %d, %s, 0x%08X'", 42, "[rfile>", 0xDEADBEEF); + + cout.format ("hash_value(s2) = %08X, string::hash(s2) = %08X\n", hash_value (s2.begin()), string::hash (s2.begin(), s2.end())); +} + +void MyFormat (const char* fmt, ...) +{ + string buf; + simd::reset_mmx(); + va_list args; + va_start (args, fmt); + buf.vformat (fmt, args); + cout.format ("Custom vararg MyFormat: %s\n", buf.c_str()); + va_end (args); +} + +StdBvtMain (TestString)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt07.std @@ -0,0 +1,32 @@ +123456789012345678901234567890 +abcdefghijklmnopqrstuvwxyz +123456789012345678901234567890 +12345678901234567890 +s3.size() = 20, max_size() = (SIZE_MAX/elsize)-1, capacity() = 48 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$ +HelloWorld +Concatenated HelloWorld string. +s1 < s2 +s1 == s1 +s1 == s4 +56789 == 56789 +&s1[7] = 89012345678901234567890 +initial: 123456789012345678901234567890 +erase(5,find(9)-5) 123459012345678901234567890 +erase(5,5) 1234545678901234567890 +push_back('x') 1234545678901234567890x +pop_back() +insert(10,#) 1234545678#901234567890 +replace(0,5,@) @45678#901234567890 +8 found at 7 +9 found at 8 +7 rfound at 26 +7 rfound again at 16 +67 rfound at 25 +X was not rfound +[456] found at 3 +[456] last found at 25 +s2 is empty [], capacity 5 bytes +<31 bytes of 31> Format '<const] 42, [rfile>, 0xDEADBEEF' +Custom vararg MyFormat: '<const] 42, [rfile>, 0xDEADBEEF' +hash_value(s2) = 95A714F3, string::hash(s2) = 95A714F3
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt08.cpp @@ -0,0 +1,57 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +inline void PrintString (const string& str) +{ + cout << str << endl; +} + +void TestStringVector (void) +{ + vector<string> v; + + vector<string>::iterator bogusi = find (v, string("bogus")); + if (bogusi != v.end()) + cout << "bogus found at position " << bogusi - v.begin() << endl; + + v.push_back (string("Hello world!")); + v.push_back (string("Hello again!")); + v.push_back (string("element3")); + v.push_back (string("element4")); + v.push_back (string("element5_long_element5")); + for_each (v, &PrintString); + + if (!(v[2] == string("element3"))) + cout << "operator== failed" << endl; + vector<string>::iterator el3i = find (v, string("element3")); + if (el3i != v.end()) + cout << *el3i << " found at position " << el3i - v.begin() << endl; + bogusi = find (v, string("bogus")); + if (bogusi != v.end()) + cout << *bogusi << " found at position " << bogusi - v.begin()<< endl; + + vector<string> v2; + v2 = v; + v = v2; + v.erase (v.end(), v.end()); + cout << "After erase (end,end):" << endl; + for_each (v, &PrintString); + v = v2; + v.erase (v.begin() + 2, 2); + cout << "After erase (2,2):" << endl; + for_each (v, &PrintString); + v = v2; + v.pop_back(); + cout << "After pop_back():" << endl; + for_each (v, &PrintString); + v = v2; + v.insert (v.begin() + 1, v2.begin() + 1, v2.begin() + 1 + 3); + cout << "After insert(1,1,3):" << endl; + for_each (v, &PrintString); +} + +StdBvtMain (TestStringVector)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt08.std @@ -0,0 +1,30 @@ +Hello world! +Hello again! +element3 +element4 +element5_long_element5 +element3 found at position 2 +After erase (end,end): +Hello world! +Hello again! +element3 +element4 +element5_long_element5 +After erase (2,2): +Hello world! +Hello again! +element5_long_element5 +After pop_back(): +Hello world! +Hello again! +element3 +element4 +After insert(1,1,3): +Hello world! +Hello again! +element3 +element4 +Hello again! +element3 +element4 +element5_long_element5
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt09.cpp @@ -0,0 +1,84 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +void TestStringStreams (void) +{ + const unsigned char magic_Char = 'c'; + const unsigned short magic_Short = 1234; + const long magic_Int = -12345678; + const unsigned long magic_UInt = 12345678; + const float magic_Float = 123.45678; + const double magic_Double = 123456789123456.789; + const bool magic_Bool = true; + + char c = magic_Char; + unsigned char uc = magic_Char; + int i = magic_Int; + short si = magic_Short; + long li = magic_Int; + unsigned int ui = magic_UInt; + unsigned short usi = magic_Short; + unsigned long uli = magic_UInt; + float f = magic_Float; + double d = magic_Double; + bool bv = magic_Bool; + + ostringstream os; + os << c << endl; + os << uc << endl; + os << bv << endl; + os << i << endl; + os << ui << endl; + os << li << endl; + os << uli << endl; + os << f << endl; + os << d << endl; + os << si << endl; + os << usi << endl << ends; + os.flush(); + cout << os.pos() << " bytes written" << endl; + + c = 0; + uc = 0; + bv = false; + i = ui = li = uli = 0; + f = 0; d = 0; + si = usi = 0; + + istringstream is (os.str()); + is >> c; + is >> uc; + is >> bv; + is >> i; + is >> ui; + is >> li; + is >> uli; + is >> f; + is >> d; + is >> si; + is >> usi; + + cout << "Values:" << endl; + cout.format ("char: '%c'\n", static_cast<int>(c)); + cout.format ("u_char: '%c'\n", static_cast<int>(uc)); + cout.format ("bool: %d\n", static_cast<int>(bv)); + cout.format ("int: %d\n", i); + cout.format ("u_int: %d\n", ui); + cout.format ("long: %ld\n", li); + cout.format ("u_long: %ld\n", uli); + cout.format ("float: %.2f\n", f); + cout.format ("double: %.2f\n", d); + cout.format ("short: %hd\n", static_cast<int>(si)); + cout.format ("u_short: %hd\n", static_cast<int>(usi)); + cout << endl; + + cout << "Dump:" << endl; + cout << os.str().cdata() << endl; + cout << endl; +} + +StdBvtMain (TestStringStreams)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt09.std @@ -0,0 +1,28 @@ +84 bytes written +Values: +char: 'c' +u_char: 'c' +bool: 1 +int: -12345678 +u_int: 12345678 +long: -12345678 +u_long: 12345678 +float: 123.46 +double: 123456789123456.78 +short: 1234 +u_short: 1234 + +Dump: +c +c +true +-12345678 +12345678 +-12345678 +12345678 +123.46 +123456789123456.78 +1234 +1234 + +
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt10.cpp @@ -0,0 +1,171 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +template <typename Container> +void PrintVector (const Container& ctr) +{ + cout << "{"; + foreach (typename Container::const_iterator, i, ctr) + cout << ' ' << *i; + cout << " }\n"; +} + +class A { +public: + A (int dv = 6) : m_v1 (0), m_v (dv) {} + int addsix (int i) { return (i + m_v); } + void addsix (int& i) const { i += m_v; } + void addtosix (int i) { m_v += i; } + inline void text_write (ostringstream& os) const { os << m_v; } +public: + int m_v1; + int m_v; +}; + +INTEGRAL_STREAMABLE(A) +TEXT_STREAMABLE(A) + +void TestFunctors (void) +{ + vector<int> v; + v.resize (20); + fill (v, 2); + foreach (vector<int>::iterator, i, v) + *i -= distance(v.begin(), i) & 1; + vector<int> v1 (v); + + cout << "start:\t\t\t"; + PrintVector (v); + + v = v1; + cout << "plus:\t\t\t"; + transform (v, v.begin(), v.begin(), plus<int>()); + PrintVector (v); + + v = v1; + cout << "minus:\t\t\t"; + transform (v, v.begin(), v.begin(), minus<int>()); + PrintVector (v); + + v = v1; + cout << "divides:\t\t"; + transform (v, v.begin(), v.begin(), divides<int>()); + PrintVector (v); + + v = v1; + cout << "multiplies:\t\t"; + transform (v, v.begin(), v.begin(), multiplies<int>()); + PrintVector (v); + + v = v1; + cout << "modulus:\t\t"; + transform (v, v.begin(), v.begin(), modulus<int>()); + PrintVector (v); + + v = v1; + cout << "logical_and:\t\t"; + transform (v, v.begin(), v.begin(), logical_and<int>()); + PrintVector (v); + + v = v1; + cout << "logical_or:\t\t"; + transform (v, v.begin(), v.begin(), logical_or<int>()); + PrintVector (v); + + v = v1; + cout << "equal_to:\t\t"; + transform (v, v.begin(), v.begin(), equal_to<int>()); + PrintVector (v); + + v = v1; + cout << "not_equal_to:\t\t"; + transform (v, v.begin(), v.begin(), not_equal_to<int>()); + PrintVector (v); + + v = v1; + cout << "greater:\t\t"; + transform (v, v.begin(), v.begin(), greater<int>()); + PrintVector (v); + + v = v1; + cout << "less:\t\t\t"; + transform (v, v.begin(), v.begin(), less<int>()); + PrintVector (v); + + v = v1; + cout << "greater_equal:\t\t"; + transform (v, v.begin(), v.begin(), greater_equal<int>()); + PrintVector (v); + + v = v1; + cout << "less_equal:\t\t"; + transform (v, v.begin(), v.begin(), less_equal<int>()); + PrintVector (v); + + v = v1; + cout << "compare:\t\t"; + transform (v, v.begin(), v.begin(), compare<int>()); + PrintVector (v); + + v = v1; + cout << "negate:\t\t\t"; + transform (v, negate<int>()); + PrintVector (v); + + v = v1; + cout << "logical_not:\t\t"; + transform (v, logical_not<int>()); + PrintVector (v); + + v = v1; + cout << "unary_neg(negate):\t"; + transform (v, unary_negator(negate<int>())); + PrintVector (v); + + v = v1; + cout << "binder1st(plus,5):\t"; + transform (v, bind1st(plus<int>(), 5)); + PrintVector (v); + + v = v1; + cout << "binder2nd(minus,1):\t"; + transform (v, bind2nd(minus<int>(), 1)); + PrintVector (v); + + v = v1; + cout << "compose1(-,+5):\t\t"; + transform (v, compose1 (negate<int>(), bind2nd(plus<int>(), 5))); + PrintVector (v); + + v = v1; + cout << "compose1(-,-4):\t\t"; + transform (v, compose1 (negate<int>(), bind2nd(minus<int>(), 4))); + PrintVector (v); + + v = v1; + cout << "compose2(/,+6,-4):\t"; + transform (v, compose2 (divides<int>(), bind2nd(plus<int>(), 6), bind2nd(minus<int>(), 4))); + PrintVector (v); + + cout << "mem_var(plus,6):\t"; + vector<A> av; + for (uoff_t i = 0; i < 20; ++ i) + av.push_back (A(i)); + transform (av, mem_var1(&A::m_v, bind2nd(plus<int>(), 6))); + PrintVector (av); + + vector<A>::iterator found = find_if (av, mem_var_equal_to(&A::m_v, 14)); + cout << "14 found at position " << found - av.begin() << endl; + found = lower_bound (av.begin(), av.end(), 18, mem_var_less(&A::m_v)); + cout << "18 found at position " << found - av.begin() << endl; + + cout << "add next:\t\t"; + transform (av.begin(), av.end() - 1, av.begin() + 1, av.begin(), mem_var2(&A::m_v, plus<int>())); + PrintVector (av); +} + +StdBvtMain (TestFunctors)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt10.std @@ -0,0 +1,27 @@ +start: { 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 } +plus: { 4 2 4 2 4 2 4 2 4 2 4 2 4 2 4 2 4 2 4 2 } +minus: { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 } +divides: { 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 } +multiplies: { 4 1 4 1 4 1 4 1 4 1 4 1 4 1 4 1 4 1 4 1 } +modulus: { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 } +logical_and: { 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 } +logical_or: { 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 } +equal_to: { 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 } +not_equal_to: { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 } +greater: { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 } +less: { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 } +greater_equal: { 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 } +less_equal: { 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 } +compare: { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 } +negate: { -2 -1 -2 -1 -2 -1 -2 -1 -2 -1 -2 -1 -2 -1 -2 -1 -2 -1 -2 -1 } +logical_not: { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 } +unary_neg(negate): { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 } +binder1st(plus,5): { 7 6 7 6 7 6 7 6 7 6 7 6 7 6 7 6 7 6 7 6 } +binder2nd(minus,1): { 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 } +compose1(-,+5): { -7 -6 -7 -6 -7 -6 -7 -6 -7 -6 -7 -6 -7 -6 -7 -6 -7 -6 -7 -6 } +compose1(-,-4): { 2 3 2 3 2 3 2 3 2 3 2 3 2 3 2 3 2 3 2 3 } +compose2(/,+6,-4): { -4 -2 -4 -2 -4 -2 -4 -2 -4 -2 -4 -2 -4 -2 -4 -2 -4 -2 -4 -2 } +mem_var(plus,6): { 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 } +14 found at position 8 +18 found at position 12 +add next: { 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 25 }
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt11.cpp @@ -0,0 +1,36 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +void PrintVector (const int* first, const int* last) +{ + cout << "{"; + while (first < last) + cout << ' ' << *first++; + cout << " }" << endl; +} + +void TestSetAndMultiset (void) +{ + const int vv[] = { 1, 8, 9, 2, 3, 1, 1, 4, 6, 1, 3, 4 }; + set<int> v (VectorRange (vv)); + multiset<int> mv (VectorRange (vv)); + cout << "set:\t\t"; + PrintVector (v.begin(), v.end()); + cout << "erase(3):\t"; + v.erase (3); + PrintVector (v.begin(), v.end()); + cout << "multiset:\t"; + PrintVector (mv.begin(), mv.end()); + cout << "count(1) = " << mv.count(1) << endl; + cout << "find(4) = " << lower_bound (mv, 4) - mv.begin() << endl; + cout << "find(5) = " << binary_search (mv, 5) << endl; + cout << "erase(3):\t"; + mv.erase (3); + PrintVector (mv.begin(), mv.end()); +} + +StdBvtMain (TestSetAndMultiset)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt11.std @@ -0,0 +1,7 @@ +set: { 1 2 3 4 6 8 9 } +erase(3): { 1 2 4 6 8 9 } +multiset: { 1 1 1 1 2 3 3 4 4 6 8 9 } +count(1) = 4 +find(4) = 7 +find(5) = false +erase(3): { 1 1 1 1 2 4 4 6 8 9 }
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt12.cpp @@ -0,0 +1,81 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +void ObjectSerialization (void) +{ + #define RW(stream) rws[stream.pos() == expect] + const void* pBufC = NULL; + void* pBuf = NULL; + memblock buffer; + string testString ("TestString"); + const string* pStrC = NULL; + string* pStr = NULL; + vector<uint16_t> tv (7); + static const char* rws[2] = { "wrong", "right" }; + + const size_t bufSize = stream_size_of(pBufC) + + stream_size_of(pBuf) + + Align(stream_size_of(testString)) + + stream_size_of(pStrC) + + stream_size_of(pStr) + + stream_size_of(tv); + buffer.resize (bufSize); + pBufC = buffer.cdata(); + pBuf = buffer.data(); + + uoff_t expect = 0; + ostream os (buffer); + os << pBufC; expect += stream_size_of(pBufC); + cout << "Write const void*, pos is " << RW(os) << endl; + os << pBuf; expect += stream_size_of(pBuf); + cout << "Write void*, pos is " << RW(os) << endl; + os << testString; expect += stream_size_of(testString); + cout << "Write string, pos is " << RW(os) << endl; + os.align(); expect = Align (expect); + os << const_cast<const string*>(&testString); expect += stream_size_of(&testString); + cout << "Write const string*, pos is " << RW(os) << endl; + os << &testString; expect += stream_size_of(&testString); + cout << "Write string*, pos is " << RW(os) << endl; + os << tv; expect += stream_size_of(tv); + cout << "Write vector<uint16_t>(7), pos is " << RW(os) << endl; + if (os.pos() != bufSize) + cout << "Incorrect number of bytes written: " << os.pos() << " of " << bufSize << endl; + + istream is (buffer); + expect = 0; + is >> pBufC; + expect += stream_size_of(pBufC); + cout << "Read const void*, pos is " << RW(is); + cout << ", value is " << rws[pBufC == buffer.cdata()] << endl; + is >> pBuf; + expect += stream_size_of(pBuf); + cout << "Read void*, pos is " << RW(is); + cout << ", value is " << rws[pBuf == buffer.cdata()] << endl; + testString.clear(); + is >> testString; + expect += stream_size_of(testString); + cout << "Read string, pos is " << RW(is) << ", value is " << testString << endl; + is.align(); + expect = Align (expect); + is >> pStrC; + expect += stream_size_of(pStrC); + cout << "Read const string*, pos is " << RW(is); + cout << ", value is " << rws[pStrC == &testString] << endl; + is >> pStr; + expect += stream_size_of(pStr); + cout << "Read string*, pos is " << RW(is); + cout << ", value is " << rws[pStr == &testString] << endl; + vector<uint16_t> rv; + is >> rv; + expect += stream_size_of(rv); + cout << "Read vector<uint16_t>(" << rv.size() << "), pos is " << RW(is); + cout << ", value is " << rws[rv == tv] << endl; + if (is.pos() != bufSize) + cout << "Incorrect number of bytes read: " << is.pos() << " of " << bufSize << endl; +} + +StdBvtMain (ObjectSerialization)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt12.std @@ -0,0 +1,12 @@ +Write const void*, pos is right +Write void*, pos is right +Write string, pos is right +Write const string*, pos is right +Write string*, pos is right +Write vector<uint16_t>(7), pos is right +Read const void*, pos is right, value is right +Read void*, pos is right, value is right +Read string, pos is right, value is TestString +Read const string*, pos is right, value is right +Read string*, pos is right, value is right +Read vector<uint16_t>(7), pos is right, value is right
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt13.cpp @@ -0,0 +1,36 @@ +// "Testing string reads" 12345678 4321 0x78675645 1.234567890123456 +// (the above line is the input to this test, so must be at the beginning) +// +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" +#include <stdio.h> + +void TestCoutCinCerr (void) +{ + string testStr; + cin >> testStr; + if (testStr != "//") { + cout.format ("You must put bvt13.cc on stdin (read \"%s\")\n", testStr.c_str()); + return; + } + uint32_t n1 = 0, n3 = 0; + uint16_t n2 = 0; + double f1 = 0.0; + cin >> testStr >> n1 >> n2 >> n3 >> f1; + cout << testStr << endl; + cout << "A string printed to stdout\n"; + cout.format ("%d %s: %d, %hd, 0x%08X, %1.15f\n", 4, "numbers", n1, n2, n3, f1); + string testString; + testString.format ("A ustl::string object printed %d times\n", 3); + for (int i = 0; i < 3; ++ i) + cout << testString; + cout.flush(); + fprintf (stderr, "All "); + cerr << "done.\n"; +} + +StdBvtMain (TestCoutCinCerr)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt13.std @@ -0,0 +1,7 @@ +Testing string reads +A string printed to stdout +4 numbers: 12345678, 4321, 0x78675645, 1.234567890123456 +A ustl::string object printed 3 times +A ustl::string object printed 3 times +A ustl::string object printed 3 times +All done.
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt14.cpp @@ -0,0 +1,59 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +void TestMap (void) +{ + typedef map<string,int> monthmap_t; + monthmap_t months; + months["january"] = 31; + months["february"] = 28; + months["march"] = 31; + months["april"] = 30; + months["may"] = 31; + months["june"] = 30; + months["july"] = 31; + months["august"] = 31; + months["september"] = 30; + months["october"] = 31; + months["november"] = 30; + months["december"] = 31; + + const monthmap_t& cmonths = months; + cout << "There are " << cmonths["january"] << " days in january." << endl; + cout << "There are " << cmonths["september"] << " days in september." << endl; + cout << "There are " << cmonths["december"] << " days in december." << endl; + monthmap_t::const_iterator found_may = months.find ("may"); + cout << found_may->first << " found at index " << found_may - months.begin() << endl; + cout << "Alphabetical listing:" << endl; + + monthmap_t::const_iterator i; + for (i = months.begin(); i < months.end(); ++ i) + cout << i->first << " has " << i->second << " days." << endl; + + monthmap_t mcopy (months); + mcopy.erase ("may"); + cout << "After erasing may:" << endl; + for (i = mcopy.begin(); i < mcopy.end(); ++ i) + cout << i->first << " "; + cout << endl; + + mcopy.assign (months.begin(), months.end() - 1); + mcopy.erase (mcopy.begin() + 1, mcopy.begin() + 4); + cout << "After erasing months 2, 3, 4, and the last one:" << endl; + for (i = mcopy.begin(); i < mcopy.end(); ++ i) + cout << i->first << " "; + cout << endl; + + mcopy = months; + monthmap_t::iterator frob = mcopy.insert (make_pair (string("frobuary"), 42)).first; + cout << "After inserting " << frob->first << "," << frob->second << ":" << endl; + for (i = mcopy.begin(); i < mcopy.end(); ++ i) + cout << i->first << " "; + cout << endl; +} + +StdBvtMain (TestMap)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt14.std @@ -0,0 +1,23 @@ +There are 31 days in january. +There are 30 days in september. +There are 31 days in december. +may found at index 8 +Alphabetical listing: +april has 30 days. +august has 31 days. +december has 31 days. +february has 28 days. +january has 31 days. +july has 31 days. +june has 30 days. +march has 31 days. +may has 31 days. +november has 30 days. +october has 31 days. +september has 30 days. +After erasing may: +april august december february january july june march november october september +After erasing months 2, 3, 4, and the last one: +april january july june march may november october +After inserting frobuary,42: +april august december february frobuary january july june march may november october september
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt15.cpp @@ -0,0 +1,55 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +typedef multimap<int,string> empmap_t; +typedef empmap_t::const_iterator citer_t; + +void PrintEntries (citer_t first, citer_t last) +{ + for (citer_t i = first; i < last; ++ i) + cout << i->second << "\t- $" << i->first << endl; +} + +inline void PrintEntries (const empmap_t& m) { PrintEntries (m.begin(), m.end()); } + +void TestMultiMap (void) +{ + empmap_t employees; + employees.insert (make_pair (27000, string("Dave"))); + employees.insert (make_pair (27000, string("Jim"))); + employees.insert (make_pair (99000, string("BigBoss"))); + employees.insert (make_pair (47000, string("Gail"))); + employees.insert (make_pair (15000, string("Dumb"))); + employees.insert (make_pair (47000, string("Barbara"))); + employees.insert (make_pair (47000, string("Mary"))); + + cout << "As-inserted listing:" << endl; + PrintEntries (employees); + + cout << "Alphabetical listing:" << endl; + sort (employees); + PrintEntries (employees); + + empmap_t::range_t middles = employees.equal_range (47000); + cout << "Employees making $" << middles.first->first << ":"; + empmap_t::const_iterator i; + for (i = middles.first; i < middles.second; ++ i) + cout << " " << i->second; + cout << endl; + + cout << "There are " << employees.count (27000) << " low-paid employees" << endl; + + cout << "Firing all low-paid employees:" << endl; + employees.erase (27000); + PrintEntries (employees); + + cout << "Firing dumb employees:" << endl; + employees.erase (employees.begin(), employees.begin() + 1); + PrintEntries (employees); +} + +StdBvtMain (TestMultiMap)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt15.std @@ -0,0 +1,29 @@ +As-inserted listing: +Dumb - $15000 +Dave - $27000 +Jim - $27000 +Gail - $47000 +Barbara - $47000 +Mary - $47000 +BigBoss - $99000 +Alphabetical listing: +Dumb - $15000 +Dave - $27000 +Jim - $27000 +Barbara - $47000 +Gail - $47000 +Mary - $47000 +BigBoss - $99000 +Employees making $47000: Barbara Gail Mary +There are 2 low-paid employees +Firing all low-paid employees: +Dumb - $15000 +Barbara - $47000 +Gail - $47000 +Mary - $47000 +BigBoss - $99000 +Firing dumb employees: +Barbara - $47000 +Gail - $47000 +Mary - $47000 +BigBoss - $99000
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt16.cpp @@ -0,0 +1,86 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +static void Widen (const string& str, vector<wchar_t>& result) +{ + result.clear(); + result.resize (str.length()); + copy (str.utf8_begin(), str.utf8_end(), result.begin()); +} + +static void DumpWchars (const vector<wchar_t>& v) +{ + foreach (vector<wchar_t>::const_iterator, i, v) + cout.format (" %u", uint32_t(*i)); +} + +void TestUTF8 (void) +{ + cout << "Generating Unicode characters "; + vector<wchar_t> srcChars; + srcChars.resize (0xFFFF); + iota (srcChars.begin(), srcChars.end(), 0); + cout.format ("%zu - %zu\n", size_t(srcChars[0]), size_t(srcChars.back())); + + cout << "Encoding to utf8.\n"; + string encoded; + encoded.reserve (srcChars.size() * 4); + copy (srcChars, utf8out (back_inserter(encoded))); + static const char c_ProperEncoding[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + if (encoded.compare (encoded.begin(), encoded.begin() + VectorSize(c_ProperEncoding), VectorRange(c_ProperEncoding))) { + cout << "Encoding failed: "; + for (string::const_iterator i = encoded.begin(); i != encoded.begin() + VectorSize(c_ProperEncoding); ++ i) + cout << uint32_t(*i); + cout << endl; + } + + cout << "Decoding back.\n"; + vector<wchar_t> decChars; + Widen (encoded, decChars); + + cout.format ("Comparing.\nsrc = %zu chars, encoded = %zu chars, decoded = %zu\n", srcChars.size(), encoded.size(), decChars.size()); + size_t nDiffs = 0; + for (uoff_t i = 0; i < min (srcChars.size(), decChars.size()); ++ i) { + if (srcChars[i] != decChars[i]) { + cout.format ("%u != %u\n", uint32_t(srcChars[i]), uint32_t(decChars[i])); + ++ nDiffs; + } + } + cout.format ("%zu differences between src and decoded.\n", nDiffs); + + cout << "Testing wide character string::insert\n"; + string ws ("1234567890", 10); + + ws.insert (ws.find('1'), wchar_t(1234)); + static const wchar_t c_WChars[2] = { 3456, 4567 }; + ws.insert (ws.find('3'), VectorRange(c_WChars), 2); + ws.insert (ws.find('3'), wchar_t(2345)); + ws.insert (ws.size(), wchar_t(5678)); + cout.format ("Values[%zu]:", ws.length()); + for (string::utf8_iterator j = ws.utf8_begin(); j < ws.utf8_end(); ++ j) + cout.format (" %u", uint32_t(*j)); + cout << endl; + + cout << "Character offsets:"; + for (string::utf8_iterator k = ws.utf8_begin(); k < ws.utf8_end(); ++ k) + cout.format (" %zu", distance (ws.begin(), k.base())); + cout << endl; + + cout.format ("Erasing character %zu: ", ws.length() - 1); + ws.erase (ws.wiat(ws.length() - 1), ws.end()); + Widen (ws, decChars); + DumpWchars (decChars); + cout << endl; + + cout << "Erasing 2 characters after '2': "; + ws.erase (ws.find('2')+1, Utf8Bytes(VectorRange(c_WChars))); + Widen (ws, decChars); + DumpWchars (decChars); + cout << endl; +} + +StdBvtMain (TestUTF8)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt16.std @@ -0,0 +1,11 @@ +Generating Unicode characters 0 - 65534 +Encoding to utf8. +Decoding back. +Comparing. +src = 65535 chars, encoded = 194429 chars, decoded = 65535 +0 differences between src and decoded. +Testing wide character string::insert +Values[17]: 1234 49 50 3456 4567 3456 4567 2345 51 52 53 54 55 56 57 48 5678 +Character offsets: 0 2 3 4 7 10 13 16 19 20 21 22 23 24 25 26 27 +Erasing character 16: 1234 49 50 3456 4567 3456 4567 2345 51 52 53 54 55 56 57 48 +Erasing 2 characters after '2': 1234 49 50 3456 4567 2345 51 52 53 54 55 56 57 48
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt17.cpp @@ -0,0 +1,98 @@ +// 011010011001011001011000100100 +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +size_t SizeOfSet (const bitset<30>& v) +{ + return (stream_size_of (v)); +} + +void TestBitset (void) +{ + bitset<30> bs1; + cout.format ("bitset<%zu> bs1: capacity() = %zu, sizeof() = %zu\n", bs1.size(), bs1.capacity(), sizeof(bs1)); + cout << bs1 << endl; + bs1.set(); + bs1.set (6, false); + cout << bs1 << endl; + bs1.flip(); + cout << bs1 << endl; + bs1.flip(); + cout << bs1 << endl; + + bs1.reset(); + string comment; // See line 0 in this file + cin >> comment >> bs1; + cout << bs1 << endl; + cout.format ("count = %zu\n", bs1.count()); + + bs1.reset(); + cout << bs1; + static const char tf[2][6] = { "false", "true" }; + cout.format ("\nany = %s, none = %s, count = %zu\n", tf[bs1.any()], tf[bs1.none()], bs1.count()); + bs1.flip(); + cout << bs1; + cout.format ("\nany = %s, none = %s, count = %zu\n", tf[bs1.any()], tf[bs1.none()], bs1.count()); + bs1.reset(); + bs1.set (4); + bs1.set (7); + bs1.set (8); + cout << bs1; + cout.format ("\ntest(7) == %s, [9] = %s, [8] = %s", tf[bs1.test(7)], tf[bs1[9]], tf[bs1[8]]); + cout.format ("\nany = %s, none = %s, count = %zu\n", tf[bs1.any()], tf[bs1.none()], bs1.count()); + cout << "~bs1 == " << ~bs1; + cout.format ("\nto_value == 0x%X\n", bs1.to_value()); + + bitset<70> bs2 ("0101101"); + cout.format ("bitset<%zu> bs2: capacity() = %zu, sizeof() = %zu\n", bs2.size(), bs2.capacity(), sizeof(bs2)); + cout << bs2; + bs2.set (34, 40, 13); + cout << "\nbs2.set(34,40,13)\n"; + cout << bs2; + cout.format ("\nbs2.at(34,40) = %u\n", bs2.at(34,40)); + + bitset<256> bs3 (0x3030); + cout.format ("bitset<%zu> bs3: capacity() = %zu, sizeof() = %zu\n", bs3.size(), bs3.capacity(), sizeof(bs3)); + cout.format ("bs3.to_value() == 0x%X\n", bs3.to_value()); + + bitset<30> bs4 (bs1); + if (bs1 == bs4) + cout << "bs4 == bs1\n"; + + bs4 = 0x50505050; + cout << "bs4 = 0x50505050: " << bs4; + bs1 = 0x30303030; + cout << "\nbs1 = 0x30303030: " << bs1; + bs4 &= bs1; + cout << "\nbs4 &= bs1; bs4 = " << bs4; + bs4 = 0x50505050; + bs4 &= bs1; + cout << "\nbs4 & bs1; bs4 = " << bs4; + bs4 = 0x50505050; + bs4 |= bs1; + cout << "\nbs4 |= bs1; bs4 = " << bs4; + bs4 = 0x50505050; + bs4 = bs4 | bs1; + cout << "\nbs4 | bs1; bs4 = " << bs4; + bs4 = 0x50505050; + bs4 ^= bs1; + cout << "\nbs4 ^= bs1; bs4 = " << bs4; + bs4 = 0x50505050; + bs4 = bs4 ^ 0x30303030; + cout << "\nbs4 ^ bs1; bs4 = " << bs4; + + memblock b (stream_size_of (bs4)); + ostream os (b); + os << bs4; + istream is (b); + bs4 = 0; + is >> bs4; + cout.format ("\nstream[%zu]; bs4 = ", b.size()); + cout << bs4 << endl; +} + +StdBvtMain (TestBitset)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt17.std @@ -0,0 +1,33 @@ +bitset<30> bs1: capacity() = 32, sizeof() = 4 +000000000000000000000000000000 +111111111111111111111110111111 +000000000000000000000001000000 +111111111111111111111110111111 +011010011001011001011000100100 +count = 13 +000000000000000000000000000000 +any = false, none = true, count = 0 +111111111111111111111111111111 +any = true, none = false, count = 32 +000000000000000000000110010000 +test(7) == true, [9] = false, [8] = true +any = true, none = false, count = 3 +~bs1 == 111111111111111111111001101111 +to_value == 0x190 +bitset<70> bs2: capacity() = 96, sizeof() = 12 +0000000000000000000000000000000000000000000000000000000000000000101101 +bs2.set(34,40,13) +0000000000000000000000000000000011010000000000000000000000000000101101 +bs2.at(34,40) = 13 +bitset<256> bs3: capacity() = 256, sizeof() = 32 +bs3.to_value() == 0x3030 +bs4 == bs1 +bs4 = 0x50505050: 010000010100000101000001010000 +bs1 = 0x30303030: 110000001100000011000000110000 +bs4 &= bs1; bs4 = 010000000100000001000000010000 +bs4 & bs1; bs4 = 010000000100000001000000010000 +bs4 |= bs1; bs4 = 110000011100000111000001110000 +bs4 | bs1; bs4 = 110000011100000111000001110000 +bs4 ^= bs1; bs4 = 100000011000000110000001100000 +bs4 ^ bs1; bs4 = 100000011000000110000001100000 +stream[4]; bs4 = 100000011000000110000001100000
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt18.cpp @@ -0,0 +1,77 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +template <size_t N, typename T> +void TestTuple (const char* ctrType) +{ + cout << "================================================" << endl; + cout << "Testing " << ctrType << endl; + cout << "================================================" << endl; + assert (N <= 8); + T pt1v[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + T increment; + tuple<N,T> pt1 (pt1v); + tuple<N,T> pt2 (5, 6, 7, 8); + increment = pt1v[2]; + + cout << "pt1:\t\t\tsize = " << pt1.size() << ", value = " << pt1 << endl; + cout << "pt2:\t\t\t" << pt2 << endl; + iota (pt2.begin(), pt2.end(), 10); + cout << "pt2:\t\t\t" << pt2 << endl; + + pt1 *= increment; + cout << "pt1 *= 3:\t\t" << pt1 << endl; + pt1 /= increment; + cout << "pt1 /= 3:\t\t" << pt1 << endl; + pt1 += increment; + cout << "pt1 += 3:\t\t" << pt1 << endl; + pt1 -= increment; + cout << "pt1 -= 3:\t\t" << pt1 << endl; + + pt1 *= pt2; + cout << "pt1 *= pt2:\t\t" << pt1 << endl; + pt1 /= pt2; + cout << "pt1 /= pt2:\t\t" << pt1 << endl; + pt1 += pt2; + cout << "pt1 += pt2:\t\t" << pt1 << endl; + pt1 -= pt2; + cout << "pt1 -= pt2:\t\t" << pt1 << endl; + + pt1 = pt1 * pt2; + cout << "pt1 = pt1 * pt2:\t" << pt1 << endl; + pt1 = pt1 / pt2; + cout << "pt1 = pt1 / pt2:\t" << pt1 << endl; + pt1 = pt1 + pt2; + cout << "pt1 = pt1 + pt2:\t" << pt1 << endl; + pt1 = pt1 - pt2; + cout << "pt1 = pt1 - pt2:\t" << pt1 << endl; +} + +void TestIntegralTuples (void) +{ + TestTuple<4,float> ("tuple<4,float>"); + TestTuple<2,float> ("tuple<2,float>"); + TestTuple<4,int32_t> ("tuple<4,int32_t>"); + TestTuple<4,uint32_t> ("tuple<4,uint32_t>"); + TestTuple<2,int32_t> ("tuple<2,int32_t>"); + TestTuple<2,uint32_t> ("tuple<2,uint32_t>"); + TestTuple<4,int16_t> ("tuple<4,int16_t>"); + TestTuple<4,uint16_t> ("tuple<4,uint16_t>"); + TestTuple<8,int8_t> ("tuple<8,int8_t>"); + TestTuple<8,uint8_t> ("tuple<8,uint8_t>"); + + cout << "================================================" << endl; + cout << "Testing tuple<3,string>" << endl; + cout << "================================================" << endl; + tuple<3, string> strv; + strv[0] = "str0"; + strv[1] = "str1"; + strv[2] = "str2"; + cout << "str: " << strv << endl; +} + +StdBvtMain (TestIntegralTuples)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt18.std @@ -0,0 +1,184 @@ +================================================ +Testing tuple<4,float> +================================================ +pt1: size = 4, value = (1.00,2.00,3.00,4.00) +pt2: (5.00,6.00,7.00,8.00) +pt2: (10.00,11.00,12.00,13.00) +pt1 *= 3: (3.00,6.00,9.00,12.00) +pt1 /= 3: (1.00,2.00,3.00,4.00) +pt1 += 3: (4.00,5.00,6.00,7.00) +pt1 -= 3: (1.00,2.00,3.00,4.00) +pt1 *= pt2: (10.00,22.00,36.00,52.00) +pt1 /= pt2: (1.00,2.00,3.00,4.00) +pt1 += pt2: (11.00,13.00,15.00,17.00) +pt1 -= pt2: (1.00,2.00,3.00,4.00) +pt1 = pt1 * pt2: (10.00,22.00,36.00,52.00) +pt1 = pt1 / pt2: (1.00,2.00,3.00,4.00) +pt1 = pt1 + pt2: (11.00,13.00,15.00,17.00) +pt1 = pt1 - pt2: (1.00,2.00,3.00,4.00) +================================================ +Testing tuple<2,float> +================================================ +pt1: size = 2, value = (1.00,2.00) +pt2: (5.00,6.00) +pt2: (10.00,11.00) +pt1 *= 3: (3.00,6.00) +pt1 /= 3: (1.00,2.00) +pt1 += 3: (4.00,5.00) +pt1 -= 3: (1.00,2.00) +pt1 *= pt2: (10.00,22.00) +pt1 /= pt2: (1.00,2.00) +pt1 += pt2: (11.00,13.00) +pt1 -= pt2: (1.00,2.00) +pt1 = pt1 * pt2: (10.00,22.00) +pt1 = pt1 / pt2: (1.00,2.00) +pt1 = pt1 + pt2: (11.00,13.00) +pt1 = pt1 - pt2: (1.00,2.00) +================================================ +Testing tuple<4,int32_t> +================================================ +pt1: size = 4, value = (1,2,3,4) +pt2: (5,6,7,8) +pt2: (10,11,12,13) +pt1 *= 3: (3,6,9,12) +pt1 /= 3: (1,2,3,4) +pt1 += 3: (4,5,6,7) +pt1 -= 3: (1,2,3,4) +pt1 *= pt2: (10,22,36,52) +pt1 /= pt2: (1,2,3,4) +pt1 += pt2: (11,13,15,17) +pt1 -= pt2: (1,2,3,4) +pt1 = pt1 * pt2: (10,22,36,52) +pt1 = pt1 / pt2: (1,2,3,4) +pt1 = pt1 + pt2: (11,13,15,17) +pt1 = pt1 - pt2: (1,2,3,4) +================================================ +Testing tuple<4,uint32_t> +================================================ +pt1: size = 4, value = (1,2,3,4) +pt2: (5,6,7,8) +pt2: (10,11,12,13) +pt1 *= 3: (3,6,9,12) +pt1 /= 3: (1,2,3,4) +pt1 += 3: (4,5,6,7) +pt1 -= 3: (1,2,3,4) +pt1 *= pt2: (10,22,36,52) +pt1 /= pt2: (1,2,3,4) +pt1 += pt2: (11,13,15,17) +pt1 -= pt2: (1,2,3,4) +pt1 = pt1 * pt2: (10,22,36,52) +pt1 = pt1 / pt2: (1,2,3,4) +pt1 = pt1 + pt2: (11,13,15,17) +pt1 = pt1 - pt2: (1,2,3,4) +================================================ +Testing tuple<2,int32_t> +================================================ +pt1: size = 2, value = (1,2) +pt2: (5,6) +pt2: (10,11) +pt1 *= 3: (3,6) +pt1 /= 3: (1,2) +pt1 += 3: (4,5) +pt1 -= 3: (1,2) +pt1 *= pt2: (10,22) +pt1 /= pt2: (1,2) +pt1 += pt2: (11,13) +pt1 -= pt2: (1,2) +pt1 = pt1 * pt2: (10,22) +pt1 = pt1 / pt2: (1,2) +pt1 = pt1 + pt2: (11,13) +pt1 = pt1 - pt2: (1,2) +================================================ +Testing tuple<2,uint32_t> +================================================ +pt1: size = 2, value = (1,2) +pt2: (5,6) +pt2: (10,11) +pt1 *= 3: (3,6) +pt1 /= 3: (1,2) +pt1 += 3: (4,5) +pt1 -= 3: (1,2) +pt1 *= pt2: (10,22) +pt1 /= pt2: (1,2) +pt1 += pt2: (11,13) +pt1 -= pt2: (1,2) +pt1 = pt1 * pt2: (10,22) +pt1 = pt1 / pt2: (1,2) +pt1 = pt1 + pt2: (11,13) +pt1 = pt1 - pt2: (1,2) +================================================ +Testing tuple<4,int16_t> +================================================ +pt1: size = 4, value = (1,2,3,4) +pt2: (5,6,7,8) +pt2: (10,11,12,13) +pt1 *= 3: (3,6,9,12) +pt1 /= 3: (1,2,3,4) +pt1 += 3: (4,5,6,7) +pt1 -= 3: (1,2,3,4) +pt1 *= pt2: (10,22,36,52) +pt1 /= pt2: (1,2,3,4) +pt1 += pt2: (11,13,15,17) +pt1 -= pt2: (1,2,3,4) +pt1 = pt1 * pt2: (10,22,36,52) +pt1 = pt1 / pt2: (1,2,3,4) +pt1 = pt1 + pt2: (11,13,15,17) +pt1 = pt1 - pt2: (1,2,3,4) +================================================ +Testing tuple<4,uint16_t> +================================================ +pt1: size = 4, value = (1,2,3,4) +pt2: (5,6,7,8) +pt2: (10,11,12,13) +pt1 *= 3: (3,6,9,12) +pt1 /= 3: (1,2,3,4) +pt1 += 3: (4,5,6,7) +pt1 -= 3: (1,2,3,4) +pt1 *= pt2: (10,22,36,52) +pt1 /= pt2: (1,2,3,4) +pt1 += pt2: (11,13,15,17) +pt1 -= pt2: (1,2,3,4) +pt1 = pt1 * pt2: (10,22,36,52) +pt1 = pt1 / pt2: (1,2,3,4) +pt1 = pt1 + pt2: (11,13,15,17) +pt1 = pt1 - pt2: (1,2,3,4) +================================================ +Testing tuple<8,int8_t> +================================================ +pt1: size = 8, value = (1,2,3,4,5,6,7,8) +pt2: (5,6,7,8,0,0,0,0) +pt2: (10,11,12,13,14,15,16,17) +pt1 *= 3: (3,6,9,12,15,18,21,24) +pt1 /= 3: (1,2,3,4,5,6,7,8) +pt1 += 3: (4,5,6,7,8,9,10,11) +pt1 -= 3: (1,2,3,4,5,6,7,8) +pt1 *= pt2: (10,22,'$','4','F','Z','p',-120) +pt1 /= pt2: (1,2,3,4,5,6,7,-7) +pt1 += pt2: (11,13,15,17,19,21,23,10) +pt1 -= pt2: (1,2,3,4,5,6,7,-7) +pt1 = pt1 * pt2: (10,22,'$','4','F','Z','p',-119) +pt1 = pt1 / pt2: (1,2,3,4,5,6,7,-7) +pt1 = pt1 + pt2: (11,13,15,17,19,21,23,10) +pt1 = pt1 - pt2: (1,2,3,4,5,6,7,-7) +================================================ +Testing tuple<8,uint8_t> +================================================ +pt1: size = 8, value = (1,2,3,4,5,6,7,8) +pt2: (5,6,7,8,0,0,0,0) +pt2: (10,11,12,13,14,15,16,17) +pt1 *= 3: (3,6,9,12,15,18,21,24) +pt1 /= 3: (1,2,3,4,5,6,7,8) +pt1 += 3: (4,5,6,7,8,9,10,11) +pt1 -= 3: (1,2,3,4,5,6,7,8) +pt1 *= pt2: (10,22,'$','4','F','Z','p',136) +pt1 /= pt2: (1,2,3,4,5,6,7,8) +pt1 += pt2: (11,13,15,17,19,21,23,25) +pt1 -= pt2: (1,2,3,4,5,6,7,8) +pt1 = pt1 * pt2: (10,22,'$','4','F','Z','p',136) +pt1 = pt1 / pt2: (1,2,3,4,5,6,7,8) +pt1 = pt1 + pt2: (11,13,15,17,19,21,23,25) +pt1 = pt1 - pt2: (1,2,3,4,5,6,7,8) +================================================ +Testing tuple<3,string> +================================================ +str: (str0,str1,str2)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt19.cpp @@ -0,0 +1,33 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +void TestEnumArithmetic (void) +{ + enum EFruit { + apple, + orange, + plum, + peach, + pear, + nectarine, + NFruits + }; + const char* fruits [NFruits + 1] = { + "apple", + "orange", + "plum", + "peach", + "pear", + "nectarine", + "invalid" + }; + cout << "Testing operator+" << endl; + cout << "apple = " << fruits [apple] << endl; + cout << "peach = " << fruits [apple + 3] << endl; +} + +StdBvtMain (TestEnumArithmetic)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt19.std @@ -0,0 +1,3 @@ +Testing operator+ +apple = apple +peach = peach
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt20.cpp @@ -0,0 +1,33 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +void TestStackAndQueue (void) +{ + stack<int> s; + cout << "Testing stack: "; + for (size_t i = 0; i < 5; ++ i) + s.push (1 + i); + cout << "popping: "; + for (size_t j = 0; j < 5; ++ j) { + cout << s.top() << ' '; + s.pop(); + } + cout << endl; + + queue<int> q; + cout << "Testing queue: "; + for (size_t k = 0; k < 5; ++ k) + q.push (1 + k); + cout << "popping: "; + for (size_t l = 0; l < 5; ++ l) { + cout << q.front() << ' '; + q.pop(); + } + cout << endl; +} + +StdBvtMain (TestStackAndQueue)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt20.std @@ -0,0 +1,2 @@ +Testing stack: popping: 5 4 3 2 1 +Testing queue: popping: 1 2 3 4 5
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt21.cpp @@ -0,0 +1,102 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +template <typename T> +void TestBswap (T v) +{ + const T vsw (bswap(v)); +#if BYTE_ORDER == LITTLE_ENDIAN + const T vbe (vsw), vle (v); +#elif BYTE_ORDER == BIG_ENDIAN + const T vbe (v), vle (vsw); +#endif + static const char ok[2][4] = { "bad", "ok" }; + cout << "bswap(" << v << ") = " << vsw << endl; + cout << "le_to_native(" << v << ") = " << ok[le_to_native(vle) == v] << endl; + cout << "native_to_le(" << v << ") = " << ok[native_to_le(v) == vle] << endl; + cout << "be_to_native(" << v << ") = " << ok[be_to_native(vbe) == v] << endl; + cout << "native_to_be(" << v << ") = " << ok[native_to_be(v) == vbe] << endl; +} + +void TestUtility (void) +{ + cout << "DivRU(13,5) = " << DivRU(13,5) << endl; + cout << "DivRU(15,5) = " << DivRU(15,5) << endl; + cout << "DivRU(-12,5) = " << DivRU(-12,5) << endl; + cout << endl; + cout << "Align(5) = " << Align(5) << endl; + cout << "Align(5,2) = " << Align(5,2) << endl; + cout << "Align(17,7) = " << Align(17,7) << endl; + cout << "Align(14,7) = " << Align(14,7) << endl; + cout << endl; + cout << "advance(42,0) = " << advance(42,0) << endl; + cout << "advance(42,3) = " << advance(42,3) << endl; + const void *cvp = (const void*) 0x1234; + void* vp = (void*) 0x4321; + cout << ios::hex; + cout << "cvp = " << cvp << endl; + cout << "vp = " << vp << endl; + cout << "advance(cvp,5) = " << advance(cvp,5) << endl; + cout << "advance(vp,4) = " << advance(vp,4) << endl; + cout << "distance(cvp,vp) = " << distance(cvp,vp) << endl; + cout << "abs_distance(vp,cvp) = " << abs_distance(vp,cvp) << endl; + cout << ios::dec << endl; + const int32_t c_Numbers[] = { 1, 2, 3, 4, 5 }; + const int32_t c_Empty[] = { }; + cout << "size_of_elements(3, c_Numbers) = " << size_of_elements(3, c_Numbers) << endl; + cout << "VectorSize(c_Numbers[5]) = " << VectorSize(c_Numbers) << endl; + cout << "VectorSize(c_Numbers[0]) = " << VectorSize(c_Empty) << endl; + cout << endl; + cout << "BitsInType(uint32_t) = " << BitsInType(uint32_t) << endl; + cout << "BitsInType(int16_t) = " << BitsInType(int16_t) << endl; + cout << "BitsInType(char) = " << BitsInType(char) << endl; + cout << ios::hex << endl; + cout << "BitMask(uint32_t,12) = " << BitMask(uint32_t,12) << endl; + cout << "BitMask(uint16_t,1) = " << BitMask(uint16_t,1) << endl; + cout << "BitMask(uint8_t,8) = " << BitMask(uint8_t,8) << endl; + cout << "BitMask(uint16_t,0) = " << BitMask(uint16_t,0) << endl; + cout << endl; + uint16_t packed16 = 0xCDCD; + pack_type (uint8_t(0x42), packed16); + cout << "pack_type(uint8_t, uint16_t) = " << packed16 << endl; + uint32_t packed32 = 0xCDCDCDCD; + pack_type (uint8_t(0x42), packed32); + cout << "pack_type(uint8_t, uint32_t) = " << packed32 << endl; + packed32 = 0xCDCDCDCD; + pack_type (uint16_t(0x4243), packed32); + cout << "pack_type(uint16_t, uint32_t) = " << packed32 << endl; + #if HAVE_INT64_T + uint64_t packed64 = UINT64_C(0x123456789ABCDEF0); + pack_type (uint8_t(0x42), packed64); + cout << "pack_type(uint8_t, uint64_t) = " << packed64 << endl; + packed64 = UINT64_C(0x123456789ABCDEF0); + pack_type (uint32_t(0x42434445), packed64); + cout << "pack_type(uint32_t, uint64_t) = " << packed64 << endl; + #else + cout << "No 64bit types available on this platform" << endl; + #endif + cout << endl; + TestBswap (uint16_t (0x1234)); + TestBswap (uint32_t (0x12345678)); + #if HAVE_INT64_T + TestBswap (uint64_t (UINT64_C(0x123456789ABCDEF0))); + #else + cout << "No 64bit types available on this platform" << endl; + #endif + cout << ios::dec << endl; + cout << "absv(12) = " << absv(12) << endl; + cout << "absv(-12) = " << absv(-12) << endl; + cout << "sign(12) = " << sign(12) << endl; + cout << "sign(-12) = " << sign(-12) << endl; + cout << "sign(0) = " << sign(0) << endl; + cout << "min(3,4) = " << min(3,4) << endl; + cout << "min(6U,1U) = " << min(6U,1U) << endl; + cout << "max(-3,-6) = " << max(-3,-6) << endl; + cout << "max(-3L,6L) = " << max(-3L,6L) << endl; +} + +StdBvtMain (TestUtility)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt21.std @@ -0,0 +1,62 @@ +DivRU(13,5) = 3 +DivRU(15,5) = 3 +DivRU(-12,5) = -3 + +Align(5) = 8 +Align(5,2) = 6 +Align(17,7) = 21 +Align(14,7) = 14 + +advance(42,0) = 42 +advance(42,3) = 45 +cvp = 1234 +vp = 4321 +advance(cvp,5) = 1239 +advance(vp,4) = 4325 +distance(cvp,vp) = 30ED +abs_distance(vp,cvp) = 30ED + +size_of_elements(3, c_Numbers) = 12 +VectorSize(c_Numbers[5]) = 5 +VectorSize(c_Numbers[0]) = 0 + +BitsInType(uint32_t) = 32 +BitsInType(int16_t) = 16 +BitsInType(char) = 8 + +BitMask(uint32_t,12) = FFF +BitMask(uint16_t,1) = 1 +BitMask(uint8_t,8) = FF +BitMask(uint16_t,0) = 0 + +pack_type(uint8_t, uint16_t) = 4242 +pack_type(uint8_t, uint32_t) = 42424242 +pack_type(uint16_t, uint32_t) = 42434243 +pack_type(uint8_t, uint64_t) = 4242424242424242 +pack_type(uint32_t, uint64_t) = 4243444542434445 + +bswap(1234) = 3412 +le_to_native(1234) = ok +native_to_le(1234) = ok +be_to_native(1234) = ok +native_to_be(1234) = ok +bswap(12345678) = 78563412 +le_to_native(12345678) = ok +native_to_le(12345678) = ok +be_to_native(12345678) = ok +native_to_be(12345678) = ok +bswap(123456789ABCDEF0) = F0DEBC9A78563412 +le_to_native(123456789ABCDEF0) = ok +native_to_le(123456789ABCDEF0) = ok +be_to_native(123456789ABCDEF0) = ok +native_to_be(123456789ABCDEF0) = ok + +absv(12) = 12 +absv(-12) = 12 +sign(12) = 1 +sign(-12) = -1 +sign(0) = 0 +min(3,4) = 3 +min(6U,1U) = 1 +max(-3,-6) = -3 +max(-3L,6L) = 6
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt22.cpp @@ -0,0 +1,71 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +template <size_t NX, size_t NY, typename T> +void TestMatrix (void) +{ + matrix<NX,NY,T> m1, m2; + load_identity (m1); + cout << "load_identity(m1)" + "\n m1 = " << m1; + m2 = m1; + cout << "\nm1 = m2" + "\n m2 = " << m2; + m1 += m2; + cout << "\nm1 += m2" + "\n m1 = " << m1; + m1 /= 2; + cout << "\nm1 /= 2" + "\n m1 = " << m1; + m1 = m1 * m2; + cout << "\nm1 = m1 * m2" + "\n m1 = " << m1; + m1 += 3; + cout << "\nm1 += 3" + "\n m1 = " << m1; + load_identity (m2); + m2 *= 2; + m1 = m1 * m2; + cout << "\nm1 *= I(2)"; + cout << "\n m1 = " << m1; + iota (m1.begin(), m1.end(), 1); + cout << "\nm1 = iota(1)" + "\n m1 = " << m1; + cout << "\n m1 row [1] = " << m1.row(1); + cout << "\n m1 column [2] = " << m1.column(2); + m1 = m1 * m2; + cout << "\nm1 *= I(2)" + "\n m1 = " << m1; + typename matrix<NX,NY,T>::column_type v, vt; + iota (v.begin(), v.end(), 1); + cout << "\nv = iota(1)" + "\n v = " << v; + load_identity (m2); + m2 *= 2; + for (uoff_t y = 0; y < NY - 1; ++ y) + m2[NY - 1][y] = 1; + cout << "\nm2 = I(2) + T(1)" + "\n m2 = " << m2; + vt = v * m2; + cout << "\nvt = v * m2" + "\n vt = " << vt << endl; +} + +void TestMatrixAlgorithms (void) +{ + cout << "========================================\n" + "Testing 4x4 int matrix:\n" + "========================================\n"; + TestMatrix<4,4,int>(); + cout << "========================================\n" + "Testing 4x4 float matrix:\n" + "========================================\n"; + cout.set_precision (1); + TestMatrix<4,4,float>(); +} + +StdBvtMain (TestMatrixAlgorithms)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt22.std @@ -0,0 +1,58 @@ +======================================== +Testing 4x4 int matrix: +======================================== +load_identity(m1) + m1 = ((1,0,0,0)(0,1,0,0)(0,0,1,0)(0,0,0,1)) +m1 = m2 + m2 = ((1,0,0,0)(0,1,0,0)(0,0,1,0)(0,0,0,1)) +m1 += m2 + m1 = ((2,0,0,0)(0,2,0,0)(0,0,2,0)(0,0,0,2)) +m1 /= 2 + m1 = ((1,0,0,0)(0,1,0,0)(0,0,1,0)(0,0,0,1)) +m1 = m1 * m2 + m1 = ((1,0,0,0)(0,1,0,0)(0,0,1,0)(0,0,0,1)) +m1 += 3 + m1 = ((4,3,3,3)(3,4,3,3)(3,3,4,3)(3,3,3,4)) +m1 *= I(2) + m1 = ((8,6,6,6)(6,8,6,6)(6,6,8,6)(6,6,6,8)) +m1 = iota(1) + m1 = ((1,2,3,4)(5,6,7,8)(9,10,11,12)(13,14,15,16)) + m1 row [1] = (5,6,7,8) + m1 column [2] = (3,7,11,15) +m1 *= I(2) + m1 = ((2,4,6,8)(10,12,14,16)(18,20,22,24)(26,28,30,32)) +v = iota(1) + v = (1,2,3,4) +m2 = I(2) + T(1) + m2 = ((2,0,0,0)(0,2,0,0)(0,0,2,0)(1,1,1,2)) +vt = v * m2 + vt = (6,8,10,8) +======================================== +Testing 4x4 float matrix: +======================================== +load_identity(m1) + m1 = ((1.0,0.0,0.0,0.0)(0.0,1.0,0.0,0.0)(0.0,0.0,1.0,0.0)(0.0,0.0,0.0,1.0)) +m1 = m2 + m2 = ((1.0,0.0,0.0,0.0)(0.0,1.0,0.0,0.0)(0.0,0.0,1.0,0.0)(0.0,0.0,0.0,1.0)) +m1 += m2 + m1 = ((2.0,0.0,0.0,0.0)(0.0,2.0,0.0,0.0)(0.0,0.0,2.0,0.0)(0.0,0.0,0.0,2.0)) +m1 /= 2 + m1 = ((1.0,0.0,0.0,0.0)(0.0,1.0,0.0,0.0)(0.0,0.0,1.0,0.0)(0.0,0.0,0.0,1.0)) +m1 = m1 * m2 + m1 = ((1.0,0.0,0.0,0.0)(0.0,1.0,0.0,0.0)(0.0,0.0,1.0,0.0)(0.0,0.0,0.0,1.0)) +m1 += 3 + m1 = ((4.0,3.0,3.0,3.0)(3.0,4.0,3.0,3.0)(3.0,3.0,4.0,3.0)(3.0,3.0,3.0,4.0)) +m1 *= I(2) + m1 = ((8.0,6.0,6.0,6.0)(6.0,8.0,6.0,6.0)(6.0,6.0,8.0,6.0)(6.0,6.0,6.0,8.0)) +m1 = iota(1) + m1 = ((1.0,2.0,3.0,4.0)(5.0,6.0,7.0,8.0)(9.0,10.0,11.0,12.0)(13.0,14.0,15.0,16.0)) + m1 row [1] = (5.0,6.0,7.0,8.0) + m1 column [2] = (3.0,7.0,11.0,15.0) +m1 *= I(2) + m1 = ((2.0,4.0,6.0,8.0)(10.0,12.0,14.0,16.0)(18.0,20.0,22.0,24.0)(26.0,28.0,30.0,32.0)) +v = iota(1) + v = (1.0,2.0,3.0,4.0) +m2 = I(2) + T(1) + m2 = ((2.0,0.0,0.0,0.0)(0.0,2.0,0.0,0.0)(0.0,0.0,2.0,0.0)(1.0,1.0,1.0,2.0)) +vt = v * m2 + vt = (6.0,8.0,10.0,8.0)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt23.cpp @@ -0,0 +1,121 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" +using namespace ustl::simd; + +template <typename Ctr> +void TestBitwiseOperations (Ctr op1, Ctr op2, const Ctr op3) +{ + passign (op3, op2); + pand (op1, op2); + cout << "pand(op1,op2) = " << op2 << endl; + passign (op3, op2); + por (op1, op2); + cout << "por(op1,op2) = " << op2 << endl; + passign (op3, op2); + pxor (op1, op2); + cout << "pxor(op1,op2) = " << op2 << endl; + passign (op3, op2); + pshl (op1, op2); + cout << "pshl(op1,op2) = " << op2 << endl; + passign (op3, op2); + pshr (op1, op2); + cout << "pshr(op1,op2) = " << op2 << endl; +} + +template <> inline void TestBitwiseOperations (tuple<2,float>, tuple<2,float>, const tuple<2,float>) {} +template <> inline void TestBitwiseOperations (tuple<4,float>, tuple<4,float>, const tuple<4,float>) {} + +template <typename Ctr> +void TestCtr (const char* ctrType) +{ + cout << "================================================" << endl; + cout << "Testing " << ctrType << endl; + cout << "================================================" << endl; + Ctr op1, op2, op3; + fill (op1, 2); + iota (op2.begin(), op2.end(), 1); + cout << "op1 = " << op1 << endl; + cout << "op2 = " << op2 << endl; + passign (op2, op3); + cout << "passign(op2,op3) = " << op3 << endl; + padd (op1, op2); + cout << "padd(op1,op2) = " << op2 << endl; + psub (op1, op2); + cout << "psub(op1,op2) = " << op2 << endl; + pmul (op1, op2); + cout << "pmul(op1,op2) = " << op2 << endl; + pdiv (op1, op2); + cout << "pdiv(op1,op2) = " << op2 << endl; + TestBitwiseOperations (op1, op2, op3); + passign (op3, op2); + reverse (op2); + pmin (op3, op2); + cout << "pmin(op3,op2) = " << op2 << endl; + passign (op3, op2); + reverse (op2); + pmax (op3, op2); + cout << "pmax(op3,op2) = " << op2 << endl; + passign (op3, op2); + reverse (op2); + reset_mmx(); + pavg (op3, op2); + cout << "pavg(op3,op2) = " << op2 << endl; + reset_mmx(); +} + +template <typename SrcCtr, typename DstCtr, typename Operation> +void TestConversion (const char* ctrType) +{ + cout << "================================================" << endl; + cout << "Testing " << ctrType << endl; + cout << "================================================" << endl; + SrcCtr src; + DstCtr dst; + typedef typename SrcCtr::value_type srcval_t; + iota (src.begin(), src.end(), srcval_t(-1.4)); + pconvert (src, dst, Operation()); + cout << src << " -> " << dst << endl; + iota (src.begin(), src.end(), srcval_t(-1.5)); + pconvert (src, dst, Operation()); + cout << src << " -> " << dst << endl; + iota (src.begin(), src.end(), srcval_t(-1.7)); + pconvert (src, dst, Operation()); + cout << src << " -> " << dst << endl; +} + +void TestSimdAlgorithms (void) +{ + TestCtr<tuple<8,uint8_t> >("uint8_t[8]"); + TestCtr<tuple<8,int8_t> >("int8_t[8]"); + TestCtr<tuple<4,uint16_t> >("uint16_t[4]"); + TestCtr<tuple<4,int16_t> >("int16_t[4]"); + TestCtr<tuple<2,uint32_t> >("uint32_t[2]"); + TestCtr<tuple<2,int32_t> >("int32_t[2]"); + #if HAVE_INT64_T + TestCtr<tuple<1,uint64_t> >("uint64_t[1]"); + TestCtr<tuple<1,int64_t> >("int64_t[1]"); + #else + cout << "No 64bit types available on this platform" << endl; + #endif + TestCtr<tuple<2,float> >("float[2]"); + TestCtr<tuple<4,float> >("float[4]"); + TestCtr<tuple<7,uint32_t> >("uint32_t[7]"); + + #if HAVE_MATH_H + #define CVT_TEST(size,src,dest,op) \ + TestConversion<tuple<size,src>, tuple<size,dest>, op<src,dest> > (#op " " #src " -> " #dest) + CVT_TEST(4,int32_t,float,fround); + CVT_TEST(4,int32_t,double,fround); + CVT_TEST(4,float,int32_t,fround); + CVT_TEST(4,double,int32_t,fround); + CVT_TEST(4,float,int32_t,fcast); + #else + cout << "CAN'T TEST: math.h functions are not available on this platform." << endl; + #endif +} + +StdBvtMain (TestSimdAlgorithms)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt23.std @@ -0,0 +1,218 @@ +================================================ +Testing uint8_t[8] +================================================ +op1 = (2,2,2,2,2,2,2,2) +op2 = (1,2,3,4,5,6,7,8) +passign(op2,op3) = (1,2,3,4,5,6,7,8) +padd(op1,op2) = (3,4,5,6,7,8,9,10) +psub(op1,op2) = (1,2,3,4,5,6,7,8) +pmul(op1,op2) = (2,4,6,8,10,12,14,16) +pdiv(op1,op2) = (1,2,3,4,5,6,7,8) +pand(op1,op2) = (0,2,2,0,0,2,2,0) +por(op1,op2) = (3,2,3,6,7,6,7,10) +pxor(op1,op2) = (3,0,1,6,7,4,5,10) +pshl(op1,op2) = (4,8,12,16,20,24,28,' ') +pshr(op1,op2) = (0,0,0,1,1,1,1,2) +pmin(op3,op2) = (1,2,3,4,4,3,2,1) +pmax(op3,op2) = (8,7,6,5,5,6,7,8) +pavg(op3,op2) = (5,5,5,5,5,5,5,5) +================================================ +Testing int8_t[8] +================================================ +op1 = (2,2,2,2,2,2,2,2) +op2 = (1,2,3,4,5,6,7,8) +passign(op2,op3) = (1,2,3,4,5,6,7,8) +padd(op1,op2) = (3,4,5,6,7,8,9,10) +psub(op1,op2) = (1,2,3,4,5,6,7,8) +pmul(op1,op2) = (2,4,6,8,10,12,14,16) +pdiv(op1,op2) = (1,2,3,4,5,6,7,8) +pand(op1,op2) = (0,2,2,0,0,2,2,0) +por(op1,op2) = (3,2,3,6,7,6,7,10) +pxor(op1,op2) = (3,0,1,6,7,4,5,10) +pshl(op1,op2) = (4,8,12,16,20,24,28,' ') +pshr(op1,op2) = (0,0,0,1,1,1,1,2) +pmin(op3,op2) = (1,2,3,4,4,3,2,1) +pmax(op3,op2) = (8,7,6,5,5,6,7,8) +pavg(op3,op2) = (5,5,5,5,5,5,5,5) +================================================ +Testing uint16_t[4] +================================================ +op1 = (2,2,2,2) +op2 = (1,2,3,4) +passign(op2,op3) = (1,2,3,4) +padd(op1,op2) = (3,4,5,6) +psub(op1,op2) = (1,2,3,4) +pmul(op1,op2) = (2,4,6,8) +pdiv(op1,op2) = (1,2,3,4) +pand(op1,op2) = (0,2,2,0) +por(op1,op2) = (3,2,3,6) +pxor(op1,op2) = (3,0,1,6) +pshl(op1,op2) = (4,8,12,16) +pshr(op1,op2) = (0,0,0,1) +pmin(op3,op2) = (1,2,2,1) +pmax(op3,op2) = (4,3,3,4) +pavg(op3,op2) = (3,3,3,3) +================================================ +Testing int16_t[4] +================================================ +op1 = (2,2,2,2) +op2 = (1,2,3,4) +passign(op2,op3) = (1,2,3,4) +padd(op1,op2) = (3,4,5,6) +psub(op1,op2) = (1,2,3,4) +pmul(op1,op2) = (2,4,6,8) +pdiv(op1,op2) = (1,2,3,4) +pand(op1,op2) = (0,2,2,0) +por(op1,op2) = (3,2,3,6) +pxor(op1,op2) = (3,0,1,6) +pshl(op1,op2) = (4,8,12,16) +pshr(op1,op2) = (0,0,0,1) +pmin(op3,op2) = (1,2,2,1) +pmax(op3,op2) = (4,3,3,4) +pavg(op3,op2) = (3,3,3,3) +================================================ +Testing uint32_t[2] +================================================ +op1 = (2,2) +op2 = (1,2) +passign(op2,op3) = (1,2) +padd(op1,op2) = (3,4) +psub(op1,op2) = (1,2) +pmul(op1,op2) = (2,4) +pdiv(op1,op2) = (1,2) +pand(op1,op2) = (0,2) +por(op1,op2) = (3,2) +pxor(op1,op2) = (3,0) +pshl(op1,op2) = (4,8) +pshr(op1,op2) = (0,0) +pmin(op3,op2) = (1,1) +pmax(op3,op2) = (2,2) +pavg(op3,op2) = (2,2) +================================================ +Testing int32_t[2] +================================================ +op1 = (2,2) +op2 = (1,2) +passign(op2,op3) = (1,2) +padd(op1,op2) = (3,4) +psub(op1,op2) = (1,2) +pmul(op1,op2) = (2,4) +pdiv(op1,op2) = (1,2) +pand(op1,op2) = (0,2) +por(op1,op2) = (3,2) +pxor(op1,op2) = (3,0) +pshl(op1,op2) = (4,8) +pshr(op1,op2) = (0,0) +pmin(op3,op2) = (1,1) +pmax(op3,op2) = (2,2) +pavg(op3,op2) = (2,2) +================================================ +Testing uint64_t[1] +================================================ +op1 = (2) +op2 = (1) +passign(op2,op3) = (1) +padd(op1,op2) = (3) +psub(op1,op2) = (1) +pmul(op1,op2) = (2) +pdiv(op1,op2) = (1) +pand(op1,op2) = (0) +por(op1,op2) = (3) +pxor(op1,op2) = (3) +pshl(op1,op2) = (4) +pshr(op1,op2) = (0) +pmin(op3,op2) = (1) +pmax(op3,op2) = (1) +pavg(op3,op2) = (1) +================================================ +Testing int64_t[1] +================================================ +op1 = (2) +op2 = (1) +passign(op2,op3) = (1) +padd(op1,op2) = (3) +psub(op1,op2) = (1) +pmul(op1,op2) = (2) +pdiv(op1,op2) = (1) +pand(op1,op2) = (0) +por(op1,op2) = (3) +pxor(op1,op2) = (3) +pshl(op1,op2) = (4) +pshr(op1,op2) = (0) +pmin(op3,op2) = (1) +pmax(op3,op2) = (1) +pavg(op3,op2) = (1) +================================================ +Testing float[2] +================================================ +op1 = (2.00,2.00) +op2 = (1.00,2.00) +passign(op2,op3) = (1.00,2.00) +padd(op1,op2) = (3.00,4.00) +psub(op1,op2) = (1.00,2.00) +pmul(op1,op2) = (2.00,4.00) +pdiv(op1,op2) = (1.00,2.00) +pmin(op3,op2) = (1.00,1.00) +pmax(op3,op2) = (2.00,2.00) +pavg(op3,op2) = (1.50,1.50) +================================================ +Testing float[4] +================================================ +op1 = (2.00,2.00,2.00,2.00) +op2 = (1.00,2.00,3.00,4.00) +passign(op2,op3) = (1.00,2.00,3.00,4.00) +padd(op1,op2) = (3.00,4.00,5.00,6.00) +psub(op1,op2) = (1.00,2.00,3.00,4.00) +pmul(op1,op2) = (2.00,4.00,6.00,8.00) +pdiv(op1,op2) = (1.00,2.00,3.00,4.00) +pmin(op3,op2) = (1.00,2.00,2.00,1.00) +pmax(op3,op2) = (4.00,3.00,3.00,4.00) +pavg(op3,op2) = (2.50,2.50,2.50,2.50) +================================================ +Testing uint32_t[7] +================================================ +op1 = (2,2,2,2,2,2,2) +op2 = (1,2,3,4,5,6,7) +passign(op2,op3) = (1,2,3,4,5,6,7) +padd(op1,op2) = (3,4,5,6,7,8,9) +psub(op1,op2) = (1,2,3,4,5,6,7) +pmul(op1,op2) = (2,4,6,8,10,12,14) +pdiv(op1,op2) = (1,2,3,4,5,6,7) +pand(op1,op2) = (0,2,2,0,0,2,2) +por(op1,op2) = (3,2,3,6,7,6,7) +pxor(op1,op2) = (3,0,1,6,7,4,5) +pshl(op1,op2) = (4,8,12,16,20,24,28) +pshr(op1,op2) = (0,0,0,1,1,1,1) +pmin(op3,op2) = (1,2,3,4,3,2,1) +pmax(op3,op2) = (7,6,5,4,5,6,7) +pavg(op3,op2) = (4,4,4,4,4,4,4) +================================================ +Testing fround int32_t -> float +================================================ +(-1,0,1,2) -> (-1.00,0.00,1.00,2.00) +(-1,0,1,2) -> (-1.00,0.00,1.00,2.00) +(-1,0,1,2) -> (-1.00,0.00,1.00,2.00) +================================================ +Testing fround int32_t -> double +================================================ +(-1,0,1,2) -> (-1.00,0.00,1.00,2.00) +(-1,0,1,2) -> (-1.00,0.00,1.00,2.00) +(-1,0,1,2) -> (-1.00,0.00,1.00,2.00) +================================================ +Testing fround float -> int32_t +================================================ +(-1.40,-0.40,0.60,1.60) -> (-1,0,1,2) +(-1.50,-0.50,0.50,1.50) -> (-2,0,0,2) +(-1.70,-0.70,0.30,1.30) -> (-2,-1,0,1) +================================================ +Testing fround double -> int32_t +================================================ +(-1.40,-0.40,0.60,1.60) -> (-1,0,1,2) +(-1.50,-0.50,0.50,1.50) -> (-2,0,0,2) +(-1.70,-0.70,0.30,1.30) -> (-2,-1,0,1) +================================================ +Testing fcast float -> int32_t +================================================ +(-1.40,-0.40,0.60,1.60) -> (-1,0,0,1) +(-1.50,-0.50,0.50,1.50) -> (-1,0,0,1) +(-1.70,-0.70,0.30,1.30) -> (-1,0,0,1)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt24.cpp @@ -0,0 +1,100 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +static void HeapSize (size_t nElements, size_t& layerWidth, size_t& nLayers) +{ + layerWidth = 0; + nLayers = 0; + for (size_t fts = 0; nElements > fts; fts += layerWidth) { + layerWidth *= 2; + if (!layerWidth) + ++ layerWidth; + ++ nLayers; + } +} + +static void PrintSpace (size_t n) +{ + for (uoff_t s = 0; s < n; ++ s) + cout << ' '; +} + +static void PrintHeap (const vector<int>& v) +{ + size_t maxWidth, nLayers; + HeapSize (v.size(), maxWidth, nLayers); + vector<int>::const_iterator src (v.begin()); + cout << ios::width(3); + maxWidth *= 3; + for (uoff_t i = 0; i < nLayers; ++ i) { + const size_t w = 1 << i; + const size_t spacing = max (0, int(maxWidth / w) - 3); + PrintSpace (spacing / 2); + for (uoff_t j = 0; j < w && src != v.end(); ++ j) { + cout << *src++; + if (j < w - 1 && src != v.end() - 1) + PrintSpace (spacing); + } + cout << endl; + } +} + +void TestHeapOperations (void) +{ + static const int c_Values [31] = { // 31 values make a full 4-layer tree + 93, 92, 90, 86, 83, 86, 77, 40, 72, 36, 68, 82, 62, 67, 63, 15, + 26, 26, 49, 21, 11, 62, 67, 27, 29, 30, 35, 23, 59, 35, 29 + }; + vector<int> v; + v.reserve (VectorSize(c_Values)); + for (uoff_t i = 0; i < VectorSize(c_Values); ++ i) { + v.push_back (c_Values[i]); + push_heap (v.begin(), v.end()); + cout << "------------------------------------------------\n"; + if (!is_heap (v.begin(), v.end())) + cout << "Is NOT a heap\n"; + PrintHeap (v); + } + cout << "------------------------------------------------\n"; + cout << "make_heap on the full range:\n"; + v.resize (VectorSize (c_Values)); + copy (VectorRange(c_Values), v.begin()); + make_heap (v.begin(), v.end()); + PrintHeap (v); + if (!is_heap (v.begin(), v.end())) + cout << "Is NOT a heap\n"; + cout << "------------------------------------------------\n"; + cout << "pop_heap:\n"; + pop_heap (v.begin(), v.end()); + v.pop_back(); + PrintHeap (v); + if (!is_heap (v.begin(), v.end())) + cout << "Is NOT a heap\n"; + + cout << "------------------------------------------------\n"; + cout << "sort_heap:\n"; + v.resize (VectorSize (c_Values)); + copy (VectorRange(c_Values), v.begin()); + make_heap (v.begin(), v.end()); + sort_heap (v.begin(), v.end()); + foreach (vector<int>::const_iterator, i, v) + cout << *i; + cout << endl; + + cout << "------------------------------------------------\n"; + cout << "priority_queue push and pop:\n"; + priority_queue<int> q; + for (uoff_t i = 0; i < VectorSize(c_Values); ++ i) + q.push (c_Values[i]); + while (!q.empty()) { + cout << q.top(); + q.pop(); + } + cout << endl; +} + +StdBvtMain (TestHeapOperations)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt24.std @@ -0,0 +1,180 @@ +------------------------------------------------ + 93 +------------------------------------------------ + 93 + 92 +------------------------------------------------ + 93 + 92 90 +------------------------------------------------ + 93 + 92 90 + 86 +------------------------------------------------ + 93 + 92 90 + 86 83 +------------------------------------------------ + 93 + 92 90 + 86 83 86 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 62 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 62 67 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 62 67 63 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 62 67 63 + 15 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 62 67 63 + 15 26 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 62 67 63 + 15 26 26 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 62 67 63 + 15 26 26 49 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 62 67 63 + 15 26 26 49 21 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 62 67 63 + 15 26 26 49 21 11 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 62 67 63 + 15 26 26 49 21 11 62 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 62 67 63 + 15 26 26 49 21 11 62 67 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 62 67 63 + 15 26 26 49 21 11 62 67 27 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 62 67 63 + 15 26 26 49 21 11 62 67 27 29 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 62 67 63 + 15 26 26 49 21 11 62 67 27 29 30 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 62 67 63 + 15 26 26 49 21 11 62 67 27 29 30 35 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 62 67 63 + 15 26 26 49 21 11 62 67 27 29 30 35 23 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 62 67 63 + 15 26 26 49 21 11 62 67 27 29 30 35 23 59 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 62 67 63 + 15 26 26 49 21 11 62 67 27 29 30 35 23 59 35 +------------------------------------------------ + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 62 67 63 + 15 26 26 49 21 11 62 67 27 29 30 35 23 59 35 29 +------------------------------------------------ +make_heap on the full range: + 93 + 92 90 + 86 83 86 77 + 40 72 36 68 82 62 67 63 + 15 26 26 49 21 11 62 67 27 29 30 35 23 59 35 29 +------------------------------------------------ +pop_heap: + 92 + 86 90 + 72 83 86 77 + 40 49 36 68 82 62 67 63 + 15 26 26 29 21 11 62 67 27 29 30 35 23 59 35 +------------------------------------------------ +sort_heap: + 11 15 21 23 26 26 27 29 29 30 35 35 36 40 49 59 62 62 63 67 67 68 72 77 82 83 86 86 90 92 93 +------------------------------------------------ +priority_queue push and pop: + 93 92 90 86 86 83 82 77 72 68 67 67 63 62 62 59 49 40 36 35 35 30 29 29 27 26 26 23 21 15 11
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt25.cpp @@ -0,0 +1,22 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +void TestFStream (void) +{ + fstream fs ("bvt/bvt25.std", ios::in | ios::nocreate); + if (!fs && !(fs.open("bvt25.std", ios::in | ios::nocreate),fs)) + cout << "Failed to open bvt25.std" << endl; + string buf; + buf.resize (fs.size()); + if (buf.size() != 71) + cout << "fstream.size() returned " << buf.size() << endl; + fs.read (buf.begin(), buf.size()); + cout << buf; + fs.close(); +} + +StdBvtMain (TestFStream)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt25.std @@ -0,0 +1,5 @@ +Hello world! +123 456 789 +two words +and three words +and even four words
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt26.cpp @@ -0,0 +1,19 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" + +void TestMacros (void) +{ + #define VARNAME(n) LARG_NUMBER(v,n) + #define VARDECL(n) VARNAME(n) = n + int COMMA_LIST (9, VARDECL); + cout << LIST(9, VARNAME, <<) << endl; + #define TO_STRING(n) #n + #define PRINT_N(n) REPEAT(n, TO_STRING) "\n" + cout << LIST(9, PRINT_N, <<); +} + +StdBvtMain (TestMacros)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt26.std @@ -0,0 +1,10 @@ +123456789 +1 +12 +123 +1234 +12345 +123456 +1234567 +12345678 +123456789
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt27.cpp @@ -0,0 +1,57 @@ +// This file is part of the uSTL library, an STL implementation. +// +// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. + +#include "stdtest.h" +using namespace tm; + +void Print (int v) + { cout.format ("PrintInt %d\n", v); } +void Print (short v) + { cout.format ("PrintShort %d\n", v); } +void Print (float v) + { cout.format ("PrintFloat %.2f\n", v); } + +class Base { }; +class Derived : public Base { }; + +void TestTypelists (void) +{ + cout << "----------------------------------------------------------------------\n" + " Testing functionality from typet.h\n" + "----------------------------------------------------------------------\n"; + NullType nullType; + cout.format ("sizeof(NullType) = %zu\n", sizeof(nullType)); + cout.format ("Int2Type(42)::value = %d\n", Int2Type<42>::value); + Type2Type<int>::OriginalType t2tiv = 56; + cout.format ("Type2Type type value = %d\n", t2tiv); + + cout << "int == int is " << bool(IsSameType<int, int>::value) << endl; + cout << "float == int is " << bool(IsSameType<float, int>::value) << endl; + + Print (Select<Conversion<long,int>::exists2Way, int, float>::Result(567)); + cout << "Base is SuperSubclass from Derived is " << bool(SuperSubclass<Base,Derived>::value) << endl; + cout << "Base is SuperSubclass from Base is " << bool(SuperSubclass<Base,Base>::value) << endl; + cout << "Base is SuperSubclassStrict from Derived is " << bool(SuperSubclassStrict<Base,Derived>::value) << endl; + cout << "Base is SuperSubclassStrict from Base is " << bool(SuperSubclassStrict<Base,Base>::value) << endl; + + cout << "\n----------------------------------------------------------------------\n" + " Testing functionality from typelist.h\n" + "----------------------------------------------------------------------\n"; + typedef tl::Seq<char, int, short, long>::Type IntTypesList; + typedef tl::Seq<float, double>::Type FloatTypesList; + cout.format ("Length of IntTypesList is %d\n", tl::Length<IntTypesList>::value); + Print (tl::TypeAt<IntTypesList, 2>::Result(1234)); + Print (tl::TypeAtNonStrict<FloatTypesList, 0, int>::Result(1235)); + Print (tl::TypeAtNonStrict<FloatTypesList, 2, short>::Result(1236)); + typedef tl::Append<IntTypesList, FloatTypesList>::Result AllTypesList; + cout.format ("Index of double in AllTypesList is %d\n", tl::IndexOf<AllTypesList,double>::value); + typedef tl::Erase<AllTypesList, float>::Result NoFloatList; + cout.format ("Index of float in NoFloatList is %d\n", tl::IndexOf<NoFloatList,float>::value); + cout.format ("Index of double in NoFloatList is %d\n", tl::IndexOf<NoFloatList,double>::value); + typedef tl::Reverse<AllTypesList>::Result ReversedList; + cout.format ("Index of double in ReversedList is %d\n", tl::IndexOf<ReversedList,double>::value); +} + +StdBvtMain (TestTypelists)
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/bvt27.std @@ -0,0 +1,25 @@ +---------------------------------------------------------------------- + Testing functionality from typet.h +---------------------------------------------------------------------- +sizeof(NullType) = 1 +Int2Type(42)::value = 42 +Type2Type type value = 56 +int == int is true +float == int is false +PrintInt 567 +Base is SuperSubclass from Derived is true +Base is SuperSubclass from Base is true +Base is SuperSubclassStrict from Derived is true +Base is SuperSubclassStrict from Base is false + +---------------------------------------------------------------------- + Testing functionality from typelist.h +---------------------------------------------------------------------- +Length of IntTypesList is 4 +PrintShort 1234 +PrintFloat 1235.00 +PrintShort 1236 +Index of double in AllTypesList is 5 +Index of float in NoFloatList is -1 +Index of double in NoFloatList is 4 +Index of double in ReversedList is 0
new file mode 100644 --- /dev/null +++ b/packages/language/cxx/ustl/current/tests/stdtest.h @@ -0,0 +1,122 @@ +// This file is part of the ustl library, an STL implementation. +// +// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net> +// This file is free software, distributed under the MIT License. +// +// \file stdtest.h +// \brief Standard BVT harness. +// +#ifndef CYGONCE_STDTEST_H +#define CYGONCE_STDTEST_H + +#include <ustl.h> +#include <signal.h> +#include <cyg/infra/testcase.h> +using namespace ustl; + +typedef void (*stdtestfunc_t)(void); + +#ifdef CYGVAR_USTL_CIN_COUT_CERR +/// Called when a signal is received. +static void OnSignal (int sig) +{ + cout.flush(); +#ifdef HAVE_STRSIGNAL + cerr.format ("Fatal error: %s received.\n", strsignal(sig)); +#else + cerr.format ("Fatal error: system signal %d received.\n", sig); +#endif + cerr.flush(); + CYG_TEST_FAIL("Test failed"); + exit (sig); +} + +/* +/// Called by the framework on unrecoverable exception handling errors. +static void Terminate (void) +{ + CYG_TEST_FAIL_FINISH("Unrecoverable exception handling error detected."); + raise (SIGABRT); + exit (EXIT_FAILURE); +} + +/// Called when an exception violates a throw specification. +static void OnUnexpected (void) +{ + CYG_TEST_FAIL("Fatal internal error: unexpected exception caught.\n"); + Terminate(); +} +*/ +/// Installs OnSignal as handler for signals. +static void InstallCleanupHandlers (void) +{ + static const uint8_t c_Signals[] = { + SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, + SIGIOT, SIGBUS, SIGFPE, SIGSEGV, SIGTERM}; + for (uoff_t i = 0; i < VectorSize(c_Signals); ++i) + { + signal (c_Signals[i], OnSignal); + } +} + +/// executes the test function +#ifndef __EXCEPTIONS +// if eCos is compiled without exceptions support then we implement and install +// our own low level exception handler +void app_exception_handler(const ustl::exception& ex) +{ + ustl::diag_print_exception(ex); + CYG_TEST_FAIL("Test failed because of an uSTL exception"); +} + +int StdTestHarness (stdtestfunc_t testFunction) +{ + InstallCleanupHandlers(); + ustl::set_app_exception_handler(app_exception_handler); + (*testFunction)(); + cout << endl; + cout.flush(); // if there is anything left to print then print it now + return (EXIT_SUCCESS); +} +#else +// if eCos is compiled with exceptions support the we use the default +// StdTestHarness implementation from uSTL library +int StdTestHarness (stdtestfunc_t testFunction) +{ + InstallCleanupHandlers(); + int rv = EXIT_FAILURE; + try { + (*testFunction)(); + rv = EXIT_SUCCESS; + } catch (ustl::exception& e) { + cout.flush(); + cerr << "Error: " << e << endl; + } catch (...) { + cout.flush(); + cerr << "Unexpected error." << endl; + } + cout << endl; + cout.flush(); // if there is anything left to print then print it now + return (rv); +} +#endif + + +#define StdBvtMain(function) int main(int argc, char *argv[]) \ +{ \ + CYG_TEST_INIT(); \ + CYG_TEST_INFO("Starting tests from uSTL testcase " #function); \ + StdTestHarness(&function); \ + CYG_TEST_PASS_FINISH(#function " finished successfully"); \ + return EXIT_SUCCESS; \ +} +#else +#define StdBvtMain(function) int main(int argc, char *argv[]) \ +{ \ + CYG_TEST_INIT(); \ + CYG_TEST_NA("cin, cout & cerr support disabled"); \ +} +#endif + +//--------------------------------------------------------------------------- +#endif // CYGONCE_STDTEST_H
