mirror of
git://projects.qi-hardware.com/gmenu2x.git
synced 2024-11-25 21:50:17 +02:00
Remove Google sparsehash library.
GMenu2X now uses tr1::unordered_map instead, which results in a much smaller binary. The Google library might have its uses when high performance is required, but for us a smaller binary is more important since that reduces startup time.
This commit is contained in:
parent
4ddc189847
commit
599628fa38
@ -27,7 +27,7 @@ noinst_HEADERS = asfont.h button.h cpu.h dirdialog.h FastDelegate.h \
|
|||||||
|
|
||||||
AM_CFLAGS= @CFLAGS@ @SDL_CFLAGS@
|
AM_CFLAGS= @CFLAGS@ @SDL_CFLAGS@
|
||||||
|
|
||||||
AM_CXXFLAGS = @CXXFLAGS@ @SDL_CFLAGS@ -Isparsehash-1.6/src -DTARGET_GP2X \
|
AM_CXXFLAGS = @CXXFLAGS@ @SDL_CFLAGS@ -DTARGET_GP2X \
|
||||||
-Wall -Wextra -Wundef -Wunused-macros
|
-Wall -Wextra -Wundef -Wunused-macros
|
||||||
|
|
||||||
gmenu2x_LDADD = @LIBS@ @SDL_LIBS@ -lSDL_image -lSDL_gfx -lSDL -ljpeg -lpng12 -lz -ldl -lpthread
|
gmenu2x_LDADD = @LIBS@ @SDL_LIBS@ -lSDL_image -lSDL_gfx -lSDL -ljpeg -lpng12 -lz -ldl -lpthread
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
opensource@google.com
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
|||||||
Copyright (c) 2005, Google Inc.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the name of Google Inc. nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,182 +0,0 @@
|
|||||||
Fri Jan 8 14:47:55 2010 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: version 1.6 release
|
|
||||||
* New accessor methods for deleted_key, empty_key (sjackman)
|
|
||||||
* Use explicit hash functions in sparsehash tests (csilvers)
|
|
||||||
* BUGFIX: Cast resize to fix SUNWspro bug (csilvers)
|
|
||||||
* Check for sz overflow in min_size (csilvers)
|
|
||||||
* Speed up clear() for dense and sparse hashtables (jeff)
|
|
||||||
* Avoid shrinking in all cases when min-load is 0 (shaunj, csilvers)
|
|
||||||
* Improve densehashtable code for the deleted key (gpike)
|
|
||||||
* BUGFIX: Fix operator= when the 2 empty-keys differ (andreidam)
|
|
||||||
* BUGFIX: Fix ht copying when empty-key isn't set (andreidam)
|
|
||||||
* PORTING: Use TmpFile() instead of /tmp on MinGW (csilvers)
|
|
||||||
* PORTING: Use filenames that work with Stratus VOS.
|
|
||||||
|
|
||||||
Tue May 12 14:16:38 2009 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: version 1.5.2 release
|
|
||||||
* Fix compile error: not initializing set_key in all constructors
|
|
||||||
|
|
||||||
Fri May 8 15:23:44 2009 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: version 1.5.1 release
|
|
||||||
* Fix broken equal_range() for all the hash-classes (csilvers)
|
|
||||||
|
|
||||||
Wed May 6 11:28:49 2009 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: version 1.5 release
|
|
||||||
* Support the tr1 unordered_map (and unordered_set) API (csilvers)
|
|
||||||
* Store only key for delkey; reduces need for 0-arg c-tor (csilvers)
|
|
||||||
* Prefer unordered_map to hash_map for the timing test (csilvers)
|
|
||||||
* PORTING: update the resource use for 64-bit machines (csilvers)
|
|
||||||
* PORTING: fix MIN/MAX collisions by un-#including windows.h (csilvers)
|
|
||||||
* Updated autoconf version to 2.61 and libtool version to 1.5.26
|
|
||||||
|
|
||||||
Wed Jan 28 17:11:31 2009 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: version 1.4 release
|
|
||||||
* Allow hashtables to be <32 buckets (csilvers)
|
|
||||||
* Fix initial-sizing bug: was sizing tables too small (csilvers)
|
|
||||||
* Add asserts that clients don't abuse deleted/empty key (csilvers)
|
|
||||||
* Improve determination of 32/64 bit for C code (csilvers)
|
|
||||||
* Small fix for doc files in rpm (csilvers)
|
|
||||||
|
|
||||||
Thu Nov 6 15:06:09 2008 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: version 1.3 release
|
|
||||||
* Add an interface to change the parameters for resizing (myl)
|
|
||||||
* Document another potentially good hash function (csilvers)
|
|
||||||
|
|
||||||
Thu Sep 18 13:53:20 2008 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: version 1.2 release
|
|
||||||
* Augment documentation to better describe namespace issues (csilvers)
|
|
||||||
* BUG FIX: replace hash<> with SPARSEHASH_HASH, for windows (csilvers)
|
|
||||||
* Add timing test to unittest to test repeated add+delete (csilvers)
|
|
||||||
* Do better picking a new size when resizing (csilvers)
|
|
||||||
* Use ::google instead of google as a namespace (csilvers)
|
|
||||||
* Improve threading test at config time (csilvers)
|
|
||||||
|
|
||||||
Mon Feb 11 16:30:11 2008 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: version 1.1 release
|
|
||||||
* Fix brown-paper-bag bug in some constructors (rafferty)
|
|
||||||
* Fix problem with variables shadowing member vars, add -Wshadow
|
|
||||||
|
|
||||||
Thu Nov 29 11:44:38 2007 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: version 1.0.2 release
|
|
||||||
* Fix a final reference to hash<> to use SPARSEHASH_HASH<> instead.
|
|
||||||
|
|
||||||
Wed Nov 14 08:47:48 2007 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: version 1.0.1 release :-(
|
|
||||||
* Remove an unnecessary (harmful) "#define hash" in windows' config.h
|
|
||||||
|
|
||||||
Tue Nov 13 15:15:46 2007 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: version 1.0 release! We are now out of beta.
|
|
||||||
* Clean up Makefile awk script to be more readable (csilvers)
|
|
||||||
* Namespace fixes: use fewer #defines, move typedefs into namespace
|
|
||||||
|
|
||||||
Fri Oct 12 12:35:24 2007 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: version 0.9.1 release
|
|
||||||
* Fix Makefile awk script to work on more architectures (csilvers)
|
|
||||||
* Add test to test code in more 'real life' situations (csilvers)
|
|
||||||
|
|
||||||
Tue Oct 9 14:15:21 2007 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: version 0.9 release
|
|
||||||
* More type-hygiene improvements, especially for 64-bit (csilvers)
|
|
||||||
* Some configure improvements to improve portability, utility (austern)
|
|
||||||
* Small bugfix for operator== for dense_hash_map (jeff)
|
|
||||||
|
|
||||||
Tue Jul 3 12:55:04 2007 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: version 0.8 release
|
|
||||||
* Minor type-hygiene improvements: size_t for int, etc. (csilvers)
|
|
||||||
* Porting improvements: tests pass on OS X, FreeBSD, Solaris (csilvers)
|
|
||||||
* Full windows port! VS solution provided for all unittests (csilvers)
|
|
||||||
|
|
||||||
Mon Jun 11 11:33:41 2007 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: version 0.7 release
|
|
||||||
* Syntax fixes to better support gcc 4.3 and VC++ 7 (mec, csilvers)
|
|
||||||
* Improved windows/VC++ support (see README.windows) (csilvers)
|
|
||||||
* Config improvements: better tcmalloc support and config.h (csilvers)
|
|
||||||
* More robust with missing hash_map + nix 'trampoline' .h's (csilvers)
|
|
||||||
* Support for STLport's hash_map/hash_fun locations (csilvers)
|
|
||||||
* Add .m4 files to distribution; now all source is there (csilvers)
|
|
||||||
* Tiny modification of shrink-threshhold to allow never-shrinking (amc)
|
|
||||||
* Protect timing tests against aggressive optimizers (csilvers)
|
|
||||||
* Extend time_hash_map to test bigger objects (csilvers)
|
|
||||||
* Extend type-trait support to work with const objects (csilvers)
|
|
||||||
* USER VISIBLE: speed up all code by replacing memmove with memcpy
|
|
||||||
(csilvers)
|
|
||||||
|
|
||||||
Tue Mar 20 17:29:34 2007 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: version 0.6 release
|
|
||||||
* Some improvement to type-traits (jyasskin)
|
|
||||||
* Better timing results when google-perftools is installed (sanjay)
|
|
||||||
* Updates and fixes to html documentation and README (csilvers)
|
|
||||||
* A bit more careful about #includes (csilvers)
|
|
||||||
* Fix for typo that broken compilation on some systems (csilvers)
|
|
||||||
* USER VISIBLE: New clear_no_resize() method added to dense_hash_map
|
|
||||||
(uszkoreit)
|
|
||||||
|
|
||||||
Sat Oct 21 13:47:47 2006 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: version 0.5 release
|
|
||||||
* Support uint16_t (SunOS) in addition to u_int16_t (BSD) (csilvers)
|
|
||||||
* Get rid of UNDERSTANDS_ITERATOR_TAGS; everyone understands (csilvers)
|
|
||||||
* Test that empty-key and deleted-key differ (rbayardo)
|
|
||||||
* Fix example docs: strcmp needs to test for NULL (csilvers)
|
|
||||||
|
|
||||||
Sun Apr 23 22:42:35 2006 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: version 0.4 release
|
|
||||||
* Remove POD requirement for keys and values! (austern)
|
|
||||||
* Add tr1-compatible type-traits system to speed up POD ops. (austern)
|
|
||||||
* Fixed const-iterator bug where postfix ++ didn't compile. (csilvers)
|
|
||||||
* Fixed iterator comparison bugs where <= was incorrect. (csilvers)
|
|
||||||
* Clean up config.h to keep its #defines from conflicting. (csilvers)
|
|
||||||
* Big documentation sweep and cleanup. (csilvers)
|
|
||||||
* Update documentation to talk more about good hash fns. (csilvers)
|
|
||||||
* Fixes to compile on MSVC (working around some MSVC bugs). (rennie)
|
|
||||||
* Avoid resizing hashtable on operator[] lookups (austern)
|
|
||||||
|
|
||||||
Thu Nov 3 20:12:31 2005 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: version 0.3 release
|
|
||||||
* Quiet compiler warnings on some compilers. (csilvers)
|
|
||||||
* Some documentation fixes: example code for dense_hash_map. (csilvers)
|
|
||||||
* Fix a bug where swap() wasn't swapping delete_key(). (csilvers)
|
|
||||||
* set_deleted_key() and set_empty_key() now take a key only,
|
|
||||||
allowing hash-map values to be forward-declared. (csilvers)
|
|
||||||
* support for std::insert_iterator (and std::inserter). (csilvers)
|
|
||||||
|
|
||||||
Mon May 2 07:04:46 2005 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: version 0.2 release
|
|
||||||
* Preliminary support for msvc++ compilation. (csilvers)
|
|
||||||
* Documentation fixes -- some example code was incomplete! (csilvers)
|
|
||||||
* Minimize size of config.h to avoid other-package conflicts (csilvers)
|
|
||||||
* Contribute a C-based version of sparsehash that served as the
|
|
||||||
inspiration for this code. One day, I hope to clean it up and
|
|
||||||
support it, but for now it's just in experimental/, for playing
|
|
||||||
around with. (csilvers)
|
|
||||||
* Change default namespace from std to google. (csilvers)
|
|
||||||
|
|
||||||
Fri Jan 14 16:53:32 2005 Google Inc. <opensource@google.com>
|
|
||||||
|
|
||||||
* sparsehash: initial release:
|
|
||||||
The sparsehash package contains several hash-map implementations,
|
|
||||||
similar in API to SGI's hash_map class, but with different
|
|
||||||
performance characteristics. sparse_hash_map uses very little
|
|
||||||
space overhead: 1-2 bits per entry. dense_hash_map is typically
|
|
||||||
faster than the default SGI STL implementation. This package
|
|
||||||
also includes hash-set analogues of these classes.
|
|
||||||
|
|
@ -1,236 +0,0 @@
|
|||||||
Installation Instructions
|
|
||||||
*************************
|
|
||||||
|
|
||||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
|
|
||||||
Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is free documentation; the Free Software Foundation gives
|
|
||||||
unlimited permission to copy, distribute and modify it.
|
|
||||||
|
|
||||||
Basic Installation
|
|
||||||
==================
|
|
||||||
|
|
||||||
These are generic installation instructions.
|
|
||||||
|
|
||||||
The `configure' shell script attempts to guess correct values for
|
|
||||||
various system-dependent variables used during compilation. It uses
|
|
||||||
those values to create a `Makefile' in each directory of the package.
|
|
||||||
It may also create one or more `.h' files containing system-dependent
|
|
||||||
definitions. Finally, it creates a shell script `config.status' that
|
|
||||||
you can run in the future to recreate the current configuration, and a
|
|
||||||
file `config.log' containing compiler output (useful mainly for
|
|
||||||
debugging `configure').
|
|
||||||
|
|
||||||
It can also use an optional file (typically called `config.cache'
|
|
||||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
|
||||||
the results of its tests to speed up reconfiguring. (Caching is
|
|
||||||
disabled by default to prevent problems with accidental use of stale
|
|
||||||
cache files.)
|
|
||||||
|
|
||||||
If you need to do unusual things to compile the package, please try
|
|
||||||
to figure out how `configure' could check whether to do them, and mail
|
|
||||||
diffs or instructions to the address given in the `README' so they can
|
|
||||||
be considered for the next release. If you are using the cache, and at
|
|
||||||
some point `config.cache' contains results you don't want to keep, you
|
|
||||||
may remove or edit it.
|
|
||||||
|
|
||||||
The file `configure.ac' (or `configure.in') is used to create
|
|
||||||
`configure' by a program called `autoconf'. You only need
|
|
||||||
`configure.ac' if you want to change it or regenerate `configure' using
|
|
||||||
a newer version of `autoconf'.
|
|
||||||
|
|
||||||
The simplest way to compile this package is:
|
|
||||||
|
|
||||||
1. `cd' to the directory containing the package's source code and type
|
|
||||||
`./configure' to configure the package for your system. If you're
|
|
||||||
using `csh' on an old version of System V, you might need to type
|
|
||||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
|
||||||
`configure' itself.
|
|
||||||
|
|
||||||
Running `configure' takes awhile. While running, it prints some
|
|
||||||
messages telling which features it is checking for.
|
|
||||||
|
|
||||||
2. Type `make' to compile the package.
|
|
||||||
|
|
||||||
3. Optionally, type `make check' to run any self-tests that come with
|
|
||||||
the package.
|
|
||||||
|
|
||||||
4. Type `make install' to install the programs and any data files and
|
|
||||||
documentation.
|
|
||||||
|
|
||||||
5. You can remove the program binaries and object files from the
|
|
||||||
source code directory by typing `make clean'. To also remove the
|
|
||||||
files that `configure' created (so you can compile the package for
|
|
||||||
a different kind of computer), type `make distclean'. There is
|
|
||||||
also a `make maintainer-clean' target, but that is intended mainly
|
|
||||||
for the package's developers. If you use it, you may have to get
|
|
||||||
all sorts of other programs in order to regenerate files that came
|
|
||||||
with the distribution.
|
|
||||||
|
|
||||||
Compilers and Options
|
|
||||||
=====================
|
|
||||||
|
|
||||||
Some systems require unusual options for compilation or linking that the
|
|
||||||
`configure' script does not know about. Run `./configure --help' for
|
|
||||||
details on some of the pertinent environment variables.
|
|
||||||
|
|
||||||
You can give `configure' initial values for configuration parameters
|
|
||||||
by setting variables in the command line or in the environment. Here
|
|
||||||
is an example:
|
|
||||||
|
|
||||||
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
|
|
||||||
|
|
||||||
*Note Defining Variables::, for more details.
|
|
||||||
|
|
||||||
Compiling For Multiple Architectures
|
|
||||||
====================================
|
|
||||||
|
|
||||||
You can compile the package for more than one kind of computer at the
|
|
||||||
same time, by placing the object files for each architecture in their
|
|
||||||
own directory. To do this, you must use a version of `make' that
|
|
||||||
supports the `VPATH' variable, such as GNU `make'. `cd' to the
|
|
||||||
directory where you want the object files and executables to go and run
|
|
||||||
the `configure' script. `configure' automatically checks for the
|
|
||||||
source code in the directory that `configure' is in and in `..'.
|
|
||||||
|
|
||||||
If you have to use a `make' that does not support the `VPATH'
|
|
||||||
variable, you have to compile the package for one architecture at a
|
|
||||||
time in the source code directory. After you have installed the
|
|
||||||
package for one architecture, use `make distclean' before reconfiguring
|
|
||||||
for another architecture.
|
|
||||||
|
|
||||||
Installation Names
|
|
||||||
==================
|
|
||||||
|
|
||||||
By default, `make install' installs the package's commands under
|
|
||||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
|
||||||
can specify an installation prefix other than `/usr/local' by giving
|
|
||||||
`configure' the option `--prefix=PREFIX'.
|
|
||||||
|
|
||||||
You can specify separate installation prefixes for
|
|
||||||
architecture-specific files and architecture-independent files. If you
|
|
||||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
|
||||||
PREFIX as the prefix for installing programs and libraries.
|
|
||||||
Documentation and other data files still use the regular prefix.
|
|
||||||
|
|
||||||
In addition, if you use an unusual directory layout you can give
|
|
||||||
options like `--bindir=DIR' to specify different values for particular
|
|
||||||
kinds of files. Run `configure --help' for a list of the directories
|
|
||||||
you can set and what kinds of files go in them.
|
|
||||||
|
|
||||||
If the package supports it, you can cause programs to be installed
|
|
||||||
with an extra prefix or suffix on their names by giving `configure' the
|
|
||||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
|
||||||
|
|
||||||
Optional Features
|
|
||||||
=================
|
|
||||||
|
|
||||||
Some packages pay attention to `--enable-FEATURE' options to
|
|
||||||
`configure', where FEATURE indicates an optional part of the package.
|
|
||||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
|
||||||
is something like `gnu-as' or `x' (for the X Window System). The
|
|
||||||
`README' should mention any `--enable-' and `--with-' options that the
|
|
||||||
package recognizes.
|
|
||||||
|
|
||||||
For packages that use the X Window System, `configure' can usually
|
|
||||||
find the X include and library files automatically, but if it doesn't,
|
|
||||||
you can use the `configure' options `--x-includes=DIR' and
|
|
||||||
`--x-libraries=DIR' to specify their locations.
|
|
||||||
|
|
||||||
Specifying the System Type
|
|
||||||
==========================
|
|
||||||
|
|
||||||
There may be some features `configure' cannot figure out automatically,
|
|
||||||
but needs to determine by the type of machine the package will run on.
|
|
||||||
Usually, assuming the package is built to be run on the _same_
|
|
||||||
architectures, `configure' can figure that out, but if it prints a
|
|
||||||
message saying it cannot guess the machine type, give it the
|
|
||||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
|
||||||
type, such as `sun4', or a canonical name which has the form:
|
|
||||||
|
|
||||||
CPU-COMPANY-SYSTEM
|
|
||||||
|
|
||||||
where SYSTEM can have one of these forms:
|
|
||||||
|
|
||||||
OS KERNEL-OS
|
|
||||||
|
|
||||||
See the file `config.sub' for the possible values of each field. If
|
|
||||||
`config.sub' isn't included in this package, then this package doesn't
|
|
||||||
need to know the machine type.
|
|
||||||
|
|
||||||
If you are _building_ compiler tools for cross-compiling, you should
|
|
||||||
use the option `--target=TYPE' to select the type of system they will
|
|
||||||
produce code for.
|
|
||||||
|
|
||||||
If you want to _use_ a cross compiler, that generates code for a
|
|
||||||
platform different from the build platform, you should specify the
|
|
||||||
"host" platform (i.e., that on which the generated programs will
|
|
||||||
eventually be run) with `--host=TYPE'.
|
|
||||||
|
|
||||||
Sharing Defaults
|
|
||||||
================
|
|
||||||
|
|
||||||
If you want to set default values for `configure' scripts to share, you
|
|
||||||
can create a site shell script called `config.site' that gives default
|
|
||||||
values for variables like `CC', `cache_file', and `prefix'.
|
|
||||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
|
||||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
|
||||||
`CONFIG_SITE' environment variable to the location of the site script.
|
|
||||||
A warning: not all `configure' scripts look for a site script.
|
|
||||||
|
|
||||||
Defining Variables
|
|
||||||
==================
|
|
||||||
|
|
||||||
Variables not defined in a site shell script can be set in the
|
|
||||||
environment passed to `configure'. However, some packages may run
|
|
||||||
configure again during the build, and the customized values of these
|
|
||||||
variables may be lost. In order to avoid this problem, you should set
|
|
||||||
them in the `configure' command line, using `VAR=value'. For example:
|
|
||||||
|
|
||||||
./configure CC=/usr/local2/bin/gcc
|
|
||||||
|
|
||||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
|
||||||
overridden in the site shell script). Here is a another example:
|
|
||||||
|
|
||||||
/bin/bash ./configure CONFIG_SHELL=/bin/bash
|
|
||||||
|
|
||||||
Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent
|
|
||||||
configuration-related scripts to be executed by `/bin/bash'.
|
|
||||||
|
|
||||||
`configure' Invocation
|
|
||||||
======================
|
|
||||||
|
|
||||||
`configure' recognizes the following options to control how it operates.
|
|
||||||
|
|
||||||
`--help'
|
|
||||||
`-h'
|
|
||||||
Print a summary of the options to `configure', and exit.
|
|
||||||
|
|
||||||
`--version'
|
|
||||||
`-V'
|
|
||||||
Print the version of Autoconf used to generate the `configure'
|
|
||||||
script, and exit.
|
|
||||||
|
|
||||||
`--cache-file=FILE'
|
|
||||||
Enable the cache: use and save the results of the tests in FILE,
|
|
||||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
|
||||||
disable caching.
|
|
||||||
|
|
||||||
`--config-cache'
|
|
||||||
`-C'
|
|
||||||
Alias for `--cache-file=config.cache'.
|
|
||||||
|
|
||||||
`--quiet'
|
|
||||||
`--silent'
|
|
||||||
`-q'
|
|
||||||
Do not print messages saying which checks are being made. To
|
|
||||||
suppress all normal output, redirect it to `/dev/null' (any error
|
|
||||||
messages will still be shown).
|
|
||||||
|
|
||||||
`--srcdir=DIR'
|
|
||||||
Look for the package's source code in directory DIR. Usually
|
|
||||||
`configure' can determine that directory automatically.
|
|
||||||
|
|
||||||
`configure' also accepts some other, not widely useful, options. Run
|
|
||||||
`configure --help' for more details.
|
|
||||||
|
|
@ -1,157 +0,0 @@
|
|||||||
## Process this file with automake to produce Makefile.in
|
|
||||||
|
|
||||||
# Make sure that when we re-make ./configure, we get the macros we need
|
|
||||||
ACLOCAL_AMFLAGS = -I m4
|
|
||||||
|
|
||||||
# This is so we can #include <google/foo>
|
|
||||||
AM_CPPFLAGS = -I$(top_srcdir)/src
|
|
||||||
|
|
||||||
# These are good warnings to turn on by default
|
|
||||||
if GCC
|
|
||||||
AM_CXXFLAGS = -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare -Wshadow
|
|
||||||
endif
|
|
||||||
|
|
||||||
googleincludedir = $(includedir)/google
|
|
||||||
## The .h files you want to install (that is, .h files that people
|
|
||||||
## who install this package can include in their own applications.)
|
|
||||||
googleinclude_HEADERS = \
|
|
||||||
src/google/dense_hash_map \
|
|
||||||
src/google/dense_hash_set \
|
|
||||||
src/google/sparse_hash_map \
|
|
||||||
src/google/sparse_hash_set \
|
|
||||||
src/google/sparsetable \
|
|
||||||
src/google/type_traits.h
|
|
||||||
|
|
||||||
docdir = $(prefix)/share/doc/$(PACKAGE)-$(VERSION)
|
|
||||||
## This is for HTML and other documentation you want to install.
|
|
||||||
## Add your documentation files (in doc/) in addition to these boilerplate
|
|
||||||
## Also add a TODO file if you have one
|
|
||||||
dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README README.windows \
|
|
||||||
TODO \
|
|
||||||
doc/dense_hash_map.html \
|
|
||||||
doc/dense_hash_set.html \
|
|
||||||
doc/sparse_hash_map.html \
|
|
||||||
doc/sparse_hash_set.html \
|
|
||||||
doc/sparsetable.html \
|
|
||||||
doc/implementation.html \
|
|
||||||
doc/performance.html \
|
|
||||||
doc/index.html \
|
|
||||||
doc/designstyle.css
|
|
||||||
|
|
||||||
## The libraries (.so's) you want to install
|
|
||||||
lib_LTLIBRARIES =
|
|
||||||
## The location of the windows project file for each binary we make
|
|
||||||
WINDOWS_PROJECTS = google-sparsehash.sln
|
|
||||||
|
|
||||||
## unittests you want to run when people type 'make check'.
|
|
||||||
## TESTS is for binary unittests, check_SCRIPTS for script-based unittests.
|
|
||||||
## TESTS_ENVIRONMENT sets environment variables for when you run unittest,
|
|
||||||
## but it only seems to take effect for *binary* unittests (argh!)
|
|
||||||
TESTS = type_traits_unittest sparsetable_unittest hashtable_unittest \
|
|
||||||
simple_test
|
|
||||||
# TODO(csilvers): get simple_test working on windows
|
|
||||||
WINDOWS_PROJECTS += vsprojects/type_traits_unittest/type_traits_unittest.vcproj \
|
|
||||||
vsprojects/sparsetable_unittest/sparsetable_unittest.vcproj \
|
|
||||||
vsprojects/hashtable_unittest/hashtable_unittest.vcproj
|
|
||||||
check_SCRIPTS =
|
|
||||||
TESTS_ENVIRONMENT =
|
|
||||||
|
|
||||||
## This should always include $(TESTS), but may also include other
|
|
||||||
## binaries that you compile but don't want automatically installed.
|
|
||||||
noinst_PROGRAMS = $(TESTS) time_hash_map
|
|
||||||
WINDOWS_PROJECTS += vsprojects/time_hash_map/time_hash_map.vcproj
|
|
||||||
|
|
||||||
|
|
||||||
## vvvv RULES TO MAKE THE LIBRARIES, BINARIES, AND UNITTESTS
|
|
||||||
|
|
||||||
# All our .h files need to read the config information in config.h. The
|
|
||||||
# autoheader config.h has too much info, including PACKAGENAME, that
|
|
||||||
# might conflict with other config.h's an application might #include.
|
|
||||||
# Thus, we create a "minimal" config.h, called sparseconfig.h, that
|
|
||||||
# includes only the #defines we really need, and that are unlikely to
|
|
||||||
# change from system to system. NOTE: The awk command is equivalent to
|
|
||||||
# fgrep -B2 -f- $(top_builddir)/src/config.h \
|
|
||||||
# fgrep -vx -e -- > _sparsehash_config
|
|
||||||
# For correctness, it depends on the fact config.h.include does not have
|
|
||||||
# any lines starting with #.
|
|
||||||
src/google/sparsehash/sparseconfig.h: $(top_builddir)/src/config.h \
|
|
||||||
$(top_srcdir)/src/config.h.include
|
|
||||||
[ -d $(@D) ] || mkdir -p $(@D)
|
|
||||||
echo "/*" > $(@D)/_sparsehash_config
|
|
||||||
echo " * NOTE: This file is for internal use only." >> $(@D)/_sparsehash_config
|
|
||||||
echo " * Do not use these #defines in your own program!" >> $(@D)/_sparsehash_config
|
|
||||||
echo " */" >> $(@D)/_sparsehash_config
|
|
||||||
$(AWK) '{prevline=currline; currline=$$0;} \
|
|
||||||
/^#/ {in_second_file = 1;} \
|
|
||||||
!in_second_file {if (currline !~ /^ *$$/) {inc[currline]=0}}; \
|
|
||||||
in_second_file { for (i in inc) { \
|
|
||||||
if (index(currline, i) != 0) { \
|
|
||||||
print "\n"prevline"\n"currline; \
|
|
||||||
delete inc[i]; \
|
|
||||||
} \
|
|
||||||
} }' \
|
|
||||||
$(top_srcdir)/src/config.h.include $(top_builddir)/src/config.h \
|
|
||||||
>> $(@D)/_sparsehash_config
|
|
||||||
mv -f $(@D)/_sparsehash_config $@
|
|
||||||
# This is how we tell automake about auto-generated .h files
|
|
||||||
BUILT_SOURCES = src/google/sparsehash/sparseconfig.h
|
|
||||||
CLEANFILES = src/google/sparsehash/sparseconfig.h
|
|
||||||
|
|
||||||
sparsehashincludedir = $(googleincludedir)/sparsehash
|
|
||||||
sparsehashinclude_HEADERS = \
|
|
||||||
src/google/sparsehash/densehashtable.h \
|
|
||||||
src/google/sparsehash/sparsehashtable.h
|
|
||||||
nodist_sparsehashinclude_HEADERS = src/google/sparsehash/sparseconfig.h
|
|
||||||
|
|
||||||
type_traits_unittest_SOURCES = \
|
|
||||||
src/type_traits_unittest.cc \
|
|
||||||
$(sparsehashinclude_HEADERS) \
|
|
||||||
src/google/type_traits.h
|
|
||||||
nodist_type_traits_unittest_SOURCES = $(nodist_sparsehashinclude_HEADERS)
|
|
||||||
|
|
||||||
sparsetable_unittest_SOURCES = \
|
|
||||||
src/sparsetable_unittest.cc \
|
|
||||||
$(sparsehashinclude_HEADERS) \
|
|
||||||
src/google/sparsetable
|
|
||||||
nodist_sparsetable_unittest_SOURCES = $(nodist_sparsehashinclude_HEADERS)
|
|
||||||
|
|
||||||
hashtable_unittest_SOURCES = \
|
|
||||||
src/hashtable_unittest.cc \
|
|
||||||
$(googleinclude_HEADERS) \
|
|
||||||
$(sparsehashinclude_HEADERS) \
|
|
||||||
src/words
|
|
||||||
nodist_hashtable_unittest_SOURCES = $(nodist_sparsehashinclude_HEADERS)
|
|
||||||
|
|
||||||
simple_test_SOURCES = \
|
|
||||||
src/simple_test.cc \
|
|
||||||
$(sparsehashinclude_HEADERS)
|
|
||||||
nodist_simple_test_SOURCES = $(nodist_sparsehashinclude_HEADERS)
|
|
||||||
|
|
||||||
time_hash_map_SOURCES = \
|
|
||||||
src/time_hash_map.cc \
|
|
||||||
$(sparsehashinclude_HEADERS) \
|
|
||||||
$(googleinclude_HEADERS)
|
|
||||||
nodist_time_hash_map_SOURCES = $(nodist_sparsehashinclude_HEADERS)
|
|
||||||
|
|
||||||
# If tcmalloc is installed, use it with time_hash_map; it gives us
|
|
||||||
# heap-usage statistics for the hash_map routines, which is very nice
|
|
||||||
time_hash_map_CXXFLAGS = @tcmalloc_flags@ $(AM_CXXFLAGS)
|
|
||||||
time_hash_map_LDFLAGS = @tcmalloc_flags@
|
|
||||||
time_hash_map_LDADD = @tcmalloc_libs@
|
|
||||||
|
|
||||||
## ^^^^ END OF RULES TO MAKE THE LIBRARIES, BINARIES, AND UNITTESTS
|
|
||||||
|
|
||||||
|
|
||||||
rpm: dist-gzip packages/rpm.sh packages/rpm/rpm.spec
|
|
||||||
@cd packages && ./rpm.sh ${PACKAGE} ${VERSION}
|
|
||||||
|
|
||||||
deb: dist-gzip packages/deb.sh packages/deb/*
|
|
||||||
@cd packages && ./deb.sh ${PACKAGE} ${VERSION}
|
|
||||||
|
|
||||||
# Windows wants write permission to .vcproj files and maybe even sln files.
|
|
||||||
dist-hook:
|
|
||||||
test -e "$(distdir)/vsprojects" \
|
|
||||||
&& chmod -R u+w $(distdir)/*.sln $(distdir)/vsprojects/
|
|
||||||
|
|
||||||
EXTRA_DIST = packages/rpm.sh packages/rpm/rpm.spec packages/deb.sh packages/deb \
|
|
||||||
src/config.h.include src/windows $(WINDOWS_PROJECTS) experimental
|
|
@ -1,149 +0,0 @@
|
|||||||
This directory contains several hash-map implementations, similar in
|
|
||||||
API to SGI's hash_map class, but with different performance
|
|
||||||
characteristics. sparse_hash_map uses very little space overhead, 1-2
|
|
||||||
bits per entry. dense_hash_map is very fast, particulary on lookup.
|
|
||||||
(sparse_hash_set and dense_hash_set are the set versions of these
|
|
||||||
routines.) On the other hand, these classes have requirements that
|
|
||||||
may not make them appropriate for all applications.
|
|
||||||
|
|
||||||
All these implementation use a hashtable with internal quadratic
|
|
||||||
probing. This method is space-efficient -- there is no pointer
|
|
||||||
overhead -- and time-efficient for good hash functions.
|
|
||||||
|
|
||||||
COMPILING
|
|
||||||
---------
|
|
||||||
To compile test applications with these classes, run ./configure
|
|
||||||
followed by make. To install these header files on your system, run
|
|
||||||
'make install'. (On Windows, the instructions are different; see
|
|
||||||
README.windows.) See INSTALL for more details.
|
|
||||||
|
|
||||||
This code should work on any modern C++ system. It has been tested on
|
|
||||||
Linux (Ubuntu, Fedora, RedHat, Debian), Solaris 10 x86, FreeBSD 6.0,
|
|
||||||
OS X 10.3 and 10.4, and Windows under both VC++7 and VC++8.
|
|
||||||
|
|
||||||
USING
|
|
||||||
-----
|
|
||||||
See the html files in the doc directory for small example programs
|
|
||||||
that use these classes. It's enough to just include the header file:
|
|
||||||
|
|
||||||
#include <google/sparse_hash_map> // or sparse_hash_set, dense_hash_map, ...
|
|
||||||
google::sparse_hash_set<int, int> number_mapper;
|
|
||||||
|
|
||||||
and use the class the way you would other hash-map implementations.
|
|
||||||
(Though see "API" below for caveats.)
|
|
||||||
|
|
||||||
By default (you can change it via a flag to ./configure), these hash
|
|
||||||
implementations are defined in the google namespace.
|
|
||||||
|
|
||||||
API
|
|
||||||
---
|
|
||||||
The API for sparse_hash_map, dense_hash_map, sparse_hash_set, and
|
|
||||||
dense_hash_set, are a superset of the API of SGI's hash_map class.
|
|
||||||
See doc/sparse_hash_map.html, et al., for more information about the
|
|
||||||
API.
|
|
||||||
|
|
||||||
The usage of these classes differ from SGI's hash_map, and other
|
|
||||||
hashtable implementations, in the following major ways:
|
|
||||||
|
|
||||||
1) dense_hash_map requires you to set aside one key value as the
|
|
||||||
'empty bucket' value, set via the set_empty_key() method. This
|
|
||||||
*MUST* be called before you can use the dense_hash_map. It is
|
|
||||||
illegal to insert any elements into a dense_hash_map whose key is
|
|
||||||
equal to the empty-key.
|
|
||||||
|
|
||||||
2) For both dense_hash_map and sparse_hash_map, if you wish to delete
|
|
||||||
elements from the hashtable, you must set aside a key value as the
|
|
||||||
'deleted bucket' value, set via the set_deleted_key() method. If
|
|
||||||
your hash-map is insert-only, there is no need to call this
|
|
||||||
method. If you call set_deleted_key(), it is illegal to insert any
|
|
||||||
elements into a dense_hash_map or sparse_hash_map whose key is
|
|
||||||
equal to the deleted-key.
|
|
||||||
|
|
||||||
3) These hash-map implementation support I/O. See below.
|
|
||||||
|
|
||||||
There are also some smaller differences:
|
|
||||||
|
|
||||||
1) The constructor takes an optional argument that specifies the
|
|
||||||
number of elements you expect to insert into the hashtable. This
|
|
||||||
differs from SGI's hash_map implementation, which takes an optional
|
|
||||||
number of buckets.
|
|
||||||
|
|
||||||
2) erase() does not immediately reclaim memory. As a consequence,
|
|
||||||
erase() does not invalidate any iterators, making loops like this
|
|
||||||
correct:
|
|
||||||
for (it = ht.begin(); it != ht.end(); ++it)
|
|
||||||
if (...) ht.erase(it);
|
|
||||||
As another consequence, a series of erase() calls can leave your
|
|
||||||
hashtable using more memory than it needs to. The hashtable will
|
|
||||||
automatically compact() at the next call to insert(), but to
|
|
||||||
manually compact a hashtable, you can call
|
|
||||||
ht.resize(0)
|
|
||||||
|
|
||||||
3) While sparse_hash_map et al. accept an Allocator template argument,
|
|
||||||
they ignore it. They use malloc() and free() for all memory
|
|
||||||
allocations.
|
|
||||||
|
|
||||||
4) sparse_hash_map et al. do not use exceptions.
|
|
||||||
|
|
||||||
I/O
|
|
||||||
---
|
|
||||||
In addition to the normal hash-map operations, sparse_hash_map can
|
|
||||||
read and write hashtables to disk. (dense_hash_map also has the API,
|
|
||||||
but it has not yet been implemented, and writes will always fail.)
|
|
||||||
|
|
||||||
In the simplest case, writing a hashtable is as easy as calling two
|
|
||||||
methods on the hashtable:
|
|
||||||
ht.write_metadata(fp);
|
|
||||||
ht.write_nopointer_data(fp);
|
|
||||||
|
|
||||||
Reading in this data is equally simple:
|
|
||||||
google::sparse_hash_map<...> ht;
|
|
||||||
ht.read_metadata(fp);
|
|
||||||
ht.read_nopointer_data(fp);
|
|
||||||
|
|
||||||
The above is sufficient if the key and value do not contain any
|
|
||||||
pointers: they are basic C types or agglomorations of basic C types.
|
|
||||||
If the key and/or value do contain pointers, you can still store the
|
|
||||||
hashtable by replacing write_nopointer_data() with a custom writing
|
|
||||||
routine. See sparse_hash_map.html et al. for more information.
|
|
||||||
|
|
||||||
SPARSETABLE
|
|
||||||
-----------
|
|
||||||
In addition to the hash-map and hash-set classes, this package also
|
|
||||||
provides sparsetable.h, an array implementation that uses space
|
|
||||||
proportional to the number of elements in the array, rather than the
|
|
||||||
maximum element index. It uses very little space overhead: 1 bit per
|
|
||||||
entry. See doc/sparsetable.html for the API.
|
|
||||||
|
|
||||||
RESOURCE USAGE
|
|
||||||
--------------
|
|
||||||
* sparse_hash_map has memory overhead of about 2 bits per hash-map
|
|
||||||
entry.
|
|
||||||
* dense_hash_map has a factor of 2-3 memory overhead: if your
|
|
||||||
hashtable data takes X bytes, dense_hash_map will use 3X-4X memory
|
|
||||||
total.
|
|
||||||
|
|
||||||
Hashtables tend to double in size when resizing, creating an
|
|
||||||
additional 50% space overhead. dense_hash_map does in fact have a
|
|
||||||
significant "high water mark" memory use requirement.
|
|
||||||
sparse_hash_map, however, is written to need very little space
|
|
||||||
overhead when resizing: only a few bits per hashtable entry.
|
|
||||||
|
|
||||||
PERFORMANCE
|
|
||||||
-----------
|
|
||||||
You can compile and run the included file time_hash_map.cc to examine
|
|
||||||
the performance of sparse_hash_map, dense_hash_map, and your native
|
|
||||||
hash_map implementation on your system. One test against the
|
|
||||||
SGI hash_map implementation gave the following timing information for
|
|
||||||
a simple find() call:
|
|
||||||
SGI hash_map: 22 ns
|
|
||||||
dense_hash_map: 13 ns
|
|
||||||
sparse_hash_map: 117 ns
|
|
||||||
SGI map: 113 ns
|
|
||||||
|
|
||||||
See doc/performance.html for more detailed charts on resource usage
|
|
||||||
and performance data.
|
|
||||||
|
|
||||||
---
|
|
||||||
16 March 2005
|
|
||||||
(Last updated: 20 March 2007)
|
|
@ -1,28 +0,0 @@
|
|||||||
1) TODO: I/O implementation in densehashtable.h
|
|
||||||
|
|
||||||
2) TODO: document SPARSEHASH_STAT_UPDATE macro, and also macros that
|
|
||||||
tweak performance. Perhaps add support to these to the API?
|
|
||||||
|
|
||||||
3) TODO: support exceptions?
|
|
||||||
|
|
||||||
4) BUG: sparsetable's operator[] doesn't work well with printf: you
|
|
||||||
need to explicitly cast the result to value_type to print it. (It
|
|
||||||
works fine with streams.)
|
|
||||||
|
|
||||||
5) TODO: consider rewriting dense_hash_map to use a 'groups' scheme,
|
|
||||||
like sparsetable, but without the sparse-allocation within a
|
|
||||||
group. This makes resizing have better memory-use properties. The
|
|
||||||
downside is that probes across groups might take longer since
|
|
||||||
groups are not contiguous in memory. Making groups the same size
|
|
||||||
as a cache-line, and ensuring they're loaded on cache-line
|
|
||||||
boundaries, might help. Needs careful testing to make sure it
|
|
||||||
doesn't hurt performance.
|
|
||||||
|
|
||||||
6) TODO: Get the C-only version of sparsehash in experimental/ ready
|
|
||||||
for prime-time.
|
|
||||||
|
|
||||||
7) TODO: use cmake (www.cmake.org) to make it easy to isntall this on
|
|
||||||
a windows system.
|
|
||||||
|
|
||||||
---
|
|
||||||
28 February 2007
|
|
868
src/sparsehash-1.6/aclocal.m4
vendored
868
src/sparsehash-1.6/aclocal.m4
vendored
@ -1,868 +0,0 @@
|
|||||||
# generated automatically by aclocal 1.9.6 -*- Autoconf -*-
|
|
||||||
|
|
||||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
|
||||||
# 2005 Free Software Foundation, Inc.
|
|
||||||
# This file is free software; the Free Software Foundation
|
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
|
||||||
# with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
|
||||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
# PARTICULAR PURPOSE.
|
|
||||||
|
|
||||||
# Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
|
|
||||||
#
|
|
||||||
# This file is free software; the Free Software Foundation
|
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
|
||||||
# with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
# AM_AUTOMAKE_VERSION(VERSION)
|
|
||||||
# ----------------------------
|
|
||||||
# Automake X.Y traces this macro to ensure aclocal.m4 has been
|
|
||||||
# generated from the m4 files accompanying Automake X.Y.
|
|
||||||
AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"])
|
|
||||||
|
|
||||||
# AM_SET_CURRENT_AUTOMAKE_VERSION
|
|
||||||
# -------------------------------
|
|
||||||
# Call AM_AUTOMAKE_VERSION so it can be traced.
|
|
||||||
# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
|
|
||||||
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
|
|
||||||
[AM_AUTOMAKE_VERSION([1.9.6])])
|
|
||||||
|
|
||||||
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
|
|
||||||
|
|
||||||
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
|
|
||||||
#
|
|
||||||
# This file is free software; the Free Software Foundation
|
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
|
||||||
# with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
|
|
||||||
# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
|
|
||||||
# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
|
|
||||||
#
|
|
||||||
# Of course, Automake must honor this variable whenever it calls a
|
|
||||||
# tool from the auxiliary directory. The problem is that $srcdir (and
|
|
||||||
# therefore $ac_aux_dir as well) can be either absolute or relative,
|
|
||||||
# depending on how configure is run. This is pretty annoying, since
|
|
||||||
# it makes $ac_aux_dir quite unusable in subdirectories: in the top
|
|
||||||
# source directory, any form will work fine, but in subdirectories a
|
|
||||||
# relative path needs to be adjusted first.
|
|
||||||
#
|
|
||||||
# $ac_aux_dir/missing
|
|
||||||
# fails when called from a subdirectory if $ac_aux_dir is relative
|
|
||||||
# $top_srcdir/$ac_aux_dir/missing
|
|
||||||
# fails if $ac_aux_dir is absolute,
|
|
||||||
# fails when called from a subdirectory in a VPATH build with
|
|
||||||
# a relative $ac_aux_dir
|
|
||||||
#
|
|
||||||
# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
|
|
||||||
# are both prefixed by $srcdir. In an in-source build this is usually
|
|
||||||
# harmless because $srcdir is `.', but things will broke when you
|
|
||||||
# start a VPATH build or use an absolute $srcdir.
|
|
||||||
#
|
|
||||||
# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
|
|
||||||
# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
|
|
||||||
# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
|
|
||||||
# and then we would define $MISSING as
|
|
||||||
# MISSING="\${SHELL} $am_aux_dir/missing"
|
|
||||||
# This will work as long as MISSING is not called from configure, because
|
|
||||||
# unfortunately $(top_srcdir) has no meaning in configure.
|
|
||||||
# However there are other variables, like CC, which are often used in
|
|
||||||
# configure, and could therefore not use this "fixed" $ac_aux_dir.
|
|
||||||
#
|
|
||||||
# Another solution, used here, is to always expand $ac_aux_dir to an
|
|
||||||
# absolute PATH. The drawback is that using absolute paths prevent a
|
|
||||||
# configured tree to be moved without reconfiguration.
|
|
||||||
|
|
||||||
AC_DEFUN([AM_AUX_DIR_EXPAND],
|
|
||||||
[dnl Rely on autoconf to set up CDPATH properly.
|
|
||||||
AC_PREREQ([2.50])dnl
|
|
||||||
# expand $ac_aux_dir to an absolute path
|
|
||||||
am_aux_dir=`cd $ac_aux_dir && pwd`
|
|
||||||
])
|
|
||||||
|
|
||||||
# AM_CONDITIONAL -*- Autoconf -*-
|
|
||||||
|
|
||||||
# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005
|
|
||||||
# Free Software Foundation, Inc.
|
|
||||||
#
|
|
||||||
# This file is free software; the Free Software Foundation
|
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
|
||||||
# with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
# serial 7
|
|
||||||
|
|
||||||
# AM_CONDITIONAL(NAME, SHELL-CONDITION)
|
|
||||||
# -------------------------------------
|
|
||||||
# Define a conditional.
|
|
||||||
AC_DEFUN([AM_CONDITIONAL],
|
|
||||||
[AC_PREREQ(2.52)dnl
|
|
||||||
ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
|
|
||||||
[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
|
|
||||||
AC_SUBST([$1_TRUE])
|
|
||||||
AC_SUBST([$1_FALSE])
|
|
||||||
if $2; then
|
|
||||||
$1_TRUE=
|
|
||||||
$1_FALSE='#'
|
|
||||||
else
|
|
||||||
$1_TRUE='#'
|
|
||||||
$1_FALSE=
|
|
||||||
fi
|
|
||||||
AC_CONFIG_COMMANDS_PRE(
|
|
||||||
[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
|
|
||||||
AC_MSG_ERROR([[conditional "$1" was never defined.
|
|
||||||
Usually this means the macro was only invoked conditionally.]])
|
|
||||||
fi])])
|
|
||||||
|
|
||||||
|
|
||||||
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
|
|
||||||
# Free Software Foundation, Inc.
|
|
||||||
#
|
|
||||||
# This file is free software; the Free Software Foundation
|
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
|
||||||
# with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
# serial 8
|
|
||||||
|
|
||||||
# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
|
|
||||||
# written in clear, in which case automake, when reading aclocal.m4,
|
|
||||||
# will think it sees a *use*, and therefore will trigger all it's
|
|
||||||
# C support machinery. Also note that it means that autoscan, seeing
|
|
||||||
# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
|
|
||||||
|
|
||||||
|
|
||||||
# _AM_DEPENDENCIES(NAME)
|
|
||||||
# ----------------------
|
|
||||||
# See how the compiler implements dependency checking.
|
|
||||||
# NAME is "CC", "CXX", "GCJ", or "OBJC".
|
|
||||||
# We try a few techniques and use that to set a single cache variable.
|
|
||||||
#
|
|
||||||
# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
|
|
||||||
# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
|
|
||||||
# dependency, and given that the user is not expected to run this macro,
|
|
||||||
# just rely on AC_PROG_CC.
|
|
||||||
AC_DEFUN([_AM_DEPENDENCIES],
|
|
||||||
[AC_REQUIRE([AM_SET_DEPDIR])dnl
|
|
||||||
AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
|
|
||||||
AC_REQUIRE([AM_MAKE_INCLUDE])dnl
|
|
||||||
AC_REQUIRE([AM_DEP_TRACK])dnl
|
|
||||||
|
|
||||||
ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
|
|
||||||
[$1], CXX, [depcc="$CXX" am_compiler_list=],
|
|
||||||
[$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
|
|
||||||
[$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
|
|
||||||
[depcc="$$1" am_compiler_list=])
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([dependency style of $depcc],
|
|
||||||
[am_cv_$1_dependencies_compiler_type],
|
|
||||||
[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
|
|
||||||
# We make a subdir and do the tests there. Otherwise we can end up
|
|
||||||
# making bogus files that we don't know about and never remove. For
|
|
||||||
# instance it was reported that on HP-UX the gcc test will end up
|
|
||||||
# making a dummy file named `D' -- because `-MD' means `put the output
|
|
||||||
# in D'.
|
|
||||||
mkdir conftest.dir
|
|
||||||
# Copy depcomp to subdir because otherwise we won't find it if we're
|
|
||||||
# using a relative directory.
|
|
||||||
cp "$am_depcomp" conftest.dir
|
|
||||||
cd conftest.dir
|
|
||||||
# We will build objects and dependencies in a subdirectory because
|
|
||||||
# it helps to detect inapplicable dependency modes. For instance
|
|
||||||
# both Tru64's cc and ICC support -MD to output dependencies as a
|
|
||||||
# side effect of compilation, but ICC will put the dependencies in
|
|
||||||
# the current directory while Tru64 will put them in the object
|
|
||||||
# directory.
|
|
||||||
mkdir sub
|
|
||||||
|
|
||||||
am_cv_$1_dependencies_compiler_type=none
|
|
||||||
if test "$am_compiler_list" = ""; then
|
|
||||||
am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
|
|
||||||
fi
|
|
||||||
for depmode in $am_compiler_list; do
|
|
||||||
# Setup a source with many dependencies, because some compilers
|
|
||||||
# like to wrap large dependency lists on column 80 (with \), and
|
|
||||||
# we should not choose a depcomp mode which is confused by this.
|
|
||||||
#
|
|
||||||
# We need to recreate these files for each test, as the compiler may
|
|
||||||
# overwrite some of them when testing with obscure command lines.
|
|
||||||
# This happens at least with the AIX C compiler.
|
|
||||||
: > sub/conftest.c
|
|
||||||
for i in 1 2 3 4 5 6; do
|
|
||||||
echo '#include "conftst'$i'.h"' >> sub/conftest.c
|
|
||||||
# Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
|
|
||||||
# Solaris 8's {/usr,}/bin/sh.
|
|
||||||
touch sub/conftst$i.h
|
|
||||||
done
|
|
||||||
echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
|
|
||||||
|
|
||||||
case $depmode in
|
|
||||||
nosideeffect)
|
|
||||||
# after this tag, mechanisms are not by side-effect, so they'll
|
|
||||||
# only be used when explicitly requested
|
|
||||||
if test "x$enable_dependency_tracking" = xyes; then
|
|
||||||
continue
|
|
||||||
else
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
none) break ;;
|
|
||||||
esac
|
|
||||||
# We check with `-c' and `-o' for the sake of the "dashmstdout"
|
|
||||||
# mode. It turns out that the SunPro C++ compiler does not properly
|
|
||||||
# handle `-M -o', and we need to detect this.
|
|
||||||
if depmode=$depmode \
|
|
||||||
source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
|
|
||||||
depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
|
|
||||||
$SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
|
|
||||||
>/dev/null 2>conftest.err &&
|
|
||||||
grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
|
|
||||||
grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
|
|
||||||
${MAKE-make} -s -f confmf > /dev/null 2>&1; then
|
|
||||||
# icc doesn't choke on unknown options, it will just issue warnings
|
|
||||||
# or remarks (even with -Werror). So we grep stderr for any message
|
|
||||||
# that says an option was ignored or not supported.
|
|
||||||
# When given -MP, icc 7.0 and 7.1 complain thusly:
|
|
||||||
# icc: Command line warning: ignoring option '-M'; no argument required
|
|
||||||
# The diagnosis changed in icc 8.0:
|
|
||||||
# icc: Command line remark: option '-MP' not supported
|
|
||||||
if (grep 'ignoring option' conftest.err ||
|
|
||||||
grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
|
|
||||||
am_cv_$1_dependencies_compiler_type=$depmode
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
cd ..
|
|
||||||
rm -rf conftest.dir
|
|
||||||
else
|
|
||||||
am_cv_$1_dependencies_compiler_type=none
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
|
|
||||||
AM_CONDITIONAL([am__fastdep$1], [
|
|
||||||
test "x$enable_dependency_tracking" != xno \
|
|
||||||
&& test "$am_cv_$1_dependencies_compiler_type" = gcc3])
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
# AM_SET_DEPDIR
|
|
||||||
# -------------
|
|
||||||
# Choose a directory name for dependency files.
|
|
||||||
# This macro is AC_REQUIREd in _AM_DEPENDENCIES
|
|
||||||
AC_DEFUN([AM_SET_DEPDIR],
|
|
||||||
[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
|
|
||||||
AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
# AM_DEP_TRACK
|
|
||||||
# ------------
|
|
||||||
AC_DEFUN([AM_DEP_TRACK],
|
|
||||||
[AC_ARG_ENABLE(dependency-tracking,
|
|
||||||
[ --disable-dependency-tracking speeds up one-time build
|
|
||||||
--enable-dependency-tracking do not reject slow dependency extractors])
|
|
||||||
if test "x$enable_dependency_tracking" != xno; then
|
|
||||||
am_depcomp="$ac_aux_dir/depcomp"
|
|
||||||
AMDEPBACKSLASH='\'
|
|
||||||
fi
|
|
||||||
AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
|
|
||||||
AC_SUBST([AMDEPBACKSLASH])
|
|
||||||
])
|
|
||||||
|
|
||||||
# Generate code to set up dependency tracking. -*- Autoconf -*-
|
|
||||||
|
|
||||||
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
|
|
||||||
# Free Software Foundation, Inc.
|
|
||||||
#
|
|
||||||
# This file is free software; the Free Software Foundation
|
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
|
||||||
# with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
#serial 3
|
|
||||||
|
|
||||||
# _AM_OUTPUT_DEPENDENCY_COMMANDS
|
|
||||||
# ------------------------------
|
|
||||||
AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
|
|
||||||
[for mf in $CONFIG_FILES; do
|
|
||||||
# Strip MF so we end up with the name of the file.
|
|
||||||
mf=`echo "$mf" | sed -e 's/:.*$//'`
|
|
||||||
# Check whether this is an Automake generated Makefile or not.
|
|
||||||
# We used to match only the files named `Makefile.in', but
|
|
||||||
# some people rename them; so instead we look at the file content.
|
|
||||||
# Grep'ing the first line is not enough: some people post-process
|
|
||||||
# each Makefile.in and add a new line on top of each file to say so.
|
|
||||||
# So let's grep whole file.
|
|
||||||
if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then
|
|
||||||
dirpart=`AS_DIRNAME("$mf")`
|
|
||||||
else
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
# Extract the definition of DEPDIR, am__include, and am__quote
|
|
||||||
# from the Makefile without running `make'.
|
|
||||||
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
|
|
||||||
test -z "$DEPDIR" && continue
|
|
||||||
am__include=`sed -n 's/^am__include = //p' < "$mf"`
|
|
||||||
test -z "am__include" && continue
|
|
||||||
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
|
|
||||||
# When using ansi2knr, U may be empty or an underscore; expand it
|
|
||||||
U=`sed -n 's/^U = //p' < "$mf"`
|
|
||||||
# Find all dependency output files, they are included files with
|
|
||||||
# $(DEPDIR) in their names. We invoke sed twice because it is the
|
|
||||||
# simplest approach to changing $(DEPDIR) to its actual value in the
|
|
||||||
# expansion.
|
|
||||||
for file in `sed -n "
|
|
||||||
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
|
|
||||||
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
|
|
||||||
# Make sure the directory exists.
|
|
||||||
test -f "$dirpart/$file" && continue
|
|
||||||
fdir=`AS_DIRNAME(["$file"])`
|
|
||||||
AS_MKDIR_P([$dirpart/$fdir])
|
|
||||||
# echo "creating $dirpart/$file"
|
|
||||||
echo '# dummy' > "$dirpart/$file"
|
|
||||||
done
|
|
||||||
done
|
|
||||||
])# _AM_OUTPUT_DEPENDENCY_COMMANDS
|
|
||||||
|
|
||||||
|
|
||||||
# AM_OUTPUT_DEPENDENCY_COMMANDS
|
|
||||||
# -----------------------------
|
|
||||||
# This macro should only be invoked once -- use via AC_REQUIRE.
|
|
||||||
#
|
|
||||||
# This code is only required when automatic dependency tracking
|
|
||||||
# is enabled. FIXME. This creates each `.P' file that we will
|
|
||||||
# need in order to bootstrap the dependency handling code.
|
|
||||||
AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
|
|
||||||
[AC_CONFIG_COMMANDS([depfiles],
|
|
||||||
[test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
|
|
||||||
[AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
|
|
||||||
])
|
|
||||||
|
|
||||||
# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
|
|
||||||
# Free Software Foundation, Inc.
|
|
||||||
#
|
|
||||||
# This file is free software; the Free Software Foundation
|
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
|
||||||
# with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
# serial 8
|
|
||||||
|
|
||||||
# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS.
|
|
||||||
AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
|
|
||||||
|
|
||||||
# Do all the work for Automake. -*- Autoconf -*-
|
|
||||||
|
|
||||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
|
|
||||||
# Free Software Foundation, Inc.
|
|
||||||
#
|
|
||||||
# This file is free software; the Free Software Foundation
|
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
|
||||||
# with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
# serial 12
|
|
||||||
|
|
||||||
# This macro actually does too much. Some checks are only needed if
|
|
||||||
# your package does certain things. But this isn't really a big deal.
|
|
||||||
|
|
||||||
# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
|
|
||||||
# AM_INIT_AUTOMAKE([OPTIONS])
|
|
||||||
# -----------------------------------------------
|
|
||||||
# The call with PACKAGE and VERSION arguments is the old style
|
|
||||||
# call (pre autoconf-2.50), which is being phased out. PACKAGE
|
|
||||||
# and VERSION should now be passed to AC_INIT and removed from
|
|
||||||
# the call to AM_INIT_AUTOMAKE.
|
|
||||||
# We support both call styles for the transition. After
|
|
||||||
# the next Automake release, Autoconf can make the AC_INIT
|
|
||||||
# arguments mandatory, and then we can depend on a new Autoconf
|
|
||||||
# release and drop the old call support.
|
|
||||||
AC_DEFUN([AM_INIT_AUTOMAKE],
|
|
||||||
[AC_PREREQ([2.58])dnl
|
|
||||||
dnl Autoconf wants to disallow AM_ names. We explicitly allow
|
|
||||||
dnl the ones we care about.
|
|
||||||
m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
|
|
||||||
AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
|
|
||||||
AC_REQUIRE([AC_PROG_INSTALL])dnl
|
|
||||||
# test to see if srcdir already configured
|
|
||||||
if test "`cd $srcdir && pwd`" != "`pwd`" &&
|
|
||||||
test -f $srcdir/config.status; then
|
|
||||||
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
|
|
||||||
fi
|
|
||||||
|
|
||||||
# test whether we have cygpath
|
|
||||||
if test -z "$CYGPATH_W"; then
|
|
||||||
if (cygpath --version) >/dev/null 2>/dev/null; then
|
|
||||||
CYGPATH_W='cygpath -w'
|
|
||||||
else
|
|
||||||
CYGPATH_W=echo
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
AC_SUBST([CYGPATH_W])
|
|
||||||
|
|
||||||
# Define the identity of the package.
|
|
||||||
dnl Distinguish between old-style and new-style calls.
|
|
||||||
m4_ifval([$2],
|
|
||||||
[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
|
|
||||||
AC_SUBST([PACKAGE], [$1])dnl
|
|
||||||
AC_SUBST([VERSION], [$2])],
|
|
||||||
[_AM_SET_OPTIONS([$1])dnl
|
|
||||||
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
|
|
||||||
AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
|
|
||||||
|
|
||||||
_AM_IF_OPTION([no-define],,
|
|
||||||
[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
|
|
||||||
AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
|
|
||||||
|
|
||||||
# Some tools Automake needs.
|
|
||||||
AC_REQUIRE([AM_SANITY_CHECK])dnl
|
|
||||||
AC_REQUIRE([AC_ARG_PROGRAM])dnl
|
|
||||||
AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
|
|
||||||
AM_MISSING_PROG(AUTOCONF, autoconf)
|
|
||||||
AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
|
|
||||||
AM_MISSING_PROG(AUTOHEADER, autoheader)
|
|
||||||
AM_MISSING_PROG(MAKEINFO, makeinfo)
|
|
||||||
AM_PROG_INSTALL_SH
|
|
||||||
AM_PROG_INSTALL_STRIP
|
|
||||||
AC_REQUIRE([AM_PROG_MKDIR_P])dnl
|
|
||||||
# We need awk for the "check" target. The system "awk" is bad on
|
|
||||||
# some platforms.
|
|
||||||
AC_REQUIRE([AC_PROG_AWK])dnl
|
|
||||||
AC_REQUIRE([AC_PROG_MAKE_SET])dnl
|
|
||||||
AC_REQUIRE([AM_SET_LEADING_DOT])dnl
|
|
||||||
_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
|
|
||||||
[_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
|
|
||||||
[_AM_PROG_TAR([v7])])])
|
|
||||||
_AM_IF_OPTION([no-dependencies],,
|
|
||||||
[AC_PROVIDE_IFELSE([AC_PROG_CC],
|
|
||||||
[_AM_DEPENDENCIES(CC)],
|
|
||||||
[define([AC_PROG_CC],
|
|
||||||
defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
|
|
||||||
AC_PROVIDE_IFELSE([AC_PROG_CXX],
|
|
||||||
[_AM_DEPENDENCIES(CXX)],
|
|
||||||
[define([AC_PROG_CXX],
|
|
||||||
defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
|
|
||||||
])
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
# When config.status generates a header, we must update the stamp-h file.
|
|
||||||
# This file resides in the same directory as the config header
|
|
||||||
# that is generated. The stamp files are numbered to have different names.
|
|
||||||
|
|
||||||
# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
|
|
||||||
# loop where config.status creates the headers, so we can generate
|
|
||||||
# our stamp files there.
|
|
||||||
AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
|
|
||||||
[# Compute $1's index in $config_headers.
|
|
||||||
_am_stamp_count=1
|
|
||||||
for _am_header in $config_headers :; do
|
|
||||||
case $_am_header in
|
|
||||||
$1 | $1:* )
|
|
||||||
break ;;
|
|
||||||
* )
|
|
||||||
_am_stamp_count=`expr $_am_stamp_count + 1` ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count])
|
|
||||||
|
|
||||||
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
|
|
||||||
#
|
|
||||||
# This file is free software; the Free Software Foundation
|
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
|
||||||
# with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
# AM_PROG_INSTALL_SH
|
|
||||||
# ------------------
|
|
||||||
# Define $install_sh.
|
|
||||||
AC_DEFUN([AM_PROG_INSTALL_SH],
|
|
||||||
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
|
|
||||||
install_sh=${install_sh-"$am_aux_dir/install-sh"}
|
|
||||||
AC_SUBST(install_sh)])
|
|
||||||
|
|
||||||
# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
|
|
||||||
#
|
|
||||||
# This file is free software; the Free Software Foundation
|
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
|
||||||
# with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
# serial 2
|
|
||||||
|
|
||||||
# Check whether the underlying file-system supports filenames
|
|
||||||
# with a leading dot. For instance MS-DOS doesn't.
|
|
||||||
AC_DEFUN([AM_SET_LEADING_DOT],
|
|
||||||
[rm -rf .tst 2>/dev/null
|
|
||||||
mkdir .tst 2>/dev/null
|
|
||||||
if test -d .tst; then
|
|
||||||
am__leading_dot=.
|
|
||||||
else
|
|
||||||
am__leading_dot=_
|
|
||||||
fi
|
|
||||||
rmdir .tst 2>/dev/null
|
|
||||||
AC_SUBST([am__leading_dot])])
|
|
||||||
|
|
||||||
# Check to see how 'make' treats includes. -*- Autoconf -*-
|
|
||||||
|
|
||||||
# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
|
|
||||||
#
|
|
||||||
# This file is free software; the Free Software Foundation
|
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
|
||||||
# with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
# serial 3
|
|
||||||
|
|
||||||
# AM_MAKE_INCLUDE()
|
|
||||||
# -----------------
|
|
||||||
# Check to see how make treats includes.
|
|
||||||
AC_DEFUN([AM_MAKE_INCLUDE],
|
|
||||||
[am_make=${MAKE-make}
|
|
||||||
cat > confinc << 'END'
|
|
||||||
am__doit:
|
|
||||||
@echo done
|
|
||||||
.PHONY: am__doit
|
|
||||||
END
|
|
||||||
# If we don't find an include directive, just comment out the code.
|
|
||||||
AC_MSG_CHECKING([for style of include used by $am_make])
|
|
||||||
am__include="#"
|
|
||||||
am__quote=
|
|
||||||
_am_result=none
|
|
||||||
# First try GNU make style include.
|
|
||||||
echo "include confinc" > confmf
|
|
||||||
# We grep out `Entering directory' and `Leaving directory'
|
|
||||||
# messages which can occur if `w' ends up in MAKEFLAGS.
|
|
||||||
# In particular we don't look at `^make:' because GNU make might
|
|
||||||
# be invoked under some other name (usually "gmake"), in which
|
|
||||||
# case it prints its new name instead of `make'.
|
|
||||||
if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
|
|
||||||
am__include=include
|
|
||||||
am__quote=
|
|
||||||
_am_result=GNU
|
|
||||||
fi
|
|
||||||
# Now try BSD make style include.
|
|
||||||
if test "$am__include" = "#"; then
|
|
||||||
echo '.include "confinc"' > confmf
|
|
||||||
if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
|
|
||||||
am__include=.include
|
|
||||||
am__quote="\""
|
|
||||||
_am_result=BSD
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
AC_SUBST([am__include])
|
|
||||||
AC_SUBST([am__quote])
|
|
||||||
AC_MSG_RESULT([$_am_result])
|
|
||||||
rm -f confinc confmf
|
|
||||||
])
|
|
||||||
|
|
||||||
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
|
|
||||||
|
|
||||||
# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005
|
|
||||||
# Free Software Foundation, Inc.
|
|
||||||
#
|
|
||||||
# This file is free software; the Free Software Foundation
|
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
|
||||||
# with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
# serial 4
|
|
||||||
|
|
||||||
# AM_MISSING_PROG(NAME, PROGRAM)
|
|
||||||
# ------------------------------
|
|
||||||
AC_DEFUN([AM_MISSING_PROG],
|
|
||||||
[AC_REQUIRE([AM_MISSING_HAS_RUN])
|
|
||||||
$1=${$1-"${am_missing_run}$2"}
|
|
||||||
AC_SUBST($1)])
|
|
||||||
|
|
||||||
|
|
||||||
# AM_MISSING_HAS_RUN
|
|
||||||
# ------------------
|
|
||||||
# Define MISSING if not defined so far and test if it supports --run.
|
|
||||||
# If it does, set am_missing_run to use it, otherwise, to nothing.
|
|
||||||
AC_DEFUN([AM_MISSING_HAS_RUN],
|
|
||||||
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
|
|
||||||
test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
|
|
||||||
# Use eval to expand $SHELL
|
|
||||||
if eval "$MISSING --run true"; then
|
|
||||||
am_missing_run="$MISSING --run "
|
|
||||||
else
|
|
||||||
am_missing_run=
|
|
||||||
AC_MSG_WARN([`missing' script is too old or missing])
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
|
|
||||||
# Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
|
|
||||||
#
|
|
||||||
# This file is free software; the Free Software Foundation
|
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
|
||||||
# with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
# AM_PROG_MKDIR_P
|
|
||||||
# ---------------
|
|
||||||
# Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise.
|
|
||||||
#
|
|
||||||
# Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories
|
|
||||||
# created by `make install' are always world readable, even if the
|
|
||||||
# installer happens to have an overly restrictive umask (e.g. 077).
|
|
||||||
# This was a mistake. There are at least two reasons why we must not
|
|
||||||
# use `-m 0755':
|
|
||||||
# - it causes special bits like SGID to be ignored,
|
|
||||||
# - it may be too restrictive (some setups expect 775 directories).
|
|
||||||
#
|
|
||||||
# Do not use -m 0755 and let people choose whatever they expect by
|
|
||||||
# setting umask.
|
|
||||||
#
|
|
||||||
# We cannot accept any implementation of `mkdir' that recognizes `-p'.
|
|
||||||
# Some implementations (such as Solaris 8's) are not thread-safe: if a
|
|
||||||
# parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c'
|
|
||||||
# concurrently, both version can detect that a/ is missing, but only
|
|
||||||
# one can create it and the other will error out. Consequently we
|
|
||||||
# restrict ourselves to GNU make (using the --version option ensures
|
|
||||||
# this.)
|
|
||||||
AC_DEFUN([AM_PROG_MKDIR_P],
|
|
||||||
[if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
|
|
||||||
# We used to keeping the `.' as first argument, in order to
|
|
||||||
# allow $(mkdir_p) to be used without argument. As in
|
|
||||||
# $(mkdir_p) $(somedir)
|
|
||||||
# where $(somedir) is conditionally defined. However this is wrong
|
|
||||||
# for two reasons:
|
|
||||||
# 1. if the package is installed by a user who cannot write `.'
|
|
||||||
# make install will fail,
|
|
||||||
# 2. the above comment should most certainly read
|
|
||||||
# $(mkdir_p) $(DESTDIR)$(somedir)
|
|
||||||
# so it does not work when $(somedir) is undefined and
|
|
||||||
# $(DESTDIR) is not.
|
|
||||||
# To support the latter case, we have to write
|
|
||||||
# test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir),
|
|
||||||
# so the `.' trick is pointless.
|
|
||||||
mkdir_p='mkdir -p --'
|
|
||||||
else
|
|
||||||
# On NextStep and OpenStep, the `mkdir' command does not
|
|
||||||
# recognize any option. It will interpret all options as
|
|
||||||
# directories to create, and then abort because `.' already
|
|
||||||
# exists.
|
|
||||||
for d in ./-p ./--version;
|
|
||||||
do
|
|
||||||
test -d $d && rmdir $d
|
|
||||||
done
|
|
||||||
# $(mkinstalldirs) is defined by Automake if mkinstalldirs exists.
|
|
||||||
if test -f "$ac_aux_dir/mkinstalldirs"; then
|
|
||||||
mkdir_p='$(mkinstalldirs)'
|
|
||||||
else
|
|
||||||
mkdir_p='$(install_sh) -d'
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
AC_SUBST([mkdir_p])])
|
|
||||||
|
|
||||||
# Helper functions for option handling. -*- Autoconf -*-
|
|
||||||
|
|
||||||
# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
|
|
||||||
#
|
|
||||||
# This file is free software; the Free Software Foundation
|
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
|
||||||
# with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
# serial 3
|
|
||||||
|
|
||||||
# _AM_MANGLE_OPTION(NAME)
|
|
||||||
# -----------------------
|
|
||||||
AC_DEFUN([_AM_MANGLE_OPTION],
|
|
||||||
[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
|
|
||||||
|
|
||||||
# _AM_SET_OPTION(NAME)
|
|
||||||
# ------------------------------
|
|
||||||
# Set option NAME. Presently that only means defining a flag for this option.
|
|
||||||
AC_DEFUN([_AM_SET_OPTION],
|
|
||||||
[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
|
|
||||||
|
|
||||||
# _AM_SET_OPTIONS(OPTIONS)
|
|
||||||
# ----------------------------------
|
|
||||||
# OPTIONS is a space-separated list of Automake options.
|
|
||||||
AC_DEFUN([_AM_SET_OPTIONS],
|
|
||||||
[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
|
|
||||||
|
|
||||||
# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
|
|
||||||
# -------------------------------------------
|
|
||||||
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
|
|
||||||
AC_DEFUN([_AM_IF_OPTION],
|
|
||||||
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
|
|
||||||
|
|
||||||
# Check to make sure that the build environment is sane. -*- Autoconf -*-
|
|
||||||
|
|
||||||
# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
|
|
||||||
# Free Software Foundation, Inc.
|
|
||||||
#
|
|
||||||
# This file is free software; the Free Software Foundation
|
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
|
||||||
# with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
# serial 4
|
|
||||||
|
|
||||||
# AM_SANITY_CHECK
|
|
||||||
# ---------------
|
|
||||||
AC_DEFUN([AM_SANITY_CHECK],
|
|
||||||
[AC_MSG_CHECKING([whether build environment is sane])
|
|
||||||
# Just in case
|
|
||||||
sleep 1
|
|
||||||
echo timestamp > conftest.file
|
|
||||||
# Do `set' in a subshell so we don't clobber the current shell's
|
|
||||||
# arguments. Must try -L first in case configure is actually a
|
|
||||||
# symlink; some systems play weird games with the mod time of symlinks
|
|
||||||
# (eg FreeBSD returns the mod time of the symlink's containing
|
|
||||||
# directory).
|
|
||||||
if (
|
|
||||||
set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
|
|
||||||
if test "$[*]" = "X"; then
|
|
||||||
# -L didn't work.
|
|
||||||
set X `ls -t $srcdir/configure conftest.file`
|
|
||||||
fi
|
|
||||||
rm -f conftest.file
|
|
||||||
if test "$[*]" != "X $srcdir/configure conftest.file" \
|
|
||||||
&& test "$[*]" != "X conftest.file $srcdir/configure"; then
|
|
||||||
|
|
||||||
# If neither matched, then we have a broken ls. This can happen
|
|
||||||
# if, for instance, CONFIG_SHELL is bash and it inherits a
|
|
||||||
# broken ls alias from the environment. This has actually
|
|
||||||
# happened. Such a system could not be considered "sane".
|
|
||||||
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
|
|
||||||
alias in your environment])
|
|
||||||
fi
|
|
||||||
|
|
||||||
test "$[2]" = conftest.file
|
|
||||||
)
|
|
||||||
then
|
|
||||||
# Ok.
|
|
||||||
:
|
|
||||||
else
|
|
||||||
AC_MSG_ERROR([newly created file is older than distributed files!
|
|
||||||
Check your system clock])
|
|
||||||
fi
|
|
||||||
AC_MSG_RESULT(yes)])
|
|
||||||
|
|
||||||
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
|
|
||||||
#
|
|
||||||
# This file is free software; the Free Software Foundation
|
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
|
||||||
# with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
# AM_PROG_INSTALL_STRIP
|
|
||||||
# ---------------------
|
|
||||||
# One issue with vendor `install' (even GNU) is that you can't
|
|
||||||
# specify the program used to strip binaries. This is especially
|
|
||||||
# annoying in cross-compiling environments, where the build's strip
|
|
||||||
# is unlikely to handle the host's binaries.
|
|
||||||
# Fortunately install-sh will honor a STRIPPROG variable, so we
|
|
||||||
# always use install-sh in `make install-strip', and initialize
|
|
||||||
# STRIPPROG with the value of the STRIP variable (set by the user).
|
|
||||||
AC_DEFUN([AM_PROG_INSTALL_STRIP],
|
|
||||||
[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
|
|
||||||
# Installed binaries are usually stripped using `strip' when the user
|
|
||||||
# run `make install-strip'. However `strip' might not be the right
|
|
||||||
# tool to use in cross-compilation environments, therefore Automake
|
|
||||||
# will honor the `STRIP' environment variable to overrule this program.
|
|
||||||
dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
|
|
||||||
if test "$cross_compiling" != no; then
|
|
||||||
AC_CHECK_TOOL([STRIP], [strip], :)
|
|
||||||
fi
|
|
||||||
INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
|
|
||||||
AC_SUBST([INSTALL_STRIP_PROGRAM])])
|
|
||||||
|
|
||||||
# Check how to create a tarball. -*- Autoconf -*-
|
|
||||||
|
|
||||||
# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
|
|
||||||
#
|
|
||||||
# This file is free software; the Free Software Foundation
|
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
|
||||||
# with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
# serial 2
|
|
||||||
|
|
||||||
# _AM_PROG_TAR(FORMAT)
|
|
||||||
# --------------------
|
|
||||||
# Check how to create a tarball in format FORMAT.
|
|
||||||
# FORMAT should be one of `v7', `ustar', or `pax'.
|
|
||||||
#
|
|
||||||
# Substitute a variable $(am__tar) that is a command
|
|
||||||
# writing to stdout a FORMAT-tarball containing the directory
|
|
||||||
# $tardir.
|
|
||||||
# tardir=directory && $(am__tar) > result.tar
|
|
||||||
#
|
|
||||||
# Substitute a variable $(am__untar) that extract such
|
|
||||||
# a tarball read from stdin.
|
|
||||||
# $(am__untar) < result.tar
|
|
||||||
AC_DEFUN([_AM_PROG_TAR],
|
|
||||||
[# Always define AMTAR for backward compatibility.
|
|
||||||
AM_MISSING_PROG([AMTAR], [tar])
|
|
||||||
m4_if([$1], [v7],
|
|
||||||
[am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
|
|
||||||
[m4_case([$1], [ustar],, [pax],,
|
|
||||||
[m4_fatal([Unknown tar format])])
|
|
||||||
AC_MSG_CHECKING([how to create a $1 tar archive])
|
|
||||||
# Loop over all known methods to create a tar archive until one works.
|
|
||||||
_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
|
|
||||||
_am_tools=${am_cv_prog_tar_$1-$_am_tools}
|
|
||||||
# Do not fold the above two line into one, because Tru64 sh and
|
|
||||||
# Solaris sh will not grok spaces in the rhs of `-'.
|
|
||||||
for _am_tool in $_am_tools
|
|
||||||
do
|
|
||||||
case $_am_tool in
|
|
||||||
gnutar)
|
|
||||||
for _am_tar in tar gnutar gtar;
|
|
||||||
do
|
|
||||||
AM_RUN_LOG([$_am_tar --version]) && break
|
|
||||||
done
|
|
||||||
am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
|
|
||||||
am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
|
|
||||||
am__untar="$_am_tar -xf -"
|
|
||||||
;;
|
|
||||||
plaintar)
|
|
||||||
# Must skip GNU tar: if it does not support --format= it doesn't create
|
|
||||||
# ustar tarball either.
|
|
||||||
(tar --version) >/dev/null 2>&1 && continue
|
|
||||||
am__tar='tar chf - "$$tardir"'
|
|
||||||
am__tar_='tar chf - "$tardir"'
|
|
||||||
am__untar='tar xf -'
|
|
||||||
;;
|
|
||||||
pax)
|
|
||||||
am__tar='pax -L -x $1 -w "$$tardir"'
|
|
||||||
am__tar_='pax -L -x $1 -w "$tardir"'
|
|
||||||
am__untar='pax -r'
|
|
||||||
;;
|
|
||||||
cpio)
|
|
||||||
am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
|
|
||||||
am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
|
|
||||||
am__untar='cpio -i -H $1 -d'
|
|
||||||
;;
|
|
||||||
none)
|
|
||||||
am__tar=false
|
|
||||||
am__tar_=false
|
|
||||||
am__untar=false
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# If the value was cached, stop now. We just wanted to have am__tar
|
|
||||||
# and am__untar set.
|
|
||||||
test -n "${am_cv_prog_tar_$1}" && break
|
|
||||||
|
|
||||||
# tar/untar a dummy directory, and stop if the command works
|
|
||||||
rm -rf conftest.dir
|
|
||||||
mkdir conftest.dir
|
|
||||||
echo GrepMe > conftest.dir/file
|
|
||||||
AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
|
|
||||||
rm -rf conftest.dir
|
|
||||||
if test -s conftest.tar; then
|
|
||||||
AM_RUN_LOG([$am__untar <conftest.tar])
|
|
||||||
grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
rm -rf conftest.dir
|
|
||||||
|
|
||||||
AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
|
|
||||||
AC_MSG_RESULT([$am_cv_prog_tar_$1])])
|
|
||||||
AC_SUBST([am__tar])
|
|
||||||
AC_SUBST([am__untar])
|
|
||||||
]) # _AM_PROG_TAR
|
|
||||||
|
|
||||||
m4_include([m4/acx_pthread.m4])
|
|
||||||
m4_include([m4/google_namespace.m4])
|
|
||||||
m4_include([m4/namespaces.m4])
|
|
||||||
m4_include([m4/stl_hash.m4])
|
|
||||||
m4_include([m4/stl_hash_fun.m4])
|
|
||||||
m4_include([m4/stl_namespace.m4])
|
|
@ -1,74 +0,0 @@
|
|||||||
## Process this file with autoconf to produce configure.
|
|
||||||
## In general, the safest way to proceed is to run ./autogen.sh
|
|
||||||
|
|
||||||
# make sure we're interpreted by some minimal autoconf
|
|
||||||
AC_PREREQ(2.57)
|
|
||||||
|
|
||||||
AC_INIT(sparsehash, 1.6, opensource@google.com)
|
|
||||||
# The argument here is just something that should be in the current directory
|
|
||||||
# (for sanity checking)
|
|
||||||
AC_CONFIG_SRCDIR(README)
|
|
||||||
AM_INIT_AUTOMAKE([dist-zip])
|
|
||||||
AM_CONFIG_HEADER(src/config.h)
|
|
||||||
|
|
||||||
# Checks for programs.
|
|
||||||
AC_PROG_CC
|
|
||||||
AC_PROG_CPP
|
|
||||||
AC_PROG_CXX
|
|
||||||
AM_CONDITIONAL(GCC, test "$GCC" = yes) # let the Makefile know if we're gcc
|
|
||||||
|
|
||||||
# Check whether some low-level functions/files are available
|
|
||||||
AC_HEADER_STDC
|
|
||||||
AC_CHECK_FUNCS(memcpy memmove)
|
|
||||||
AC_CHECK_TYPES([uint16_t]) # defined in C99 systems
|
|
||||||
AC_CHECK_TYPES([u_int16_t]) # defined in BSD-derived systems, and gnu
|
|
||||||
AC_CHECK_TYPES([__uint16]) # defined in some windows systems (vc7)
|
|
||||||
AC_CHECK_TYPES([long long]) # probably defined everywhere, but...
|
|
||||||
|
|
||||||
# These are 'only' needed for unittests
|
|
||||||
AC_CHECK_HEADERS(sys/resource.h unistd.h sys/time.h sys/utsname.h)
|
|
||||||
|
|
||||||
# If you have google-perftools installed, we can do a bit more testing.
|
|
||||||
# We not only want to set HAVE_MALLOC_EXTENSION_H, we also want to set
|
|
||||||
# a variable to let the Makefile to know to link in tcmalloc.
|
|
||||||
AC_LANG([C++])
|
|
||||||
AC_CHECK_HEADERS(google/malloc_extension.h,
|
|
||||||
tcmalloc_libs=-ltcmalloc,
|
|
||||||
tcmalloc_libs=)
|
|
||||||
# On some systems, when linking in tcmalloc you also need to link in
|
|
||||||
# pthread. That's a bug somewhere, but we'll work around it for now.
|
|
||||||
tcmalloc_flags=""
|
|
||||||
if test -n "$tcmalloc_libs"; then
|
|
||||||
ACX_PTHREAD
|
|
||||||
tcmalloc_flags="\$(PTHREAD_CFLAGS)"
|
|
||||||
tcmalloc_libs="$tcmalloc_libs \$(PTHREAD_LIBS)"
|
|
||||||
fi
|
|
||||||
AC_SUBST(tcmalloc_flags)
|
|
||||||
AC_SUBST(tcmalloc_libs)
|
|
||||||
|
|
||||||
# Figure out where hash_map lives and also hash_fun.h (or stl_hash_fun.h).
|
|
||||||
# This also tells us what namespace hash code lives in.
|
|
||||||
AC_CXX_STL_HASH
|
|
||||||
AC_CXX_STL_HASH_FUN
|
|
||||||
|
|
||||||
# Find out what namespace 'normal' STL code lives in, and also what namespace
|
|
||||||
# the user wants our classes to be defined in
|
|
||||||
AC_CXX_STL_NAMESPACE
|
|
||||||
AC_DEFINE_GOOGLE_NAMESPACE(google)
|
|
||||||
|
|
||||||
# In unix-based systems, hash is always defined as hash<> (in namespace.
|
|
||||||
# HASH_NAMESPACE.) So we can use a simple AC_DEFINE here. On
|
|
||||||
# windows, and possibly on future unix STL implementations, this
|
|
||||||
# macro will evaluate to something different.)
|
|
||||||
AC_DEFINE(SPARSEHASH_HASH_NO_NAMESPACE, hash,
|
|
||||||
[The system-provided hash function, in namespace HASH_NAMESPACE.])
|
|
||||||
|
|
||||||
# Do *not* define this in terms of SPARSEHASH_HASH_NO_NAMESPACE, because
|
|
||||||
# SPARSEHASH_HASH is exported to sparseconfig.h, but S_H_NO_NAMESPACE isn't.
|
|
||||||
AC_DEFINE(SPARSEHASH_HASH, HASH_NAMESPACE::hash,
|
|
||||||
[The system-provided hash function including the namespace.])
|
|
||||||
|
|
||||||
|
|
||||||
# Write generated configuration file
|
|
||||||
AC_CONFIG_FILES([Makefile])
|
|
||||||
AC_OUTPUT
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,115 +0,0 @@
|
|||||||
body {
|
|
||||||
background-color: #ffffff;
|
|
||||||
color: black;
|
|
||||||
margin-right: 1in;
|
|
||||||
margin-left: 1in;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6 {
|
|
||||||
color: #3366ff;
|
|
||||||
font-family: sans-serif;
|
|
||||||
}
|
|
||||||
@media print {
|
|
||||||
/* Darker version for printing */
|
|
||||||
h1, h2, h3, h4, h5, h6 {
|
|
||||||
color: #000080;
|
|
||||||
font-family: helvetica, sans-serif;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
text-align: center;
|
|
||||||
font-size: 18pt;
|
|
||||||
}
|
|
||||||
h2 {
|
|
||||||
margin-left: -0.5in;
|
|
||||||
}
|
|
||||||
h3 {
|
|
||||||
margin-left: -0.25in;
|
|
||||||
}
|
|
||||||
h4 {
|
|
||||||
margin-left: -0.125in;
|
|
||||||
}
|
|
||||||
hr {
|
|
||||||
margin-left: -1in;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Definition lists: definition term bold */
|
|
||||||
dt {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
address {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
/* Use the <code> tag for bits of code and <var> for variables and objects. */
|
|
||||||
code,pre,samp,var {
|
|
||||||
color: #006000;
|
|
||||||
}
|
|
||||||
/* Use the <file> tag for file and directory paths and names. */
|
|
||||||
file {
|
|
||||||
color: #905050;
|
|
||||||
font-family: monospace;
|
|
||||||
}
|
|
||||||
/* Use the <kbd> tag for stuff the user should type. */
|
|
||||||
kbd {
|
|
||||||
color: #600000;
|
|
||||||
}
|
|
||||||
div.note p {
|
|
||||||
float: right;
|
|
||||||
width: 3in;
|
|
||||||
margin-right: 0%;
|
|
||||||
padding: 1px;
|
|
||||||
border: 2px solid #6060a0;
|
|
||||||
background-color: #fffff0;
|
|
||||||
}
|
|
||||||
|
|
||||||
UL.nobullets {
|
|
||||||
list-style-type: none;
|
|
||||||
list-style-image: none;
|
|
||||||
margin-left: -1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
body:after {
|
|
||||||
content: "Google Confidential";
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* pretty printing styles. See prettify.js */
|
|
||||||
.str { color: #080; }
|
|
||||||
.kwd { color: #008; }
|
|
||||||
.com { color: #800; }
|
|
||||||
.typ { color: #606; }
|
|
||||||
.lit { color: #066; }
|
|
||||||
.pun { color: #660; }
|
|
||||||
.pln { color: #000; }
|
|
||||||
.tag { color: #008; }
|
|
||||||
.atn { color: #606; }
|
|
||||||
.atv { color: #080; }
|
|
||||||
pre.prettyprint { padding: 2px; border: 1px solid #888; }
|
|
||||||
|
|
||||||
.embsrc { background: #eee; }
|
|
||||||
|
|
||||||
@media print {
|
|
||||||
.str { color: #060; }
|
|
||||||
.kwd { color: #006; font-weight: bold; }
|
|
||||||
.com { color: #600; font-style: italic; }
|
|
||||||
.typ { color: #404; font-weight: bold; }
|
|
||||||
.lit { color: #044; }
|
|
||||||
.pun { color: #440; }
|
|
||||||
.pln { color: #000; }
|
|
||||||
.tag { color: #006; font-weight: bold; }
|
|
||||||
.atn { color: #404; }
|
|
||||||
.atv { color: #060; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Table Column Headers */
|
|
||||||
.hdr {
|
|
||||||
color: #006;
|
|
||||||
font-weight: bold;
|
|
||||||
background-color: #dddddd; }
|
|
||||||
.hdr2 {
|
|
||||||
color: #006;
|
|
||||||
background-color: #eeeeee; }
|
|
@ -1,371 +0,0 @@
|
|||||||
<HTML>
|
|
||||||
|
|
||||||
<HEAD>
|
|
||||||
<title>Implementation notes: sparse_hash, dense_hash, sparsetable</title>
|
|
||||||
</HEAD>
|
|
||||||
|
|
||||||
<BODY>
|
|
||||||
|
|
||||||
<h1>Implementation of sparse_hash_map, dense_hash_map, and
|
|
||||||
sparsetable</h1>
|
|
||||||
|
|
||||||
This document contains a few notes on how the data structures in this
|
|
||||||
package are implemented. This discussion refers at several points to
|
|
||||||
the classic text in this area: Knuth, <i>The Art of Computer
|
|
||||||
Programming</i>, Vol 3, Hashing.
|
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h2><tt>sparsetable</tt></h2>
|
|
||||||
|
|
||||||
<p>For specificity, consider the declaration </p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
sparsetable<Foo> t(100); // a sparse array with 100 elements
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>A sparsetable is a random container that implements a sparse array,
|
|
||||||
that is, an array that uses very little memory to store unassigned
|
|
||||||
indices (in this case, between 1-2 bits per unassigned index). For
|
|
||||||
instance, if you allocate an array of size 5 and assign a[2] = [big
|
|
||||||
struct], then a[2] will take up a lot of memory but a[0], a[1], a[3],
|
|
||||||
and a[4] will not. Array elements that have a value are called
|
|
||||||
"assigned". Array elements that have no value yet, or have had their
|
|
||||||
value cleared using erase() or clear(), are called "unassigned".
|
|
||||||
For assigned elements, lookups return the assigned value; for
|
|
||||||
unassigned elements, they return the default value, which for t is
|
|
||||||
Foo().</p>
|
|
||||||
|
|
||||||
<p>sparsetable is implemented as an array of "groups". Each group is
|
|
||||||
responsible for M array indices. The first group knows about
|
|
||||||
t[0]..t[M-1], the second about t[M]..t[2M-1], and so forth. (M is 48
|
|
||||||
by default.) At construct time, t creates an array of (99/M + 1)
|
|
||||||
groups. From this point on, all operations -- insert, delete, lookup
|
|
||||||
-- are passed to the appropriate group. In particular, any operation
|
|
||||||
on t[i] is actually performed on (t.group[i / M])[i % M].</p>
|
|
||||||
|
|
||||||
<p>Each group contains of a vector, which holds assigned values, and a
|
|
||||||
bitmap of size M, which indicates which indices are assigned. A
|
|
||||||
lookup works as follows: the group is asked to look up index i, where
|
|
||||||
i < M. The group looks at bitmap[i]. If it's 0, the lookup fails.
|
|
||||||
If it's 1, then the group has to find the appropriate value in the
|
|
||||||
vector.</p>
|
|
||||||
|
|
||||||
<h3><tt>find()</tt></h3>
|
|
||||||
|
|
||||||
<p>Finding the appropriate vector element is the most expensive part of
|
|
||||||
the lookup. The code counts all bitmap entries <= i that are set to
|
|
||||||
1. (There's at least 1 of them, since bitmap[i] is 1.) Suppose there
|
|
||||||
are 4 such entries. Then the right value to return is the 4th element
|
|
||||||
of the vector: vector[3]. This takes time O(M), which is a constant
|
|
||||||
since M is a constant.</p>
|
|
||||||
|
|
||||||
<h3><tt>insert()</tt></h3>
|
|
||||||
|
|
||||||
<p>Insert starts with a lookup. If the lookup succeeds, the code merely
|
|
||||||
replaces vector[3] with the new value. If the lookup fails, then the
|
|
||||||
code must insert a new entry into the middle of the vector. Again, to
|
|
||||||
insert at position i, the code must count all the bitmap entries <= i
|
|
||||||
that are set to i. This indicates the position to insert into the
|
|
||||||
vector. All vector entries above that position must be moved to make
|
|
||||||
room for the new entry. This takes time, but still constant time
|
|
||||||
since the vector has size at most M.</p>
|
|
||||||
|
|
||||||
<p>(Inserts could be made faster by using a list instead of a vector to
|
|
||||||
hold group values, but this would use much more memory, since each
|
|
||||||
list element requires a full pointer of overhead.)</p>
|
|
||||||
|
|
||||||
<p>The only metadata that needs to be updated, after the actual value is
|
|
||||||
inserted, is to set bitmap[i] to 1. No other counts must be
|
|
||||||
maintained.</p>
|
|
||||||
|
|
||||||
<h3><tt>delete()</tt></h3>
|
|
||||||
|
|
||||||
<p>Deletes are similar to inserts. They start with a lookup. If it
|
|
||||||
fails, the delete is a noop. Otherwise, the appropriate entry is
|
|
||||||
removed from the vector, all the vector elements above it are moved
|
|
||||||
down one, and bitmap[i] is set to 0.</p>
|
|
||||||
|
|
||||||
<h3>iterators</h3>
|
|
||||||
|
|
||||||
<p>Sparsetable iterators pose a special burden. They must iterate over
|
|
||||||
unassigned array values, but the act of iterating should not cause an
|
|
||||||
assignment to happen -- otherwise, iterating over a sparsetable would
|
|
||||||
cause it to take up much more room. For const iterators, the matter
|
|
||||||
is simple: the iterator is merely programmed to return the default
|
|
||||||
value -- Foo() -- when dereferenced while pointing to an unassigned
|
|
||||||
entry.</p>
|
|
||||||
|
|
||||||
<p>For non-const iterators, such simple techniques fail. Instead,
|
|
||||||
dereferencing a sparsetable_iterator returns an opaque object that
|
|
||||||
acts like a Foo in almost all situations, but isn't actually a Foo.
|
|
||||||
(It does this by defining operator=(), operator value_type(), and,
|
|
||||||
most sneakily, operator&().) This works in almost all cases. If it
|
|
||||||
doesn't, an explicit cast to value_type will solve the problem:</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
printf("%d", static_cast<Foo>(*t.find(0)));
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>To avoid such problems, consider using get() and set() instead of an
|
|
||||||
iterator:</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
for (int i = 0; i < t.size(); ++i)
|
|
||||||
if (t.get(i) == ...) t.set(i, ...);
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>Sparsetable also has a special class of iterator, besides normal and
|
|
||||||
const: nonempty_iterator. This only iterates over array values that
|
|
||||||
are assigned. This is particularly fast given the sparsetable
|
|
||||||
implementation, since it can ignore the bitmaps entirely and just
|
|
||||||
iterate over the various group vectors.</p>
|
|
||||||
|
|
||||||
<h3>Resource use</h3>
|
|
||||||
|
|
||||||
<p>The space overhead for an sparsetable of size N is N + 48N/M bits.
|
|
||||||
For the default value of M, this is exactly 2 bits per array entry.
|
|
||||||
(That's for 32-bit pointers; for machines with 64-bit pointers, it's N
|
|
||||||
+ 80N/M bits, or 2.67 bits per entry.)
|
|
||||||
A larger M would use less overhead -- approaching 1 bit per array
|
|
||||||
entry -- but take longer for inserts, deletes, and lookups. A smaller
|
|
||||||
M would use more overhead but make operations somewhat faster.</p>
|
|
||||||
|
|
||||||
<p>You can also look at some specific <A
|
|
||||||
HREF="performance.html">performance numbers</A>.</p>
|
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h2><tt>sparse_hash_set</tt></h2>
|
|
||||||
|
|
||||||
<p>For specificity, consider the declaration </p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
sparse_hash_set<Foo> t;
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>sparse_hash_set is a hashtable. For more information on hashtables,
|
|
||||||
see Knuth. Hashtables are basically arrays with complicated logic on
|
|
||||||
top of them. sparse_hash_set uses a sparsetable to implement the
|
|
||||||
underlying array.</p>
|
|
||||||
|
|
||||||
<p>In particular, sparse_hash_set stores its data in a sparsetable using
|
|
||||||
quadratic internal probing (see Knuth). Many hashtable
|
|
||||||
implementations use external probing, so each table element is
|
|
||||||
actually a pointer chain, holding many hashtable values.
|
|
||||||
sparse_hash_set, on the other hand, always stores at most one value in
|
|
||||||
each table location. If the hashtable wants to store a second value
|
|
||||||
at a given table location, it can't; it's forced to look somewhere
|
|
||||||
else.</p>
|
|
||||||
|
|
||||||
<h3><tt>insert()</tt></h3>
|
|
||||||
|
|
||||||
<p>As a specific example, suppose t is a new sparse_hash_set. It then
|
|
||||||
holds a sparsetable of size 32. The code for t.insert(foo) works as
|
|
||||||
follows:</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
1) Call hash<Foo>(foo) to convert foo into an integer i. (hash<Foo> is
|
|
||||||
the default hash function; you can specify a different one in the
|
|
||||||
template arguments.)
|
|
||||||
|
|
||||||
</p><p>
|
|
||||||
2a) Look at t.sparsetable[i % 32]. If it's unassigned, assign it to
|
|
||||||
foo. foo is now in the hashtable.
|
|
||||||
|
|
||||||
</p><p>
|
|
||||||
2b) If t.sparsetable[i % 32] is assigned, and its value is foo, then
|
|
||||||
do nothing: foo was already in t and the insert is a noop.
|
|
||||||
|
|
||||||
</p><p>
|
|
||||||
2c) If t.sparsetable[i % 32] is assigned, but to a value other than
|
|
||||||
foo, look at t.sparsetable[(i+1) % 32]. If that also fails, try
|
|
||||||
t.sparsetable[(i+3) % 32], then t.sparsetable[(i+6) % 32]. In
|
|
||||||
general, keep trying the next triangular number.
|
|
||||||
|
|
||||||
</p><p>
|
|
||||||
3) If the table is now "too full" -- say, 25 of the 32 table entries
|
|
||||||
are now assigned -- grow the table by creating a new sparsetable
|
|
||||||
that's twice as big, and rehashing every single element from the
|
|
||||||
old table into the new one. This keeps the table from ever filling
|
|
||||||
up.
|
|
||||||
|
|
||||||
</p><p>
|
|
||||||
4) If the table is now "too empty" -- say, only 3 of the 32 table
|
|
||||||
entries are now assigned -- shrink the table by creating a new
|
|
||||||
sparsetable that's half as big, and rehashing every element as in
|
|
||||||
the growing case. This keeps the table overhead proportional to
|
|
||||||
the number of elements in the table.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>Instead of using triangular numbers as offsets, one could just use
|
|
||||||
regular integers: try i, then i+1, then i+2, then i+3. This has bad
|
|
||||||
'clumping' behavior, as explored in Knuth. Quadratic probing, using
|
|
||||||
the triangular numbers, avoids the clumping while keeping cache
|
|
||||||
coherency in the common case. As long as the table size is a power of
|
|
||||||
2, the quadratic-probing method described above will explore every
|
|
||||||
table element if necessary, to find a good place to insert.</p>
|
|
||||||
|
|
||||||
<p>(As a side note, using a table size that's a power of two has several
|
|
||||||
advantages, including the speed of calculating (i % table_size). On
|
|
||||||
the other hand, power-of-two tables are not very forgiving of a poor
|
|
||||||
hash function. Make sure your hash function is a good one! There are
|
|
||||||
plenty of dos and don'ts on the web (and in Knuth), for writing hash
|
|
||||||
functions.)</p>
|
|
||||||
|
|
||||||
<p>The "too full" value, also called the "maximum occupancy", determines
|
|
||||||
a time-space tradeoff: in general, the higher it is, the less space is
|
|
||||||
wasted but the more probes must be performed for each insert.
|
|
||||||
sparse_hash_set uses a high maximum occupancy, since space is more
|
|
||||||
important than speed for this data structure.</p>
|
|
||||||
|
|
||||||
<p>The "too empty" value is not necessary for performance but helps with
|
|
||||||
space use. It's rare for hashtable implementations to check this
|
|
||||||
value at insert() time -- after all, how will inserting cause a
|
|
||||||
hashtable to get too small? However, the sparse_hash_set
|
|
||||||
implementation never resizes on erase(); it's nice to have an erase()
|
|
||||||
that does not invalidate iterators. Thus, the first insert() after a
|
|
||||||
long string of erase()s could well trigger a hashtable shrink.</p>
|
|
||||||
|
|
||||||
<h3><tt>find()</tt></h3>
|
|
||||||
|
|
||||||
<p>find() works similarly to insert. The only difference is in step
|
|
||||||
(2a): if the value is unassigned, then the lookup fails immediately.</p>
|
|
||||||
|
|
||||||
<h3><tt>delete()</tt></h3>
|
|
||||||
|
|
||||||
<p>delete() is tricky in an internal-probing scheme. The obvious
|
|
||||||
implementation of just "unassigning" the relevant table entry doesn't
|
|
||||||
work. Consider the following scenario:</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
t.insert(foo1); // foo1 hashes to 4, is put in table[4]
|
|
||||||
t.insert(foo2); // foo2 hashes to 4, is put in table[5]
|
|
||||||
t.erase(foo1); // table[4] is now 'unassigned'
|
|
||||||
t.lookup(foo2); // fails since table[hash(foo2)] is unassigned
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>To avoid these failure situations, delete(foo1) is actually
|
|
||||||
implemented by replacing foo1 by a special 'delete' value in the
|
|
||||||
hashtable. This 'delete' value causes the table entry to be
|
|
||||||
considered unassigned for the purposes of insertion -- if foo3 hashes
|
|
||||||
to 4 as well, it can go into table[4] no problem -- but assigned for
|
|
||||||
the purposes of lookup.</p>
|
|
||||||
|
|
||||||
<p>What is this special 'delete' value? The delete value has to be an
|
|
||||||
element of type Foo, since the table can't hold anything else. It
|
|
||||||
obviously must be an element the client would never want to insert on
|
|
||||||
its own, or else the code couldn't distinguish deleted entries from
|
|
||||||
'real' entries with the same value. There's no way to determine a
|
|
||||||
good value automatically. The client has to specify it explicitly.
|
|
||||||
This is what the set_deleted_key() method does.</p>
|
|
||||||
|
|
||||||
<p>Note that set_deleted_key() is only necessary if the client actually
|
|
||||||
wants to call t.erase(). For insert-only hash-sets, set_deleted_key()
|
|
||||||
is unnecessary.</p>
|
|
||||||
|
|
||||||
<p>When copying the hashtable, either to grow it or shrink it, the
|
|
||||||
special 'delete' values are <b>not</b> copied into the new table. The
|
|
||||||
copy-time rehash makes them unnecessary.</p>
|
|
||||||
|
|
||||||
<h3>Resource use</h3>
|
|
||||||
|
|
||||||
<p>The data is stored in a sparsetable, so space use is the same as
|
|
||||||
for sparsetable. However, by default the sparse_hash_set
|
|
||||||
implementation tries to keep about half the table buckets empty, to
|
|
||||||
keep lookup-chains short. Since sparsehashmap has about 2 bits
|
|
||||||
overhead per bucket (or 2.5 bits on 64-bit systems), sparse_hash_map
|
|
||||||
has about 4-5 bits overhead per hashtable item.</p>
|
|
||||||
|
|
||||||
<p>Time use is also determined in large part by the sparsetable
|
|
||||||
implementation. However, there is also an extra probing cost in
|
|
||||||
hashtables, which depends in large part on the "too full" value. It
|
|
||||||
should be rare to need more than 4-5 probes per lookup, and usually
|
|
||||||
significantly less will suffice.</p>
|
|
||||||
|
|
||||||
<p>A note on growing and shrinking the hashtable: all hashtable
|
|
||||||
implementations use the most memory when growing a hashtable, since
|
|
||||||
they must have room for both the old table and the new table at the
|
|
||||||
same time. sparse_hash_set is careful to delete entries from the old
|
|
||||||
hashtable as soon as they're copied into the new one, to minimize this
|
|
||||||
space overhead. (It does this efficiently by using its knowledge of
|
|
||||||
the sparsetable class and copying one sparsetable group at a time.)</p>
|
|
||||||
|
|
||||||
<p>You can also look at some specific <A
|
|
||||||
HREF="performance.html">performance numbers</A>.</p>
|
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h2><tt>sparse_hash_map</tt></h2>
|
|
||||||
|
|
||||||
<p>sparse_hash_map is implemented identically to sparse_hash_set. The
|
|
||||||
only difference is instead of storing just Foo in each table entry,
|
|
||||||
the data structure stores pair<Foo, Value>.</p>
|
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h2><tt>dense_hash_set</tt></h2>
|
|
||||||
|
|
||||||
<p>The hashtable aspects of dense_hash_set are identical to
|
|
||||||
sparse_hash_set: it uses quadratic internal probing, and resizes
|
|
||||||
hashtables in exactly the same way. The difference is in the
|
|
||||||
underlying array: instead of using a sparsetable, dense_hash_set uses
|
|
||||||
a C array. This means much more space is used, especially if Foo is
|
|
||||||
big. However, it makes all operations faster, since sparsetable has
|
|
||||||
memory management overhead that C arrays do not.</p>
|
|
||||||
|
|
||||||
<p>The use of C arrays instead of sparsetables points to one immediate
|
|
||||||
complication dense_hash_set has that sparse_hash_set does not: the
|
|
||||||
need to distinguish assigned from unassigned entries. In a
|
|
||||||
sparsetable, this is accomplished by a bitmap. dense_hash_set, on the
|
|
||||||
other hand, uses a dedicated value to specify unassigned entries.
|
|
||||||
Thus, dense_hash_set has two special values: one to indicate deleted
|
|
||||||
table entries, and one to indicated unassigned table entries. At
|
|
||||||
construct time, all table entries are initialized to 'unassigned'.</p>
|
|
||||||
|
|
||||||
<p>dense_hash_set provides the method set_empty_key() to indicate the
|
|
||||||
value that should be used for unassigned entries. Like
|
|
||||||
set_deleted_key(), set_empty_key() requires a value that will not be
|
|
||||||
used by the client for any legitimate purpose. Unlike
|
|
||||||
set_deleted_key(), set_empty_key() is always required, no matter what
|
|
||||||
hashtable operations the client wishes to perform.</p>
|
|
||||||
|
|
||||||
<h3>Resource use</h3>
|
|
||||||
|
|
||||||
<p>This implementation is fast because even though dense_hash_set may not
|
|
||||||
be space efficient, most lookups are localized: a single lookup may
|
|
||||||
need to access table[i], and maybe table[i+1] and table[i+3], but
|
|
||||||
nothing other than that. For all but the biggest data structures,
|
|
||||||
these will frequently be in a single cache line.</p>
|
|
||||||
|
|
||||||
<p>This implementation takes, for every unused bucket, space as big as
|
|
||||||
the key-type. Usually between half and two-thirds of the buckets are
|
|
||||||
empty.</p>
|
|
||||||
|
|
||||||
<p>The doubling method used by dense_hash_set tends to work poorly
|
|
||||||
with most memory allocators. This is because memory allocators tend
|
|
||||||
to have memory 'buckets' which are a power of two. Since each
|
|
||||||
doubling of a dense_hash_set doubles the memory use, a single
|
|
||||||
hashtable doubling will require a new memory 'bucket' from the memory
|
|
||||||
allocator, leaving the old bucket stranded as fragmented memory.
|
|
||||||
Hence, it's not recommended this data structure be used with many
|
|
||||||
inserts in memory-constrained situations.</p>
|
|
||||||
|
|
||||||
<p>You can also look at some specific <A
|
|
||||||
HREF="performance.html">performance numbers</A>.</p>
|
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h2><tt>dense_hash_map</tt></h2>
|
|
||||||
|
|
||||||
<p>dense_hash_map is identical to dense_hash_set except for what values
|
|
||||||
are stored in each table entry.</p>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<author>
|
|
||||||
Craig Silverstein<br>
|
|
||||||
Thu Jan 6 20:15:42 PST 2005
|
|
||||||
</author>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,69 +0,0 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Google Sparsehash Package</title>
|
|
||||||
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
||||||
<link href="http://www.google.com/favicon.ico" type="image/x-icon"
|
|
||||||
rel="shortcut icon">
|
|
||||||
<link href="designstyle.css" type="text/css" rel="stylesheet">
|
|
||||||
<style>
|
|
||||||
<!--
|
|
||||||
ol.bluelist li {
|
|
||||||
color: #3366ff;
|
|
||||||
font-family: sans-serif;
|
|
||||||
}
|
|
||||||
ol.bluelist li p {
|
|
||||||
color: #000;
|
|
||||||
font-family: "Times Roman", times, serif;
|
|
||||||
}
|
|
||||||
ul.blacklist li {
|
|
||||||
color: #000;
|
|
||||||
font-family: "Times Roman", times, serif;
|
|
||||||
}
|
|
||||||
//-->
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<h1> <a name="Google_Sparsehash_Package"></a>Google Sparsehash Package </h1>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
<p>The Google sparsehash package consists of two hashtable
|
|
||||||
implementations: <i>sparse</i>, which is designed to be very space
|
|
||||||
efficient, and <i>dense</i>, which is designed to be very time
|
|
||||||
efficient. For each one, the package provides both a hash-map and a
|
|
||||||
hash-set, to mirror the classes in the common STL implementation.</p>
|
|
||||||
|
|
||||||
<p>Documentation on how to use these classes:</p>
|
|
||||||
<ul>
|
|
||||||
<li> <A HREF="sparse_hash_map.html">sparse_hash_map</A>
|
|
||||||
<li> <A HREF="sparse_hash_set.html">sparse_hash_set</A>
|
|
||||||
<li> <A HREF="dense_hash_map.html">dense_hash_map</A>
|
|
||||||
<li> <A HREF="dense_hash_set.html">dense_hash_set</A>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>In addition to the hash-map (and hash-set) classes, there's also a
|
|
||||||
lower-level class that implements a "sparse" array. This class can be
|
|
||||||
useful in its own right; consider using it when you'd normally use a
|
|
||||||
<code>sparse_hash_map</code>, but your keys are all small-ish
|
|
||||||
integers.</p>
|
|
||||||
<ul>
|
|
||||||
<li> <A HREF="sparsetable.html">sparsetable</A>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>There is also a doc explaining the <A
|
|
||||||
HREF="implementation.html">implementation details</A> of these
|
|
||||||
classes, for those who are curious. And finally, you can see some
|
|
||||||
<A HREF="performance.html">performance comparisons</A>, both between
|
|
||||||
the various classes here, but also between these implementations and
|
|
||||||
other standard hashtable implementations.</p>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<address>
|
|
||||||
Craig Silverstein<br>
|
|
||||||
Last modified: Thu Jan 25 17:58:02 PST 2007
|
|
||||||
</address>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,96 +0,0 @@
|
|||||||
<HTML>
|
|
||||||
|
|
||||||
<HEAD>
|
|
||||||
<title>Performance notes: sparse_hash, dense_hash, sparsetable</title>
|
|
||||||
</HEAD>
|
|
||||||
|
|
||||||
<BODY>
|
|
||||||
|
|
||||||
<H2>Performance Numbers</H2>
|
|
||||||
|
|
||||||
<p>Here are some performance numbers from an example desktop machine,
|
|
||||||
taken from a version of time_hash_map that was instrumented to also
|
|
||||||
report memory allocation information (this modification is not
|
|
||||||
included by default because it required a big hack to do, including
|
|
||||||
modifying the STL code to not try to do its own freelist management).</p>
|
|
||||||
|
|
||||||
<p>Note there are lots of caveats on these numbers: they may differ from
|
|
||||||
machine to machine and compiler to compiler, and they only test a very
|
|
||||||
particular usage pattern that may not match how you use hashtables --
|
|
||||||
for instance, they test hashtables with very small keys. However,
|
|
||||||
they're still useful for a baseline comparison of the various
|
|
||||||
hashtable implementations.</p>
|
|
||||||
|
|
||||||
<p>These figures are from a 2.80GHz Pentium 4 with 2G of memory. The
|
|
||||||
'standard' hash_map and map implementations are the SGI STL code
|
|
||||||
included with <tt>gcc2</tt>. Compiled with <tt>gcc2.95.3 -g
|
|
||||||
-O2</tt></p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
======
|
|
||||||
Average over 10000000 iterations
|
|
||||||
Wed Dec 8 14:56:38 PST 2004
|
|
||||||
|
|
||||||
SPARSE_HASH_MAP:
|
|
||||||
map_grow 665 ns
|
|
||||||
map_predict/grow 303 ns
|
|
||||||
map_replace 177 ns
|
|
||||||
map_fetch 117 ns
|
|
||||||
map_remove 192 ns
|
|
||||||
memory used in map_grow 84.3956 Mbytes
|
|
||||||
|
|
||||||
DENSE_HASH_MAP:
|
|
||||||
map_grow 84 ns
|
|
||||||
map_predict/grow 22 ns
|
|
||||||
map_replace 18 ns
|
|
||||||
map_fetch 13 ns
|
|
||||||
map_remove 23 ns
|
|
||||||
memory used in map_grow 256.0000 Mbytes
|
|
||||||
|
|
||||||
STANDARD HASH_MAP:
|
|
||||||
map_grow 162 ns
|
|
||||||
map_predict/grow 107 ns
|
|
||||||
map_replace 44 ns
|
|
||||||
map_fetch 22 ns
|
|
||||||
map_remove 124 ns
|
|
||||||
memory used in map_grow 204.1643 Mbytes
|
|
||||||
|
|
||||||
STANDARD MAP:
|
|
||||||
map_grow 297 ns
|
|
||||||
map_predict/grow 282 ns
|
|
||||||
map_replace 113 ns
|
|
||||||
map_fetch 113 ns
|
|
||||||
map_remove 238 ns
|
|
||||||
memory used in map_grow 236.8081 Mbytes
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
|
|
||||||
<H2><A name="hashfn">A Note on Hash Functions</A></H2>
|
|
||||||
|
|
||||||
<p>For good performance, the Google hash routines depend on a good
|
|
||||||
hash function: one that distributes data evenly. Many hashtable
|
|
||||||
implementations come with sub-optimal hash functions that can degrade
|
|
||||||
performance. For instance, the hash function given in Knuth's _Art of
|
|
||||||
Computer Programming_, and the default string hash function in SGI's
|
|
||||||
STL implementation, both distribute certain data sets unevenly,
|
|
||||||
leading to poor performance.</p>
|
|
||||||
|
|
||||||
<p>As an example, in one test of the default SGI STL string hash
|
|
||||||
function against the Hsieh hash function (see below), for a particular
|
|
||||||
set of string keys, the Hsieh function resulted in hashtable lookups
|
|
||||||
that were 20 times as fast as the STLPort hash function. The string
|
|
||||||
keys were chosen to be "hard" to hash well, so these results may not
|
|
||||||
be typical, but they are suggestive.</p>
|
|
||||||
|
|
||||||
<p>There has been much research over the years into good hash
|
|
||||||
functions. Here are some hash functions of note.</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li> Bob Jenkins: <A HREF="http://burtleburtle.net/bob/hash/">http://burtleburtle.net/bob/hash/</A>
|
|
||||||
<li> Paul Hsieh: <A HREF="http://www.azillionmonkeys.com/qed/hash.html">http://www.azillionmonkeys.com/qed/hash.html</A>
|
|
||||||
<li> Fowler/Noll/Vo (FNV): <A HREF="http://www.isthe.com/chongo/tech/comp/fnv/">http://www.isthe.com/chongo/tech/comp/fnv/</A>
|
|
||||||
<li> MurmurHash: <A HREF="http://murmurhash.googlepages.com/">http://murmurhash.googlepages.com/</A>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,9 +0,0 @@
|
|||||||
example: example.o libchash.o
|
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
|
|
||||||
|
|
||||||
.SUFFIXES: .c .o .h
|
|
||||||
.c.o:
|
|
||||||
$(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $<
|
|
||||||
|
|
||||||
example.o: example.c libchash.h
|
|
||||||
libchash.o: libchash.c libchash.h
|
|
@ -1,14 +0,0 @@
|
|||||||
This is a C version of sparsehash (and also, maybe, densehash) that I
|
|
||||||
wrote way back when, and served as the inspiration for the C++
|
|
||||||
version. The API for the C version is much uglier than the C++,
|
|
||||||
because of the lack of template support. I believe the class works,
|
|
||||||
but I'm not convinced it's really flexible or easy enough to use.
|
|
||||||
|
|
||||||
It would be nice to rework this C class to follow the C++ API as
|
|
||||||
closely as possible (eg have a set_deleted_key() instead of using a
|
|
||||||
#define like this code does now). I believe the code compiles and
|
|
||||||
runs, if anybody is interested in using it now, but it's subject to
|
|
||||||
major change in the future, as people work on it.
|
|
||||||
|
|
||||||
Craig Silverstein
|
|
||||||
20 March 2005
|
|
@ -1,54 +0,0 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include "libchash.h"
|
|
||||||
|
|
||||||
static void TestInsert() {
|
|
||||||
struct HashTable* ht;
|
|
||||||
HTItem* bck;
|
|
||||||
|
|
||||||
ht = AllocateHashTable(1, 0); /* value is 1 byte, 0: don't copy keys */
|
|
||||||
|
|
||||||
HashInsert(ht, PTR_KEY(ht, "January"), 31); /* 0: don't overwrite old val */
|
|
||||||
bck = HashInsert(ht, PTR_KEY(ht, "February"), 28);
|
|
||||||
bck = HashInsert(ht, PTR_KEY(ht, "March"), 31);
|
|
||||||
|
|
||||||
bck = HashFind(ht, PTR_KEY(ht, "February"));
|
|
||||||
assert(bck);
|
|
||||||
assert(bck->data == 28);
|
|
||||||
|
|
||||||
FreeHashTable(ht);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TestFindOrInsert() {
|
|
||||||
struct HashTable* ht;
|
|
||||||
int i;
|
|
||||||
int iterations = 1000000;
|
|
||||||
int range = 30; /* random number between 1 and 30 */
|
|
||||||
|
|
||||||
ht = AllocateHashTable(4, 0); /* value is 4 bytes, 0: don't copy keys */
|
|
||||||
|
|
||||||
/* We'll test how good rand() is as a random number generator */
|
|
||||||
for (i = 0; i < iterations; ++i) {
|
|
||||||
int key = rand() % range;
|
|
||||||
HTItem* bck = HashFindOrInsert(ht, key, 0); /* initialize to 0 */
|
|
||||||
bck->data++; /* found one more of them */
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < range; ++i) {
|
|
||||||
HTItem* bck = HashFind(ht, i);
|
|
||||||
if (bck) {
|
|
||||||
printf("%3d: %d\n", bck->key, bck->data);
|
|
||||||
} else {
|
|
||||||
printf("%3d: 0\n", i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeHashTable(ht);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
TestInsert();
|
|
||||||
TestFindOrInsert();
|
|
||||||
return 0;
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,252 +0,0 @@
|
|||||||
/* Copyright (c) 1998 - 2005, Google Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are
|
|
||||||
* met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* * Redistributions in binary form must reproduce the above
|
|
||||||
* copyright notice, this list of conditions and the following disclaimer
|
|
||||||
* in the documentation and/or other materials provided with the
|
|
||||||
* distribution.
|
|
||||||
* * Neither the name of Google Inc. nor the names of its
|
|
||||||
* contributors may be used to endorse or promote products derived from
|
|
||||||
* this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* ---
|
|
||||||
* Author: Craig Silverstein
|
|
||||||
*
|
|
||||||
* This library is intended to be used for in-memory hash tables,
|
|
||||||
* though it provides rudimentary permanent-storage capabilities.
|
|
||||||
* It attempts to be fast, portable, and small. The best algorithm
|
|
||||||
* to fulfill these goals is an internal probing hashing algorithm,
|
|
||||||
* as in Knuth, _Art of Computer Programming_, vol III. Unlike
|
|
||||||
* chained (open) hashing, it doesn't require a pointer for every
|
|
||||||
* item, yet it is still constant time lookup in practice.
|
|
||||||
*
|
|
||||||
* Also to save space, we let the contents (both data and key) that
|
|
||||||
* you insert be a union: if the key/data is small, we store it
|
|
||||||
* directly in the hashtable, otherwise we store a pointer to it.
|
|
||||||
* To keep you from having to figure out which, use KEY_PTR and
|
|
||||||
* PTR_KEY to convert between the arguments to these functions and
|
|
||||||
* a pointer to the real data. For instance:
|
|
||||||
* char key[] = "ab", *key2;
|
|
||||||
* HTItem *bck; HashTable *ht;
|
|
||||||
* HashInsert(ht, PTR_KEY(ht, key), 0);
|
|
||||||
* bck = HashFind(ht, PTR_KEY(ht, "ab"));
|
|
||||||
* key2 = KEY_PTR(ht, bck->key);
|
|
||||||
*
|
|
||||||
* There are a rich set of operations supported:
|
|
||||||
* AllocateHashTable() -- Allocates a hashtable structure and
|
|
||||||
* returns it.
|
|
||||||
* cchKey: if it's a positive number, then each key is a
|
|
||||||
* fixed-length record of that length. If it's 0,
|
|
||||||
* the key is assumed to be a \0-terminated string.
|
|
||||||
* fSaveKey: normally, you are responsible for allocating
|
|
||||||
* space for the key. If this is 1, we make a
|
|
||||||
* copy of the key for you.
|
|
||||||
* ClearHashTable() -- Removes everything from a hashtable
|
|
||||||
* FreeHashTable() -- Frees memory used by a hashtable
|
|
||||||
*
|
|
||||||
* HashFind() -- takes a key (use PTR_KEY) and returns the
|
|
||||||
* HTItem containing that key, or NULL if the
|
|
||||||
* key is not in the hashtable.
|
|
||||||
* HashFindLast() -- returns the item found by last HashFind()
|
|
||||||
* HashFindOrInsert() -- inserts the key/data pair if the key
|
|
||||||
* is not already in the hashtable, or
|
|
||||||
* returns the appropraite HTItem if it is.
|
|
||||||
* HashFindOrInsertItem() -- takes key/data as an HTItem.
|
|
||||||
* HashInsert() -- adds a key/data pair to the hashtable. What
|
|
||||||
* it does if the key is already in the table
|
|
||||||
* depends on the value of SAMEKEY_OVERWRITE.
|
|
||||||
* HashInsertItem() -- takes key/data as an HTItem.
|
|
||||||
* HashDelete() -- removes a key/data pair from the hashtable,
|
|
||||||
* if it's there. RETURNS 1 if it was there,
|
|
||||||
* 0 else.
|
|
||||||
* If you use sparse tables and never delete, the full data
|
|
||||||
* space is available. Otherwise we steal -2 (maybe -3),
|
|
||||||
* so you can't have data fields with those values.
|
|
||||||
* HashDeleteLast() -- deletes the item returned by the last Find().
|
|
||||||
*
|
|
||||||
* HashFirstBucket() -- used to iterate over the buckets in a
|
|
||||||
* hashtable. DON'T INSERT OR DELETE WHILE
|
|
||||||
* ITERATING! You can't nest iterations.
|
|
||||||
* HashNextBucket() -- RETURNS NULL at the end of iterating.
|
|
||||||
*
|
|
||||||
* HashSetDeltaGoalSize() -- if you're going to insert 1000 items
|
|
||||||
* at once, call this fn with arg 1000.
|
|
||||||
* It grows the table more intelligently.
|
|
||||||
*
|
|
||||||
* HashSave() -- saves the hashtable to a file. It saves keys ok,
|
|
||||||
* but it doesn't know how to interpret the data field,
|
|
||||||
* so if the data field is a pointer to some complex
|
|
||||||
* structure, you must send a function that takes a
|
|
||||||
* file pointer and a pointer to the structure, and
|
|
||||||
* write whatever you want to write. It should return
|
|
||||||
* the number of bytes written. If the file is NULL,
|
|
||||||
* it should just return the number of bytes it would
|
|
||||||
* write, without writing anything.
|
|
||||||
* If your data field is just an integer, not a
|
|
||||||
* pointer, just send NULL for the function.
|
|
||||||
* HashLoad() -- loads a hashtable. It needs a function that takes
|
|
||||||
* a file and the size of the structure, and expects
|
|
||||||
* you to read in the structure and return a pointer
|
|
||||||
* to it. You must do memory allocation, etc. If
|
|
||||||
* the data is just a number, send NULL.
|
|
||||||
* HashLoadKeys() -- unlike HashLoad(), doesn't load the data off disk
|
|
||||||
* until needed. This saves memory, but if you look
|
|
||||||
* up the same key a lot, it does a disk access each
|
|
||||||
* time.
|
|
||||||
* You can't do Insert() or Delete() on hashtables that were loaded
|
|
||||||
* from disk.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h> /* includes definition of "ulong", we hope */
|
|
||||||
#define ulong u_long
|
|
||||||
|
|
||||||
#define MAGIC_KEY "CHsh" /* when we save the file */
|
|
||||||
|
|
||||||
#ifndef LOG_WORD_SIZE /* 5 for 32 bit words, 6 for 64 */
|
|
||||||
#if defined (__LP64__) || defined (_LP64)
|
|
||||||
#define LOG_WORD_SIZE 6 /* log_2(sizeof(ulong)) [in bits] */
|
|
||||||
#else
|
|
||||||
#define LOG_WORD_SIZE 5 /* log_2(sizeof(ulong)) [in bits] */
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The following gives a speed/time tradeoff: how many buckets are *
|
|
||||||
* in each bin. 0 gives 32 buckets/bin, which is a good number. */
|
|
||||||
#ifndef LOG_BM_WORDS
|
|
||||||
#define LOG_BM_WORDS 0 /* each group has 2^L_B_W * 32 buckets */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The following are all parameters that affect performance. */
|
|
||||||
#ifndef JUMP
|
|
||||||
#define JUMP(key, offset) ( ++(offset) ) /* ( 1 ) for linear hashing */
|
|
||||||
#endif
|
|
||||||
#ifndef Table
|
|
||||||
#define Table(x) Sparse##x /* Dense##x for dense tables */
|
|
||||||
#endif
|
|
||||||
#ifndef FAST_DELETE
|
|
||||||
#define FAST_DELETE 0 /* if it's 1, we never shrink the ht */
|
|
||||||
#endif
|
|
||||||
#ifndef SAMEKEY_OVERWRITE
|
|
||||||
#define SAMEKEY_OVERWRITE 1 /* overwrite item with our key on insert? */
|
|
||||||
#endif
|
|
||||||
#ifndef OCCUPANCY_PCT
|
|
||||||
#define OCCUPANCY_PCT 0.5 /* large PCT means smaller and slower */
|
|
||||||
#endif
|
|
||||||
#ifndef MIN_HASH_SIZE
|
|
||||||
#define MIN_HASH_SIZE 512 /* ht size when first created */
|
|
||||||
#endif
|
|
||||||
/* When deleting a bucket, we can't just empty it (future hashes *
|
|
||||||
* may fail); instead we set the data field to DELETED. Thus you *
|
|
||||||
* should set DELETED to a data value you never use. Better yet, *
|
|
||||||
* if you don't need to delete, define INSERT_ONLY. */
|
|
||||||
#ifndef INSERT_ONLY
|
|
||||||
#define DELETED -2UL
|
|
||||||
#define IS_BCK_DELETED(bck) ( (bck) && (bck)->data == DELETED )
|
|
||||||
#define SET_BCK_DELETED(ht, bck) do { (bck)->data = DELETED; \
|
|
||||||
FREE_KEY(ht, (bck)->key); } while ( 0 )
|
|
||||||
#else
|
|
||||||
#define IS_BCK_DELETED(bck) 0
|
|
||||||
#define SET_BCK_DELETED(ht, bck) \
|
|
||||||
do { fprintf(stderr, "Deletion not supported for insert-only hashtable\n");\
|
|
||||||
exit(2); } while ( 0 )
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* We need the following only for dense buckets (Dense##x above). *
|
|
||||||
* If you need to, set this to a value you'll never use for data. */
|
|
||||||
#define EMPTY -3UL /* steal more of the bck->data space */
|
|
||||||
|
|
||||||
|
|
||||||
/* This is what an item is. Either can be cast to a pointer. */
|
|
||||||
typedef struct {
|
|
||||||
ulong data; /* 4 bytes for data: either a pointer or an integer */
|
|
||||||
ulong key; /* 4 bytes for the key: either a pointer or an int */
|
|
||||||
} HTItem;
|
|
||||||
|
|
||||||
struct Table(Bin); /* defined in chash.c, I hope */
|
|
||||||
struct Table(Iterator);
|
|
||||||
typedef struct Table(Bin) Table; /* Expands to SparseBin, etc */
|
|
||||||
typedef struct Table(Iterator) TableIterator;
|
|
||||||
|
|
||||||
/* for STORES_PTR to work ok, cchKey MUST BE DEFINED 1st, cItems 2nd! */
|
|
||||||
typedef struct HashTable {
|
|
||||||
ulong cchKey; /* the length of the key, or if it's \0 terminated */
|
|
||||||
ulong cItems; /* number of items currently in the hashtable */
|
|
||||||
ulong cDeletedItems; /* # of buckets holding DELETE in the hashtable */
|
|
||||||
ulong cBuckets; /* size of the table */
|
|
||||||
Table *table; /* The actual contents of the hashtable */
|
|
||||||
int fSaveKeys; /* 1 if we copy keys locally; 2 if keys in one block */
|
|
||||||
int cDeltaGoalSize; /* # of coming inserts (or deletes, if <0) we expect */
|
|
||||||
HTItem *posLastFind; /* position of last Find() command */
|
|
||||||
TableIterator *iter; /* used in First/NextBucket */
|
|
||||||
|
|
||||||
FILE *fpData; /* if non-NULL, what item->data points into */
|
|
||||||
char * (*dataRead)(FILE *, int); /* how to load data from disk */
|
|
||||||
HTItem bckData; /* holds data after being loaded from disk */
|
|
||||||
} HashTable;
|
|
||||||
|
|
||||||
/* Small keys are stored and passed directly, but large keys are
|
|
||||||
* stored and passed as pointers. To make it easier to remember
|
|
||||||
* what to pass, we provide two functions:
|
|
||||||
* PTR_KEY: give it a pointer to your data, and it returns
|
|
||||||
* something appropriate to send to Hash() functions or
|
|
||||||
* be stored in a data field.
|
|
||||||
* KEY_PTR: give it something returned by a Hash() routine, and
|
|
||||||
* it returns a (char *) pointer to the actual data.
|
|
||||||
*/
|
|
||||||
#define HashKeySize(ht) ( ((ulong *)(ht))[0] ) /* this is how we inline */
|
|
||||||
#define HashSize(ht) ( ((ulong *)(ht))[1] ) /* ...a la C++ :-) */
|
|
||||||
|
|
||||||
#define STORES_PTR(ht) ( HashKeySize(ht) == 0 || \
|
|
||||||
HashKeySize(ht) > sizeof(ulong) )
|
|
||||||
#define KEY_PTR(ht, key) ( STORES_PTR(ht) ? (char *)(key) : (char *)&(key) )
|
|
||||||
#ifdef DONT_HAVE_TO_WORRY_ABOUT_BUS_ERRORS
|
|
||||||
#define PTR_KEY(ht, ptr) ( STORES_PTR(ht) ? (ulong)(ptr) : *(ulong *)(ptr) )
|
|
||||||
#else
|
|
||||||
#define PTR_KEY(ht, ptr) ( STORES_PTR(ht) ? (ulong)(ptr) : HTcopy((char *)ptr))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Function prototypes */
|
|
||||||
unsigned long HTcopy(char *pul); /* for PTR_KEY, not for users */
|
|
||||||
|
|
||||||
struct HashTable *AllocateHashTable(int cchKey, int fSaveKeys);
|
|
||||||
void ClearHashTable(struct HashTable *ht);
|
|
||||||
void FreeHashTable(struct HashTable *ht);
|
|
||||||
|
|
||||||
HTItem *HashFind(struct HashTable *ht, ulong key);
|
|
||||||
HTItem *HashFindLast(struct HashTable *ht);
|
|
||||||
HTItem *HashFindOrInsert(struct HashTable *ht, ulong key, ulong dataInsert);
|
|
||||||
HTItem *HashFindOrInsertItem(struct HashTable *ht, HTItem *pItem);
|
|
||||||
|
|
||||||
HTItem *HashInsert(struct HashTable *ht, ulong key, ulong data);
|
|
||||||
HTItem *HashInsertItem(struct HashTable *ht, HTItem *pItem);
|
|
||||||
|
|
||||||
int HashDelete(struct HashTable *ht, ulong key);
|
|
||||||
int HashDeleteLast(struct HashTable *ht);
|
|
||||||
|
|
||||||
HTItem *HashFirstBucket(struct HashTable *ht);
|
|
||||||
HTItem *HashNextBucket(struct HashTable *ht);
|
|
||||||
|
|
||||||
int HashSetDeltaGoalSize(struct HashTable *ht, int delta);
|
|
||||||
|
|
||||||
void HashSave(FILE *fp, struct HashTable *ht, int (*write)(FILE *, char *));
|
|
||||||
struct HashTable *HashLoad(FILE *fp, char * (*read)(FILE *, int));
|
|
||||||
struct HashTable *HashLoadKeys(FILE *fp, char * (*read)(FILE *, int));
|
|
@ -1,47 +0,0 @@
|
|||||||
Microsoft Visual Studio Solution File, Format Version 8.00
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "type_traits_unittest", "vsprojects\type_traits_unittest\type_traits_unittest.vcproj", "{008CCFED-7D7B-46F8-8E13-03837A2258B3}"
|
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sparsetable_unittest", "vsprojects\sparsetable_unittest\sparsetable_unittest.vcproj", "{E420867B-8BFA-4739-99EC-E008AB762FF9}"
|
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hashtable_unittest", "vsprojects\hashtable_unittest\hashtable_unittest.vcproj", "{FCDB3718-F01C-4DE4-B9F5-E10F2C5C0535}"
|
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "time_hash_map", "vsprojects\time_hash_map\time_hash_map.vcproj", "{A74E5DB8-5295-487A-AB1D-23859F536F45}"
|
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfiguration) = preSolution
|
|
||||||
Debug = Debug
|
|
||||||
Release = Release
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectDependencies) = postSolution
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfiguration) = postSolution
|
|
||||||
{008CCFED-7D7B-46F8-8E13-03837A2258B3}.Debug.ActiveCfg = Debug|Win32
|
|
||||||
{008CCFED-7D7B-46F8-8E13-03837A2258B3}.Debug.Build.0 = Debug|Win32
|
|
||||||
{008CCFED-7D7B-46F8-8E13-03837A2258B3}.Release.ActiveCfg = Release|Win32
|
|
||||||
{008CCFED-7D7B-46F8-8E13-03837A2258B3}.Release.Build.0 = Release|Win32
|
|
||||||
{E420867B-8BFA-4739-99EC-E008AB762FF9}.Debug.ActiveCfg = Debug|Win32
|
|
||||||
{E420867B-8BFA-4739-99EC-E008AB762FF9}.Debug.Build.0 = Debug|Win32
|
|
||||||
{E420867B-8BFA-4739-99EC-E008AB762FF9}.Release.ActiveCfg = Release|Win32
|
|
||||||
{E420867B-8BFA-4739-99EC-E008AB762FF9}.Release.Build.0 = Release|Win32
|
|
||||||
{FCDB3718-F01C-4DE4-B9F5-E10F2C5C0535}.Debug.ActiveCfg = Debug|Win32
|
|
||||||
{FCDB3718-F01C-4DE4-B9F5-E10F2C5C0535}.Debug.Build.0 = Debug|Win32
|
|
||||||
{FCDB3718-F01C-4DE4-B9F5-E10F2C5C0535}.Release.ActiveCfg = Release|Win32
|
|
||||||
{FCDB3718-F01C-4DE4-B9F5-E10F2C5C0535}.Release.Build.0 = Release|Win32
|
|
||||||
{A74E5DB8-5295-487A-AB1D-23859F536F45}.Debug.ActiveCfg = Debug|Win32
|
|
||||||
{A74E5DB8-5295-487A-AB1D-23859F536F45}.Debug.Build.0 = Debug|Win32
|
|
||||||
{A74E5DB8-5295-487A-AB1D-23859F536F45}.Release.ActiveCfg = Release|Win32
|
|
||||||
{A74E5DB8-5295-487A-AB1D-23859F536F45}.Release.Build.0 = Release|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
Binary file not shown.
@ -1,363 +0,0 @@
|
|||||||
# This was retrieved from
|
|
||||||
# http://svn.0pointer.de/viewvc/trunk/common/acx_pthread.m4?revision=1277&root=avahi
|
|
||||||
# See also (perhaps for new versions?)
|
|
||||||
# http://svn.0pointer.de/viewvc/trunk/common/acx_pthread.m4?root=avahi
|
|
||||||
#
|
|
||||||
# We've rewritten the inconsistency check code (from avahi), to work
|
|
||||||
# more broadly. In particular, it no longer assumes ld accepts -zdefs.
|
|
||||||
# This caused a restructing of the code, but the functionality has only
|
|
||||||
# changed a little.
|
|
||||||
|
|
||||||
dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
|
|
||||||
dnl
|
|
||||||
dnl @summary figure out how to build C programs using POSIX threads
|
|
||||||
dnl
|
|
||||||
dnl This macro figures out how to build C programs using POSIX threads.
|
|
||||||
dnl It sets the PTHREAD_LIBS output variable to the threads library and
|
|
||||||
dnl linker flags, and the PTHREAD_CFLAGS output variable to any special
|
|
||||||
dnl C compiler flags that are needed. (The user can also force certain
|
|
||||||
dnl compiler flags/libs to be tested by setting these environment
|
|
||||||
dnl variables.)
|
|
||||||
dnl
|
|
||||||
dnl Also sets PTHREAD_CC to any special C compiler that is needed for
|
|
||||||
dnl multi-threaded programs (defaults to the value of CC otherwise).
|
|
||||||
dnl (This is necessary on AIX to use the special cc_r compiler alias.)
|
|
||||||
dnl
|
|
||||||
dnl NOTE: You are assumed to not only compile your program with these
|
|
||||||
dnl flags, but also link it with them as well. e.g. you should link
|
|
||||||
dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS
|
|
||||||
dnl $LIBS
|
|
||||||
dnl
|
|
||||||
dnl If you are only building threads programs, you may wish to use
|
|
||||||
dnl these variables in your default LIBS, CFLAGS, and CC:
|
|
||||||
dnl
|
|
||||||
dnl LIBS="$PTHREAD_LIBS $LIBS"
|
|
||||||
dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
|
||||||
dnl CC="$PTHREAD_CC"
|
|
||||||
dnl
|
|
||||||
dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute
|
|
||||||
dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to
|
|
||||||
dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
|
||||||
dnl
|
|
||||||
dnl ACTION-IF-FOUND is a list of shell commands to run if a threads
|
|
||||||
dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to
|
|
||||||
dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the
|
|
||||||
dnl default action will define HAVE_PTHREAD.
|
|
||||||
dnl
|
|
||||||
dnl Please let the authors know if this macro fails on any platform, or
|
|
||||||
dnl if you have any other suggestions or comments. This macro was based
|
|
||||||
dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with
|
|
||||||
dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros
|
|
||||||
dnl posted by Alejandro Forero Cuervo to the autoconf macro repository.
|
|
||||||
dnl We are also grateful for the helpful feedback of numerous users.
|
|
||||||
dnl
|
|
||||||
dnl @category InstalledPackages
|
|
||||||
dnl @author Steven G. Johnson <stevenj@alum.mit.edu>
|
|
||||||
dnl @version 2006-05-29
|
|
||||||
dnl @license GPLWithACException
|
|
||||||
dnl
|
|
||||||
dnl Checks for GCC shared/pthread inconsistency based on work by
|
|
||||||
dnl Marcin Owsiany <marcin@owsiany.pl>
|
|
||||||
|
|
||||||
|
|
||||||
AC_DEFUN([ACX_PTHREAD], [
|
|
||||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
|
||||||
AC_LANG_SAVE
|
|
||||||
AC_LANG_C
|
|
||||||
acx_pthread_ok=no
|
|
||||||
|
|
||||||
# We used to check for pthread.h first, but this fails if pthread.h
|
|
||||||
# requires special compiler flags (e.g. on True64 or Sequent).
|
|
||||||
# It gets checked for in the link test anyway.
|
|
||||||
|
|
||||||
# First of all, check if the user has set any of the PTHREAD_LIBS,
|
|
||||||
# etcetera environment variables, and if threads linking works using
|
|
||||||
# them:
|
|
||||||
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
|
|
||||||
save_CFLAGS="$CFLAGS"
|
|
||||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
|
||||||
save_LIBS="$LIBS"
|
|
||||||
LIBS="$PTHREAD_LIBS $LIBS"
|
|
||||||
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
|
|
||||||
AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
|
|
||||||
AC_MSG_RESULT($acx_pthread_ok)
|
|
||||||
if test x"$acx_pthread_ok" = xno; then
|
|
||||||
PTHREAD_LIBS=""
|
|
||||||
PTHREAD_CFLAGS=""
|
|
||||||
fi
|
|
||||||
LIBS="$save_LIBS"
|
|
||||||
CFLAGS="$save_CFLAGS"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# We must check for the threads library under a number of different
|
|
||||||
# names; the ordering is very important because some systems
|
|
||||||
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
|
|
||||||
# libraries is broken (non-POSIX).
|
|
||||||
|
|
||||||
# Create a list of thread flags to try. Items starting with a "-" are
|
|
||||||
# C compiler flags, and other items are library names, except for "none"
|
|
||||||
# which indicates that we try without any flags at all, and "pthread-config"
|
|
||||||
# which is a program returning the flags for the Pth emulation library.
|
|
||||||
|
|
||||||
acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
|
||||||
|
|
||||||
# The ordering *is* (sometimes) important. Some notes on the
|
|
||||||
# individual items follow:
|
|
||||||
|
|
||||||
# pthreads: AIX (must check this before -lpthread)
|
|
||||||
# none: in case threads are in libc; should be tried before -Kthread and
|
|
||||||
# other compiler flags to prevent continual compiler warnings
|
|
||||||
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
|
||||||
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
|
||||||
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
|
||||||
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
|
|
||||||
# -pthreads: Solaris/gcc
|
|
||||||
# -mthreads: Mingw32/gcc, Lynx/gcc
|
|
||||||
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
|
||||||
# doesn't hurt to check since this sometimes defines pthreads too;
|
|
||||||
# also defines -D_REENTRANT)
|
|
||||||
# ... -mt is also the pthreads flag for HP/aCC
|
|
||||||
# pthread: Linux, etcetera
|
|
||||||
# --thread-safe: KAI C++
|
|
||||||
# pthread-config: use pthread-config program (for GNU Pth library)
|
|
||||||
|
|
||||||
case "${host_cpu}-${host_os}" in
|
|
||||||
*solaris*)
|
|
||||||
|
|
||||||
# On Solaris (at least, for some versions), libc contains stubbed
|
|
||||||
# (non-functional) versions of the pthreads routines, so link-based
|
|
||||||
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
|
|
||||||
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
|
|
||||||
# a function called by this macro, so we could check for that, but
|
|
||||||
# who knows whether they'll stub that too in a future libc.) So,
|
|
||||||
# we'll just look for -pthreads and -lpthread first:
|
|
||||||
|
|
||||||
acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if test x"$acx_pthread_ok" = xno; then
|
|
||||||
for flag in $acx_pthread_flags; do
|
|
||||||
|
|
||||||
case $flag in
|
|
||||||
none)
|
|
||||||
AC_MSG_CHECKING([whether pthreads work without any flags])
|
|
||||||
;;
|
|
||||||
|
|
||||||
-*)
|
|
||||||
AC_MSG_CHECKING([whether pthreads work with $flag])
|
|
||||||
PTHREAD_CFLAGS="$flag"
|
|
||||||
;;
|
|
||||||
|
|
||||||
pthread-config)
|
|
||||||
AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no)
|
|
||||||
if test x"$acx_pthread_config" = xno; then continue; fi
|
|
||||||
PTHREAD_CFLAGS="`pthread-config --cflags`"
|
|
||||||
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
AC_MSG_CHECKING([for the pthreads library -l$flag])
|
|
||||||
PTHREAD_LIBS="-l$flag"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
save_LIBS="$LIBS"
|
|
||||||
save_CFLAGS="$CFLAGS"
|
|
||||||
LIBS="$PTHREAD_LIBS $LIBS"
|
|
||||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
|
||||||
|
|
||||||
# Check for various functions. We must include pthread.h,
|
|
||||||
# since some functions may be macros. (On the Sequent, we
|
|
||||||
# need a special flag -Kthread to make this header compile.)
|
|
||||||
# We check for pthread_join because it is in -lpthread on IRIX
|
|
||||||
# while pthread_create is in libc. We check for pthread_attr_init
|
|
||||||
# due to DEC craziness with -lpthreads. We check for
|
|
||||||
# pthread_cleanup_push because it is one of the few pthread
|
|
||||||
# functions on Solaris that doesn't have a non-functional libc stub.
|
|
||||||
# We try pthread_create on general principles.
|
|
||||||
AC_TRY_LINK([#include <pthread.h>],
|
|
||||||
[pthread_t th; pthread_join(th, 0);
|
|
||||||
pthread_attr_init(0); pthread_cleanup_push(0, 0);
|
|
||||||
pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
|
|
||||||
[acx_pthread_ok=yes])
|
|
||||||
|
|
||||||
LIBS="$save_LIBS"
|
|
||||||
CFLAGS="$save_CFLAGS"
|
|
||||||
|
|
||||||
AC_MSG_RESULT($acx_pthread_ok)
|
|
||||||
if test "x$acx_pthread_ok" = xyes; then
|
|
||||||
break;
|
|
||||||
fi
|
|
||||||
|
|
||||||
PTHREAD_LIBS=""
|
|
||||||
PTHREAD_CFLAGS=""
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Various other checks:
|
|
||||||
if test "x$acx_pthread_ok" = xyes; then
|
|
||||||
save_LIBS="$LIBS"
|
|
||||||
LIBS="$PTHREAD_LIBS $LIBS"
|
|
||||||
save_CFLAGS="$CFLAGS"
|
|
||||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
|
||||||
|
|
||||||
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
|
|
||||||
AC_MSG_CHECKING([for joinable pthread attribute])
|
|
||||||
attr_name=unknown
|
|
||||||
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
|
||||||
AC_TRY_LINK([#include <pthread.h>], [int attr=$attr; return attr;],
|
|
||||||
[attr_name=$attr; break])
|
|
||||||
done
|
|
||||||
AC_MSG_RESULT($attr_name)
|
|
||||||
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
|
|
||||||
AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
|
|
||||||
[Define to necessary symbol if this constant
|
|
||||||
uses a non-standard name on your system.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_MSG_CHECKING([if more special flags are required for pthreads])
|
|
||||||
flag=no
|
|
||||||
case "${host_cpu}-${host_os}" in
|
|
||||||
*-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
|
|
||||||
*solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
|
|
||||||
esac
|
|
||||||
AC_MSG_RESULT(${flag})
|
|
||||||
if test "x$flag" != xno; then
|
|
||||||
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
|
|
||||||
fi
|
|
||||||
|
|
||||||
LIBS="$save_LIBS"
|
|
||||||
CFLAGS="$save_CFLAGS"
|
|
||||||
# More AIX lossage: must compile with xlc_r or cc_r
|
|
||||||
if test x"$GCC" != xyes; then
|
|
||||||
AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
|
|
||||||
else
|
|
||||||
PTHREAD_CC=$CC
|
|
||||||
fi
|
|
||||||
|
|
||||||
# The next part tries to detect GCC inconsistency with -shared on some
|
|
||||||
# architectures and systems. The problem is that in certain
|
|
||||||
# configurations, when -shared is specified, GCC "forgets" to
|
|
||||||
# internally use various flags which are still necessary.
|
|
||||||
|
|
||||||
#
|
|
||||||
# Prepare the flags
|
|
||||||
#
|
|
||||||
save_CFLAGS="$CFLAGS"
|
|
||||||
save_LIBS="$LIBS"
|
|
||||||
save_CC="$CC"
|
|
||||||
|
|
||||||
# Try with the flags determined by the earlier checks.
|
|
||||||
#
|
|
||||||
# -Wl,-z,defs forces link-time symbol resolution, so that the
|
|
||||||
# linking checks with -shared actually have any value
|
|
||||||
#
|
|
||||||
# FIXME: -fPIC is required for -shared on many architectures,
|
|
||||||
# so we specify it here, but the right way would probably be to
|
|
||||||
# properly detect whether it is actually required.
|
|
||||||
CFLAGS="-shared -fPIC -Wl,-z,defs $CFLAGS $PTHREAD_CFLAGS"
|
|
||||||
LIBS="$PTHREAD_LIBS $LIBS"
|
|
||||||
CC="$PTHREAD_CC"
|
|
||||||
|
|
||||||
# In order not to create several levels of indentation, we test
|
|
||||||
# the value of "$done" until we find the cure or run out of ideas.
|
|
||||||
done="no"
|
|
||||||
|
|
||||||
# First, make sure the CFLAGS we added are actually accepted by our
|
|
||||||
# compiler. If not (and OS X's ld, for instance, does not accept -z),
|
|
||||||
# then we can't do this test.
|
|
||||||
if test x"$done" = xno; then
|
|
||||||
AC_MSG_CHECKING([whether to check for GCC pthread/shared inconsistencies])
|
|
||||||
AC_TRY_LINK(,, , [done=yes])
|
|
||||||
|
|
||||||
if test "x$done" = xyes ; then
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT([yes])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test x"$done" = xno; then
|
|
||||||
AC_MSG_CHECKING([whether -pthread is sufficient with -shared])
|
|
||||||
AC_TRY_LINK([#include <pthread.h>],
|
|
||||||
[pthread_t th; pthread_join(th, 0);
|
|
||||||
pthread_attr_init(0); pthread_cleanup_push(0, 0);
|
|
||||||
pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
|
|
||||||
[done=yes])
|
|
||||||
|
|
||||||
if test "x$done" = xyes; then
|
|
||||||
AC_MSG_RESULT([yes])
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
#
|
|
||||||
# Linux gcc on some architectures such as mips/mipsel forgets
|
|
||||||
# about -lpthread
|
|
||||||
#
|
|
||||||
if test x"$done" = xno; then
|
|
||||||
AC_MSG_CHECKING([whether -lpthread fixes that])
|
|
||||||
LIBS="-lpthread $PTHREAD_LIBS $save_LIBS"
|
|
||||||
AC_TRY_LINK([#include <pthread.h>],
|
|
||||||
[pthread_t th; pthread_join(th, 0);
|
|
||||||
pthread_attr_init(0); pthread_cleanup_push(0, 0);
|
|
||||||
pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
|
|
||||||
[done=yes])
|
|
||||||
|
|
||||||
if test "x$done" = xyes; then
|
|
||||||
AC_MSG_RESULT([yes])
|
|
||||||
PTHREAD_LIBS="-lpthread $PTHREAD_LIBS"
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
#
|
|
||||||
# FreeBSD 4.10 gcc forgets to use -lc_r instead of -lc
|
|
||||||
#
|
|
||||||
if test x"$done" = xno; then
|
|
||||||
AC_MSG_CHECKING([whether -lc_r fixes that])
|
|
||||||
LIBS="-lc_r $PTHREAD_LIBS $save_LIBS"
|
|
||||||
AC_TRY_LINK([#include <pthread.h>],
|
|
||||||
[pthread_t th; pthread_join(th, 0);
|
|
||||||
pthread_attr_init(0); pthread_cleanup_push(0, 0);
|
|
||||||
pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
|
|
||||||
[done=yes])
|
|
||||||
|
|
||||||
if test "x$done" = xyes; then
|
|
||||||
AC_MSG_RESULT([yes])
|
|
||||||
PTHREAD_LIBS="-lc_r $PTHREAD_LIBS"
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if test x"$done" = xno; then
|
|
||||||
# OK, we have run out of ideas
|
|
||||||
AC_MSG_WARN([Impossible to determine how to use pthreads with shared libraries])
|
|
||||||
|
|
||||||
# so it's not safe to assume that we may use pthreads
|
|
||||||
acx_pthread_ok=no
|
|
||||||
fi
|
|
||||||
|
|
||||||
CFLAGS="$save_CFLAGS"
|
|
||||||
LIBS="$save_LIBS"
|
|
||||||
CC="$save_CC"
|
|
||||||
else
|
|
||||||
PTHREAD_CC="$CC"
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_SUBST(PTHREAD_LIBS)
|
|
||||||
AC_SUBST(PTHREAD_CFLAGS)
|
|
||||||
AC_SUBST(PTHREAD_CC)
|
|
||||||
|
|
||||||
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
|
||||||
if test x"$acx_pthread_ok" = xyes; then
|
|
||||||
ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
|
|
||||||
:
|
|
||||||
else
|
|
||||||
acx_pthread_ok=no
|
|
||||||
$2
|
|
||||||
fi
|
|
||||||
AC_LANG_RESTORE
|
|
||||||
])dnl ACX_PTHREAD
|
|
@ -1,42 +0,0 @@
|
|||||||
# Allow users to override the namespace we define our application's classes in
|
|
||||||
# Arg $1 is the default namespace to use if --enable-namespace isn't present.
|
|
||||||
|
|
||||||
# In general, $1 should be 'google', so we put all our exported symbols in a
|
|
||||||
# unique namespace that is not likely to conflict with anyone else. However,
|
|
||||||
# when it makes sense -- for instance, when publishing stl-like code -- you
|
|
||||||
# may want to go with a different default, like 'std'.
|
|
||||||
|
|
||||||
# We guarantee the invariant that GOOGLE_NAMESPACE starts with ::,
|
|
||||||
# unless it's the empty string. Thus, it's always safe to do
|
|
||||||
# GOOGLE_NAMESPACE::foo and be sure you're getting the foo that's
|
|
||||||
# actually in the google namespace, and not some other namespace that
|
|
||||||
# the namespace rules might kick in.
|
|
||||||
|
|
||||||
AC_DEFUN([AC_DEFINE_GOOGLE_NAMESPACE],
|
|
||||||
[google_namespace_default=[$1]
|
|
||||||
AC_ARG_ENABLE(namespace, [ --enable-namespace=FOO to define these Google
|
|
||||||
classes in the FOO namespace. --disable-namespace
|
|
||||||
to define them in the global namespace. Default
|
|
||||||
is to define them in namespace $1.],
|
|
||||||
[case "$enableval" in
|
|
||||||
yes) google_namespace="$google_namespace_default" ;;
|
|
||||||
no) google_namespace="" ;;
|
|
||||||
*) google_namespace="$enableval" ;;
|
|
||||||
esac],
|
|
||||||
[google_namespace="$google_namespace_default"])
|
|
||||||
if test -n "$google_namespace"; then
|
|
||||||
ac_google_namespace="::$google_namespace"
|
|
||||||
ac_google_start_namespace="namespace $google_namespace {"
|
|
||||||
ac_google_end_namespace="}"
|
|
||||||
else
|
|
||||||
ac_google_namespace=""
|
|
||||||
ac_google_start_namespace=""
|
|
||||||
ac_google_end_namespace=""
|
|
||||||
fi
|
|
||||||
AC_DEFINE_UNQUOTED(GOOGLE_NAMESPACE, $ac_google_namespace,
|
|
||||||
Namespace for Google classes)
|
|
||||||
AC_DEFINE_UNQUOTED(_START_GOOGLE_NAMESPACE_, $ac_google_start_namespace,
|
|
||||||
Puts following code inside the Google namespace)
|
|
||||||
AC_DEFINE_UNQUOTED(_END_GOOGLE_NAMESPACE_, $ac_google_end_namespace,
|
|
||||||
Stops putting the code inside the Google namespace)
|
|
||||||
])
|
|
@ -1,15 +0,0 @@
|
|||||||
# Checks whether the compiler implements namespaces
|
|
||||||
AC_DEFUN([AC_CXX_NAMESPACES],
|
|
||||||
[AC_CACHE_CHECK(whether the compiler implements namespaces,
|
|
||||||
ac_cv_cxx_namespaces,
|
|
||||||
[AC_LANG_SAVE
|
|
||||||
AC_LANG_CPLUSPLUS
|
|
||||||
AC_TRY_COMPILE([namespace Outer {
|
|
||||||
namespace Inner { int i = 0; }}],
|
|
||||||
[using namespace Outer::Inner; return i;],
|
|
||||||
ac_cv_cxx_namespaces=yes,
|
|
||||||
ac_cv_cxx_namespaces=no)
|
|
||||||
AC_LANG_RESTORE])
|
|
||||||
if test "$ac_cv_cxx_namespaces" = yes; then
|
|
||||||
AC_DEFINE(HAVE_NAMESPACES, 1, [define if the compiler implements namespaces])
|
|
||||||
fi])
|
|
@ -1,70 +0,0 @@
|
|||||||
# We check two things: where the include file is for
|
|
||||||
# unordered_map/hash_map (we prefer the first form), and what
|
|
||||||
# namespace unordered/hash_map lives in within that include file. We
|
|
||||||
# include AC_TRY_COMPILE for all the combinations we've seen in the
|
|
||||||
# wild. We define HASH_MAP_H to the location of the header file, and
|
|
||||||
# HASH_NAMESPACE to the namespace the class (unordered_map or
|
|
||||||
# hash_map) is in. We define HAVE_UNORDERED_MAP if the class we found
|
|
||||||
# is named unordered_map, or leave it undefined if not.
|
|
||||||
|
|
||||||
# This also checks if unordered map exists.
|
|
||||||
AC_DEFUN([AC_CXX_STL_HASH],
|
|
||||||
[AC_REQUIRE([AC_CXX_NAMESPACES])
|
|
||||||
AC_MSG_CHECKING(the location of hash_map)
|
|
||||||
AC_LANG_SAVE
|
|
||||||
AC_LANG_CPLUSPLUS
|
|
||||||
ac_cv_cxx_hash_map=""
|
|
||||||
# First try unordered_map, but not on gcc's before 4.2 -- I've
|
|
||||||
# seen unexplainable unordered_map bugs with -O2 on older gcc's.
|
|
||||||
AC_TRY_COMPILE([#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2))
|
|
||||||
# error GCC too old for unordered_map
|
|
||||||
#endif
|
|
||||||
],
|
|
||||||
[/* no program body necessary */],
|
|
||||||
[stl_hash_old_gcc=no],
|
|
||||||
[stl_hash_old_gcc=yes])
|
|
||||||
for location in unordered_map tr1/unordered_map; do
|
|
||||||
for namespace in std std::tr1; do
|
|
||||||
if test -z "$ac_cv_cxx_hash_map" -a "$stl_hash_old_gcc" != yes; then
|
|
||||||
# Some older gcc's have a buggy tr1, so test a bit of code.
|
|
||||||
AC_TRY_COMPILE([#include <$location>],
|
|
||||||
[const ${namespace}::unordered_map<int, int> t;
|
|
||||||
return t.find(5) == t.end();],
|
|
||||||
[ac_cv_cxx_hash_map="<$location>";
|
|
||||||
ac_cv_cxx_hash_namespace="$namespace";
|
|
||||||
ac_cv_cxx_have_unordered_map="yes";])
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
done
|
|
||||||
# Now try hash_map
|
|
||||||
for location in ext/hash_map hash_map; do
|
|
||||||
for namespace in __gnu_cxx "" std stdext; do
|
|
||||||
if test -z "$ac_cv_cxx_hash_map"; then
|
|
||||||
AC_TRY_COMPILE([#include <$location>],
|
|
||||||
[${namespace}::hash_map<int, int> t],
|
|
||||||
[ac_cv_cxx_hash_map="<$location>";
|
|
||||||
ac_cv_cxx_hash_namespace="$namespace";
|
|
||||||
ac_cv_cxx_have_unordered_map="no";])
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
done
|
|
||||||
ac_cv_cxx_hash_set=`echo "$ac_cv_cxx_hash_map" | sed s/map/set/`;
|
|
||||||
if test -n "$ac_cv_cxx_hash_map"; then
|
|
||||||
AC_DEFINE(HAVE_HASH_MAP, 1, [define if the compiler has hash_map])
|
|
||||||
AC_DEFINE(HAVE_HASH_SET, 1, [define if the compiler has hash_set])
|
|
||||||
AC_DEFINE_UNQUOTED(HASH_MAP_H,$ac_cv_cxx_hash_map,
|
|
||||||
[the location of <unordered_map> or <hash_map>])
|
|
||||||
AC_DEFINE_UNQUOTED(HASH_SET_H,$ac_cv_cxx_hash_set,
|
|
||||||
[the location of <unordered_set> or <hash_set>])
|
|
||||||
AC_DEFINE_UNQUOTED(HASH_NAMESPACE,$ac_cv_cxx_hash_namespace,
|
|
||||||
[the namespace of hash_map/hash_set])
|
|
||||||
if test "$ac_cv_cxx_have_unordered_map" = yes; then
|
|
||||||
AC_DEFINE(HAVE_UNORDERED_MAP,1,
|
|
||||||
[define if the compiler supports unordered_{map,set}])
|
|
||||||
fi
|
|
||||||
AC_MSG_RESULT([$ac_cv_cxx_hash_map])
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT()
|
|
||||||
AC_MSG_WARN([could not find an STL hash_map])
|
|
||||||
fi
|
|
||||||
])
|
|
@ -1,36 +0,0 @@
|
|||||||
# We just try to figure out where hash<> is defined. It's in some file
|
|
||||||
# that ends in hash_fun.h...
|
|
||||||
#
|
|
||||||
# Ideally we'd use AC_CACHE_CHECK, but that only lets us store one value
|
|
||||||
# at a time, and we need to store two (filename and namespace).
|
|
||||||
# prints messages itself, so we have to do the message-printing ourselves
|
|
||||||
# via AC_MSG_CHECKING + AC_MSG_RESULT. (TODO(csilvers): can we cache?)
|
|
||||||
#
|
|
||||||
# tr1/functional_hash.h: new gcc's with tr1 support
|
|
||||||
# stl_hash_fun.h: old gcc's (gc2.95?)
|
|
||||||
# ext/hash_fun.h: newer gcc's (gcc4)
|
|
||||||
# stl/_hash_fun.h: STLport
|
|
||||||
|
|
||||||
AC_DEFUN([AC_CXX_STL_HASH_FUN],
|
|
||||||
[AC_REQUIRE([AC_CXX_STL_HASH])
|
|
||||||
AC_MSG_CHECKING(how to include hash_fun directly)
|
|
||||||
AC_LANG_SAVE
|
|
||||||
AC_LANG_CPLUSPLUS
|
|
||||||
ac_cv_cxx_stl_hash_fun=""
|
|
||||||
for location in functional tr1/functional \
|
|
||||||
ext/hash_fun.h ext/stl_hash_fun.h \
|
|
||||||
hash_fun.h stl_hash_fun.h \
|
|
||||||
stl/_hash_fun.h; do
|
|
||||||
if test -z "$ac_cv_cxx_stl_hash_fun"; then
|
|
||||||
AC_TRY_COMPILE([#include <$location>],
|
|
||||||
[int x = ${ac_cv_cxx_hash_namespace}::hash<int>()(5)],
|
|
||||||
[ac_cv_cxx_stl_hash_fun="<$location>";])
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
AC_LANG_RESTORE
|
|
||||||
AC_DEFINE_UNQUOTED(HASH_FUN_H,$ac_cv_cxx_stl_hash_fun,
|
|
||||||
[the location of the header defining hash functions])
|
|
||||||
AC_DEFINE_UNQUOTED(HASH_NAMESPACE,$ac_cv_cxx_hash_namespace,
|
|
||||||
[the namespace of the hash<> function])
|
|
||||||
AC_MSG_RESULT([$ac_cv_cxx_stl_hash_fun])
|
|
||||||
])
|
|
@ -1,25 +0,0 @@
|
|||||||
# We check what namespace stl code like vector expects to be executed in
|
|
||||||
|
|
||||||
AC_DEFUN([AC_CXX_STL_NAMESPACE],
|
|
||||||
[AC_CACHE_CHECK(
|
|
||||||
what namespace STL code is in,
|
|
||||||
ac_cv_cxx_stl_namespace,
|
|
||||||
[AC_REQUIRE([AC_CXX_NAMESPACES])
|
|
||||||
AC_LANG_SAVE
|
|
||||||
AC_LANG_CPLUSPLUS
|
|
||||||
AC_TRY_COMPILE([#include <vector>],
|
|
||||||
[vector<int> t; return 0;],
|
|
||||||
ac_cv_cxx_stl_namespace=none)
|
|
||||||
AC_TRY_COMPILE([#include <vector>],
|
|
||||||
[std::vector<int> t; return 0;],
|
|
||||||
ac_cv_cxx_stl_namespace=std)
|
|
||||||
AC_LANG_RESTORE])
|
|
||||||
if test "$ac_cv_cxx_stl_namespace" = none; then
|
|
||||||
AC_DEFINE(STL_NAMESPACE,,
|
|
||||||
[the namespace where STL code like vector<> is defined])
|
|
||||||
fi
|
|
||||||
if test "$ac_cv_cxx_stl_namespace" = std; then
|
|
||||||
AC_DEFINE(STL_NAMESPACE,std,
|
|
||||||
[the namespace where STL code like vector<> is defined])
|
|
||||||
fi
|
|
||||||
])
|
|
@ -1,360 +0,0 @@
|
|||||||
#! /bin/sh
|
|
||||||
# Common stub for a few missing GNU programs while installing.
|
|
||||||
|
|
||||||
scriptversion=2005-06-08.21
|
|
||||||
|
|
||||||
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005
|
|
||||||
# Free Software Foundation, Inc.
|
|
||||||
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
|
||||||
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
# As a special exception to the GNU General Public License, if you
|
|
||||||
# distribute this file as part of a program that contains a
|
|
||||||
# configuration script generated by Autoconf, you may include it under
|
|
||||||
# the same distribution terms that you use for the rest of that program.
|
|
||||||
|
|
||||||
if test $# -eq 0; then
|
|
||||||
echo 1>&2 "Try \`$0 --help' for more information"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
run=:
|
|
||||||
|
|
||||||
# In the cases where this matters, `missing' is being run in the
|
|
||||||
# srcdir already.
|
|
||||||
if test -f configure.ac; then
|
|
||||||
configure_ac=configure.ac
|
|
||||||
else
|
|
||||||
configure_ac=configure.in
|
|
||||||
fi
|
|
||||||
|
|
||||||
msg="missing on your system"
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
--run)
|
|
||||||
# Try to run requested program, and just exit if it succeeds.
|
|
||||||
run=
|
|
||||||
shift
|
|
||||||
"$@" && exit 0
|
|
||||||
# Exit code 63 means version mismatch. This often happens
|
|
||||||
# when the user try to use an ancient version of a tool on
|
|
||||||
# a file that requires a minimum version. In this case we
|
|
||||||
# we should proceed has if the program had been absent, or
|
|
||||||
# if --run hadn't been passed.
|
|
||||||
if test $? = 63; then
|
|
||||||
run=:
|
|
||||||
msg="probably too old"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
|
|
||||||
-h|--h|--he|--hel|--help)
|
|
||||||
echo "\
|
|
||||||
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
|
||||||
|
|
||||||
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
|
|
||||||
error status if there is no known handling for PROGRAM.
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-h, --help display this help and exit
|
|
||||||
-v, --version output version information and exit
|
|
||||||
--run try to run the given command, and emulate it if it fails
|
|
||||||
|
|
||||||
Supported PROGRAM values:
|
|
||||||
aclocal touch file \`aclocal.m4'
|
|
||||||
autoconf touch file \`configure'
|
|
||||||
autoheader touch file \`config.h.in'
|
|
||||||
automake touch all \`Makefile.in' files
|
|
||||||
bison create \`y.tab.[ch]', if possible, from existing .[ch]
|
|
||||||
flex create \`lex.yy.c', if possible, from existing .c
|
|
||||||
help2man touch the output file
|
|
||||||
lex create \`lex.yy.c', if possible, from existing .c
|
|
||||||
makeinfo touch the output file
|
|
||||||
tar try tar, gnutar, gtar, then tar without non-portable flags
|
|
||||||
yacc create \`y.tab.[ch]', if possible, from existing .[ch]
|
|
||||||
|
|
||||||
Send bug reports to <bug-automake@gnu.org>."
|
|
||||||
exit $?
|
|
||||||
;;
|
|
||||||
|
|
||||||
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
|
||||||
echo "missing $scriptversion (GNU Automake)"
|
|
||||||
exit $?
|
|
||||||
;;
|
|
||||||
|
|
||||||
-*)
|
|
||||||
echo 1>&2 "$0: Unknown \`$1' option"
|
|
||||||
echo 1>&2 "Try \`$0 --help' for more information"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Now exit if we have it, but it failed. Also exit now if we
|
|
||||||
# don't have it and --version was passed (most likely to detect
|
|
||||||
# the program).
|
|
||||||
case "$1" in
|
|
||||||
lex|yacc)
|
|
||||||
# Not GNU programs, they don't have --version.
|
|
||||||
;;
|
|
||||||
|
|
||||||
tar)
|
|
||||||
if test -n "$run"; then
|
|
||||||
echo 1>&2 "ERROR: \`tar' requires --run"
|
|
||||||
exit 1
|
|
||||||
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
|
||||||
# We have it, but it failed.
|
|
||||||
exit 1
|
|
||||||
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
|
|
||||||
# Could not run --version or --help. This is probably someone
|
|
||||||
# running `$TOOL --version' or `$TOOL --help' to check whether
|
|
||||||
# $TOOL exists and not knowing $TOOL uses missing.
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# If it does not exist, or fails to run (possibly an outdated version),
|
|
||||||
# try to emulate it.
|
|
||||||
case "$1" in
|
|
||||||
aclocal*)
|
|
||||||
echo 1>&2 "\
|
|
||||||
WARNING: \`$1' is $msg. You should only need it if
|
|
||||||
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
|
|
||||||
to install the \`Automake' and \`Perl' packages. Grab them from
|
|
||||||
any GNU archive site."
|
|
||||||
touch aclocal.m4
|
|
||||||
;;
|
|
||||||
|
|
||||||
autoconf)
|
|
||||||
echo 1>&2 "\
|
|
||||||
WARNING: \`$1' is $msg. You should only need it if
|
|
||||||
you modified \`${configure_ac}'. You might want to install the
|
|
||||||
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
|
|
||||||
archive site."
|
|
||||||
touch configure
|
|
||||||
;;
|
|
||||||
|
|
||||||
autoheader)
|
|
||||||
echo 1>&2 "\
|
|
||||||
WARNING: \`$1' is $msg. You should only need it if
|
|
||||||
you modified \`acconfig.h' or \`${configure_ac}'. You might want
|
|
||||||
to install the \`Autoconf' and \`GNU m4' packages. Grab them
|
|
||||||
from any GNU archive site."
|
|
||||||
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
|
|
||||||
test -z "$files" && files="config.h"
|
|
||||||
touch_files=
|
|
||||||
for f in $files; do
|
|
||||||
case "$f" in
|
|
||||||
*:*) touch_files="$touch_files "`echo "$f" |
|
|
||||||
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
|
|
||||||
*) touch_files="$touch_files $f.in";;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
touch $touch_files
|
|
||||||
;;
|
|
||||||
|
|
||||||
automake*)
|
|
||||||
echo 1>&2 "\
|
|
||||||
WARNING: \`$1' is $msg. You should only need it if
|
|
||||||
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
|
|
||||||
You might want to install the \`Automake' and \`Perl' packages.
|
|
||||||
Grab them from any GNU archive site."
|
|
||||||
find . -type f -name Makefile.am -print |
|
|
||||||
sed 's/\.am$/.in/' |
|
|
||||||
while read f; do touch "$f"; done
|
|
||||||
;;
|
|
||||||
|
|
||||||
autom4te)
|
|
||||||
echo 1>&2 "\
|
|
||||||
WARNING: \`$1' is needed, but is $msg.
|
|
||||||
You might have modified some files without having the
|
|
||||||
proper tools for further handling them.
|
|
||||||
You can get \`$1' as part of \`Autoconf' from any GNU
|
|
||||||
archive site."
|
|
||||||
|
|
||||||
file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
|
|
||||||
test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
|
|
||||||
if test -f "$file"; then
|
|
||||||
touch $file
|
|
||||||
else
|
|
||||||
test -z "$file" || exec >$file
|
|
||||||
echo "#! /bin/sh"
|
|
||||||
echo "# Created by GNU Automake missing as a replacement of"
|
|
||||||
echo "# $ $@"
|
|
||||||
echo "exit 0"
|
|
||||||
chmod +x $file
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
|
|
||||||
bison|yacc)
|
|
||||||
echo 1>&2 "\
|
|
||||||
WARNING: \`$1' $msg. You should only need it if
|
|
||||||
you modified a \`.y' file. You may need the \`Bison' package
|
|
||||||
in order for those modifications to take effect. You can get
|
|
||||||
\`Bison' from any GNU archive site."
|
|
||||||
rm -f y.tab.c y.tab.h
|
|
||||||
if [ $# -ne 1 ]; then
|
|
||||||
eval LASTARG="\${$#}"
|
|
||||||
case "$LASTARG" in
|
|
||||||
*.y)
|
|
||||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
|
|
||||||
if [ -f "$SRCFILE" ]; then
|
|
||||||
cp "$SRCFILE" y.tab.c
|
|
||||||
fi
|
|
||||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
|
|
||||||
if [ -f "$SRCFILE" ]; then
|
|
||||||
cp "$SRCFILE" y.tab.h
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
if [ ! -f y.tab.h ]; then
|
|
||||||
echo >y.tab.h
|
|
||||||
fi
|
|
||||||
if [ ! -f y.tab.c ]; then
|
|
||||||
echo 'main() { return 0; }' >y.tab.c
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
|
|
||||||
lex|flex)
|
|
||||||
echo 1>&2 "\
|
|
||||||
WARNING: \`$1' is $msg. You should only need it if
|
|
||||||
you modified a \`.l' file. You may need the \`Flex' package
|
|
||||||
in order for those modifications to take effect. You can get
|
|
||||||
\`Flex' from any GNU archive site."
|
|
||||||
rm -f lex.yy.c
|
|
||||||
if [ $# -ne 1 ]; then
|
|
||||||
eval LASTARG="\${$#}"
|
|
||||||
case "$LASTARG" in
|
|
||||||
*.l)
|
|
||||||
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
|
|
||||||
if [ -f "$SRCFILE" ]; then
|
|
||||||
cp "$SRCFILE" lex.yy.c
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
if [ ! -f lex.yy.c ]; then
|
|
||||||
echo 'main() { return 0; }' >lex.yy.c
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
|
|
||||||
help2man)
|
|
||||||
echo 1>&2 "\
|
|
||||||
WARNING: \`$1' is $msg. You should only need it if
|
|
||||||
you modified a dependency of a manual page. You may need the
|
|
||||||
\`Help2man' package in order for those modifications to take
|
|
||||||
effect. You can get \`Help2man' from any GNU archive site."
|
|
||||||
|
|
||||||
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
|
|
||||||
if test -z "$file"; then
|
|
||||||
file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
|
|
||||||
fi
|
|
||||||
if [ -f "$file" ]; then
|
|
||||||
touch $file
|
|
||||||
else
|
|
||||||
test -z "$file" || exec >$file
|
|
||||||
echo ".ab help2man is required to generate this page"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
|
|
||||||
makeinfo)
|
|
||||||
echo 1>&2 "\
|
|
||||||
WARNING: \`$1' is $msg. You should only need it if
|
|
||||||
you modified a \`.texi' or \`.texinfo' file, or any other file
|
|
||||||
indirectly affecting the aspect of the manual. The spurious
|
|
||||||
call might also be the consequence of using a buggy \`make' (AIX,
|
|
||||||
DU, IRIX). You might want to install the \`Texinfo' package or
|
|
||||||
the \`GNU make' package. Grab either from any GNU archive site."
|
|
||||||
# The file to touch is that specified with -o ...
|
|
||||||
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
|
|
||||||
if test -z "$file"; then
|
|
||||||
# ... or it is the one specified with @setfilename ...
|
|
||||||
infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
|
|
||||||
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile`
|
|
||||||
# ... or it is derived from the source name (dir/f.texi becomes f.info)
|
|
||||||
test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
|
|
||||||
fi
|
|
||||||
# If the file does not exist, the user really needs makeinfo;
|
|
||||||
# let's fail without touching anything.
|
|
||||||
test -f $file || exit 1
|
|
||||||
touch $file
|
|
||||||
;;
|
|
||||||
|
|
||||||
tar)
|
|
||||||
shift
|
|
||||||
|
|
||||||
# We have already tried tar in the generic part.
|
|
||||||
# Look for gnutar/gtar before invocation to avoid ugly error
|
|
||||||
# messages.
|
|
||||||
if (gnutar --version > /dev/null 2>&1); then
|
|
||||||
gnutar "$@" && exit 0
|
|
||||||
fi
|
|
||||||
if (gtar --version > /dev/null 2>&1); then
|
|
||||||
gtar "$@" && exit 0
|
|
||||||
fi
|
|
||||||
firstarg="$1"
|
|
||||||
if shift; then
|
|
||||||
case "$firstarg" in
|
|
||||||
*o*)
|
|
||||||
firstarg=`echo "$firstarg" | sed s/o//`
|
|
||||||
tar "$firstarg" "$@" && exit 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
case "$firstarg" in
|
|
||||||
*h*)
|
|
||||||
firstarg=`echo "$firstarg" | sed s/h//`
|
|
||||||
tar "$firstarg" "$@" && exit 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo 1>&2 "\
|
|
||||||
WARNING: I can't seem to be able to run \`tar' with the given arguments.
|
|
||||||
You may want to install GNU tar or Free paxutils, or check the
|
|
||||||
command line arguments."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
echo 1>&2 "\
|
|
||||||
WARNING: \`$1' is needed, and is $msg.
|
|
||||||
You might have modified some files without having the
|
|
||||||
proper tools for further handling them. Check the \`README' file,
|
|
||||||
it often tells you about the needed prerequisites for installing
|
|
||||||
this package. You may also peek at any GNU archive site, in case
|
|
||||||
some other package would contain this missing \`$1' program."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
|
|
||||||
# Local variables:
|
|
||||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
|
||||||
# time-stamp-start: "scriptversion="
|
|
||||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
|
||||||
# time-stamp-end: "$"
|
|
||||||
# End:
|
|
@ -1,158 +0,0 @@
|
|||||||
#! /bin/sh
|
|
||||||
# mkinstalldirs --- make directory hierarchy
|
|
||||||
|
|
||||||
scriptversion=2005-06-29.22
|
|
||||||
|
|
||||||
# Original author: Noah Friedman <friedman@prep.ai.mit.edu>
|
|
||||||
# Created: 1993-05-16
|
|
||||||
# Public domain.
|
|
||||||
#
|
|
||||||
# This file is maintained in Automake, please report
|
|
||||||
# bugs to <bug-automake@gnu.org> or send patches to
|
|
||||||
# <automake-patches@gnu.org>.
|
|
||||||
|
|
||||||
errstatus=0
|
|
||||||
dirmode=
|
|
||||||
|
|
||||||
usage="\
|
|
||||||
Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ...
|
|
||||||
|
|
||||||
Create each directory DIR (with mode MODE, if specified), including all
|
|
||||||
leading file name components.
|
|
||||||
|
|
||||||
Report bugs to <bug-automake@gnu.org>."
|
|
||||||
|
|
||||||
# process command line arguments
|
|
||||||
while test $# -gt 0 ; do
|
|
||||||
case $1 in
|
|
||||||
-h | --help | --h*) # -h for help
|
|
||||||
echo "$usage"
|
|
||||||
exit $?
|
|
||||||
;;
|
|
||||||
-m) # -m PERM arg
|
|
||||||
shift
|
|
||||||
test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
|
|
||||||
dirmode=$1
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
--version)
|
|
||||||
echo "$0 $scriptversion"
|
|
||||||
exit $?
|
|
||||||
;;
|
|
||||||
--) # stop option processing
|
|
||||||
shift
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
-*) # unknown option
|
|
||||||
echo "$usage" 1>&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
*) # first non-opt arg
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
for file
|
|
||||||
do
|
|
||||||
if test -d "$file"; then
|
|
||||||
shift
|
|
||||||
else
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
case $# in
|
|
||||||
0) exit 0 ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and
|
|
||||||
# mkdir -p a/c at the same time, both will detect that a is missing,
|
|
||||||
# one will create a, then the other will try to create a and die with
|
|
||||||
# a "File exists" error. This is a problem when calling mkinstalldirs
|
|
||||||
# from a parallel make. We use --version in the probe to restrict
|
|
||||||
# ourselves to GNU mkdir, which is thread-safe.
|
|
||||||
case $dirmode in
|
|
||||||
'')
|
|
||||||
if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
|
|
||||||
echo "mkdir -p -- $*"
|
|
||||||
exec mkdir -p -- "$@"
|
|
||||||
else
|
|
||||||
# On NextStep and OpenStep, the `mkdir' command does not
|
|
||||||
# recognize any option. It will interpret all options as
|
|
||||||
# directories to create, and then abort because `.' already
|
|
||||||
# exists.
|
|
||||||
test -d ./-p && rmdir ./-p
|
|
||||||
test -d ./--version && rmdir ./--version
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 &&
|
|
||||||
test ! -d ./--version; then
|
|
||||||
echo "mkdir -m $dirmode -p -- $*"
|
|
||||||
exec mkdir -m "$dirmode" -p -- "$@"
|
|
||||||
else
|
|
||||||
# Clean up after NextStep and OpenStep mkdir.
|
|
||||||
for d in ./-m ./-p ./--version "./$dirmode";
|
|
||||||
do
|
|
||||||
test -d $d && rmdir $d
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
for file
|
|
||||||
do
|
|
||||||
case $file in
|
|
||||||
/*) pathcomp=/ ;;
|
|
||||||
*) pathcomp= ;;
|
|
||||||
esac
|
|
||||||
oIFS=$IFS
|
|
||||||
IFS=/
|
|
||||||
set fnord $file
|
|
||||||
shift
|
|
||||||
IFS=$oIFS
|
|
||||||
|
|
||||||
for d
|
|
||||||
do
|
|
||||||
test "x$d" = x && continue
|
|
||||||
|
|
||||||
pathcomp=$pathcomp$d
|
|
||||||
case $pathcomp in
|
|
||||||
-*) pathcomp=./$pathcomp ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if test ! -d "$pathcomp"; then
|
|
||||||
echo "mkdir $pathcomp"
|
|
||||||
|
|
||||||
mkdir "$pathcomp" || lasterr=$?
|
|
||||||
|
|
||||||
if test ! -d "$pathcomp"; then
|
|
||||||
errstatus=$lasterr
|
|
||||||
else
|
|
||||||
if test ! -z "$dirmode"; then
|
|
||||||
echo "chmod $dirmode $pathcomp"
|
|
||||||
lasterr=
|
|
||||||
chmod "$dirmode" "$pathcomp" || lasterr=$?
|
|
||||||
|
|
||||||
if test ! -z "$lasterr"; then
|
|
||||||
errstatus=$lasterr
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
pathcomp=$pathcomp/
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
exit $errstatus
|
|
||||||
|
|
||||||
# Local Variables:
|
|
||||||
# mode: shell-script
|
|
||||||
# sh-indentation: 2
|
|
||||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
|
||||||
# time-stamp-start: "scriptversion="
|
|
||||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
|
||||||
# time-stamp-end: "$"
|
|
||||||
# End:
|
|
@ -1,74 +0,0 @@
|
|||||||
#!/bin/bash -e
|
|
||||||
|
|
||||||
# This takes one commandline argument, the name of the package. If no
|
|
||||||
# name is given, then we'll end up just using the name associated with
|
|
||||||
# an arbitrary .tar.gz file in the rootdir. That's fine: there's probably
|
|
||||||
# only one.
|
|
||||||
#
|
|
||||||
# Run this from the 'packages' directory, just under rootdir
|
|
||||||
|
|
||||||
## Set LIB to lib if exporting a library, empty-string else
|
|
||||||
LIB=
|
|
||||||
#LIB=lib
|
|
||||||
|
|
||||||
PACKAGE="$1"
|
|
||||||
VERSION="$2"
|
|
||||||
|
|
||||||
# We can only build Debian packages, if the Debian build tools are installed
|
|
||||||
if [ \! -x /usr/bin/debuild ]; then
|
|
||||||
echo "Cannot find /usr/bin/debuild. Not building Debian packages." 1>&2
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Double-check we're in the packages directory, just under rootdir
|
|
||||||
if [ \! -r ../Makefile -a \! -r ../INSTALL ]; then
|
|
||||||
echo "Must run $0 in the 'packages' directory, under the root directory." 1>&2
|
|
||||||
echo "Also, you must run \"make dist\" before running this script." 1>&2
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Find the top directory for this package
|
|
||||||
topdir="${PWD%/*}"
|
|
||||||
|
|
||||||
# Find the tar archive built by "make dist"
|
|
||||||
archive="${PACKAGE}-${VERSION}"
|
|
||||||
archive_with_underscore="${PACKAGE}_${VERSION}"
|
|
||||||
if [ -z "${archive}" ]; then
|
|
||||||
echo "Cannot find ../$PACKAGE*.tar.gz. Run \"make dist\" first." 1>&2
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create a pristine directory for building the Debian package files
|
|
||||||
trap 'rm -rf '`pwd`/tmp'; exit $?' EXIT SIGHUP SIGINT SIGTERM
|
|
||||||
|
|
||||||
rm -rf tmp
|
|
||||||
mkdir -p tmp
|
|
||||||
cd tmp
|
|
||||||
|
|
||||||
# Debian has very specific requirements about the naming of build
|
|
||||||
# directories, and tar archives. It also wants to write all generated
|
|
||||||
# packages to the parent of the source directory. We accommodate these
|
|
||||||
# requirements by building directly from the tar file.
|
|
||||||
ln -s "${topdir}/${archive}.tar.gz" "${LIB}${archive}.orig.tar.gz"
|
|
||||||
# Some version of debuilder want foo.orig.tar.gz with _ between versions.
|
|
||||||
ln -s "${topdir}/${archive}.tar.gz" "${LIB}${archive_with_underscore}.orig.tar.gz"
|
|
||||||
tar zfx "${LIB}${archive}.orig.tar.gz"
|
|
||||||
[ -n "${LIB}" ] && mv "${archive}" "${LIB}${archive}"
|
|
||||||
cd "${LIB}${archive}"
|
|
||||||
# This is one of those 'specific requirements': where the deb control files live
|
|
||||||
cp -a "packages/deb" "debian"
|
|
||||||
|
|
||||||
# Now, we can call Debian's standard build tool
|
|
||||||
debuild -uc -us
|
|
||||||
cd ../.. # get back to the original top-level dir
|
|
||||||
|
|
||||||
# We'll put the result in a subdirectory that's named after the OS version
|
|
||||||
# we've made this .deb file for.
|
|
||||||
destdir="debian-$(cat /etc/debian_version 2>/dev/null || echo UNKNOWN)"
|
|
||||||
|
|
||||||
rm -rf "$destdir"
|
|
||||||
mkdir -p "$destdir"
|
|
||||||
mv $(find tmp -mindepth 1 -maxdepth 1 -type f) "$destdir"
|
|
||||||
|
|
||||||
echo
|
|
||||||
echo "The Debian package files are located in $PWD/$destdir"
|
|
@ -1,7 +0,0 @@
|
|||||||
The list of files here isn't complete. For a step-by-step guide on
|
|
||||||
how to set this package up correctly, check out
|
|
||||||
http://www.debian.org/doc/maint-guide/
|
|
||||||
|
|
||||||
Most of the files that are in this directory are boilerplate.
|
|
||||||
However, you may need to change the list of binary-arch dependencies
|
|
||||||
in 'rules'.
|
|
@ -1,113 +0,0 @@
|
|||||||
sparsehash (1.6-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* New upstream release.
|
|
||||||
|
|
||||||
-- Google Inc. <opensource@google.com> Fri, 08 Jan 2010 14:47:55 -0800
|
|
||||||
|
|
||||||
sparsehash (1.5.2-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* New upstream release.
|
|
||||||
|
|
||||||
-- Google Inc. <opensource@google.com> Tue, 12 May 2009 14:16:38 -0700
|
|
||||||
|
|
||||||
sparsehash (1.5.1-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* New upstream release.
|
|
||||||
|
|
||||||
-- Google Inc. <opensource@google.com> Fri, 08 May 2009 15:23:44 -0700
|
|
||||||
|
|
||||||
sparsehash (1.5-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* New upstream release.
|
|
||||||
|
|
||||||
-- Google Inc. <opensource@google.com> Wed, 06 May 2009 11:28:49 -0700
|
|
||||||
|
|
||||||
sparsehash (1.4-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* New upstream release.
|
|
||||||
|
|
||||||
-- Google Inc. <opensource@google.com> Wed, 28 Jan 2009 17:11:31 -0800
|
|
||||||
|
|
||||||
sparsehash (1.3-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* New upstream release.
|
|
||||||
|
|
||||||
-- Google Inc. <opensource@google.com> Thu, 06 Nov 2008 15:06:09 -0800
|
|
||||||
|
|
||||||
sparsehash (1.2-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* New upstream release.
|
|
||||||
|
|
||||||
-- Google Inc. <opensource@google.com> Thu, 18 Sep 2008 13:53:20 -0700
|
|
||||||
|
|
||||||
sparsehash (1.1-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* New upstream release.
|
|
||||||
|
|
||||||
-- Google Inc. <opensource@google.com> Mon, 11 Feb 2008 16:30:11 -0800
|
|
||||||
|
|
||||||
sparsehash (1.0-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* New upstream release. We are now out of beta.
|
|
||||||
|
|
||||||
-- Google Inc. <opensource@google.com> Tue, 13 Nov 2007 15:15:46 -0800
|
|
||||||
|
|
||||||
sparsehash (0.9.1-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* New upstream release.
|
|
||||||
|
|
||||||
-- Google Inc. <opensource@google.com> Fri, 12 Oct 2007 12:35:24 -0700
|
|
||||||
|
|
||||||
sparsehash (0.9-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* New upstream release.
|
|
||||||
|
|
||||||
-- Google Inc. <opensource@google.com> Tue, 09 Oct 2007 14:15:21 -0700
|
|
||||||
|
|
||||||
sparsehash (0.8-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* New upstream release.
|
|
||||||
|
|
||||||
-- Google Inc. <opensource@google.com> Tue, 03 Jul 2007 12:55:04 -0700
|
|
||||||
|
|
||||||
sparsehash (0.7-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* New upstream release.
|
|
||||||
|
|
||||||
-- Google Inc. <opensource@google.com> Mon, 11 Jun 2007 11:33:41 -0700
|
|
||||||
|
|
||||||
sparsehash (0.6-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* New upstream release.
|
|
||||||
|
|
||||||
-- Google Inc. <opensource@google.com> Tue, 20 Mar 2007 17:29:34 -0700
|
|
||||||
|
|
||||||
sparsehash (0.5-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* New upstream release.
|
|
||||||
|
|
||||||
-- Google Inc. <opensource@google.com> Sat, 21 Oct 2006 13:47:47 -0700
|
|
||||||
|
|
||||||
sparsehash (0.4-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* New upstream release.
|
|
||||||
|
|
||||||
-- Google Inc. <opensource@google.com> Sun, 23 Apr 2006 22:42:35 -0700
|
|
||||||
|
|
||||||
sparsehash (0.3-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* New upstream release.
|
|
||||||
|
|
||||||
-- Google Inc. <opensource@google.com> Thu, 03 Nov 2005 20:12:31 -0800
|
|
||||||
|
|
||||||
sparsehash (0.2-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* New upstream release.
|
|
||||||
|
|
||||||
-- Google Inc. <opensource@google.com> Mon, 02 May 2005 07:04:46 -0700
|
|
||||||
|
|
||||||
sparsehash (0.1-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* Initial release.
|
|
||||||
|
|
||||||
-- Google Inc. <opensource@google.com> Tue, 15 Feb 2005 07:17:02 -0800
|
|
@ -1 +0,0 @@
|
|||||||
4
|
|
@ -1,17 +0,0 @@
|
|||||||
Source: sparsehash
|
|
||||||
Section: libdevel
|
|
||||||
Priority: optional
|
|
||||||
Maintainer: Google Inc. <opensource@google.com>
|
|
||||||
Build-Depends: debhelper (>= 4.0.0)
|
|
||||||
Standards-Version: 3.6.1
|
|
||||||
|
|
||||||
Package: sparsehash
|
|
||||||
Section: libs
|
|
||||||
Architecture: any
|
|
||||||
Description: hash_map and hash_set classes with minimal space overhead
|
|
||||||
This package contains several hash-map implementations, similar
|
|
||||||
in API to SGI's hash_map class, but with different performance
|
|
||||||
characteristics. sparse_hash_map uses very little space overhead: 1-2
|
|
||||||
bits per entry. dense_hash_map is typically faster than the default
|
|
||||||
SGI STL implementation. This package also includes hash-set analogues
|
|
||||||
of these classes.
|
|
@ -1,35 +0,0 @@
|
|||||||
This package was debianized by Google Inc. <opensource@google.com> on
|
|
||||||
15 February 2005.
|
|
||||||
|
|
||||||
It was downloaded from http://code.google.com/
|
|
||||||
|
|
||||||
Upstream Author: opensource@google.com
|
|
||||||
|
|
||||||
Copyright (c) 2005, Google Inc.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the name of Google Inc. nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,16 +0,0 @@
|
|||||||
AUTHORS
|
|
||||||
COPYING
|
|
||||||
ChangeLog
|
|
||||||
INSTALL
|
|
||||||
NEWS
|
|
||||||
README
|
|
||||||
TODO
|
|
||||||
doc/dense_hash_map.html
|
|
||||||
doc/dense_hash_set.html
|
|
||||||
doc/sparse_hash_map.html
|
|
||||||
doc/sparse_hash_set.html
|
|
||||||
doc/sparsetable.html
|
|
||||||
doc/implementation.html
|
|
||||||
doc/performance.html
|
|
||||||
doc/index.html
|
|
||||||
doc/designstyle.css
|
|
@ -1,117 +0,0 @@
|
|||||||
#!/usr/bin/make -f
|
|
||||||
# -*- makefile -*-
|
|
||||||
# Sample debian/rules that uses debhelper.
|
|
||||||
# This file was originally written by Joey Hess and Craig Small.
|
|
||||||
# As a special exception, when this file is copied by dh-make into a
|
|
||||||
# dh-make output file, you may use that output file without restriction.
|
|
||||||
# This special exception was added by Craig Small in version 0.37 of dh-make.
|
|
||||||
|
|
||||||
# Uncomment this to turn on verbose mode.
|
|
||||||
#export DH_VERBOSE=1
|
|
||||||
|
|
||||||
|
|
||||||
# These are used for cross-compiling and for saving the configure script
|
|
||||||
# from having to guess our platform (since we know it already)
|
|
||||||
DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
|
|
||||||
DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
|
|
||||||
|
|
||||||
|
|
||||||
CFLAGS = -Wall -g
|
|
||||||
|
|
||||||
ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
|
|
||||||
CFLAGS += -O0
|
|
||||||
else
|
|
||||||
CFLAGS += -O2
|
|
||||||
endif
|
|
||||||
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
|
||||||
INSTALL_PROGRAM += -s
|
|
||||||
endif
|
|
||||||
|
|
||||||
# shared library versions, option 1
|
|
||||||
#version=2.0.5
|
|
||||||
#major=2
|
|
||||||
# option 2, assuming the library is created as src/.libs/libfoo.so.2.0.5 or so
|
|
||||||
version=`ls src/.libs/lib*.so.* | \
|
|
||||||
awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'`
|
|
||||||
major=`ls src/.libs/lib*.so.* | \
|
|
||||||
awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'`
|
|
||||||
|
|
||||||
config.status: configure
|
|
||||||
dh_testdir
|
|
||||||
# Add here commands to configure the package.
|
|
||||||
CFLAGS="$(CFLAGS)" ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info
|
|
||||||
|
|
||||||
|
|
||||||
build: build-stamp
|
|
||||||
build-stamp: config.status
|
|
||||||
dh_testdir
|
|
||||||
|
|
||||||
# Add here commands to compile the package.
|
|
||||||
$(MAKE)
|
|
||||||
|
|
||||||
touch build-stamp
|
|
||||||
|
|
||||||
clean:
|
|
||||||
dh_testdir
|
|
||||||
dh_testroot
|
|
||||||
rm -f build-stamp
|
|
||||||
|
|
||||||
# Add here commands to clean up after the build process.
|
|
||||||
-$(MAKE) distclean
|
|
||||||
ifneq "$(wildcard /usr/share/misc/config.sub)" ""
|
|
||||||
cp -f /usr/share/misc/config.sub config.sub
|
|
||||||
endif
|
|
||||||
ifneq "$(wildcard /usr/share/misc/config.guess)" ""
|
|
||||||
cp -f /usr/share/misc/config.guess config.guess
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
dh_clean
|
|
||||||
|
|
||||||
install: build
|
|
||||||
dh_testdir
|
|
||||||
dh_testroot
|
|
||||||
dh_clean -k
|
|
||||||
dh_installdirs
|
|
||||||
|
|
||||||
# Add here commands to install the package into debian/tmp
|
|
||||||
$(MAKE) install DESTDIR=$(CURDIR)/debian/tmp
|
|
||||||
|
|
||||||
|
|
||||||
# Build architecture-independent files here.
|
|
||||||
binary-indep: build install
|
|
||||||
# We have nothing to do by default.
|
|
||||||
|
|
||||||
# Build architecture-dependent files here.
|
|
||||||
binary-arch: build install
|
|
||||||
dh_testdir
|
|
||||||
dh_testroot
|
|
||||||
dh_installchangelogs ChangeLog
|
|
||||||
dh_installdocs
|
|
||||||
dh_installexamples
|
|
||||||
dh_install --sourcedir=debian/tmp
|
|
||||||
# dh_installmenu
|
|
||||||
# dh_installdebconf
|
|
||||||
# dh_installlogrotate
|
|
||||||
# dh_installemacsen
|
|
||||||
# dh_installpam
|
|
||||||
# dh_installmime
|
|
||||||
# dh_installinit
|
|
||||||
# dh_installcron
|
|
||||||
# dh_installinfo
|
|
||||||
dh_installman
|
|
||||||
dh_link
|
|
||||||
dh_strip
|
|
||||||
dh_compress
|
|
||||||
dh_fixperms
|
|
||||||
# dh_perl
|
|
||||||
# dh_python
|
|
||||||
dh_makeshlibs
|
|
||||||
dh_installdeb
|
|
||||||
dh_shlibdeps
|
|
||||||
dh_gencontrol
|
|
||||||
dh_md5sums
|
|
||||||
dh_builddeb
|
|
||||||
|
|
||||||
binary: binary-indep binary-arch
|
|
||||||
.PHONY: build clean binary-indep binary-arch binary install
|
|
@ -1,2 +0,0 @@
|
|||||||
usr/include
|
|
||||||
usr/include/google
|
|
@ -1,2 +0,0 @@
|
|||||||
usr/include/google/*
|
|
||||||
debian/tmp/usr/include/google/*
|
|
@ -1,86 +0,0 @@
|
|||||||
#!/bin/sh -e
|
|
||||||
|
|
||||||
# Run this from the 'packages' directory, just under rootdir
|
|
||||||
|
|
||||||
# We can only build rpm packages, if the rpm build tools are installed
|
|
||||||
if [ \! -x /usr/bin/rpmbuild ]
|
|
||||||
then
|
|
||||||
echo "Cannot find /usr/bin/rpmbuild. Not building an rpm." 1>&2
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check the commandline flags
|
|
||||||
PACKAGE="$1"
|
|
||||||
VERSION="$2"
|
|
||||||
fullname="${PACKAGE}-${VERSION}"
|
|
||||||
archive=../$fullname.tar.gz
|
|
||||||
|
|
||||||
if [ -z "$1" -o -z "$2" ]
|
|
||||||
then
|
|
||||||
echo "Usage: $0 <package name> <package version>" 1>&2
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Double-check we're in the packages directory, just under rootdir
|
|
||||||
if [ \! -r ../Makefile -a \! -r ../INSTALL ]
|
|
||||||
then
|
|
||||||
echo "Must run $0 in the 'packages' directory, under the root directory." 1>&2
|
|
||||||
echo "Also, you must run \"make dist\" before running this script." 1>&2
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ \! -r "$archive" ]
|
|
||||||
then
|
|
||||||
echo "Cannot find $archive. Run \"make dist\" first." 1>&2
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create the directory where the input lives, and where the output should live
|
|
||||||
RPM_SOURCE_DIR="/tmp/rpmsource-$fullname"
|
|
||||||
RPM_BUILD_DIR="/tmp/rpmbuild-$fullname"
|
|
||||||
|
|
||||||
trap 'rm -rf $RPM_SOURCE_DIR $RPM_BUILD_DIR; exit $?' EXIT SIGHUP SIGINT SIGTERM
|
|
||||||
|
|
||||||
rm -rf "$RPM_SOURCE_DIR" "$RPM_BUILD_DIR"
|
|
||||||
mkdir "$RPM_SOURCE_DIR"
|
|
||||||
mkdir "$RPM_BUILD_DIR"
|
|
||||||
|
|
||||||
cp "$archive" "$RPM_SOURCE_DIR"
|
|
||||||
|
|
||||||
# rpmbuild -- as far as I can tell -- asks the OS what CPU it has.
|
|
||||||
# This may differ from what kind of binaries gcc produces. dpkg
|
|
||||||
# does a better job of this, so if we can run 'dpkg --print-architecture'
|
|
||||||
# to get the build CPU, we use that in preference of the rpmbuild
|
|
||||||
# default.
|
|
||||||
target=`dpkg --print-architecture 2>/dev/null` # "" if dpkg isn't found
|
|
||||||
if [ -n "$target" ]
|
|
||||||
then
|
|
||||||
target=" --target $target"
|
|
||||||
fi
|
|
||||||
|
|
||||||
rpmbuild -bb rpm/rpm.spec $target \
|
|
||||||
--define "NAME $PACKAGE" \
|
|
||||||
--define "VERSION $VERSION" \
|
|
||||||
--define "_sourcedir $RPM_SOURCE_DIR" \
|
|
||||||
--define "_builddir $RPM_BUILD_DIR" \
|
|
||||||
--define "_rpmdir $RPM_SOURCE_DIR"
|
|
||||||
|
|
||||||
# We put the output in a directory based on what system we've built for
|
|
||||||
destdir=rpm-unknown
|
|
||||||
if [ -r /etc/issue ]
|
|
||||||
then
|
|
||||||
grep "Red Hat.*release 7" /etc/issue >/dev/null 2>&1 && destdir=rh7
|
|
||||||
grep "Red Hat.*release 8" /etc/issue >/dev/null 2>&1 && destdir=rh8
|
|
||||||
grep "Red Hat.*release 9" /etc/issue >/dev/null 2>&1 && destdir=rh9
|
|
||||||
grep "Fedora Core.*release 1" /etc/issue >/dev/null 2>&1 && destdir=fc1
|
|
||||||
grep "Fedora Core.*release 2" /etc/issue >/dev/null 2>&1 && destdir=fc2
|
|
||||||
grep "Fedora Core.*release 3" /etc/issue >/dev/null 2>&1 && destdir=fc3
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -rf "$destdir"
|
|
||||||
mkdir -p "$destdir"
|
|
||||||
# We want to get not only the main package but devel etc, hence the middle *
|
|
||||||
mv "$RPM_SOURCE_DIR"/*/"${PACKAGE}"-*"${VERSION}"*.rpm "$destdir"
|
|
||||||
|
|
||||||
echo
|
|
||||||
echo "The rpm package file(s) are located in $PWD/$destdir"
|
|
@ -1,61 +0,0 @@
|
|||||||
%define RELEASE 1
|
|
||||||
%define rel %{?CUSTOM_RELEASE} %{!?CUSTOM_RELEASE:%RELEASE}
|
|
||||||
%define prefix /usr
|
|
||||||
|
|
||||||
Name: %NAME
|
|
||||||
Summary: hash_map and hash_set classes with minimal space overhead
|
|
||||||
Version: %VERSION
|
|
||||||
Release: %rel
|
|
||||||
Group: Development/Libraries
|
|
||||||
URL: http://code.google.com/p/google-sparsehash
|
|
||||||
License: BSD
|
|
||||||
Vendor: Google
|
|
||||||
Packager: Google <opensource@google.com>
|
|
||||||
Source: http://%{NAME}.googlecode.com/files/%{NAME}-%{VERSION}.tar.gz
|
|
||||||
Distribution: Redhat 7 and above.
|
|
||||||
Buildroot: %{_tmppath}/%{name}-root
|
|
||||||
Prefix: %prefix
|
|
||||||
Buildarch: noarch
|
|
||||||
|
|
||||||
%description
|
|
||||||
The %name package contains several hash-map implementations, similar
|
|
||||||
in API to the SGI hash_map class, but with different performance
|
|
||||||
characteristics. sparse_hash_map uses very little space overhead: 1-2
|
|
||||||
bits per entry. dense_hash_map is typically faster than the default
|
|
||||||
SGI STL implementation. This package also includes hash-set analogues
|
|
||||||
of these classes.
|
|
||||||
|
|
||||||
%changelog
|
|
||||||
* Wed Apr 22 2009 <opensource@google.com>
|
|
||||||
- Change build rule to use %configure instead of ./configure
|
|
||||||
- Change install to use DESTDIR instead of prefix for make install
|
|
||||||
- Use wildcards for doc/ and lib/ directories
|
|
||||||
- Use {_includedir} instead of {prefix}/include
|
|
||||||
|
|
||||||
* Fri Jan 14 2005 <opensource@google.com>
|
|
||||||
- First draft
|
|
||||||
|
|
||||||
%prep
|
|
||||||
%setup
|
|
||||||
|
|
||||||
%build
|
|
||||||
# I can't use '% configure', because it defines -m32 which breaks on
|
|
||||||
# my development environment for some reason. But I do take
|
|
||||||
# as much from % configure (in /usr/lib/rpm/macros) as I can.
|
|
||||||
./configure --prefix=%{_prefix} --exec-prefix=%{_exec_prefix} --bindir=%{_bindir} --sbindir=%{_sbindir} --sysconfdir=%{_sysconfdir} --datadir=%{_datadir} --includedir=%{_includedir} --libdir=%{_libdir} --libexecdir=%{_libexecdir} --localstatedir=%{_localstatedir} --sharedstatedir=%{_sharedstatedir} --mandir=%{_mandir} --infodir=%{_infodir}
|
|
||||||
make
|
|
||||||
|
|
||||||
%install
|
|
||||||
rm -rf $RPM_BUILD_ROOT
|
|
||||||
make DESTDIR=$RPM_BUILD_ROOT install
|
|
||||||
|
|
||||||
%clean
|
|
||||||
rm -rf $RPM_BUILD_ROOT
|
|
||||||
|
|
||||||
%files
|
|
||||||
%defattr(-,root,root)
|
|
||||||
|
|
||||||
%docdir %{prefix}/share/doc/%{NAME}-%{VERSION}
|
|
||||||
%{prefix}/share/doc/%{NAME}-%{VERSION}/*
|
|
||||||
|
|
||||||
%{_includedir}/google
|
|
Binary file not shown.
Binary file not shown.
@ -1,132 +0,0 @@
|
|||||||
/* src/config.h. Generated from config.h.in by configure. */
|
|
||||||
/* src/config.h.in. Generated from configure.ac by autoheader. */
|
|
||||||
|
|
||||||
/* Namespace for Google classes */
|
|
||||||
#define GOOGLE_NAMESPACE ::google
|
|
||||||
|
|
||||||
/* the location of the header defining hash functions */
|
|
||||||
#define HASH_FUN_H <tr1/functional>
|
|
||||||
|
|
||||||
/* the location of <unordered_map> or <hash_map> */
|
|
||||||
#define HASH_MAP_H <tr1/unordered_map>
|
|
||||||
|
|
||||||
/* the namespace of the hash<> function */
|
|
||||||
#define HASH_NAMESPACE std::tr1
|
|
||||||
|
|
||||||
/* the location of <unordered_set> or <hash_set> */
|
|
||||||
#define HASH_SET_H <tr1/unordered_set>
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <google/malloc_extension.h> header file. */
|
|
||||||
/* #undef HAVE_GOOGLE_MALLOC_EXTENSION_H */
|
|
||||||
|
|
||||||
/* define if the compiler has hash_map */
|
|
||||||
#define HAVE_HASH_MAP 1
|
|
||||||
|
|
||||||
/* define if the compiler has hash_set */
|
|
||||||
#define HAVE_HASH_SET 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
|
||||||
#define HAVE_INTTYPES_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `long long'. */
|
|
||||||
#define HAVE_LONG_LONG 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `memcpy' function. */
|
|
||||||
#define HAVE_MEMCPY 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `memmove' function. */
|
|
||||||
#define HAVE_MEMMOVE 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <memory.h> header file. */
|
|
||||||
#define HAVE_MEMORY_H 1
|
|
||||||
|
|
||||||
/* define if the compiler implements namespaces */
|
|
||||||
#define HAVE_NAMESPACES 1
|
|
||||||
|
|
||||||
/* Define if you have POSIX threads libraries and header files. */
|
|
||||||
/* #undef HAVE_PTHREAD */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
|
||||||
#define HAVE_STDINT_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 <strings.h> header file. */
|
|
||||||
#define HAVE_STRINGS_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <string.h> header file. */
|
|
||||||
#define HAVE_STRING_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/resource.h> header file. */
|
|
||||||
#define HAVE_SYS_RESOURCE_H 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/time.h> header file. */
|
|
||||||
#define HAVE_SYS_TIME_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 the <sys/utsname.h> header file. */
|
|
||||||
#define HAVE_SYS_UTSNAME_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uint16_t'. */
|
|
||||||
#define HAVE_UINT16_T 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
|
||||||
#define HAVE_UNISTD_H 1
|
|
||||||
|
|
||||||
/* define if the compiler supports unordered_{map,set} */
|
|
||||||
#define HAVE_UNORDERED_MAP 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `u_int16_t'. */
|
|
||||||
#define HAVE_U_INT16_T 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `__uint16'. */
|
|
||||||
/* #undef HAVE___UINT16 */
|
|
||||||
|
|
||||||
/* Name of package */
|
|
||||||
#define PACKAGE "sparsehash"
|
|
||||||
|
|
||||||
/* Define to the address where bug reports for this package should be sent. */
|
|
||||||
#define PACKAGE_BUGREPORT "opensource@google.com"
|
|
||||||
|
|
||||||
/* Define to the full name of this package. */
|
|
||||||
#define PACKAGE_NAME "sparsehash"
|
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
|
||||||
#define PACKAGE_STRING "sparsehash 1.6"
|
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
|
||||||
#define PACKAGE_TARNAME "sparsehash"
|
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
|
||||||
#define PACKAGE_VERSION "1.6"
|
|
||||||
|
|
||||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
|
||||||
your system. */
|
|
||||||
/* #undef PTHREAD_CREATE_JOINABLE */
|
|
||||||
|
|
||||||
/* The system-provided hash function including the namespace. */
|
|
||||||
#define SPARSEHASH_HASH HASH_NAMESPACE::hash
|
|
||||||
|
|
||||||
/* The system-provided hash function, in namespace HASH_NAMESPACE. */
|
|
||||||
#define SPARSEHASH_HASH_NO_NAMESPACE hash
|
|
||||||
|
|
||||||
/* Define to 1 if you have the ANSI C header files. */
|
|
||||||
#define STDC_HEADERS 1
|
|
||||||
|
|
||||||
/* the namespace where STL code like vector<> is defined */
|
|
||||||
#define STL_NAMESPACE std
|
|
||||||
|
|
||||||
/* Version number of package */
|
|
||||||
#define VERSION "1.6"
|
|
||||||
|
|
||||||
/* Stops putting the code inside the Google namespace */
|
|
||||||
#define _END_GOOGLE_NAMESPACE_ }
|
|
||||||
|
|
||||||
/* Puts following code inside the Google namespace */
|
|
||||||
#define _START_GOOGLE_NAMESPACE_ namespace google {
|
|
@ -1,131 +0,0 @@
|
|||||||
/* src/config.h.in. Generated from configure.ac by autoheader. */
|
|
||||||
|
|
||||||
/* Namespace for Google classes */
|
|
||||||
#undef GOOGLE_NAMESPACE
|
|
||||||
|
|
||||||
/* the location of the header defining hash functions */
|
|
||||||
#undef HASH_FUN_H
|
|
||||||
|
|
||||||
/* the location of <unordered_map> or <hash_map> */
|
|
||||||
#undef HASH_MAP_H
|
|
||||||
|
|
||||||
/* the namespace of the hash<> function */
|
|
||||||
#undef HASH_NAMESPACE
|
|
||||||
|
|
||||||
/* the location of <unordered_set> or <hash_set> */
|
|
||||||
#undef HASH_SET_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <google/malloc_extension.h> header file. */
|
|
||||||
#undef HAVE_GOOGLE_MALLOC_EXTENSION_H
|
|
||||||
|
|
||||||
/* define if the compiler has hash_map */
|
|
||||||
#undef HAVE_HASH_MAP
|
|
||||||
|
|
||||||
/* define if the compiler has hash_set */
|
|
||||||
#undef HAVE_HASH_SET
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
|
||||||
#undef HAVE_INTTYPES_H
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `long long'. */
|
|
||||||
#undef HAVE_LONG_LONG
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `memcpy' function. */
|
|
||||||
#undef HAVE_MEMCPY
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `memmove' function. */
|
|
||||||
#undef HAVE_MEMMOVE
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <memory.h> header file. */
|
|
||||||
#undef HAVE_MEMORY_H
|
|
||||||
|
|
||||||
/* define if the compiler implements namespaces */
|
|
||||||
#undef HAVE_NAMESPACES
|
|
||||||
|
|
||||||
/* Define if you have POSIX threads libraries and header files. */
|
|
||||||
#undef HAVE_PTHREAD
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
|
||||||
#undef HAVE_STDINT_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
|
||||||
#undef HAVE_STDLIB_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <strings.h> header file. */
|
|
||||||
#undef HAVE_STRINGS_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <string.h> header file. */
|
|
||||||
#undef HAVE_STRING_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/resource.h> header file. */
|
|
||||||
#undef HAVE_SYS_RESOURCE_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
|
||||||
#undef HAVE_SYS_STAT_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
|
||||||
#undef HAVE_SYS_TIME_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
|
||||||
#undef HAVE_SYS_TYPES_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/utsname.h> header file. */
|
|
||||||
#undef HAVE_SYS_UTSNAME_H
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uint16_t'. */
|
|
||||||
#undef HAVE_UINT16_T
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
|
||||||
#undef HAVE_UNISTD_H
|
|
||||||
|
|
||||||
/* define if the compiler supports unordered_{map,set} */
|
|
||||||
#undef HAVE_UNORDERED_MAP
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `u_int16_t'. */
|
|
||||||
#undef HAVE_U_INT16_T
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `__uint16'. */
|
|
||||||
#undef HAVE___UINT16
|
|
||||||
|
|
||||||
/* Name of package */
|
|
||||||
#undef PACKAGE
|
|
||||||
|
|
||||||
/* Define to the address where bug reports for this package should be sent. */
|
|
||||||
#undef PACKAGE_BUGREPORT
|
|
||||||
|
|
||||||
/* Define to the full name of this package. */
|
|
||||||
#undef PACKAGE_NAME
|
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
|
||||||
#undef PACKAGE_STRING
|
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
|
||||||
#undef PACKAGE_TARNAME
|
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
|
||||||
#undef PACKAGE_VERSION
|
|
||||||
|
|
||||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
|
||||||
your system. */
|
|
||||||
#undef PTHREAD_CREATE_JOINABLE
|
|
||||||
|
|
||||||
/* The system-provided hash function including the namespace. */
|
|
||||||
#undef SPARSEHASH_HASH
|
|
||||||
|
|
||||||
/* The system-provided hash function, in namespace HASH_NAMESPACE. */
|
|
||||||
#undef SPARSEHASH_HASH_NO_NAMESPACE
|
|
||||||
|
|
||||||
/* Define to 1 if you have the ANSI C header files. */
|
|
||||||
#undef STDC_HEADERS
|
|
||||||
|
|
||||||
/* the namespace where STL code like vector<> is defined */
|
|
||||||
#undef STL_NAMESPACE
|
|
||||||
|
|
||||||
/* Version number of package */
|
|
||||||
#undef VERSION
|
|
||||||
|
|
||||||
/* Stops putting the code inside the Google namespace */
|
|
||||||
#undef _END_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
/* Puts following code inside the Google namespace */
|
|
||||||
#undef _START_GOOGLE_NAMESPACE_
|
|
@ -1,23 +0,0 @@
|
|||||||
/***
|
|
||||||
*** These are #defines that autoheader puts in config.h.in that we
|
|
||||||
*** want to show up in sparseconfig.h, the minimal config.h file
|
|
||||||
*** #included by all our .h files. The reason we don't take
|
|
||||||
*** everything that autoheader emits is that we have to include a
|
|
||||||
*** config.h in installed header files, and we want to minimize the
|
|
||||||
*** number of #defines we make so as to not pollute the namespace.
|
|
||||||
***/
|
|
||||||
GOOGLE_NAMESPACE
|
|
||||||
HASH_NAMESPACE
|
|
||||||
HASH_FUN_H
|
|
||||||
SPARSEHASH_HASH
|
|
||||||
HAVE_UINT16_T
|
|
||||||
HAVE_U_INT16_T
|
|
||||||
HAVE___UINT16
|
|
||||||
HAVE_LONG_LONG
|
|
||||||
HAVE_SYS_TYPES_H
|
|
||||||
HAVE_STDINT_H
|
|
||||||
HAVE_INTTYPES_H
|
|
||||||
HAVE_MEMCPY
|
|
||||||
STL_NAMESPACE
|
|
||||||
_END_GOOGLE_NAMESPACE_
|
|
||||||
_START_GOOGLE_NAMESPACE_
|
|
@ -1,319 +0,0 @@
|
|||||||
// Copyright (c) 2005, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// Author: Craig Silverstein
|
|
||||||
//
|
|
||||||
// This is just a very thin wrapper over densehashtable.h, just
|
|
||||||
// like sgi stl's stl_hash_map is a very thin wrapper over
|
|
||||||
// stl_hashtable. The major thing we define is operator[], because
|
|
||||||
// we have a concept of a data_type which stl_hashtable doesn't
|
|
||||||
// (it only has a key and a value).
|
|
||||||
//
|
|
||||||
// NOTE: this is exactly like sparse_hash_map.h, with the word
|
|
||||||
// "sparse" replaced by "dense", except for the addition of
|
|
||||||
// set_empty_key().
|
|
||||||
//
|
|
||||||
// YOU MUST CALL SET_EMPTY_KEY() IMMEDIATELY AFTER CONSTRUCTION.
|
|
||||||
//
|
|
||||||
// Otherwise your program will die in mysterious ways.
|
|
||||||
//
|
|
||||||
// In other respects, we adhere mostly to the STL semantics for
|
|
||||||
// hash-map. One important exception is that insert() may invalidate
|
|
||||||
// iterators entirely -- STL semantics are that insert() may reorder
|
|
||||||
// iterators, but they all still refer to something valid in the
|
|
||||||
// hashtable. Not so for us. Likewise, insert() may invalidate
|
|
||||||
// pointers into the hashtable. (Whether insert invalidates iterators
|
|
||||||
// and pointers depends on whether it results in a hashtable resize).
|
|
||||||
// On the plus side, delete() doesn't invalidate iterators or pointers
|
|
||||||
// at all, or even change the ordering of elements.
|
|
||||||
//
|
|
||||||
// Here are a few "power user" tips:
|
|
||||||
//
|
|
||||||
// 1) set_deleted_key():
|
|
||||||
// If you want to use erase() you *must* call set_deleted_key(),
|
|
||||||
// in addition to set_empty_key(), after construction.
|
|
||||||
// The deleted and empty keys must differ.
|
|
||||||
//
|
|
||||||
// 2) resize(0):
|
|
||||||
// When an item is deleted, its memory isn't freed right
|
|
||||||
// away. This allows you to iterate over a hashtable,
|
|
||||||
// and call erase(), without invalidating the iterator.
|
|
||||||
// To force the memory to be freed, call resize(0).
|
|
||||||
// For tr1 compatibility, this can also be called as rehash(0).
|
|
||||||
//
|
|
||||||
// 3) min_load_factor(0.0)
|
|
||||||
// Setting the minimum load factor to 0.0 guarantees that
|
|
||||||
// the hash table will never shrink.
|
|
||||||
//
|
|
||||||
// Roughly speaking:
|
|
||||||
// (1) dense_hash_map: fastest, uses the most memory unless entries are small
|
|
||||||
// (2) sparse_hash_map: slowest, uses the least memory
|
|
||||||
// (3) hash_map / unordered_map (STL): in the middle
|
|
||||||
//
|
|
||||||
// Typically I use sparse_hash_map when I care about space and/or when
|
|
||||||
// I need to save the hashtable on disk. I use hash_map otherwise. I
|
|
||||||
// don't personally use dense_hash_set ever; some people use it for
|
|
||||||
// small sets with lots of lookups.
|
|
||||||
//
|
|
||||||
// - dense_hash_map has, typically, about 78% memory overhead (if your
|
|
||||||
// data takes up X bytes, the hash_map uses .78X more bytes in overhead).
|
|
||||||
// - sparse_hash_map has about 4 bits overhead per entry.
|
|
||||||
// - sparse_hash_map can be 3-7 times slower than the others for lookup and,
|
|
||||||
// especially, inserts. See time_hash_map.cc for details.
|
|
||||||
//
|
|
||||||
// See /usr/(local/)?doc/sparsehash-*/dense_hash_map.html
|
|
||||||
// for information about how to use this class.
|
|
||||||
|
|
||||||
#ifndef _DENSE_HASH_MAP_H_
|
|
||||||
#define _DENSE_HASH_MAP_H_
|
|
||||||
|
|
||||||
#include <google/sparsehash/sparseconfig.h>
|
|
||||||
#include <stdio.h> // for FILE * in read()/write()
|
|
||||||
#include <algorithm> // for the default template args
|
|
||||||
#include <functional> // for equal_to
|
|
||||||
#include <memory> // for alloc<>
|
|
||||||
#include <utility> // for pair<>
|
|
||||||
#include HASH_FUN_H // defined in config.h
|
|
||||||
#include <google/sparsehash/densehashtable.h>
|
|
||||||
|
|
||||||
|
|
||||||
_START_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
using STL_NAMESPACE::pair;
|
|
||||||
|
|
||||||
template <class Key, class T,
|
|
||||||
class HashFcn = SPARSEHASH_HASH<Key>, // defined in sparseconfig.h
|
|
||||||
class EqualKey = STL_NAMESPACE::equal_to<Key>,
|
|
||||||
class Alloc = STL_NAMESPACE::allocator<T> >
|
|
||||||
class dense_hash_map {
|
|
||||||
private:
|
|
||||||
// Apparently select1st is not stl-standard, so we define our own
|
|
||||||
struct SelectKey {
|
|
||||||
const Key& operator()(const pair<const Key, T>& p) const {
|
|
||||||
return p.first;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
struct SetKey {
|
|
||||||
void operator()(pair<const Key, T>* value, const Key& new_key) const {
|
|
||||||
*const_cast<Key*>(&value->first) = new_key;
|
|
||||||
// It would be nice to clear the rest of value here as well, in
|
|
||||||
// case it's taking up a lot of memory. We do this by clearing
|
|
||||||
// the value. This assumes T has a zero-arg constructor!
|
|
||||||
value->second = T();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// The actual data
|
|
||||||
typedef dense_hashtable<pair<const Key, T>, Key, HashFcn,
|
|
||||||
SelectKey, SetKey, EqualKey, Alloc> ht;
|
|
||||||
ht rep;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef typename ht::key_type key_type;
|
|
||||||
typedef T data_type;
|
|
||||||
typedef T mapped_type;
|
|
||||||
typedef typename ht::value_type value_type;
|
|
||||||
typedef typename ht::hasher hasher;
|
|
||||||
typedef typename ht::key_equal key_equal;
|
|
||||||
typedef Alloc allocator_type;
|
|
||||||
|
|
||||||
typedef typename ht::size_type size_type;
|
|
||||||
typedef typename ht::difference_type difference_type;
|
|
||||||
typedef typename ht::pointer pointer;
|
|
||||||
typedef typename ht::const_pointer const_pointer;
|
|
||||||
typedef typename ht::reference reference;
|
|
||||||
typedef typename ht::const_reference const_reference;
|
|
||||||
|
|
||||||
typedef typename ht::iterator iterator;
|
|
||||||
typedef typename ht::const_iterator const_iterator;
|
|
||||||
typedef typename ht::local_iterator local_iterator;
|
|
||||||
typedef typename ht::const_local_iterator const_local_iterator;
|
|
||||||
|
|
||||||
// Iterator functions
|
|
||||||
iterator begin() { return rep.begin(); }
|
|
||||||
iterator end() { return rep.end(); }
|
|
||||||
const_iterator begin() const { return rep.begin(); }
|
|
||||||
const_iterator end() const { return rep.end(); }
|
|
||||||
|
|
||||||
|
|
||||||
// These come from tr1's unordered_map. For us, a bucket has 0 or 1 elements.
|
|
||||||
local_iterator begin(size_type i) { return rep.begin(i); }
|
|
||||||
local_iterator end(size_type i) { return rep.end(i); }
|
|
||||||
const_local_iterator begin(size_type i) const { return rep.begin(i); }
|
|
||||||
const_local_iterator end(size_type i) const { return rep.end(i); }
|
|
||||||
|
|
||||||
// Accessor functions
|
|
||||||
// TODO(csilvers): implement Alloc get_allocator() const;
|
|
||||||
hasher hash_funct() const { return rep.hash_funct(); }
|
|
||||||
hasher hash_function() const { return hash_funct(); }
|
|
||||||
key_equal key_eq() const { return rep.key_eq(); }
|
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
explicit dense_hash_map(size_type expected_max_items_in_table = 0,
|
|
||||||
const hasher& hf = hasher(),
|
|
||||||
const key_equal& eql = key_equal())
|
|
||||||
: rep(expected_max_items_in_table, hf, eql) { }
|
|
||||||
|
|
||||||
template <class InputIterator>
|
|
||||||
dense_hash_map(InputIterator f, InputIterator l,
|
|
||||||
size_type expected_max_items_in_table = 0,
|
|
||||||
const hasher& hf = hasher(),
|
|
||||||
const key_equal& eql = key_equal())
|
|
||||||
: rep(expected_max_items_in_table, hf, eql) {
|
|
||||||
rep.insert(f, l);
|
|
||||||
}
|
|
||||||
// We use the default copy constructor
|
|
||||||
// We use the default operator=()
|
|
||||||
// We use the default destructor
|
|
||||||
|
|
||||||
void clear() { rep.clear(); }
|
|
||||||
// This clears the hash map without resizing it down to the minimum
|
|
||||||
// bucket count, but rather keeps the number of buckets constant
|
|
||||||
void clear_no_resize() { rep.clear_no_resize(); }
|
|
||||||
void swap(dense_hash_map& hs) { rep.swap(hs.rep); }
|
|
||||||
|
|
||||||
|
|
||||||
// Functions concerning size
|
|
||||||
size_type size() const { return rep.size(); }
|
|
||||||
size_type max_size() const { return rep.max_size(); }
|
|
||||||
bool empty() const { return rep.empty(); }
|
|
||||||
size_type bucket_count() const { return rep.bucket_count(); }
|
|
||||||
size_type max_bucket_count() const { return rep.max_bucket_count(); }
|
|
||||||
|
|
||||||
// These are tr1 methods. bucket() is the bucket the key is or would be in.
|
|
||||||
size_type bucket_size(size_type i) const { return rep.bucket_size(i); }
|
|
||||||
size_type bucket(const key_type& key) const { return rep.bucket(key); }
|
|
||||||
float load_factor() const {
|
|
||||||
return size() * 1.0f / bucket_count();
|
|
||||||
}
|
|
||||||
float max_load_factor() const {
|
|
||||||
float shrink, grow;
|
|
||||||
rep.get_resizing_parameters(&shrink, &grow);
|
|
||||||
return grow;
|
|
||||||
}
|
|
||||||
void max_load_factor(float new_grow) {
|
|
||||||
float shrink, grow;
|
|
||||||
rep.get_resizing_parameters(&shrink, &grow);
|
|
||||||
rep.set_resizing_parameters(shrink, new_grow);
|
|
||||||
}
|
|
||||||
// These aren't tr1 methods but perhaps ought to be.
|
|
||||||
float min_load_factor() const {
|
|
||||||
float shrink, grow;
|
|
||||||
rep.get_resizing_parameters(&shrink, &grow);
|
|
||||||
return shrink;
|
|
||||||
}
|
|
||||||
void min_load_factor(float new_shrink) {
|
|
||||||
float shrink, grow;
|
|
||||||
rep.get_resizing_parameters(&shrink, &grow);
|
|
||||||
rep.set_resizing_parameters(new_shrink, grow);
|
|
||||||
}
|
|
||||||
// Deprecated; use min_load_factor() or max_load_factor() instead.
|
|
||||||
void set_resizing_parameters(float shrink, float grow) {
|
|
||||||
return rep.set_resizing_parameters(shrink, grow);
|
|
||||||
}
|
|
||||||
|
|
||||||
void resize(size_type hint) { rep.resize(hint); }
|
|
||||||
void rehash(size_type hint) { resize(hint); } // the tr1 name
|
|
||||||
|
|
||||||
// Lookup routines
|
|
||||||
iterator find(const key_type& key) { return rep.find(key); }
|
|
||||||
const_iterator find(const key_type& key) const { return rep.find(key); }
|
|
||||||
|
|
||||||
data_type& operator[](const key_type& key) { // This is our value-add!
|
|
||||||
iterator it = find(key);
|
|
||||||
if (it != end()) {
|
|
||||||
return it->second;
|
|
||||||
} else {
|
|
||||||
return insert(value_type(key, data_type())).first->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_type count(const key_type& key) const { return rep.count(key); }
|
|
||||||
|
|
||||||
pair<iterator, iterator> equal_range(const key_type& key) {
|
|
||||||
return rep.equal_range(key);
|
|
||||||
}
|
|
||||||
pair<const_iterator, const_iterator> equal_range(const key_type& key) const {
|
|
||||||
return rep.equal_range(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insertion routines
|
|
||||||
pair<iterator, bool> insert(const value_type& obj) { return rep.insert(obj); }
|
|
||||||
template <class InputIterator>
|
|
||||||
void insert(InputIterator f, InputIterator l) { rep.insert(f, l); }
|
|
||||||
void insert(const_iterator f, const_iterator l) { rep.insert(f, l); }
|
|
||||||
// required for std::insert_iterator; the passed-in iterator is ignored
|
|
||||||
iterator insert(iterator, const value_type& obj) { return insert(obj).first; }
|
|
||||||
|
|
||||||
|
|
||||||
// Deletion and empty routines
|
|
||||||
// THESE ARE NON-STANDARD! I make you specify an "impossible" key
|
|
||||||
// value to identify deleted and empty buckets. You can change the
|
|
||||||
// deleted key as time goes on, or get rid of it entirely to be insert-only.
|
|
||||||
void set_empty_key(const key_type& key) { // YOU MUST CALL THIS!
|
|
||||||
rep.set_empty_key(value_type(key, data_type())); // rep wants a value
|
|
||||||
}
|
|
||||||
key_type empty_key() const {
|
|
||||||
return rep.empty_key().first; // rep returns a value
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_deleted_key(const key_type& key) { rep.set_deleted_key(key); }
|
|
||||||
void clear_deleted_key() { rep.clear_deleted_key(); }
|
|
||||||
key_type deleted_key() const { return rep.deleted_key(); }
|
|
||||||
|
|
||||||
// These are standard
|
|
||||||
size_type erase(const key_type& key) { return rep.erase(key); }
|
|
||||||
void erase(iterator it) { rep.erase(it); }
|
|
||||||
void erase(iterator f, iterator l) { rep.erase(f, l); }
|
|
||||||
|
|
||||||
|
|
||||||
// Comparison
|
|
||||||
bool operator==(const dense_hash_map& hs) const { return rep == hs.rep; }
|
|
||||||
bool operator!=(const dense_hash_map& hs) const { return rep != hs.rep; }
|
|
||||||
|
|
||||||
|
|
||||||
// I/O -- this is an add-on for writing metainformation to disk
|
|
||||||
bool write_metadata(FILE *fp) { return rep.write_metadata(fp); }
|
|
||||||
bool read_metadata(FILE *fp) { return rep.read_metadata(fp); }
|
|
||||||
bool write_nopointer_data(FILE *fp) { return rep.write_nopointer_data(fp); }
|
|
||||||
bool read_nopointer_data(FILE *fp) { return rep.read_nopointer_data(fp); }
|
|
||||||
};
|
|
||||||
|
|
||||||
// We need a global swap as well
|
|
||||||
template <class Key, class T, class HashFcn, class EqualKey, class Alloc>
|
|
||||||
inline void swap(dense_hash_map<Key, T, HashFcn, EqualKey, Alloc>& hm1,
|
|
||||||
dense_hash_map<Key, T, HashFcn, EqualKey, Alloc>& hm2) {
|
|
||||||
hm1.swap(hm2);
|
|
||||||
}
|
|
||||||
|
|
||||||
_END_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
#endif /* _DENSE_HASH_MAP_H_ */
|
|
@ -1,296 +0,0 @@
|
|||||||
// Copyright (c) 2005, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// ---
|
|
||||||
// Author: Craig Silverstein
|
|
||||||
//
|
|
||||||
// This is just a very thin wrapper over densehashtable.h, just
|
|
||||||
// like sgi stl's stl_hash_set is a very thin wrapper over
|
|
||||||
// stl_hashtable. The major thing we define is operator[], because
|
|
||||||
// we have a concept of a data_type which stl_hashtable doesn't
|
|
||||||
// (it only has a key and a value).
|
|
||||||
//
|
|
||||||
// This is more different from dense_hash_map than you might think,
|
|
||||||
// because all iterators for sets are const (you obviously can't
|
|
||||||
// change the key, and for sets there is no value).
|
|
||||||
//
|
|
||||||
// NOTE: this is exactly like sparse_hash_set.h, with the word
|
|
||||||
// "sparse" replaced by "dense", except for the addition of
|
|
||||||
// set_empty_key().
|
|
||||||
//
|
|
||||||
// YOU MUST CALL SET_EMPTY_KEY() IMMEDIATELY AFTER CONSTRUCTION.
|
|
||||||
//
|
|
||||||
// Otherwise your program will die in mysterious ways.
|
|
||||||
//
|
|
||||||
// In other respects, we adhere mostly to the STL semantics for
|
|
||||||
// hash-map. One important exception is that insert() may invalidate
|
|
||||||
// iterators entirely -- STL semantics are that insert() may reorder
|
|
||||||
// iterators, but they all still refer to something valid in the
|
|
||||||
// hashtable. Not so for us. Likewise, insert() may invalidate
|
|
||||||
// pointers into the hashtable. (Whether insert invalidates iterators
|
|
||||||
// and pointers depends on whether it results in a hashtable resize).
|
|
||||||
// On the plus side, delete() doesn't invalidate iterators or pointers
|
|
||||||
// at all, or even change the ordering of elements.
|
|
||||||
//
|
|
||||||
// Here are a few "power user" tips:
|
|
||||||
//
|
|
||||||
// 1) set_deleted_key():
|
|
||||||
// If you want to use erase() you must call set_deleted_key(),
|
|
||||||
// in addition to set_empty_key(), after construction.
|
|
||||||
// The deleted and empty keys must differ.
|
|
||||||
//
|
|
||||||
// 2) resize(0):
|
|
||||||
// When an item is deleted, its memory isn't freed right
|
|
||||||
// away. This allows you to iterate over a hashtable,
|
|
||||||
// and call erase(), without invalidating the iterator.
|
|
||||||
// To force the memory to be freed, call resize(0).
|
|
||||||
// For tr1 compatibility, this can also be called as rehash(0).
|
|
||||||
//
|
|
||||||
// 3) min_load_factor(0.0)
|
|
||||||
// Setting the minimum load factor to 0.0 guarantees that
|
|
||||||
// the hash table will never shrink.
|
|
||||||
//
|
|
||||||
// Roughly speaking:
|
|
||||||
// (1) dense_hash_set: fastest, uses the most memory unless entries are small
|
|
||||||
// (2) sparse_hash_set: slowest, uses the least memory
|
|
||||||
// (3) hash_set / unordered_set (STL): in the middle
|
|
||||||
//
|
|
||||||
// Typically I use sparse_hash_set when I care about space and/or when
|
|
||||||
// I need to save the hashtable on disk. I use hash_set otherwise. I
|
|
||||||
// don't personally use dense_hash_set ever; some people use it for
|
|
||||||
// small sets with lots of lookups.
|
|
||||||
//
|
|
||||||
// - dense_hash_set has, typically, about 78% memory overhead (if your
|
|
||||||
// data takes up X bytes, the hash_set uses .78X more bytes in overhead).
|
|
||||||
// - sparse_hash_set has about 4 bits overhead per entry.
|
|
||||||
// - sparse_hash_set can be 3-7 times slower than the others for lookup and,
|
|
||||||
// especially, inserts. See time_hash_map.cc for details.
|
|
||||||
//
|
|
||||||
// See /usr/(local/)?doc/sparsehash-*/dense_hash_set.html
|
|
||||||
// for information about how to use this class.
|
|
||||||
|
|
||||||
#ifndef _DENSE_HASH_SET_H_
|
|
||||||
#define _DENSE_HASH_SET_H_
|
|
||||||
|
|
||||||
#include <google/sparsehash/sparseconfig.h>
|
|
||||||
#include <stdio.h> // for FILE * in read()/write()
|
|
||||||
#include <algorithm> // for the default template args
|
|
||||||
#include <functional> // for equal_to
|
|
||||||
#include <memory> // for alloc<>
|
|
||||||
#include <utility> // for pair<>
|
|
||||||
#include HASH_FUN_H // defined in config.h
|
|
||||||
#include <google/sparsehash/densehashtable.h>
|
|
||||||
|
|
||||||
|
|
||||||
_START_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
using STL_NAMESPACE::pair;
|
|
||||||
|
|
||||||
template <class Value,
|
|
||||||
class HashFcn = SPARSEHASH_HASH<Value>, // defined in sparseconfig.h
|
|
||||||
class EqualKey = STL_NAMESPACE::equal_to<Value>,
|
|
||||||
class Alloc = STL_NAMESPACE::allocator<Value> >
|
|
||||||
class dense_hash_set {
|
|
||||||
private:
|
|
||||||
// Apparently identity is not stl-standard, so we define our own
|
|
||||||
struct Identity {
|
|
||||||
Value& operator()(Value& v) const { return v; }
|
|
||||||
const Value& operator()(const Value& v) const { return v; }
|
|
||||||
};
|
|
||||||
struct SetKey {
|
|
||||||
void operator()(Value* value, const Value& new_key) const {
|
|
||||||
*value = new_key;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// The actual data
|
|
||||||
typedef dense_hashtable<Value, Value, HashFcn,
|
|
||||||
Identity, SetKey, EqualKey, Alloc> ht;
|
|
||||||
ht rep;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef typename ht::key_type key_type;
|
|
||||||
typedef typename ht::value_type value_type;
|
|
||||||
typedef typename ht::hasher hasher;
|
|
||||||
typedef typename ht::key_equal key_equal;
|
|
||||||
typedef Alloc allocator_type;
|
|
||||||
|
|
||||||
typedef typename ht::size_type size_type;
|
|
||||||
typedef typename ht::difference_type difference_type;
|
|
||||||
typedef typename ht::const_pointer pointer;
|
|
||||||
typedef typename ht::const_pointer const_pointer;
|
|
||||||
typedef typename ht::const_reference reference;
|
|
||||||
typedef typename ht::const_reference const_reference;
|
|
||||||
|
|
||||||
typedef typename ht::const_iterator iterator;
|
|
||||||
typedef typename ht::const_iterator const_iterator;
|
|
||||||
typedef typename ht::const_local_iterator local_iterator;
|
|
||||||
typedef typename ht::const_local_iterator const_local_iterator;
|
|
||||||
|
|
||||||
|
|
||||||
// Iterator functions -- recall all iterators are const
|
|
||||||
iterator begin() const { return rep.begin(); }
|
|
||||||
iterator end() const { return rep.end(); }
|
|
||||||
|
|
||||||
// These come from tr1's unordered_set. For us, a bucket has 0 or 1 elements.
|
|
||||||
local_iterator begin(size_type i) const { return rep.begin(i); }
|
|
||||||
local_iterator end(size_type i) const { return rep.end(i); }
|
|
||||||
|
|
||||||
|
|
||||||
// Accessor functions
|
|
||||||
hasher hash_funct() const { return rep.hash_funct(); }
|
|
||||||
key_equal key_eq() const { return rep.key_eq(); }
|
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
explicit dense_hash_set(size_type expected_max_items_in_table = 0,
|
|
||||||
const hasher& hf = hasher(),
|
|
||||||
const key_equal& eql = key_equal())
|
|
||||||
: rep(expected_max_items_in_table, hf, eql) { }
|
|
||||||
|
|
||||||
template <class InputIterator>
|
|
||||||
dense_hash_set(InputIterator f, InputIterator l,
|
|
||||||
size_type expected_max_items_in_table = 0,
|
|
||||||
const hasher& hf = hasher(),
|
|
||||||
const key_equal& eql = key_equal())
|
|
||||||
: rep(expected_max_items_in_table, hf, eql) {
|
|
||||||
rep.insert(f, l);
|
|
||||||
}
|
|
||||||
// We use the default copy constructor
|
|
||||||
// We use the default operator=()
|
|
||||||
// We use the default destructor
|
|
||||||
|
|
||||||
void clear() { rep.clear(); }
|
|
||||||
// This clears the hash set without resizing it down to the minimum
|
|
||||||
// bucket count, but rather keeps the number of buckets constant
|
|
||||||
void clear_no_resize() { rep.clear_no_resize(); }
|
|
||||||
void swap(dense_hash_set& hs) { rep.swap(hs.rep); }
|
|
||||||
|
|
||||||
|
|
||||||
// Functions concerning size
|
|
||||||
size_type size() const { return rep.size(); }
|
|
||||||
size_type max_size() const { return rep.max_size(); }
|
|
||||||
bool empty() const { return rep.empty(); }
|
|
||||||
size_type bucket_count() const { return rep.bucket_count(); }
|
|
||||||
size_type max_bucket_count() const { return rep.max_bucket_count(); }
|
|
||||||
|
|
||||||
// These are tr1 methods. bucket() is the bucket the key is or would be in.
|
|
||||||
size_type bucket_size(size_type i) const { return rep.bucket_size(i); }
|
|
||||||
size_type bucket(const key_type& key) const { return rep.bucket(key); }
|
|
||||||
float load_factor() const {
|
|
||||||
return size() * 1.0f / bucket_count();
|
|
||||||
}
|
|
||||||
float max_load_factor() const {
|
|
||||||
float shrink, grow;
|
|
||||||
rep.get_resizing_parameters(&shrink, &grow);
|
|
||||||
return grow;
|
|
||||||
}
|
|
||||||
void max_load_factor(float new_grow) {
|
|
||||||
float shrink, grow;
|
|
||||||
rep.get_resizing_parameters(&shrink, &grow);
|
|
||||||
rep.set_resizing_parameters(shrink, new_grow);
|
|
||||||
}
|
|
||||||
// These aren't tr1 methods but perhaps ought to be.
|
|
||||||
float min_load_factor() const {
|
|
||||||
float shrink, grow;
|
|
||||||
rep.get_resizing_parameters(&shrink, &grow);
|
|
||||||
return shrink;
|
|
||||||
}
|
|
||||||
void min_load_factor(float new_shrink) {
|
|
||||||
float shrink, grow;
|
|
||||||
rep.get_resizing_parameters(&shrink, &grow);
|
|
||||||
rep.set_resizing_parameters(new_shrink, grow);
|
|
||||||
}
|
|
||||||
// Deprecated; use min_load_factor() or max_load_factor() instead.
|
|
||||||
void set_resizing_parameters(float shrink, float grow) {
|
|
||||||
return rep.set_resizing_parameters(shrink, grow);
|
|
||||||
}
|
|
||||||
|
|
||||||
void resize(size_type hint) { rep.resize(hint); }
|
|
||||||
void rehash(size_type hint) { resize(hint); } // the tr1 name
|
|
||||||
|
|
||||||
// Lookup routines
|
|
||||||
iterator find(const key_type& key) const { return rep.find(key); }
|
|
||||||
|
|
||||||
size_type count(const key_type& key) const { return rep.count(key); }
|
|
||||||
|
|
||||||
pair<iterator, iterator> equal_range(const key_type& key) const {
|
|
||||||
return rep.equal_range(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insertion routines
|
|
||||||
pair<iterator, bool> insert(const value_type& obj) {
|
|
||||||
pair<typename ht::iterator, bool> p = rep.insert(obj);
|
|
||||||
return pair<iterator, bool>(p.first, p.second); // const to non-const
|
|
||||||
}
|
|
||||||
template <class InputIterator>
|
|
||||||
void insert(InputIterator f, InputIterator l) { rep.insert(f, l); }
|
|
||||||
void insert(const_iterator f, const_iterator l) { rep.insert(f, l); }
|
|
||||||
// required for std::insert_iterator; the passed-in iterator is ignored
|
|
||||||
iterator insert(iterator, const value_type& obj) { return insert(obj).first; }
|
|
||||||
|
|
||||||
|
|
||||||
// Deletion and empty routines
|
|
||||||
// THESE ARE NON-STANDARD! I make you specify an "impossible" key
|
|
||||||
// value to identify deleted and empty buckets. You can change the
|
|
||||||
// deleted key as time goes on, or get rid of it entirely to be insert-only.
|
|
||||||
void set_empty_key(const key_type& key) { rep.set_empty_key(key); }
|
|
||||||
key_type empty_key() const { return rep.empty_key(); }
|
|
||||||
|
|
||||||
void set_deleted_key(const key_type& key) { rep.set_deleted_key(key); }
|
|
||||||
void clear_deleted_key() { rep.clear_deleted_key(); }
|
|
||||||
key_type deleted_key() const { return rep.deleted_key(); }
|
|
||||||
|
|
||||||
// These are standard
|
|
||||||
size_type erase(const key_type& key) { return rep.erase(key); }
|
|
||||||
void erase(iterator it) { rep.erase(it); }
|
|
||||||
void erase(iterator f, iterator l) { rep.erase(f, l); }
|
|
||||||
|
|
||||||
|
|
||||||
// Comparison
|
|
||||||
bool operator==(const dense_hash_set& hs) const { return rep == hs.rep; }
|
|
||||||
bool operator!=(const dense_hash_set& hs) const { return rep != hs.rep; }
|
|
||||||
|
|
||||||
|
|
||||||
// I/O -- this is an add-on for writing metainformation to disk
|
|
||||||
bool write_metadata(FILE *fp) { return rep.write_metadata(fp); }
|
|
||||||
bool read_metadata(FILE *fp) { return rep.read_metadata(fp); }
|
|
||||||
bool write_nopointer_data(FILE *fp) { return rep.write_nopointer_data(fp); }
|
|
||||||
bool read_nopointer_data(FILE *fp) { return rep.read_nopointer_data(fp); }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Val, class HashFcn, class EqualKey, class Alloc>
|
|
||||||
inline void swap(dense_hash_set<Val, HashFcn, EqualKey, Alloc>& hs1,
|
|
||||||
dense_hash_set<Val, HashFcn, EqualKey, Alloc>& hs2) {
|
|
||||||
hs1.swap(hs2);
|
|
||||||
}
|
|
||||||
|
|
||||||
_END_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
#endif /* _DENSE_HASH_SET_H_ */
|
|
@ -1,301 +0,0 @@
|
|||||||
// Copyright (c) 2005, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// ---
|
|
||||||
// Author: Craig Silverstein
|
|
||||||
//
|
|
||||||
// This is just a very thin wrapper over sparsehashtable.h, just
|
|
||||||
// like sgi stl's stl_hash_map is a very thin wrapper over
|
|
||||||
// stl_hashtable. The major thing we define is operator[], because
|
|
||||||
// we have a concept of a data_type which stl_hashtable doesn't
|
|
||||||
// (it only has a key and a value).
|
|
||||||
//
|
|
||||||
// We adhere mostly to the STL semantics for hash-map. One important
|
|
||||||
// exception is that insert() may invalidate iterators entirely -- STL
|
|
||||||
// semantics are that insert() may reorder iterators, but they all
|
|
||||||
// still refer to something valid in the hashtable. Not so for us.
|
|
||||||
// Likewise, insert() may invalidate pointers into the hashtable.
|
|
||||||
// (Whether insert invalidates iterators and pointers depends on
|
|
||||||
// whether it results in a hashtable resize). On the plus side,
|
|
||||||
// delete() doesn't invalidate iterators or pointers at all, or even
|
|
||||||
// change the ordering of elements.
|
|
||||||
//
|
|
||||||
// Here are a few "power user" tips:
|
|
||||||
//
|
|
||||||
// 1) set_deleted_key():
|
|
||||||
// Unlike STL's hash_map, if you want to use erase() you
|
|
||||||
// *must* call set_deleted_key() after construction.
|
|
||||||
//
|
|
||||||
// 2) resize(0):
|
|
||||||
// When an item is deleted, its memory isn't freed right
|
|
||||||
// away. This is what allows you to iterate over a hashtable
|
|
||||||
// and call erase() without invalidating the iterator.
|
|
||||||
// To force the memory to be freed, call resize(0).
|
|
||||||
// For tr1 compatibility, this can also be called as rehash(0).
|
|
||||||
//
|
|
||||||
// 3) min_load_factor(0.0)
|
|
||||||
// Setting the minimum load factor to 0.0 guarantees that
|
|
||||||
// the hash table will never shrink.
|
|
||||||
//
|
|
||||||
// Roughly speaking:
|
|
||||||
// (1) dense_hash_map: fastest, uses the most memory unless entries are small
|
|
||||||
// (2) sparse_hash_map: slowest, uses the least memory
|
|
||||||
// (3) hash_map / unordered_map (STL): in the middle
|
|
||||||
//
|
|
||||||
// Typically I use sparse_hash_map when I care about space and/or when
|
|
||||||
// I need to save the hashtable on disk. I use hash_map otherwise. I
|
|
||||||
// don't personally use dense_hash_map ever; some people use it for
|
|
||||||
// small maps with lots of lookups.
|
|
||||||
//
|
|
||||||
// - dense_hash_map has, typically, about 78% memory overhead (if your
|
|
||||||
// data takes up X bytes, the hash_map uses .78X more bytes in overhead).
|
|
||||||
// - sparse_hash_map has about 4 bits overhead per entry.
|
|
||||||
// - sparse_hash_map can be 3-7 times slower than the others for lookup and,
|
|
||||||
// especially, inserts. See time_hash_map.cc for details.
|
|
||||||
//
|
|
||||||
// See /usr/(local/)?doc/sparsehash-*/sparse_hash_map.html
|
|
||||||
// for information about how to use this class.
|
|
||||||
|
|
||||||
#ifndef _SPARSE_HASH_MAP_H_
|
|
||||||
#define _SPARSE_HASH_MAP_H_
|
|
||||||
|
|
||||||
#include <google/sparsehash/sparseconfig.h>
|
|
||||||
#include <stdio.h> // for FILE * in read()/write()
|
|
||||||
#include <algorithm> // for the default template args
|
|
||||||
#include <functional> // for equal_to
|
|
||||||
#include <memory> // for alloc<>
|
|
||||||
#include <utility> // for pair<>
|
|
||||||
#include HASH_FUN_H // defined in config.h
|
|
||||||
#include <google/sparsehash/sparsehashtable.h>
|
|
||||||
|
|
||||||
|
|
||||||
_START_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
using STL_NAMESPACE::pair;
|
|
||||||
|
|
||||||
template <class Key, class T,
|
|
||||||
class HashFcn = SPARSEHASH_HASH<Key>, // defined in sparseconfig.h
|
|
||||||
class EqualKey = STL_NAMESPACE::equal_to<Key>,
|
|
||||||
class Alloc = STL_NAMESPACE::allocator<T> >
|
|
||||||
class sparse_hash_map {
|
|
||||||
private:
|
|
||||||
// Apparently select1st is not stl-standard, so we define our own
|
|
||||||
struct SelectKey {
|
|
||||||
const Key& operator()(const pair<const Key, T>& p) const {
|
|
||||||
return p.first;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
struct SetKey {
|
|
||||||
void operator()(pair<const Key, T>* value, const Key& new_key) const {
|
|
||||||
*const_cast<Key*>(&value->first) = new_key;
|
|
||||||
// It would be nice to clear the rest of value here as well, in
|
|
||||||
// case it's taking up a lot of memory. We do this by clearing
|
|
||||||
// the value. This assumes T has a zero-arg constructor!
|
|
||||||
value->second = T();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// The actual data
|
|
||||||
typedef sparse_hashtable<pair<const Key, T>, Key, HashFcn,
|
|
||||||
SelectKey, SetKey, EqualKey, Alloc> ht;
|
|
||||||
ht rep;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef typename ht::key_type key_type;
|
|
||||||
typedef T data_type;
|
|
||||||
typedef T mapped_type;
|
|
||||||
typedef typename ht::value_type value_type;
|
|
||||||
typedef typename ht::hasher hasher;
|
|
||||||
typedef typename ht::key_equal key_equal;
|
|
||||||
typedef Alloc allocator_type;
|
|
||||||
|
|
||||||
typedef typename ht::size_type size_type;
|
|
||||||
typedef typename ht::difference_type difference_type;
|
|
||||||
typedef typename ht::pointer pointer;
|
|
||||||
typedef typename ht::const_pointer const_pointer;
|
|
||||||
typedef typename ht::reference reference;
|
|
||||||
typedef typename ht::const_reference const_reference;
|
|
||||||
|
|
||||||
typedef typename ht::iterator iterator;
|
|
||||||
typedef typename ht::const_iterator const_iterator;
|
|
||||||
typedef typename ht::local_iterator local_iterator;
|
|
||||||
typedef typename ht::const_local_iterator const_local_iterator;
|
|
||||||
|
|
||||||
// Iterator functions
|
|
||||||
iterator begin() { return rep.begin(); }
|
|
||||||
iterator end() { return rep.end(); }
|
|
||||||
const_iterator begin() const { return rep.begin(); }
|
|
||||||
const_iterator end() const { return rep.end(); }
|
|
||||||
|
|
||||||
// These come from tr1's unordered_map. For us, a bucket has 0 or 1 elements.
|
|
||||||
local_iterator begin(size_type i) { return rep.begin(i); }
|
|
||||||
local_iterator end(size_type i) { return rep.end(i); }
|
|
||||||
const_local_iterator begin(size_type i) const { return rep.begin(i); }
|
|
||||||
const_local_iterator end(size_type i) const { return rep.end(i); }
|
|
||||||
|
|
||||||
// Accessor functions
|
|
||||||
// TODO(csilvers): implement Alloc get_allocator() const;
|
|
||||||
hasher hash_funct() const { return rep.hash_funct(); }
|
|
||||||
hasher hash_function() const { return hash_funct(); }
|
|
||||||
key_equal key_eq() const { return rep.key_eq(); }
|
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
explicit sparse_hash_map(size_type expected_max_items_in_table = 0,
|
|
||||||
const hasher& hf = hasher(),
|
|
||||||
const key_equal& eql = key_equal())
|
|
||||||
: rep(expected_max_items_in_table, hf, eql) { }
|
|
||||||
|
|
||||||
template <class InputIterator>
|
|
||||||
sparse_hash_map(InputIterator f, InputIterator l,
|
|
||||||
size_type expected_max_items_in_table = 0,
|
|
||||||
const hasher& hf = hasher(),
|
|
||||||
const key_equal& eql = key_equal())
|
|
||||||
: rep(expected_max_items_in_table, hf, eql) {
|
|
||||||
rep.insert(f, l);
|
|
||||||
}
|
|
||||||
// We use the default copy constructor
|
|
||||||
// We use the default operator=()
|
|
||||||
// We use the default destructor
|
|
||||||
|
|
||||||
void clear() { rep.clear(); }
|
|
||||||
void swap(sparse_hash_map& hs) { rep.swap(hs.rep); }
|
|
||||||
|
|
||||||
|
|
||||||
// Functions concerning size
|
|
||||||
size_type size() const { return rep.size(); }
|
|
||||||
size_type max_size() const { return rep.max_size(); }
|
|
||||||
bool empty() const { return rep.empty(); }
|
|
||||||
size_type bucket_count() const { return rep.bucket_count(); }
|
|
||||||
size_type max_bucket_count() const { return rep.max_bucket_count(); }
|
|
||||||
|
|
||||||
// These are tr1 methods. bucket() is the bucket the key is or would be in.
|
|
||||||
size_type bucket_size(size_type i) const { return rep.bucket_size(i); }
|
|
||||||
size_type bucket(const key_type& key) const { return rep.bucket(key); }
|
|
||||||
float load_factor() const {
|
|
||||||
return size() * 1.0f / bucket_count();
|
|
||||||
}
|
|
||||||
float max_load_factor() const {
|
|
||||||
float shrink, grow;
|
|
||||||
rep.get_resizing_parameters(&shrink, &grow);
|
|
||||||
return grow;
|
|
||||||
}
|
|
||||||
void max_load_factor(float new_grow) {
|
|
||||||
float shrink, grow;
|
|
||||||
rep.get_resizing_parameters(&shrink, &grow);
|
|
||||||
rep.set_resizing_parameters(shrink, new_grow);
|
|
||||||
}
|
|
||||||
// These aren't tr1 methods but perhaps ought to be.
|
|
||||||
float min_load_factor() const {
|
|
||||||
float shrink, grow;
|
|
||||||
rep.get_resizing_parameters(&shrink, &grow);
|
|
||||||
return shrink;
|
|
||||||
}
|
|
||||||
void min_load_factor(float new_shrink) {
|
|
||||||
float shrink, grow;
|
|
||||||
rep.get_resizing_parameters(&shrink, &grow);
|
|
||||||
rep.set_resizing_parameters(new_shrink, grow);
|
|
||||||
}
|
|
||||||
// Deprecated; use min_load_factor() or max_load_factor() instead.
|
|
||||||
void set_resizing_parameters(float shrink, float grow) {
|
|
||||||
return rep.set_resizing_parameters(shrink, grow);
|
|
||||||
}
|
|
||||||
|
|
||||||
void resize(size_type hint) { rep.resize(hint); }
|
|
||||||
void rehash(size_type hint) { resize(hint); } // the tr1 name
|
|
||||||
|
|
||||||
// Lookup routines
|
|
||||||
iterator find(const key_type& key) { return rep.find(key); }
|
|
||||||
const_iterator find(const key_type& key) const { return rep.find(key); }
|
|
||||||
|
|
||||||
data_type& operator[](const key_type& key) { // This is our value-add!
|
|
||||||
iterator it = find(key);
|
|
||||||
if (it != end()) {
|
|
||||||
return it->second;
|
|
||||||
} else {
|
|
||||||
return insert(value_type(key, data_type())).first->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_type count(const key_type& key) const { return rep.count(key); }
|
|
||||||
|
|
||||||
pair<iterator, iterator> equal_range(const key_type& key) {
|
|
||||||
return rep.equal_range(key);
|
|
||||||
}
|
|
||||||
pair<const_iterator, const_iterator> equal_range(const key_type& key) const {
|
|
||||||
return rep.equal_range(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insertion routines
|
|
||||||
pair<iterator, bool> insert(const value_type& obj) { return rep.insert(obj); }
|
|
||||||
template <class InputIterator>
|
|
||||||
void insert(InputIterator f, InputIterator l) { rep.insert(f, l); }
|
|
||||||
void insert(const_iterator f, const_iterator l) { rep.insert(f, l); }
|
|
||||||
// required for std::insert_iterator; the passed-in iterator is ignored
|
|
||||||
iterator insert(iterator, const value_type& obj) { return insert(obj).first; }
|
|
||||||
|
|
||||||
|
|
||||||
// Deletion routines
|
|
||||||
// THESE ARE NON-STANDARD! I make you specify an "impossible" key
|
|
||||||
// value to identify deleted buckets. You can change the key as
|
|
||||||
// time goes on, or get rid of it entirely to be insert-only.
|
|
||||||
void set_deleted_key(const key_type& key) {
|
|
||||||
rep.set_deleted_key(key);
|
|
||||||
}
|
|
||||||
void clear_deleted_key() { rep.clear_deleted_key(); }
|
|
||||||
key_type deleted_key() const { return rep.deleted_key(); }
|
|
||||||
|
|
||||||
// These are standard
|
|
||||||
size_type erase(const key_type& key) { return rep.erase(key); }
|
|
||||||
void erase(iterator it) { rep.erase(it); }
|
|
||||||
void erase(iterator f, iterator l) { rep.erase(f, l); }
|
|
||||||
|
|
||||||
|
|
||||||
// Comparison
|
|
||||||
bool operator==(const sparse_hash_map& hs) const { return rep == hs.rep; }
|
|
||||||
bool operator!=(const sparse_hash_map& hs) const { return rep != hs.rep; }
|
|
||||||
|
|
||||||
|
|
||||||
// I/O -- this is an add-on for writing metainformation to disk
|
|
||||||
bool write_metadata(FILE *fp) { return rep.write_metadata(fp); }
|
|
||||||
bool read_metadata(FILE *fp) { return rep.read_metadata(fp); }
|
|
||||||
bool write_nopointer_data(FILE *fp) { return rep.write_nopointer_data(fp); }
|
|
||||||
bool read_nopointer_data(FILE *fp) { return rep.read_nopointer_data(fp); }
|
|
||||||
};
|
|
||||||
|
|
||||||
// We need a global swap as well
|
|
||||||
template <class Key, class T, class HashFcn, class EqualKey, class Alloc>
|
|
||||||
inline void swap(sparse_hash_map<Key, T, HashFcn, EqualKey, Alloc>& hm1,
|
|
||||||
sparse_hash_map<Key, T, HashFcn, EqualKey, Alloc>& hm2) {
|
|
||||||
hm1.swap(hm2);
|
|
||||||
}
|
|
||||||
|
|
||||||
_END_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
#endif /* _SPARSE_HASH_MAP_H_ */
|
|
@ -1,282 +0,0 @@
|
|||||||
// Copyright (c) 2005, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// ---
|
|
||||||
// Author: Craig Silverstein
|
|
||||||
//
|
|
||||||
// This is just a very thin wrapper over sparsehashtable.h, just
|
|
||||||
// like sgi stl's stl_hash_set is a very thin wrapper over
|
|
||||||
// stl_hashtable. The major thing we define is operator[], because
|
|
||||||
// we have a concept of a data_type which stl_hashtable doesn't
|
|
||||||
// (it only has a key and a value).
|
|
||||||
//
|
|
||||||
// This is more different from sparse_hash_map than you might think,
|
|
||||||
// because all iterators for sets are const (you obviously can't
|
|
||||||
// change the key, and for sets there is no value).
|
|
||||||
//
|
|
||||||
// We adhere mostly to the STL semantics for hash-map. One important
|
|
||||||
// exception is that insert() may invalidate iterators entirely -- STL
|
|
||||||
// semantics are that insert() may reorder iterators, but they all
|
|
||||||
// still refer to something valid in the hashtable. Not so for us.
|
|
||||||
// Likewise, insert() may invalidate pointers into the hashtable.
|
|
||||||
// (Whether insert invalidates iterators and pointers depends on
|
|
||||||
// whether it results in a hashtable resize). On the plus side,
|
|
||||||
// delete() doesn't invalidate iterators or pointers at all, or even
|
|
||||||
// change the ordering of elements.
|
|
||||||
//
|
|
||||||
// Here are a few "power user" tips:
|
|
||||||
//
|
|
||||||
// 1) set_deleted_key():
|
|
||||||
// Unlike STL's hash_map, if you want to use erase() you
|
|
||||||
// *must* call set_deleted_key() after construction.
|
|
||||||
//
|
|
||||||
// 2) resize(0):
|
|
||||||
// When an item is deleted, its memory isn't freed right
|
|
||||||
// away. This allows you to iterate over a hashtable,
|
|
||||||
// and call erase(), without invalidating the iterator.
|
|
||||||
// To force the memory to be freed, call resize(0).
|
|
||||||
// For tr1 compatibility, this can also be called as rehash(0).
|
|
||||||
//
|
|
||||||
// 3) min_load_factor(0.0)
|
|
||||||
// Setting the minimum load factor to 0.0 guarantees that
|
|
||||||
// the hash table will never shrink.
|
|
||||||
//
|
|
||||||
// Roughly speaking:
|
|
||||||
// (1) dense_hash_set: fastest, uses the most memory unless entries are small
|
|
||||||
// (2) sparse_hash_set: slowest, uses the least memory
|
|
||||||
// (3) hash_set / unordered_set (STL): in the middle
|
|
||||||
//
|
|
||||||
// Typically I use sparse_hash_set when I care about space and/or when
|
|
||||||
// I need to save the hashtable on disk. I use hash_set otherwise. I
|
|
||||||
// don't personally use dense_hash_set ever; some people use it for
|
|
||||||
// small sets with lots of lookups.
|
|
||||||
//
|
|
||||||
// - dense_hash_set has, typically, about 78% memory overhead (if your
|
|
||||||
// data takes up X bytes, the hash_set uses .78X more bytes in overhead).
|
|
||||||
// - sparse_hash_set has about 4 bits overhead per entry.
|
|
||||||
// - sparse_hash_set can be 3-7 times slower than the others for lookup and,
|
|
||||||
// especially, inserts. See time_hash_map.cc for details.
|
|
||||||
//
|
|
||||||
// See /usr/(local/)?doc/sparsehash-*/sparse_hash_set.html
|
|
||||||
// for information about how to use this class.
|
|
||||||
|
|
||||||
#ifndef _SPARSE_HASH_SET_H_
|
|
||||||
#define _SPARSE_HASH_SET_H_
|
|
||||||
|
|
||||||
#include <google/sparsehash/sparseconfig.h>
|
|
||||||
#include <stdio.h> // for FILE * in read()/write()
|
|
||||||
#include <algorithm> // for the default template args
|
|
||||||
#include <functional> // for equal_to
|
|
||||||
#include <memory> // for alloc<>
|
|
||||||
#include <utility> // for pair<>
|
|
||||||
#include HASH_FUN_H // defined in config.h
|
|
||||||
#include <google/sparsehash/sparsehashtable.h>
|
|
||||||
|
|
||||||
_START_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
using STL_NAMESPACE::pair;
|
|
||||||
|
|
||||||
template <class Value,
|
|
||||||
class HashFcn = SPARSEHASH_HASH<Value>, // defined in sparseconfig.h
|
|
||||||
class EqualKey = STL_NAMESPACE::equal_to<Value>,
|
|
||||||
class Alloc = STL_NAMESPACE::allocator<Value> >
|
|
||||||
class sparse_hash_set {
|
|
||||||
private:
|
|
||||||
// Apparently identity is not stl-standard, so we define our own
|
|
||||||
struct Identity {
|
|
||||||
Value& operator()(Value& v) const { return v; }
|
|
||||||
const Value& operator()(const Value& v) const { return v; }
|
|
||||||
};
|
|
||||||
struct SetKey {
|
|
||||||
void operator()(Value* value, const Value& new_key) const {
|
|
||||||
*value = new_key;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// The actual data
|
|
||||||
typedef sparse_hashtable<Value, Value, HashFcn,
|
|
||||||
Identity, SetKey, EqualKey, Alloc> ht;
|
|
||||||
ht rep;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef typename ht::key_type key_type;
|
|
||||||
typedef typename ht::value_type value_type;
|
|
||||||
typedef typename ht::hasher hasher;
|
|
||||||
typedef typename ht::key_equal key_equal;
|
|
||||||
typedef Alloc allocator_type;
|
|
||||||
|
|
||||||
typedef typename ht::size_type size_type;
|
|
||||||
typedef typename ht::difference_type difference_type;
|
|
||||||
typedef typename ht::const_pointer pointer;
|
|
||||||
typedef typename ht::const_pointer const_pointer;
|
|
||||||
typedef typename ht::const_reference reference;
|
|
||||||
typedef typename ht::const_reference const_reference;
|
|
||||||
|
|
||||||
typedef typename ht::const_iterator iterator;
|
|
||||||
typedef typename ht::const_iterator const_iterator;
|
|
||||||
typedef typename ht::const_local_iterator local_iterator;
|
|
||||||
typedef typename ht::const_local_iterator const_local_iterator;
|
|
||||||
|
|
||||||
|
|
||||||
// Iterator functions -- recall all iterators are const
|
|
||||||
iterator begin() const { return rep.begin(); }
|
|
||||||
iterator end() const { return rep.end(); }
|
|
||||||
|
|
||||||
// These come from tr1's unordered_set. For us, a bucket has 0 or 1 elements.
|
|
||||||
local_iterator begin(size_type i) const { return rep.begin(i); }
|
|
||||||
local_iterator end(size_type i) const { return rep.end(i); }
|
|
||||||
|
|
||||||
|
|
||||||
// Accessor functions
|
|
||||||
// TODO(csilvers): implement Alloc get_allocator() const;
|
|
||||||
hasher hash_funct() const { return rep.hash_funct(); }
|
|
||||||
hasher hash_function() const { return hash_funct(); } // tr1 name
|
|
||||||
key_equal key_eq() const { return rep.key_eq(); }
|
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
explicit sparse_hash_set(size_type expected_max_items_in_table = 0,
|
|
||||||
const hasher& hf = hasher(),
|
|
||||||
const key_equal& eql = key_equal())
|
|
||||||
: rep(expected_max_items_in_table, hf, eql) { }
|
|
||||||
|
|
||||||
template <class InputIterator>
|
|
||||||
sparse_hash_set(InputIterator f, InputIterator l,
|
|
||||||
size_type expected_max_items_in_table = 0,
|
|
||||||
const hasher& hf = hasher(),
|
|
||||||
const key_equal& eql = key_equal())
|
|
||||||
: rep(expected_max_items_in_table, hf, eql) {
|
|
||||||
rep.insert(f, l);
|
|
||||||
}
|
|
||||||
// We use the default copy constructor
|
|
||||||
// We use the default operator=()
|
|
||||||
// We use the default destructor
|
|
||||||
|
|
||||||
void clear() { rep.clear(); }
|
|
||||||
void swap(sparse_hash_set& hs) { rep.swap(hs.rep); }
|
|
||||||
|
|
||||||
|
|
||||||
// Functions concerning size
|
|
||||||
size_type size() const { return rep.size(); }
|
|
||||||
size_type max_size() const { return rep.max_size(); }
|
|
||||||
bool empty() const { return rep.empty(); }
|
|
||||||
size_type bucket_count() const { return rep.bucket_count(); }
|
|
||||||
size_type max_bucket_count() const { return rep.max_bucket_count(); }
|
|
||||||
|
|
||||||
// These are tr1 methods. bucket() is the bucket the key is or would be in.
|
|
||||||
size_type bucket_size(size_type i) const { return rep.bucket_size(i); }
|
|
||||||
size_type bucket(const key_type& key) const { return rep.bucket(key); }
|
|
||||||
float load_factor() const {
|
|
||||||
return size() * 1.0f / bucket_count();
|
|
||||||
}
|
|
||||||
float max_load_factor() const {
|
|
||||||
float shrink, grow;
|
|
||||||
rep.get_resizing_parameters(&shrink, &grow);
|
|
||||||
return grow;
|
|
||||||
}
|
|
||||||
void max_load_factor(float new_grow) {
|
|
||||||
float shrink, grow;
|
|
||||||
rep.get_resizing_parameters(&shrink, &grow);
|
|
||||||
rep.set_resizing_parameters(shrink, new_grow);
|
|
||||||
}
|
|
||||||
// These aren't tr1 methods but perhaps ought to be.
|
|
||||||
float min_load_factor() const {
|
|
||||||
float shrink, grow;
|
|
||||||
rep.get_resizing_parameters(&shrink, &grow);
|
|
||||||
return shrink;
|
|
||||||
}
|
|
||||||
void min_load_factor(float new_shrink) {
|
|
||||||
float shrink, grow;
|
|
||||||
rep.get_resizing_parameters(&shrink, &grow);
|
|
||||||
rep.set_resizing_parameters(new_shrink, grow);
|
|
||||||
}
|
|
||||||
// Deprecated; use min_load_factor() or max_load_factor() instead.
|
|
||||||
void set_resizing_parameters(float shrink, float grow) {
|
|
||||||
return rep.set_resizing_parameters(shrink, grow);
|
|
||||||
}
|
|
||||||
|
|
||||||
void resize(size_type hint) { rep.resize(hint); }
|
|
||||||
void rehash(size_type hint) { resize(hint); } // the tr1 name
|
|
||||||
|
|
||||||
// Lookup routines
|
|
||||||
iterator find(const key_type& key) const { return rep.find(key); }
|
|
||||||
|
|
||||||
size_type count(const key_type& key) const { return rep.count(key); }
|
|
||||||
|
|
||||||
pair<iterator, iterator> equal_range(const key_type& key) const {
|
|
||||||
return rep.equal_range(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insertion routines
|
|
||||||
pair<iterator, bool> insert(const value_type& obj) {
|
|
||||||
pair<typename ht::iterator, bool> p = rep.insert(obj);
|
|
||||||
return pair<iterator, bool>(p.first, p.second); // const to non-const
|
|
||||||
}
|
|
||||||
template <class InputIterator>
|
|
||||||
void insert(InputIterator f, InputIterator l) { rep.insert(f, l); }
|
|
||||||
void insert(const_iterator f, const_iterator l) { rep.insert(f, l); }
|
|
||||||
// required for std::insert_iterator; the passed-in iterator is ignored
|
|
||||||
iterator insert(iterator, const value_type& obj) { return insert(obj).first; }
|
|
||||||
|
|
||||||
|
|
||||||
// Deletion routines
|
|
||||||
// THESE ARE NON-STANDARD! I make you specify an "impossible" key
|
|
||||||
// value to identify deleted buckets. You can change the key as
|
|
||||||
// time goes on, or get rid of it entirely to be insert-only.
|
|
||||||
void set_deleted_key(const key_type& key) { rep.set_deleted_key(key); }
|
|
||||||
void clear_deleted_key() { rep.clear_deleted_key(); }
|
|
||||||
key_type deleted_key() const { return rep.deleted_key(); }
|
|
||||||
|
|
||||||
// These are standard
|
|
||||||
size_type erase(const key_type& key) { return rep.erase(key); }
|
|
||||||
void erase(iterator it) { rep.erase(it); }
|
|
||||||
void erase(iterator f, iterator l) { rep.erase(f, l); }
|
|
||||||
|
|
||||||
|
|
||||||
// Comparison
|
|
||||||
bool operator==(const sparse_hash_set& hs) const { return rep == hs.rep; }
|
|
||||||
bool operator!=(const sparse_hash_set& hs) const { return rep != hs.rep; }
|
|
||||||
|
|
||||||
|
|
||||||
// I/O -- this is an add-on for writing metainformation to disk
|
|
||||||
bool write_metadata(FILE *fp) { return rep.write_metadata(fp); }
|
|
||||||
bool read_metadata(FILE *fp) { return rep.read_metadata(fp); }
|
|
||||||
bool write_nopointer_data(FILE *fp) { return rep.write_nopointer_data(fp); }
|
|
||||||
bool read_nopointer_data(FILE *fp) { return rep.read_nopointer_data(fp); }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Val, class HashFcn, class EqualKey, class Alloc>
|
|
||||||
inline void swap(sparse_hash_set<Val, HashFcn, EqualKey, Alloc>& hs1,
|
|
||||||
sparse_hash_set<Val, HashFcn, EqualKey, Alloc>& hs2) {
|
|
||||||
hs1.swap(hs2);
|
|
||||||
}
|
|
||||||
|
|
||||||
_END_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
#endif /* _SPARSE_HASH_SET_H_ */
|
|
File diff suppressed because it is too large
Load Diff
@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* NOTE: This file is for internal use only.
|
|
||||||
* Do not use these #defines in your own program!
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Namespace for Google classes */
|
|
||||||
#define GOOGLE_NAMESPACE ::google
|
|
||||||
|
|
||||||
/* the location of the header defining hash functions */
|
|
||||||
#define HASH_FUN_H <tr1/functional>
|
|
||||||
|
|
||||||
/* the namespace of the hash<> function */
|
|
||||||
#define HASH_NAMESPACE std::tr1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
|
||||||
#define HAVE_INTTYPES_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `long long'. */
|
|
||||||
#define HAVE_LONG_LONG 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `memcpy' function. */
|
|
||||||
#define HAVE_MEMCPY 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
|
||||||
#define HAVE_STDINT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
|
||||||
#define HAVE_SYS_TYPES_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uint16_t'. */
|
|
||||||
#define HAVE_UINT16_T 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `u_int16_t'. */
|
|
||||||
#define HAVE_U_INT16_T 1
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `__uint16'. */
|
|
||||||
/* #undef HAVE___UINT16 */
|
|
||||||
|
|
||||||
/* The system-provided hash function including the namespace. */
|
|
||||||
#define SPARSEHASH_HASH HASH_NAMESPACE::hash
|
|
||||||
|
|
||||||
/* the namespace where STL code like vector<> is defined */
|
|
||||||
#define STL_NAMESPACE std
|
|
||||||
|
|
||||||
/* Stops putting the code inside the Google namespace */
|
|
||||||
#define _END_GOOGLE_NAMESPACE_ }
|
|
||||||
|
|
||||||
/* Puts following code inside the Google namespace */
|
|
||||||
#define _START_GOOGLE_NAMESPACE_ namespace google {
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,250 +0,0 @@
|
|||||||
// Copyright (c) 2006, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// Author: Matt Austern
|
|
||||||
//
|
|
||||||
// Define a small subset of tr1 type traits. The traits we define are:
|
|
||||||
// is_integral
|
|
||||||
// is_floating_point
|
|
||||||
// is_pointer
|
|
||||||
// is_reference
|
|
||||||
// is_pod
|
|
||||||
// has_trivial_constructor
|
|
||||||
// has_trivial_copy
|
|
||||||
// has_trivial_assign
|
|
||||||
// has_trivial_destructor
|
|
||||||
// remove_const
|
|
||||||
// remove_volatile
|
|
||||||
// remove_cv
|
|
||||||
// remove_reference
|
|
||||||
// remove_pointer
|
|
||||||
// is_convertible
|
|
||||||
// We can add more type traits as required.
|
|
||||||
|
|
||||||
#ifndef BASE_TYPE_TRAITS_H_
|
|
||||||
#define BASE_TYPE_TRAITS_H_
|
|
||||||
|
|
||||||
#include <google/sparsehash/sparseconfig.h>
|
|
||||||
#include <utility> // For pair
|
|
||||||
|
|
||||||
_START_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
// integral_constant, defined in tr1, is a wrapper for an integer
|
|
||||||
// value. We don't really need this generality; we could get away
|
|
||||||
// with hardcoding the integer type to bool. We use the fully
|
|
||||||
// general integer_constant for compatibility with tr1.
|
|
||||||
|
|
||||||
template<class T, T v>
|
|
||||||
struct integral_constant {
|
|
||||||
static const T value = v;
|
|
||||||
typedef T value_type;
|
|
||||||
typedef integral_constant<T, v> type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T, T v> const T integral_constant<T, v>::value;
|
|
||||||
|
|
||||||
// Abbreviations: true_type and false_type are structs that represent
|
|
||||||
// boolean true and false values.
|
|
||||||
typedef integral_constant<bool, true> true_type;
|
|
||||||
typedef integral_constant<bool, false> false_type;
|
|
||||||
|
|
||||||
// Types small_ and big_ are guaranteed such that sizeof(small_) <
|
|
||||||
// sizeof(big_)
|
|
||||||
typedef char small_;
|
|
||||||
|
|
||||||
struct big_ {
|
|
||||||
char dummy[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
// is_integral is false except for the built-in integer types.
|
|
||||||
template <class T> struct is_integral : false_type { };
|
|
||||||
template<> struct is_integral<bool> : true_type { };
|
|
||||||
template<> struct is_integral<char> : true_type { };
|
|
||||||
template<> struct is_integral<unsigned char> : true_type { };
|
|
||||||
template<> struct is_integral<signed char> : true_type { };
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
// wchar_t is not by default a distinct type from unsigned short in
|
|
||||||
// Microsoft C.
|
|
||||||
// See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx
|
|
||||||
template<> struct is_integral<__wchar_t> : true_type { };
|
|
||||||
#else
|
|
||||||
template<> struct is_integral<wchar_t> : true_type { };
|
|
||||||
#endif
|
|
||||||
template<> struct is_integral<short> : true_type { };
|
|
||||||
template<> struct is_integral<unsigned short> : true_type { };
|
|
||||||
template<> struct is_integral<int> : true_type { };
|
|
||||||
template<> struct is_integral<unsigned int> : true_type { };
|
|
||||||
template<> struct is_integral<long> : true_type { };
|
|
||||||
template<> struct is_integral<unsigned long> : true_type { };
|
|
||||||
#ifdef HAVE_LONG_LONG
|
|
||||||
template<> struct is_integral<long long> : true_type { };
|
|
||||||
template<> struct is_integral<unsigned long long> : true_type { };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// is_floating_point is false except for the built-in floating-point types.
|
|
||||||
template <class T> struct is_floating_point : false_type { };
|
|
||||||
template<> struct is_floating_point<float> : true_type { };
|
|
||||||
template<> struct is_floating_point<double> : true_type { };
|
|
||||||
template<> struct is_floating_point<long double> : true_type { };
|
|
||||||
|
|
||||||
|
|
||||||
// is_pointer is false except for pointer types.
|
|
||||||
template <class T> struct is_pointer : false_type { };
|
|
||||||
template <class T> struct is_pointer<T*> : true_type { };
|
|
||||||
|
|
||||||
|
|
||||||
// is_reference is false except for reference types.
|
|
||||||
template<typename T> struct is_reference : false_type {};
|
|
||||||
template<typename T> struct is_reference<T&> : true_type {};
|
|
||||||
|
|
||||||
|
|
||||||
// We can't get is_pod right without compiler help, so fail conservatively.
|
|
||||||
// We will assume it's false except for arithmetic types and pointers,
|
|
||||||
// and const versions thereof. Note that std::pair is not a POD.
|
|
||||||
template <class T> struct is_pod
|
|
||||||
: integral_constant<bool, (is_integral<T>::value ||
|
|
||||||
is_floating_point<T>::value ||
|
|
||||||
is_pointer<T>::value)> { };
|
|
||||||
template <class T> struct is_pod<const T> : is_pod<T> { };
|
|
||||||
|
|
||||||
|
|
||||||
// We can't get has_trivial_constructor right without compiler help, so
|
|
||||||
// fail conservatively. We will assume it's false except for: (1) types
|
|
||||||
// for which is_pod is true. (2) std::pair of types with trivial
|
|
||||||
// constructors. (3) array of a type with a trivial constructor.
|
|
||||||
// (4) const versions thereof.
|
|
||||||
template <class T> struct has_trivial_constructor : is_pod<T> { };
|
|
||||||
template <class T, class U> struct has_trivial_constructor<std::pair<T, U> >
|
|
||||||
: integral_constant<bool,
|
|
||||||
(has_trivial_constructor<T>::value &&
|
|
||||||
has_trivial_constructor<U>::value)> { };
|
|
||||||
template <class A, int N> struct has_trivial_constructor<A[N]>
|
|
||||||
: has_trivial_constructor<A> { };
|
|
||||||
template <class T> struct has_trivial_constructor<const T>
|
|
||||||
: has_trivial_constructor<T> { };
|
|
||||||
|
|
||||||
// We can't get has_trivial_copy right without compiler help, so fail
|
|
||||||
// conservatively. We will assume it's false except for: (1) types
|
|
||||||
// for which is_pod is true. (2) std::pair of types with trivial copy
|
|
||||||
// constructors. (3) array of a type with a trivial copy constructor.
|
|
||||||
// (4) const versions thereof.
|
|
||||||
template <class T> struct has_trivial_copy : is_pod<T> { };
|
|
||||||
template <class T, class U> struct has_trivial_copy<std::pair<T, U> >
|
|
||||||
: integral_constant<bool,
|
|
||||||
(has_trivial_copy<T>::value &&
|
|
||||||
has_trivial_copy<U>::value)> { };
|
|
||||||
template <class A, int N> struct has_trivial_copy<A[N]>
|
|
||||||
: has_trivial_copy<A> { };
|
|
||||||
template <class T> struct has_trivial_copy<const T> : has_trivial_copy<T> { };
|
|
||||||
|
|
||||||
// We can't get has_trivial_assign right without compiler help, so fail
|
|
||||||
// conservatively. We will assume it's false except for: (1) types
|
|
||||||
// for which is_pod is true. (2) std::pair of types with trivial copy
|
|
||||||
// constructors. (3) array of a type with a trivial assign constructor.
|
|
||||||
template <class T> struct has_trivial_assign : is_pod<T> { };
|
|
||||||
template <class T, class U> struct has_trivial_assign<std::pair<T, U> >
|
|
||||||
: integral_constant<bool,
|
|
||||||
(has_trivial_assign<T>::value &&
|
|
||||||
has_trivial_assign<U>::value)> { };
|
|
||||||
template <class A, int N> struct has_trivial_assign<A[N]>
|
|
||||||
: has_trivial_assign<A> { };
|
|
||||||
|
|
||||||
// We can't get has_trivial_destructor right without compiler help, so
|
|
||||||
// fail conservatively. We will assume it's false except for: (1) types
|
|
||||||
// for which is_pod is true. (2) std::pair of types with trivial
|
|
||||||
// destructors. (3) array of a type with a trivial destructor.
|
|
||||||
// (4) const versions thereof.
|
|
||||||
template <class T> struct has_trivial_destructor : is_pod<T> { };
|
|
||||||
template <class T, class U> struct has_trivial_destructor<std::pair<T, U> >
|
|
||||||
: integral_constant<bool,
|
|
||||||
(has_trivial_destructor<T>::value &&
|
|
||||||
has_trivial_destructor<U>::value)> { };
|
|
||||||
template <class A, int N> struct has_trivial_destructor<A[N]>
|
|
||||||
: has_trivial_destructor<A> { };
|
|
||||||
template <class T> struct has_trivial_destructor<const T>
|
|
||||||
: has_trivial_destructor<T> { };
|
|
||||||
|
|
||||||
// Specified by TR1 [4.7.1]
|
|
||||||
template<typename T> struct remove_const { typedef T type; };
|
|
||||||
template<typename T> struct remove_const<T const> { typedef T type; };
|
|
||||||
template<typename T> struct remove_volatile { typedef T type; };
|
|
||||||
template<typename T> struct remove_volatile<T volatile> { typedef T type; };
|
|
||||||
template<typename T> struct remove_cv {
|
|
||||||
typedef typename remove_const<typename remove_volatile<T>::type>::type type;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Specified by TR1 [4.7.2]
|
|
||||||
template<typename T> struct remove_reference { typedef T type; };
|
|
||||||
template<typename T> struct remove_reference<T&> { typedef T type; };
|
|
||||||
|
|
||||||
// Specified by TR1 [4.7.4] Pointer modifications.
|
|
||||||
template<typename T> struct remove_pointer { typedef T type; };
|
|
||||||
template<typename T> struct remove_pointer<T*> { typedef T type; };
|
|
||||||
template<typename T> struct remove_pointer<T* const> { typedef T type; };
|
|
||||||
template<typename T> struct remove_pointer<T* volatile> { typedef T type; };
|
|
||||||
template<typename T> struct remove_pointer<T* const volatile> {
|
|
||||||
typedef T type; };
|
|
||||||
|
|
||||||
// Specified by TR1 [4.6] Relationships between types
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
// This class is an implementation detail for is_convertible, and you
|
|
||||||
// don't need to know how it works to use is_convertible. For those
|
|
||||||
// who care: we declare two different functions, one whose argument is
|
|
||||||
// of type To and one with a variadic argument list. We give them
|
|
||||||
// return types of different size, so we can use sizeof to trick the
|
|
||||||
// compiler into telling us which function it would have chosen if we
|
|
||||||
// had called it with an argument of type From. See Alexandrescu's
|
|
||||||
// _Modern C++ Design_ for more details on this sort of trick.
|
|
||||||
|
|
||||||
template <typename From, typename To>
|
|
||||||
struct ConvertHelper {
|
|
||||||
static small_ Test(To);
|
|
||||||
static big_ Test(...);
|
|
||||||
static From Create();
|
|
||||||
};
|
|
||||||
} // namespace internal
|
|
||||||
|
|
||||||
// Inherits from true_type if From is convertible to To, false_type otherwise.
|
|
||||||
template <typename From, typename To>
|
|
||||||
struct is_convertible
|
|
||||||
: integral_constant<bool,
|
|
||||||
sizeof(internal::ConvertHelper<From, To>::Test(
|
|
||||||
internal::ConvertHelper<From, To>::Create()))
|
|
||||||
== sizeof(small_)> {
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
_END_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
#endif // BASE_TYPE_TRAITS_H_
|
|
File diff suppressed because it is too large
Load Diff
@ -1,103 +0,0 @@
|
|||||||
// Copyright (c) 2007, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// ---
|
|
||||||
// Author: Craig Silverstein
|
|
||||||
//
|
|
||||||
// This tests mostly that we can #include the files correctly
|
|
||||||
// and have them work. This unittest purposefully does not
|
|
||||||
// #include <config.h>; it's meant to emulate what a 'regular
|
|
||||||
// install' of sparsehash would be able to see.
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <google/sparse_hash_set>
|
|
||||||
#include <google/sparse_hash_map>
|
|
||||||
#include <google/dense_hash_set>
|
|
||||||
#include <google/dense_hash_map>
|
|
||||||
|
|
||||||
#define CHECK_IFF(cond, when) do { \
|
|
||||||
if (when) { \
|
|
||||||
if (!(cond)) { \
|
|
||||||
puts("ERROR: " #cond " failed when " #when " is true\n"); \
|
|
||||||
exit(1); \
|
|
||||||
} \
|
|
||||||
} else { \
|
|
||||||
if (cond) { \
|
|
||||||
puts("ERROR: " #cond " succeeded when " #when " is false\n"); \
|
|
||||||
exit(1); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
// Run with an argument to get verbose output
|
|
||||||
const bool verbose = argc > 1;
|
|
||||||
|
|
||||||
google::sparse_hash_set<int> sset;
|
|
||||||
google::sparse_hash_map<int, int> smap;
|
|
||||||
google::dense_hash_set<int> dset;
|
|
||||||
google::dense_hash_map<int, int> dmap;
|
|
||||||
dset.set_empty_key(-1);
|
|
||||||
dmap.set_empty_key(-1);
|
|
||||||
|
|
||||||
for (int i = 0; i < 100; i += 10) { // go by tens
|
|
||||||
sset.insert(i);
|
|
||||||
smap[i] = i+1;
|
|
||||||
dset.insert(i + 5);
|
|
||||||
dmap[i+5] = i+6;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (verbose) {
|
|
||||||
for (google::sparse_hash_set<int>::const_iterator it = sset.begin();
|
|
||||||
it != sset.end(); ++it)
|
|
||||||
printf("sset: %d\n", *it);
|
|
||||||
for (google::sparse_hash_map<int,int>::const_iterator it = smap.begin();
|
|
||||||
it != smap.end(); ++it)
|
|
||||||
printf("smap: %d -> %d\n", it->first, it->second);
|
|
||||||
for (google::dense_hash_set<int>::const_iterator it = dset.begin();
|
|
||||||
it != dset.end(); ++it)
|
|
||||||
printf("dset: %d\n", *it);
|
|
||||||
for (google::dense_hash_map<int,int>::const_iterator it = dmap.begin();
|
|
||||||
it != dmap.end(); ++it)
|
|
||||||
printf("dmap: %d -> %d\n", it->first, it->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 100; i++) {
|
|
||||||
CHECK_IFF(sset.find(i) != sset.end(), (i % 10) == 0);
|
|
||||||
CHECK_IFF(smap.find(i) != smap.end(), (i % 10) == 0);
|
|
||||||
CHECK_IFF(smap.find(i) != smap.end() && smap.find(i)->second == i+1,
|
|
||||||
(i % 10) == 0);
|
|
||||||
CHECK_IFF(dset.find(i) != dset.end(), (i % 10) == 5);
|
|
||||||
CHECK_IFF(dmap.find(i) != dmap.end(), (i % 10) == 5);
|
|
||||||
CHECK_IFF(dmap.find(i) != dmap.end() && dmap.find(i)->second == i+1,
|
|
||||||
(i % 10) == 5);
|
|
||||||
}
|
|
||||||
printf("PASS\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,696 +0,0 @@
|
|||||||
// Copyright (c) 2005, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// ---
|
|
||||||
// Author: Craig Silverstein
|
|
||||||
//
|
|
||||||
// This tests <google/sparsetable>
|
|
||||||
//
|
|
||||||
// Since sparsetable is templatized, it's important that we test every
|
|
||||||
// function in every class in this file -- not just to see if it
|
|
||||||
// works, but even if it compiles.
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include <string>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h> // for memcmp()
|
|
||||||
#include <stdlib.h> // defines unlink() on some windows platforms(?)
|
|
||||||
#ifdef HAVE_UNISTD_H
|
|
||||||
#include <unistd.h> // for unlink()
|
|
||||||
#include <sys/types.h> // for size_t
|
|
||||||
#include <string>
|
|
||||||
#endif
|
|
||||||
#include <google/sparsetable>
|
|
||||||
|
|
||||||
using STL_NAMESPACE::string;
|
|
||||||
using GOOGLE_NAMESPACE::sparsetable;
|
|
||||||
|
|
||||||
// Many sparsetable operations return a size_t. Rather than have to
|
|
||||||
// use PRIuS everywhere, we'll just cast to a "big enough" value.
|
|
||||||
#define UL(x) ( static_cast<unsigned long>(x) )
|
|
||||||
|
|
||||||
|
|
||||||
static char outbuf[10240]; // big enough for these tests
|
|
||||||
static char* out = outbuf; // where to write next
|
|
||||||
#define LEFT (outbuf + sizeof(outbuf) - out)
|
|
||||||
|
|
||||||
#define TEST(cond) out += snprintf(out, LEFT, #cond "? %s\n", \
|
|
||||||
(cond) ? "yes" : "no");
|
|
||||||
|
|
||||||
inline string AsString(int n) {
|
|
||||||
const int N = 64;
|
|
||||||
char buf[N];
|
|
||||||
snprintf(buf, N, "%d", n);
|
|
||||||
return string(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test sparsetable with a POD type, int.
|
|
||||||
void TestInt() {
|
|
||||||
out += snprintf(out, LEFT, "int test\n");
|
|
||||||
sparsetable<int> x(7), y(70), z;
|
|
||||||
x.set(4, 10);
|
|
||||||
y.set(12, -12);
|
|
||||||
y.set(47, -47);
|
|
||||||
y.set(48, -48);
|
|
||||||
y.set(49, -49);
|
|
||||||
|
|
||||||
const sparsetable<int> constx(x);
|
|
||||||
const sparsetable<int> consty(y);
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
// Test the plain iterators
|
|
||||||
|
|
||||||
for ( sparsetable<int>::iterator it = x.begin(); it != x.end(); ++it ) {
|
|
||||||
out += snprintf(out, LEFT, "x[%lu]: %d\n", UL(it - x.begin()), int(*it));
|
|
||||||
}
|
|
||||||
for ( sparsetable<int>::const_iterator it = x.begin(); it != x.end(); ++it ) {
|
|
||||||
out += snprintf(out, LEFT, "x[%lu]: %d\n", UL(it - x.begin()), *it);
|
|
||||||
}
|
|
||||||
for ( sparsetable<int>::reverse_iterator it = x.rbegin(); it != x.rend(); ++it ) {
|
|
||||||
out += snprintf(out, LEFT, "x[%lu]: %d\n", UL(x.rend()-1 - it), int(*it));
|
|
||||||
}
|
|
||||||
for ( sparsetable<int>::const_reverse_iterator it = constx.rbegin(); it != constx.rend(); ++it ) {
|
|
||||||
out += snprintf(out, LEFT, "x[%lu]: %d\n", UL(constx.rend()-1 - it), *it);
|
|
||||||
}
|
|
||||||
for ( sparsetable<int>::iterator it = z.begin(); it != z.end(); ++it ) {
|
|
||||||
out += snprintf(out, LEFT, "z[%lu]: %d\n", UL(it - z.begin()), int(*it));
|
|
||||||
}
|
|
||||||
|
|
||||||
{ // array version
|
|
||||||
out += snprintf(out, LEFT, "x[3]: %d\n", int(x[3]));
|
|
||||||
out += snprintf(out, LEFT, "x[4]: %d\n", int(x[4]));
|
|
||||||
out += snprintf(out, LEFT, "x[5]: %d\n", int(x[5]));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
sparsetable<int>::iterator it; // non-const version
|
|
||||||
out += snprintf(out, LEFT, "x[4]: %d\n", int(x.begin()[4]));
|
|
||||||
it = x.begin() + 4; // should point to the non-zero value
|
|
||||||
out += snprintf(out, LEFT, "x[4]: %d\n", int(*it));
|
|
||||||
it--;
|
|
||||||
--it;
|
|
||||||
it += 5;
|
|
||||||
it -= 2;
|
|
||||||
it++;
|
|
||||||
++it;
|
|
||||||
it = it - 3;
|
|
||||||
it = 1 + it; // now at 5
|
|
||||||
out += snprintf(out, LEFT, "x[3]: %d\n", int(it[-2]));
|
|
||||||
out += snprintf(out, LEFT, "x[4]: %d\n", int(it[-1]));
|
|
||||||
*it = 55;
|
|
||||||
out += snprintf(out, LEFT, "x[5]: %d\n", int(it[0]));
|
|
||||||
out += snprintf(out, LEFT, "x[5]: %d\n", int(*it));
|
|
||||||
int *x6 = &(it[1]);
|
|
||||||
*x6 = 66;
|
|
||||||
out += snprintf(out, LEFT, "x[6]: %d\n", int(*(it + 1)));
|
|
||||||
// Let's test comparitors as well
|
|
||||||
TEST(it == it);
|
|
||||||
TEST(!(it != it));
|
|
||||||
TEST(!(it < it));
|
|
||||||
TEST(!(it > it));
|
|
||||||
TEST(it <= it);
|
|
||||||
TEST(it >= it);
|
|
||||||
|
|
||||||
sparsetable<int>::iterator it_minus_1 = it - 1;
|
|
||||||
TEST(!(it == it_minus_1));
|
|
||||||
TEST(it != it_minus_1);
|
|
||||||
TEST(!(it < it_minus_1));
|
|
||||||
TEST(it > it_minus_1);
|
|
||||||
TEST(!(it <= it_minus_1));
|
|
||||||
TEST(it >= it_minus_1);
|
|
||||||
TEST(!(it_minus_1 == it));
|
|
||||||
TEST(it_minus_1 != it);
|
|
||||||
TEST(it_minus_1 < it);
|
|
||||||
TEST(!(it_minus_1 > it));
|
|
||||||
TEST(it_minus_1 <= it);
|
|
||||||
TEST(!(it_minus_1 >= it));
|
|
||||||
|
|
||||||
sparsetable<int>::iterator it_plus_1 = it + 1;
|
|
||||||
TEST(!(it == it_plus_1));
|
|
||||||
TEST(it != it_plus_1);
|
|
||||||
TEST(it < it_plus_1);
|
|
||||||
TEST(!(it > it_plus_1));
|
|
||||||
TEST(it <= it_plus_1);
|
|
||||||
TEST(!(it >= it_plus_1));
|
|
||||||
TEST(!(it_plus_1 == it));
|
|
||||||
TEST(it_plus_1 != it);
|
|
||||||
TEST(!(it_plus_1 < it));
|
|
||||||
TEST(it_plus_1 > it);
|
|
||||||
TEST(!(it_plus_1 <= it));
|
|
||||||
TEST(it_plus_1 >= it);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
sparsetable<int>::const_iterator it; // const version
|
|
||||||
out += snprintf(out, LEFT, "x[4]: %d\n", int(x.begin()[4]));
|
|
||||||
it = x.begin() + 4; // should point to the non-zero value
|
|
||||||
out += snprintf(out, LEFT, "x[4]: %d\n", *it);
|
|
||||||
it--;
|
|
||||||
--it;
|
|
||||||
it += 5;
|
|
||||||
it -= 2;
|
|
||||||
it++;
|
|
||||||
++it;
|
|
||||||
it = it - 3;
|
|
||||||
it = 1 + it; // now at 5
|
|
||||||
out += snprintf(out, LEFT, "x[3]: %d\n", it[-2]);
|
|
||||||
out += snprintf(out, LEFT, "x[4]: %d\n", it[-1]);
|
|
||||||
out += snprintf(out, LEFT, "x[5]: %d\n", *it);
|
|
||||||
out += snprintf(out, LEFT, "x[6]: %d\n", *(it + 1));
|
|
||||||
// Let's test comparitors as well
|
|
||||||
TEST(it == it);
|
|
||||||
TEST(!(it != it));
|
|
||||||
TEST(!(it < it));
|
|
||||||
TEST(!(it > it));
|
|
||||||
TEST(it <= it);
|
|
||||||
TEST(it >= it);
|
|
||||||
|
|
||||||
sparsetable<int>::const_iterator it_minus_1 = it - 1;
|
|
||||||
TEST(!(it == it_minus_1));
|
|
||||||
TEST(it != it_minus_1);
|
|
||||||
TEST(!(it < it_minus_1));
|
|
||||||
TEST(it > it_minus_1);
|
|
||||||
TEST(!(it <= it_minus_1));
|
|
||||||
TEST(it >= it_minus_1);
|
|
||||||
TEST(!(it_minus_1 == it));
|
|
||||||
TEST(it_minus_1 != it);
|
|
||||||
TEST(it_minus_1 < it);
|
|
||||||
TEST(!(it_minus_1 > it));
|
|
||||||
TEST(it_minus_1 <= it);
|
|
||||||
TEST(!(it_minus_1 >= it));
|
|
||||||
|
|
||||||
sparsetable<int>::const_iterator it_plus_1 = it + 1;
|
|
||||||
TEST(!(it == it_plus_1));
|
|
||||||
TEST(it != it_plus_1);
|
|
||||||
TEST(it < it_plus_1);
|
|
||||||
TEST(!(it > it_plus_1));
|
|
||||||
TEST(it <= it_plus_1);
|
|
||||||
TEST(!(it >= it_plus_1));
|
|
||||||
TEST(!(it_plus_1 == it));
|
|
||||||
TEST(it_plus_1 != it);
|
|
||||||
TEST(!(it_plus_1 < it));
|
|
||||||
TEST(it_plus_1 > it);
|
|
||||||
TEST(!(it_plus_1 <= it));
|
|
||||||
TEST(it_plus_1 >= it);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(x.begin() == x.begin() + 1 - 1);
|
|
||||||
TEST(x.begin() < x.end());
|
|
||||||
TEST(z.begin() < z.end());
|
|
||||||
TEST(z.begin() <= z.end());
|
|
||||||
TEST(z.begin() == z.end());
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
// Test the non-empty iterators
|
|
||||||
|
|
||||||
for ( sparsetable<int>::nonempty_iterator it = x.nonempty_begin(); it != x.nonempty_end(); ++it ) {
|
|
||||||
out += snprintf(out, LEFT, "x[??]: %d\n", *it);
|
|
||||||
}
|
|
||||||
for ( sparsetable<int>::const_nonempty_iterator it = y.nonempty_begin(); it != y.nonempty_end(); ++it ) {
|
|
||||||
out += snprintf(out, LEFT, "y[??]: %d\n", *it);
|
|
||||||
}
|
|
||||||
for ( sparsetable<int>::reverse_nonempty_iterator it = y.nonempty_rbegin(); it != y.nonempty_rend(); ++it ) {
|
|
||||||
out += snprintf(out, LEFT, "y[??]: %d\n", *it);
|
|
||||||
}
|
|
||||||
for ( sparsetable<int>::const_reverse_nonempty_iterator it = consty.nonempty_rbegin(); it != consty.nonempty_rend(); ++it ) {
|
|
||||||
out += snprintf(out, LEFT, "y[??]: %d\n", *it);
|
|
||||||
}
|
|
||||||
for ( sparsetable<int>::nonempty_iterator it = z.nonempty_begin(); it != z.nonempty_end(); ++it ) {
|
|
||||||
out += snprintf(out, LEFT, "z[??]: %d\n", *it);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
sparsetable<int>::nonempty_iterator it; // non-const version
|
|
||||||
out += snprintf(out, LEFT, "first non-empty y: %d\n", *y.nonempty_begin());
|
|
||||||
out += snprintf(out, LEFT, "first non-empty x: %d\n", *x.nonempty_begin());
|
|
||||||
it = x.nonempty_begin();
|
|
||||||
++it; // should be at end
|
|
||||||
--it;
|
|
||||||
out += snprintf(out, LEFT, "first non-empty x: %d\n", *it++);
|
|
||||||
it--;
|
|
||||||
out += snprintf(out, LEFT, "first non-empty x: %d\n", *it++);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
sparsetable<int>::const_nonempty_iterator it; // non-const version
|
|
||||||
out += snprintf(out, LEFT, "first non-empty y: %d\n", *y.nonempty_begin());
|
|
||||||
out += snprintf(out, LEFT, "first non-empty x: %d\n", *x.nonempty_begin());
|
|
||||||
it = x.nonempty_begin();
|
|
||||||
++it; // should be at end
|
|
||||||
--it;
|
|
||||||
out += snprintf(out, LEFT, "first non-empty x: %d\n", *it++);
|
|
||||||
it--;
|
|
||||||
out += snprintf(out, LEFT, "first non-empty x: %d\n", *it++);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(x.begin() == x.begin() + 1 - 1);
|
|
||||||
TEST(z.begin() != z.end());
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
// Test sparsetable functions
|
|
||||||
out += snprintf(out, LEFT, "x has %lu/%lu buckets, "
|
|
||||||
"y %lu/%lu, z %lu/%lu\n",
|
|
||||||
UL(x.num_nonempty()), UL(x.size()),
|
|
||||||
UL(y.num_nonempty()), UL(y.size()),
|
|
||||||
UL(z.num_nonempty()), UL(z.size()));
|
|
||||||
|
|
||||||
y.resize(48); // should get rid of 48 and 49
|
|
||||||
y.resize(70); // 48 and 49 should still be gone
|
|
||||||
out += snprintf(out, LEFT, "y shrank and grew: it's now %lu/%lu\n",
|
|
||||||
UL(y.num_nonempty()), UL(y.size()));
|
|
||||||
out += snprintf(out, LEFT, "y[12] = %d, y.get(12) = %d\n", int(y[12]), y.get(12));
|
|
||||||
y.erase(12);
|
|
||||||
out += snprintf(out, LEFT, "y[12] cleared. y now %lu/%lu. "
|
|
||||||
"y[12] = %d, y.get(12) = %d\n",
|
|
||||||
UL(y.num_nonempty()), UL(y.size()), int(y[12]), y.get(12));
|
|
||||||
|
|
||||||
swap(x, y);
|
|
||||||
|
|
||||||
y.clear();
|
|
||||||
TEST(y == z);
|
|
||||||
|
|
||||||
y.resize(70);
|
|
||||||
for ( int i = 10; i < 40; ++i )
|
|
||||||
y[i] = -i;
|
|
||||||
y.erase(y.begin() + 15, y.begin() + 30);
|
|
||||||
y.erase(y.begin() + 34);
|
|
||||||
y.erase(12);
|
|
||||||
y.resize(38);
|
|
||||||
y.resize(10000);
|
|
||||||
y[9898] = -9898;
|
|
||||||
for ( sparsetable<int>::const_iterator it = y.begin(); it != y.end(); ++it ) {
|
|
||||||
if ( y.test(it) )
|
|
||||||
out += snprintf(out, LEFT, "y[%lu] is set\n", UL(it - y.begin()));
|
|
||||||
}
|
|
||||||
out += snprintf(out, LEFT, "That's %lu set buckets\n", UL(y.num_nonempty()));
|
|
||||||
|
|
||||||
out += snprintf(out, LEFT, "Starting from y[32]...\n");
|
|
||||||
for ( sparsetable<int>::const_nonempty_iterator it = y.get_iter(32);
|
|
||||||
it != y.nonempty_end(); ++it )
|
|
||||||
out += snprintf(out, LEFT, "y[??] = %d\n", *it);
|
|
||||||
|
|
||||||
out += snprintf(out, LEFT, "From y[32] down...\n");
|
|
||||||
for ( sparsetable<int>::nonempty_iterator it = y.get_iter(32);
|
|
||||||
it != y.nonempty_begin(); )
|
|
||||||
out += snprintf(out, LEFT, "y[??] = %d\n", *--it);
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
// Test I/O
|
|
||||||
string filestr = "/tmp/.sparsetable.test";
|
|
||||||
const char *file = filestr.c_str();
|
|
||||||
FILE *fp = fopen(file, "wb");
|
|
||||||
if ( fp == NULL ) {
|
|
||||||
// maybe we can't write to /tmp/. Try the current directory
|
|
||||||
file = ".sparsetable.test";
|
|
||||||
fp = fopen(file, "wb");
|
|
||||||
}
|
|
||||||
if ( fp == NULL ) {
|
|
||||||
out += snprintf(out, LEFT, "Can't open %s, skipping disk write...\n", file);
|
|
||||||
} else {
|
|
||||||
y.write_metadata(fp); // only write meta-information
|
|
||||||
y.write_nopointer_data(fp);
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
fp = fopen(file, "rb");
|
|
||||||
if ( fp == NULL ) {
|
|
||||||
out += snprintf(out, LEFT, "Can't open %s, skipping disk read...\n", file);
|
|
||||||
} else {
|
|
||||||
sparsetable<int> y2;
|
|
||||||
y2.read_metadata(fp);
|
|
||||||
y2.read_nopointer_data(fp);
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
for ( sparsetable<int>::const_iterator it = y2.begin(); it != y2.end(); ++it ) {
|
|
||||||
if ( y2.test(it) )
|
|
||||||
out += snprintf(out, LEFT, "y2[%lu] is %d\n", UL(it - y2.begin()), *it);
|
|
||||||
}
|
|
||||||
out += snprintf(out, LEFT, "That's %lu set buckets\n", UL(y2.num_nonempty()));
|
|
||||||
}
|
|
||||||
unlink(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test sparsetable with a non-POD type, std::string
|
|
||||||
void TestString() {
|
|
||||||
out += snprintf(out, LEFT, "string test\n");
|
|
||||||
sparsetable<string> x(7), y(70), z;
|
|
||||||
x.set(4, "foo");
|
|
||||||
y.set(12, "orange");
|
|
||||||
y.set(47, "grape");
|
|
||||||
y.set(48, "pear");
|
|
||||||
y.set(49, "apple");
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
// Test the plain iterators
|
|
||||||
|
|
||||||
for ( sparsetable<string>::iterator it = x.begin(); it != x.end(); ++it ) {
|
|
||||||
out += snprintf(out, LEFT, "x[%lu]: %s\n",
|
|
||||||
UL(it - x.begin()), static_cast<string>(*it).c_str());
|
|
||||||
}
|
|
||||||
for ( sparsetable<string>::iterator it = z.begin(); it != z.end(); ++it ) {
|
|
||||||
out += snprintf(out, LEFT, "z[%lu]: %s\n",
|
|
||||||
UL(it - z.begin()), static_cast<string>(*it).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(x.begin() == x.begin() + 1 - 1);
|
|
||||||
TEST(x.begin() < x.end());
|
|
||||||
TEST(z.begin() < z.end());
|
|
||||||
TEST(z.begin() <= z.end());
|
|
||||||
TEST(z.begin() == z.end());
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
// Test the non-empty iterators
|
|
||||||
for ( sparsetable<string>::nonempty_iterator it = x.nonempty_begin(); it != x.nonempty_end(); ++it ) {
|
|
||||||
out += snprintf(out, LEFT, "x[??]: %s\n", it->c_str());
|
|
||||||
}
|
|
||||||
for ( sparsetable<string>::const_nonempty_iterator it = y.nonempty_begin(); it != y.nonempty_end(); ++it ) {
|
|
||||||
out += snprintf(out, LEFT, "y[??]: %s\n", it->c_str());
|
|
||||||
}
|
|
||||||
for ( sparsetable<string>::nonempty_iterator it = z.nonempty_begin(); it != z.nonempty_end(); ++it ) {
|
|
||||||
out += snprintf(out, LEFT, "z[??]: %s\n", it->c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
// Test sparsetable functions
|
|
||||||
out += snprintf(out, LEFT, "x has %lu/%lu buckets, y %lu/%lu, z %lu/%lu\n",
|
|
||||||
UL(x.num_nonempty()), UL(x.size()),
|
|
||||||
UL(y.num_nonempty()), UL(y.size()),
|
|
||||||
UL(z.num_nonempty()), UL(z.size()));
|
|
||||||
|
|
||||||
y.resize(48); // should get rid of 48 and 49
|
|
||||||
y.resize(70); // 48 and 49 should still be gone
|
|
||||||
out += snprintf(out, LEFT, "y shrank and grew: it's now %lu/%lu\n",
|
|
||||||
UL(y.num_nonempty()), UL(y.size()));
|
|
||||||
out += snprintf(out, LEFT, "y[12] = %s, y.get(12) = %s\n",
|
|
||||||
static_cast<string>(y[12]).c_str(), y.get(12).c_str());
|
|
||||||
y.erase(12);
|
|
||||||
out += snprintf(out, LEFT, "y[12] cleared. y now %lu/%lu. "
|
|
||||||
"y[12] = %s, y.get(12) = %s\n",
|
|
||||||
UL(y.num_nonempty()), UL(y.size()),
|
|
||||||
static_cast<string>(y[12]).c_str(),
|
|
||||||
static_cast<string>(y.get(12)).c_str());
|
|
||||||
swap(x, y);
|
|
||||||
|
|
||||||
y.clear();
|
|
||||||
TEST(y == z);
|
|
||||||
|
|
||||||
y.resize(70);
|
|
||||||
for ( int i = 10; i < 40; ++i )
|
|
||||||
y.set(i, AsString(-i));
|
|
||||||
y.erase(y.begin() + 15, y.begin() + 30);
|
|
||||||
y.erase(y.begin() + 34);
|
|
||||||
y.erase(12);
|
|
||||||
y.resize(38);
|
|
||||||
y.resize(10000);
|
|
||||||
y.set(9898, AsString(-9898));
|
|
||||||
for ( sparsetable<string>::const_iterator it = y.begin(); it != y.end(); ++it ) {
|
|
||||||
if ( y.test(it) )
|
|
||||||
out += snprintf(out, LEFT, "y[%lu] is set\n", UL(it - y.begin()));
|
|
||||||
}
|
|
||||||
out += snprintf(out, LEFT, "That's %lu set buckets\n", UL(y.num_nonempty()));
|
|
||||||
|
|
||||||
out += snprintf(out, LEFT, "Starting from y[32]...\n");
|
|
||||||
for ( sparsetable<string>::const_nonempty_iterator it = y.get_iter(32);
|
|
||||||
it != y.nonempty_end(); ++it )
|
|
||||||
out += snprintf(out, LEFT, "y[??] = %s\n", it->c_str());
|
|
||||||
|
|
||||||
out += snprintf(out, LEFT, "From y[32] down...\n");
|
|
||||||
for ( sparsetable<string>::nonempty_iterator it = y.get_iter(32);
|
|
||||||
it != y.nonempty_begin(); )
|
|
||||||
out += snprintf(out, LEFT, "y[??] = %s\n", (*--it).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
// The expected output from all of the above: TestInt() and TestString()
|
|
||||||
static const char g_expected[] = (
|
|
||||||
"int test\n"
|
|
||||||
"x[0]: 0\n"
|
|
||||||
"x[1]: 0\n"
|
|
||||||
"x[2]: 0\n"
|
|
||||||
"x[3]: 0\n"
|
|
||||||
"x[4]: 10\n"
|
|
||||||
"x[5]: 0\n"
|
|
||||||
"x[6]: 0\n"
|
|
||||||
"x[0]: 0\n"
|
|
||||||
"x[1]: 0\n"
|
|
||||||
"x[2]: 0\n"
|
|
||||||
"x[3]: 0\n"
|
|
||||||
"x[4]: 10\n"
|
|
||||||
"x[5]: 0\n"
|
|
||||||
"x[6]: 0\n"
|
|
||||||
"x[6]: 0\n"
|
|
||||||
"x[5]: 0\n"
|
|
||||||
"x[4]: 10\n"
|
|
||||||
"x[3]: 0\n"
|
|
||||||
"x[2]: 0\n"
|
|
||||||
"x[1]: 0\n"
|
|
||||||
"x[0]: 0\n"
|
|
||||||
"x[6]: 0\n"
|
|
||||||
"x[5]: 0\n"
|
|
||||||
"x[4]: 10\n"
|
|
||||||
"x[3]: 0\n"
|
|
||||||
"x[2]: 0\n"
|
|
||||||
"x[1]: 0\n"
|
|
||||||
"x[0]: 0\n"
|
|
||||||
"x[3]: 0\n"
|
|
||||||
"x[4]: 10\n"
|
|
||||||
"x[5]: 0\n"
|
|
||||||
"x[4]: 10\n"
|
|
||||||
"x[4]: 10\n"
|
|
||||||
"x[3]: 0\n"
|
|
||||||
"x[4]: 10\n"
|
|
||||||
"x[5]: 55\n"
|
|
||||||
"x[5]: 55\n"
|
|
||||||
"x[6]: 66\n"
|
|
||||||
"it == it? yes\n"
|
|
||||||
"!(it != it)? yes\n"
|
|
||||||
"!(it < it)? yes\n"
|
|
||||||
"!(it > it)? yes\n"
|
|
||||||
"it <= it? yes\n"
|
|
||||||
"it >= it? yes\n"
|
|
||||||
"!(it == it_minus_1)? yes\n"
|
|
||||||
"it != it_minus_1? yes\n"
|
|
||||||
"!(it < it_minus_1)? yes\n"
|
|
||||||
"it > it_minus_1? yes\n"
|
|
||||||
"!(it <= it_minus_1)? yes\n"
|
|
||||||
"it >= it_minus_1? yes\n"
|
|
||||||
"!(it_minus_1 == it)? yes\n"
|
|
||||||
"it_minus_1 != it? yes\n"
|
|
||||||
"it_minus_1 < it? yes\n"
|
|
||||||
"!(it_minus_1 > it)? yes\n"
|
|
||||||
"it_minus_1 <= it? yes\n"
|
|
||||||
"!(it_minus_1 >= it)? yes\n"
|
|
||||||
"!(it == it_plus_1)? yes\n"
|
|
||||||
"it != it_plus_1? yes\n"
|
|
||||||
"it < it_plus_1? yes\n"
|
|
||||||
"!(it > it_plus_1)? yes\n"
|
|
||||||
"it <= it_plus_1? yes\n"
|
|
||||||
"!(it >= it_plus_1)? yes\n"
|
|
||||||
"!(it_plus_1 == it)? yes\n"
|
|
||||||
"it_plus_1 != it? yes\n"
|
|
||||||
"!(it_plus_1 < it)? yes\n"
|
|
||||||
"it_plus_1 > it? yes\n"
|
|
||||||
"!(it_plus_1 <= it)? yes\n"
|
|
||||||
"it_plus_1 >= it? yes\n"
|
|
||||||
"x[4]: 10\n"
|
|
||||||
"x[4]: 10\n"
|
|
||||||
"x[3]: 0\n"
|
|
||||||
"x[4]: 10\n"
|
|
||||||
"x[5]: 55\n"
|
|
||||||
"x[6]: 66\n"
|
|
||||||
"it == it? yes\n"
|
|
||||||
"!(it != it)? yes\n"
|
|
||||||
"!(it < it)? yes\n"
|
|
||||||
"!(it > it)? yes\n"
|
|
||||||
"it <= it? yes\n"
|
|
||||||
"it >= it? yes\n"
|
|
||||||
"!(it == it_minus_1)? yes\n"
|
|
||||||
"it != it_minus_1? yes\n"
|
|
||||||
"!(it < it_minus_1)? yes\n"
|
|
||||||
"it > it_minus_1? yes\n"
|
|
||||||
"!(it <= it_minus_1)? yes\n"
|
|
||||||
"it >= it_minus_1? yes\n"
|
|
||||||
"!(it_minus_1 == it)? yes\n"
|
|
||||||
"it_minus_1 != it? yes\n"
|
|
||||||
"it_minus_1 < it? yes\n"
|
|
||||||
"!(it_minus_1 > it)? yes\n"
|
|
||||||
"it_minus_1 <= it? yes\n"
|
|
||||||
"!(it_minus_1 >= it)? yes\n"
|
|
||||||
"!(it == it_plus_1)? yes\n"
|
|
||||||
"it != it_plus_1? yes\n"
|
|
||||||
"it < it_plus_1? yes\n"
|
|
||||||
"!(it > it_plus_1)? yes\n"
|
|
||||||
"it <= it_plus_1? yes\n"
|
|
||||||
"!(it >= it_plus_1)? yes\n"
|
|
||||||
"!(it_plus_1 == it)? yes\n"
|
|
||||||
"it_plus_1 != it? yes\n"
|
|
||||||
"!(it_plus_1 < it)? yes\n"
|
|
||||||
"it_plus_1 > it? yes\n"
|
|
||||||
"!(it_plus_1 <= it)? yes\n"
|
|
||||||
"it_plus_1 >= it? yes\n"
|
|
||||||
"x.begin() == x.begin() + 1 - 1? yes\n"
|
|
||||||
"x.begin() < x.end()? yes\n"
|
|
||||||
"z.begin() < z.end()? no\n"
|
|
||||||
"z.begin() <= z.end()? yes\n"
|
|
||||||
"z.begin() == z.end()? yes\n"
|
|
||||||
"x[??]: 10\n"
|
|
||||||
"x[??]: 55\n"
|
|
||||||
"x[??]: 66\n"
|
|
||||||
"y[??]: -12\n"
|
|
||||||
"y[??]: -47\n"
|
|
||||||
"y[??]: -48\n"
|
|
||||||
"y[??]: -49\n"
|
|
||||||
"y[??]: -49\n"
|
|
||||||
"y[??]: -48\n"
|
|
||||||
"y[??]: -47\n"
|
|
||||||
"y[??]: -12\n"
|
|
||||||
"y[??]: -49\n"
|
|
||||||
"y[??]: -48\n"
|
|
||||||
"y[??]: -47\n"
|
|
||||||
"y[??]: -12\n"
|
|
||||||
"first non-empty y: -12\n"
|
|
||||||
"first non-empty x: 10\n"
|
|
||||||
"first non-empty x: 10\n"
|
|
||||||
"first non-empty x: 10\n"
|
|
||||||
"first non-empty y: -12\n"
|
|
||||||
"first non-empty x: 10\n"
|
|
||||||
"first non-empty x: 10\n"
|
|
||||||
"first non-empty x: 10\n"
|
|
||||||
"x.begin() == x.begin() + 1 - 1? yes\n"
|
|
||||||
"z.begin() != z.end()? no\n"
|
|
||||||
"x has 3/7 buckets, y 4/70, z 0/0\n"
|
|
||||||
"y shrank and grew: it's now 2/70\n"
|
|
||||||
"y[12] = -12, y.get(12) = -12\n"
|
|
||||||
"y[12] cleared. y now 1/70. y[12] = 0, y.get(12) = 0\n"
|
|
||||||
"y == z? no\n"
|
|
||||||
"y[10] is set\n"
|
|
||||||
"y[11] is set\n"
|
|
||||||
"y[13] is set\n"
|
|
||||||
"y[14] is set\n"
|
|
||||||
"y[30] is set\n"
|
|
||||||
"y[31] is set\n"
|
|
||||||
"y[32] is set\n"
|
|
||||||
"y[33] is set\n"
|
|
||||||
"y[35] is set\n"
|
|
||||||
"y[36] is set\n"
|
|
||||||
"y[37] is set\n"
|
|
||||||
"y[9898] is set\n"
|
|
||||||
"That's 12 set buckets\n"
|
|
||||||
"Starting from y[32]...\n"
|
|
||||||
"y[??] = -32\n"
|
|
||||||
"y[??] = -33\n"
|
|
||||||
"y[??] = -35\n"
|
|
||||||
"y[??] = -36\n"
|
|
||||||
"y[??] = -37\n"
|
|
||||||
"y[??] = -9898\n"
|
|
||||||
"From y[32] down...\n"
|
|
||||||
"y[??] = -31\n"
|
|
||||||
"y[??] = -30\n"
|
|
||||||
"y[??] = -14\n"
|
|
||||||
"y[??] = -13\n"
|
|
||||||
"y[??] = -11\n"
|
|
||||||
"y[??] = -10\n"
|
|
||||||
"y2[10] is -10\n"
|
|
||||||
"y2[11] is -11\n"
|
|
||||||
"y2[13] is -13\n"
|
|
||||||
"y2[14] is -14\n"
|
|
||||||
"y2[30] is -30\n"
|
|
||||||
"y2[31] is -31\n"
|
|
||||||
"y2[32] is -32\n"
|
|
||||||
"y2[33] is -33\n"
|
|
||||||
"y2[35] is -35\n"
|
|
||||||
"y2[36] is -36\n"
|
|
||||||
"y2[37] is -37\n"
|
|
||||||
"y2[9898] is -9898\n"
|
|
||||||
"That's 12 set buckets\n"
|
|
||||||
"string test\n"
|
|
||||||
"x[0]: \n"
|
|
||||||
"x[1]: \n"
|
|
||||||
"x[2]: \n"
|
|
||||||
"x[3]: \n"
|
|
||||||
"x[4]: foo\n"
|
|
||||||
"x[5]: \n"
|
|
||||||
"x[6]: \n"
|
|
||||||
"x.begin() == x.begin() + 1 - 1? yes\n"
|
|
||||||
"x.begin() < x.end()? yes\n"
|
|
||||||
"z.begin() < z.end()? no\n"
|
|
||||||
"z.begin() <= z.end()? yes\n"
|
|
||||||
"z.begin() == z.end()? yes\n"
|
|
||||||
"x[??]: foo\n"
|
|
||||||
"y[??]: orange\n"
|
|
||||||
"y[??]: grape\n"
|
|
||||||
"y[??]: pear\n"
|
|
||||||
"y[??]: apple\n"
|
|
||||||
"x has 1/7 buckets, y 4/70, z 0/0\n"
|
|
||||||
"y shrank and grew: it's now 2/70\n"
|
|
||||||
"y[12] = orange, y.get(12) = orange\n"
|
|
||||||
"y[12] cleared. y now 1/70. y[12] = , y.get(12) = \n"
|
|
||||||
"y == z? no\n"
|
|
||||||
"y[10] is set\n"
|
|
||||||
"y[11] is set\n"
|
|
||||||
"y[13] is set\n"
|
|
||||||
"y[14] is set\n"
|
|
||||||
"y[30] is set\n"
|
|
||||||
"y[31] is set\n"
|
|
||||||
"y[32] is set\n"
|
|
||||||
"y[33] is set\n"
|
|
||||||
"y[35] is set\n"
|
|
||||||
"y[36] is set\n"
|
|
||||||
"y[37] is set\n"
|
|
||||||
"y[9898] is set\n"
|
|
||||||
"That's 12 set buckets\n"
|
|
||||||
"Starting from y[32]...\n"
|
|
||||||
"y[??] = -32\n"
|
|
||||||
"y[??] = -33\n"
|
|
||||||
"y[??] = -35\n"
|
|
||||||
"y[??] = -36\n"
|
|
||||||
"y[??] = -37\n"
|
|
||||||
"y[??] = -9898\n"
|
|
||||||
"From y[32] down...\n"
|
|
||||||
"y[??] = -31\n"
|
|
||||||
"y[??] = -30\n"
|
|
||||||
"y[??] = -14\n"
|
|
||||||
"y[??] = -13\n"
|
|
||||||
"y[??] = -11\n"
|
|
||||||
"y[??] = -10\n"
|
|
||||||
);
|
|
||||||
|
|
||||||
// defined at bottom of file for ease of maintainence
|
|
||||||
int main(int argc, char **argv) { // though we ignore the args
|
|
||||||
TestInt();
|
|
||||||
TestString();
|
|
||||||
|
|
||||||
// Finally, check to see if our output (in out) is what it's supposed to be.
|
|
||||||
const size_t r = sizeof(g_expected) - 1;
|
|
||||||
if ( r != out - outbuf || // output not the same size
|
|
||||||
memcmp(outbuf, g_expected, r) ) { // or bytes differed
|
|
||||||
fprintf(stderr, "TESTS FAILED\n\nEXPECTED:\n\n%s\n\nACTUAL:\n\n%s\n\n",
|
|
||||||
g_expected, outbuf);
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
printf("PASS.\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
timestamp for src/config.h
|
|
@ -1,488 +0,0 @@
|
|||||||
// Copyright (c) 2005, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// ---
|
|
||||||
// Authors: Sanjay Ghemawat and Craig Silverstein
|
|
||||||
//
|
|
||||||
// Time various hash map implementations
|
|
||||||
//
|
|
||||||
// See PERFORMANCE for the output of one example run.
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
extern "C" {
|
|
||||||
#include <time.h>
|
|
||||||
#ifdef HAVE_SYS_TIME_H
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_RESOURCE_H
|
|
||||||
#include <sys/resource.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_UTSNAME_H
|
|
||||||
#include <sys/utsname.h> // for uname()
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_WINDOWS_H
|
|
||||||
#include <Windows.h> // for GetTickCount()
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// The functions that we call on each map, that differ for different types.
|
|
||||||
// By default each is a noop, but we redefine them for types that need them.
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include HASH_MAP_H
|
|
||||||
#include <google/type_traits.h>
|
|
||||||
|
|
||||||
#include <google/sparse_hash_map>
|
|
||||||
using GOOGLE_NAMESPACE::sparse_hash_map;
|
|
||||||
|
|
||||||
#include <google/dense_hash_map>
|
|
||||||
using GOOGLE_NAMESPACE::dense_hash_map;
|
|
||||||
|
|
||||||
|
|
||||||
static const int kDefaultIters = 10000000;
|
|
||||||
|
|
||||||
// Normally I don't like non-const references, but using them here ensures
|
|
||||||
// the inlined code ends up as efficient as possible.
|
|
||||||
|
|
||||||
// These are operations that are supported on some hash impls but not others
|
|
||||||
template<class MapType> inline void SET_DELETED_KEY(MapType& m, int key) {}
|
|
||||||
template<class MapType> inline void SET_EMPTY_KEY(MapType& m, int key) {}
|
|
||||||
template<class MapType> inline void RESIZE(MapType& m, int iters) {}
|
|
||||||
|
|
||||||
template<class K, class V, class H>
|
|
||||||
inline void SET_DELETED_KEY(sparse_hash_map<K,V,H>& m, int key) {
|
|
||||||
m.set_deleted_key(key);
|
|
||||||
}
|
|
||||||
template<class K, class V, class H>
|
|
||||||
inline void SET_DELETED_KEY(dense_hash_map<K,V,H>& m, int key) {
|
|
||||||
m.set_deleted_key(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class K, class V, class H>
|
|
||||||
inline void SET_EMPTY_KEY(dense_hash_map<K,V,H>& m, int key) {
|
|
||||||
m.set_empty_key(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class K, class V, class H>
|
|
||||||
inline void RESIZE(sparse_hash_map<K,V,H>& m, int iters) {
|
|
||||||
m.resize(iters);
|
|
||||||
}
|
|
||||||
template<class K, class V, class H>
|
|
||||||
inline void RESIZE(dense_hash_map<K,V,H>& m, int iters) {
|
|
||||||
m.resize(iters);
|
|
||||||
}
|
|
||||||
#if defined(HAVE_UNORDERED_MAP)
|
|
||||||
template<class K, class V, class H>
|
|
||||||
inline void RESIZE(HASH_NAMESPACE::unordered_map<K,V,H>& m, int iters) {
|
|
||||||
m.rehash(iters); // the tr1 name for resize()
|
|
||||||
}
|
|
||||||
#elif defined(HAVE_HASH_MAP)
|
|
||||||
template<class K, class V, class H>
|
|
||||||
inline void RESIZE(HASH_NAMESPACE::hash_map<K,V,H>& m, int iters) {
|
|
||||||
#ifndef _MSC_VER /* apparently windows hash_map doesn't support resizing */
|
|
||||||
m.resize(iters);
|
|
||||||
#endif // _MSC_VER
|
|
||||||
}
|
|
||||||
#endif // HAVE_HASH_MAP
|
|
||||||
|
|
||||||
/*
|
|
||||||
* These are the objects we hash. Size is the size of the object
|
|
||||||
* (must be > sizeof(int). Hashsize is how many of these bytes we
|
|
||||||
* use when hashing (must be > sizeof(int) and < Size).
|
|
||||||
*/
|
|
||||||
template<int Size, int Hashsize> class HashObject {
|
|
||||||
public:
|
|
||||||
typedef HashObject<Size, Hashsize> class_type;
|
|
||||||
HashObject() {}
|
|
||||||
HashObject(int i) : i_(i) {
|
|
||||||
memset(buffer_, i & 255, sizeof(buffer_)); // a "random" char
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Hash() const {
|
|
||||||
int hashval = i_;
|
|
||||||
for (int i = 0; i < Hashsize - sizeof(i_); ++i) {
|
|
||||||
hashval += buffer_[i];
|
|
||||||
}
|
|
||||||
return SPARSEHASH_HASH<int>()(hashval); // defined in sparseconfig.h
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const class_type& that) const { return this->i_ == that.i_; }
|
|
||||||
bool operator< (const class_type& that) const { return this->i_ < that.i_; }
|
|
||||||
bool operator<=(const class_type& that) const { return this->i_ <= that.i_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
int i_; // the key used for hashing
|
|
||||||
char buffer_[Size - sizeof(int)];
|
|
||||||
};
|
|
||||||
|
|
||||||
// A specialization for the case sizeof(buffer_) == 0
|
|
||||||
template<> class HashObject<sizeof(int), sizeof(int)> {
|
|
||||||
public:
|
|
||||||
typedef HashObject<sizeof(int), sizeof(int)> class_type;
|
|
||||||
HashObject() {}
|
|
||||||
HashObject(int i) : i_(i) {}
|
|
||||||
|
|
||||||
size_t Hash() const { return SPARSEHASH_HASH<int>()(i_); }
|
|
||||||
|
|
||||||
bool operator==(const class_type& that) const { return this->i_ == that.i_; }
|
|
||||||
bool operator< (const class_type& that) const { return this->i_ < that.i_; }
|
|
||||||
bool operator<=(const class_type& that) const { return this->i_ <= that.i_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
int i_; // the key used for hashing
|
|
||||||
};
|
|
||||||
|
|
||||||
// Let the hashtable implementations know it can use an optimized memcpy,
|
|
||||||
// because the compiler defines both the destructor and copy constructor.
|
|
||||||
|
|
||||||
_START_GOOGLE_NAMESPACE_
|
|
||||||
template<int Size, int Hashsize>
|
|
||||||
struct has_trivial_copy< HashObject<Size, Hashsize> > : true_type { };
|
|
||||||
|
|
||||||
template<int Size, int Hashsize>
|
|
||||||
struct has_trivial_destructor< HashObject<Size, Hashsize> > : true_type { };
|
|
||||||
_END_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
class HashFn {
|
|
||||||
public:
|
|
||||||
template<int Size, int Hashsize>
|
|
||||||
size_t operator()(const HashObject<Size,Hashsize>& obj) const {
|
|
||||||
return obj.Hash();
|
|
||||||
}
|
|
||||||
// For windows
|
|
||||||
template<int Size, int Hashsize>
|
|
||||||
bool operator()(const HashObject<Size,Hashsize>& a,
|
|
||||||
const HashObject<Size,Hashsize>& b) const {
|
|
||||||
return a < b;
|
|
||||||
}
|
|
||||||
// These two public members are required by msvc. 4 and 8 are defaults.
|
|
||||||
static const size_t bucket_size = 4;
|
|
||||||
static const size_t min_buckets = 8;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Measure resource usage.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Rusage {
|
|
||||||
public:
|
|
||||||
/* Start collecting usage */
|
|
||||||
Rusage() { Reset(); }
|
|
||||||
|
|
||||||
/* Reset collection */
|
|
||||||
void Reset();
|
|
||||||
|
|
||||||
/* Show usage */
|
|
||||||
double UserTime();
|
|
||||||
|
|
||||||
private:
|
|
||||||
#if defined HAVE_SYS_RESOURCE_H
|
|
||||||
struct rusage start;
|
|
||||||
#elif defined HAVE_WINDOWS_H
|
|
||||||
long long int start;
|
|
||||||
#else
|
|
||||||
time_t start_time_t;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void Rusage::Reset() {
|
|
||||||
#if defined HAVE_SYS_RESOURCE_H
|
|
||||||
getrusage(RUSAGE_SELF, &start);
|
|
||||||
#elif defined HAVE_WINDOWS_H
|
|
||||||
start = GetTickCount();
|
|
||||||
#else
|
|
||||||
time(&start_time_t);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline double Rusage::UserTime() {
|
|
||||||
#if defined HAVE_SYS_RESOURCE_H
|
|
||||||
struct rusage u;
|
|
||||||
|
|
||||||
getrusage(RUSAGE_SELF, &u);
|
|
||||||
|
|
||||||
struct timeval result;
|
|
||||||
result.tv_sec = u.ru_utime.tv_sec - start.ru_utime.tv_sec;
|
|
||||||
result.tv_usec = u.ru_utime.tv_usec - start.ru_utime.tv_usec;
|
|
||||||
|
|
||||||
return double(result.tv_sec) + double(result.tv_usec) / 1000000.0;
|
|
||||||
#elif defined HAVE_WINDOWS_H
|
|
||||||
return double(GetTickCount() - start) / 1000.0;
|
|
||||||
#else
|
|
||||||
time_t now;
|
|
||||||
time(&now);
|
|
||||||
return now - start_time_t;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void print_uname() {
|
|
||||||
#ifdef HAVE_SYS_UTSNAME_H
|
|
||||||
struct utsname u;
|
|
||||||
if (uname(&u) == 0) {
|
|
||||||
printf("%s %s %s %s %s\n",
|
|
||||||
u.sysname, u.nodename, u.release, u.version, u.machine);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate stamp for this run
|
|
||||||
static void stamp_run(int iters) {
|
|
||||||
time_t now = time(0);
|
|
||||||
printf("======\n");
|
|
||||||
fflush(stdout);
|
|
||||||
print_uname();
|
|
||||||
printf("Average over %d iterations\n", iters);
|
|
||||||
fflush(stdout);
|
|
||||||
// don't need asctime_r/gmtime_r: we're not threaded
|
|
||||||
printf("Current time (GMT): %s", asctime(gmtime(&now)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If you have google-perftools (http://code.google.com/p/google-perftools),
|
|
||||||
// then you can figure out how much memory these implementations use
|
|
||||||
// as well.
|
|
||||||
#ifdef HAVE_GOOGLE_MALLOC_EXTENSION_H
|
|
||||||
#include <google/malloc_extension.h>
|
|
||||||
|
|
||||||
static size_t CurrentMemoryUsage() {
|
|
||||||
size_t result;
|
|
||||||
if (MallocExtension::instance()->GetNumericProperty(
|
|
||||||
"generic.current_allocated_bytes",
|
|
||||||
&result)) {
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* not HAVE_GOOGLE_MALLOC_EXTENSION_H */
|
|
||||||
static size_t CurrentMemoryUsage() { return 0; }
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void report(char const* title, double t,
|
|
||||||
int iters,
|
|
||||||
size_t heap_growth) {
|
|
||||||
// Construct heap growth report text if applicable
|
|
||||||
char heap[100];
|
|
||||||
if (heap_growth > 0) {
|
|
||||||
snprintf(heap, sizeof(heap), "%8.1f MB", heap_growth / 1048576.0);
|
|
||||||
} else {
|
|
||||||
heap[0] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%-20s %8.1f ns %s\n", title, (t * 1000000000.0 / iters), heap);
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class MapType>
|
|
||||||
static void time_map_grow(int iters) {
|
|
||||||
MapType set;
|
|
||||||
Rusage t;
|
|
||||||
|
|
||||||
SET_EMPTY_KEY(set, -2);
|
|
||||||
const size_t start = CurrentMemoryUsage();
|
|
||||||
t.Reset();
|
|
||||||
for (int i = 0; i < iters; i++) {
|
|
||||||
set[i] = i+1;
|
|
||||||
}
|
|
||||||
double ut = t.UserTime();
|
|
||||||
const size_t finish = CurrentMemoryUsage();
|
|
||||||
report("map_grow", ut, iters, finish - start);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class MapType>
|
|
||||||
static void time_map_grow_predicted(int iters) {
|
|
||||||
MapType set;
|
|
||||||
Rusage t;
|
|
||||||
|
|
||||||
SET_EMPTY_KEY(set, -2);
|
|
||||||
const size_t start = CurrentMemoryUsage();
|
|
||||||
RESIZE(set, iters);
|
|
||||||
t.Reset();
|
|
||||||
for (int i = 0; i < iters; i++) {
|
|
||||||
set[i] = i+1;
|
|
||||||
}
|
|
||||||
double ut = t.UserTime();
|
|
||||||
const size_t finish = CurrentMemoryUsage();
|
|
||||||
report("map_predict/grow", ut, iters, finish - start);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class MapType>
|
|
||||||
static void time_map_replace(int iters) {
|
|
||||||
MapType set;
|
|
||||||
Rusage t;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
SET_EMPTY_KEY(set, -2);
|
|
||||||
for (i = 0; i < iters; i++) {
|
|
||||||
set[i] = i+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Reset();
|
|
||||||
for (i = 0; i < iters; i++) {
|
|
||||||
set[i] = i+1;
|
|
||||||
}
|
|
||||||
double ut = t.UserTime();
|
|
||||||
|
|
||||||
report("map_replace", ut, iters, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class MapType>
|
|
||||||
static void time_map_fetch(int iters) {
|
|
||||||
MapType set;
|
|
||||||
Rusage t;
|
|
||||||
int r;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
SET_EMPTY_KEY(set, -2);
|
|
||||||
for (i = 0; i < iters; i++) {
|
|
||||||
set[i] = i+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = 1;
|
|
||||||
t.Reset();
|
|
||||||
for (i = 0; i < iters; i++) {
|
|
||||||
r ^= static_cast<int>(set.find(i) != set.end());
|
|
||||||
}
|
|
||||||
double ut = t.UserTime();
|
|
||||||
|
|
||||||
srand(r); // keep compiler from optimizing away r (we never call rand())
|
|
||||||
report("map_fetch", ut, iters, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class MapType>
|
|
||||||
static void time_map_fetch_empty(int iters) {
|
|
||||||
MapType set;
|
|
||||||
Rusage t;
|
|
||||||
int r;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
SET_EMPTY_KEY(set, -2);
|
|
||||||
r = 1;
|
|
||||||
t.Reset();
|
|
||||||
for (i = 0; i < iters; i++) {
|
|
||||||
r ^= static_cast<int>(set.find(i) != set.end());
|
|
||||||
}
|
|
||||||
double ut = t.UserTime();
|
|
||||||
|
|
||||||
srand(r); // keep compiler from optimizing away r (we never call rand())
|
|
||||||
report("map_fetch_empty", ut, iters, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class MapType>
|
|
||||||
static void time_map_remove(int iters) {
|
|
||||||
MapType set;
|
|
||||||
Rusage t;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
SET_EMPTY_KEY(set, -2);
|
|
||||||
for (i = 0; i < iters; i++) {
|
|
||||||
set[i] = i+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Reset();
|
|
||||||
SET_DELETED_KEY(set, -1);
|
|
||||||
for (i = 0; i < iters; i++) {
|
|
||||||
set.erase(i);
|
|
||||||
}
|
|
||||||
double ut = t.UserTime();
|
|
||||||
|
|
||||||
report("map_remove", ut, iters, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class MapType>
|
|
||||||
static void time_map_toggle(int iters) {
|
|
||||||
MapType set;
|
|
||||||
Rusage t;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
const size_t start = CurrentMemoryUsage();
|
|
||||||
t.Reset();
|
|
||||||
SET_DELETED_KEY(set, -1);
|
|
||||||
SET_EMPTY_KEY(set, -2);
|
|
||||||
for (i = 0; i < iters; i++) {
|
|
||||||
set[i] = i+1;
|
|
||||||
set.erase(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
double ut = t.UserTime();
|
|
||||||
const size_t finish = CurrentMemoryUsage();
|
|
||||||
|
|
||||||
report("map_toggle", ut, iters, finish - start);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class MapType>
|
|
||||||
static void measure_map(const char* label, int iters) {
|
|
||||||
printf("\n%s:\n", label);
|
|
||||||
if (1) time_map_grow<MapType>(iters);
|
|
||||||
if (1) time_map_grow_predicted<MapType>(iters);
|
|
||||||
if (1) time_map_replace<MapType>(iters);
|
|
||||||
if (1) time_map_fetch<MapType>(iters);
|
|
||||||
if (1) time_map_fetch_empty<MapType>(iters);
|
|
||||||
if (1) time_map_remove<MapType>(iters);
|
|
||||||
if (1) time_map_toggle<MapType>(iters);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
int iters = kDefaultIters;
|
|
||||||
if (argc > 1) { // first arg is # of iterations
|
|
||||||
iters = atoi(argv[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// It would be nice to set these at run-time, but by setting them at
|
|
||||||
// compile-time, we allow optimizations that make it as fast to use
|
|
||||||
// a HashObject as it would be to use just a straight int/char buffer.
|
|
||||||
const int obj_size = 4;
|
|
||||||
const int hash_size = 4;
|
|
||||||
typedef HashObject<obj_size, hash_size> HashObj;
|
|
||||||
|
|
||||||
stamp_run(iters);
|
|
||||||
|
|
||||||
#ifndef HAVE_SYS_RESOURCE_H
|
|
||||||
printf("\n*** WARNING ***: sys/resources.h was not found, so all times\n"
|
|
||||||
" reported are wall-clock time, not user time\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
measure_map< sparse_hash_map<HashObj,int,HashFn> >("SPARSE_HASH_MAP", iters);
|
|
||||||
measure_map< dense_hash_map<HashObj,int,HashFn> >("DENSE_HASH_MAP", iters);
|
|
||||||
#if defined(HAVE_UNORDERED_MAP)
|
|
||||||
measure_map< HASH_NAMESPACE::unordered_map<HashObj,int,HashFn> >(
|
|
||||||
"TR1 UNORDERED_MAP", iters);
|
|
||||||
#elif defined(HAVE_HASH_MAP)
|
|
||||||
measure_map< HASH_NAMESPACE::hash_map<HashObj,int,HashFn> >(
|
|
||||||
"STANDARD HASH_MAP", iters);
|
|
||||||
#endif
|
|
||||||
measure_map< STL_NAMESPACE::map<HashObj,int,HashFn> >("STANDARD MAP", iters);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,492 +0,0 @@
|
|||||||
// Copyright (c) 2006, Google Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// Author: Matt Austern
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include <stdlib.h> // for exit()
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <google/type_traits.h>
|
|
||||||
|
|
||||||
using STL_NAMESPACE::string;
|
|
||||||
using STL_NAMESPACE::vector;
|
|
||||||
using STL_NAMESPACE::pair;
|
|
||||||
|
|
||||||
#define ASSERT_TRUE(cond) do { \
|
|
||||||
if ( !(cond) ) { \
|
|
||||||
printf("Test failed: " #cond "\n"); \
|
|
||||||
exit(1); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define ASSERT_FALSE(cond) ASSERT_TRUE(!(cond))
|
|
||||||
|
|
||||||
|
|
||||||
// A user-defined POD type.
|
|
||||||
struct A {
|
|
||||||
int n_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// A user-defined non-POD type with a trivial copy constructor.
|
|
||||||
class B {
|
|
||||||
public:
|
|
||||||
explicit B(int n) : n_(n) { }
|
|
||||||
private:
|
|
||||||
int n_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Another user-defined non-POD type with a trivial copy constructor.
|
|
||||||
// We will explicitly declare C to have a trivial copy constructor
|
|
||||||
// by specializing has_trivial_copy.
|
|
||||||
class C {
|
|
||||||
public:
|
|
||||||
explicit C(int n) : n_(n) { }
|
|
||||||
private:
|
|
||||||
int n_;
|
|
||||||
};
|
|
||||||
|
|
||||||
_START_GOOGLE_NAMESPACE_
|
|
||||||
template<> struct has_trivial_copy<C> : true_type { };
|
|
||||||
_END_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
// Another user-defined non-POD type with a trivial assignment operator.
|
|
||||||
// We will explicitly declare C to have a trivial assignment operator
|
|
||||||
// by specializing has_trivial_assign.
|
|
||||||
class D {
|
|
||||||
public:
|
|
||||||
explicit D(int n) : n_(n) { }
|
|
||||||
private:
|
|
||||||
int n_;
|
|
||||||
};
|
|
||||||
|
|
||||||
_START_GOOGLE_NAMESPACE_
|
|
||||||
template<> struct has_trivial_assign<D> : true_type { };
|
|
||||||
_END_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
// Another user-defined non-POD type with a trivial constructor.
|
|
||||||
// We will explicitly declare E to have a trivial constructor
|
|
||||||
// by specializing has_trivial_constructor.
|
|
||||||
class E {
|
|
||||||
public:
|
|
||||||
int n_;
|
|
||||||
};
|
|
||||||
|
|
||||||
_START_GOOGLE_NAMESPACE_
|
|
||||||
template<> struct has_trivial_constructor<E> : true_type { };
|
|
||||||
_END_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
// Another user-defined non-POD type with a trivial destructor.
|
|
||||||
// We will explicitly declare E to have a trivial destructor
|
|
||||||
// by specializing has_trivial_destructor.
|
|
||||||
class F {
|
|
||||||
public:
|
|
||||||
explicit F(int n) : n_(n) { }
|
|
||||||
private:
|
|
||||||
int n_;
|
|
||||||
};
|
|
||||||
|
|
||||||
_START_GOOGLE_NAMESPACE_
|
|
||||||
template<> struct has_trivial_destructor<F> : true_type { };
|
|
||||||
_END_GOOGLE_NAMESPACE_
|
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// type_equals_ is a template type comparator, similar to Loki IsSameType.
|
|
||||||
// type_equals_<A, B>::value is true iff "A" is the same type as "B".
|
|
||||||
template<typename A, typename B>
|
|
||||||
struct type_equals_ : public GOOGLE_NAMESPACE::false_type {
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename A>
|
|
||||||
struct type_equals_<A, A> : public GOOGLE_NAMESPACE::true_type {
|
|
||||||
};
|
|
||||||
|
|
||||||
// A base class and a derived class that inherits from it, used for
|
|
||||||
// testing conversion type traits.
|
|
||||||
class Base {
|
|
||||||
public:
|
|
||||||
virtual ~Base() { }
|
|
||||||
};
|
|
||||||
|
|
||||||
class Derived : public Base {
|
|
||||||
};
|
|
||||||
|
|
||||||
// This assertion produces errors like "error: invalid use of
|
|
||||||
// undefined type 'struct <unnamed>::AssertTypesEq<const int, int>'"
|
|
||||||
// when it fails.
|
|
||||||
template<typename T, typename U> struct AssertTypesEq;
|
|
||||||
template<typename T> struct AssertTypesEq<T, T> {};
|
|
||||||
#define COMPILE_ASSERT_TYPES_EQ(T, U) AssertTypesEq<T, U>()
|
|
||||||
|
|
||||||
class TypeTraitsTest {
|
|
||||||
public:
|
|
||||||
static void TestIsInteger() {
|
|
||||||
// Verify that is_integral is true for all integer types.
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<bool>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<char>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<unsigned char>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<signed char>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<wchar_t>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<int>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<unsigned int>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<short>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<unsigned short>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<long>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<unsigned long>::value);
|
|
||||||
|
|
||||||
// Verify that is_integral is false for a few non-integer types.
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::is_integral<void>::value);
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::is_integral<float>::value);
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::is_integral<string>::value);
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::is_integral<int*>::value);
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::is_integral<A>::value);
|
|
||||||
ASSERT_FALSE((GOOGLE_NAMESPACE::is_integral<pair<int, int> >::value));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TestIsFloating() {
|
|
||||||
// Verify that is_floating_point is true for all floating-point types.
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_floating_point<float>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_floating_point<double>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_floating_point<long double>::value);
|
|
||||||
|
|
||||||
// Verify that is_floating_point is false for a few non-float types.
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::is_floating_point<void>::value);
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::is_floating_point<long>::value);
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::is_floating_point<string>::value);
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::is_floating_point<float*>::value);
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::is_floating_point<A>::value);
|
|
||||||
ASSERT_FALSE((GOOGLE_NAMESPACE::is_floating_point<pair<int, int> >::value));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TestIsReference() {
|
|
||||||
// Verifies that is_reference is true for all reference types.
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_reference<float&>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_reference<const int&>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_reference<const int*&>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_reference<int (&)(bool)>::value);
|
|
||||||
|
|
||||||
// Verifies that is_reference is false for all non-reference types.
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::is_reference<float>::value);
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::is_reference<const int*>::value);
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::is_reference<int()>::value);
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::is_reference<void(*)(const char&)>::value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TestIsPod() {
|
|
||||||
// Verify that arithmetic types and pointers are marked as PODs.
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<bool>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<char>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<unsigned char>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<signed char>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<wchar_t>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<int>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<unsigned int>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<short>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<unsigned short>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<long>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<unsigned long>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<float>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<double>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<long double>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<string*>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<A*>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<const B*>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<C**>::value);
|
|
||||||
|
|
||||||
// Verify that some non-POD types are not marked as PODs.
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::is_pod<void>::value);
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::is_pod<string>::value);
|
|
||||||
ASSERT_FALSE((GOOGLE_NAMESPACE::is_pod<pair<int, int> >::value));
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::is_pod<A>::value);
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::is_pod<B>::value);
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::is_pod<C>::value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TestHasTrivialCopy() {
|
|
||||||
// Verify that arithmetic types and pointers have trivial copy
|
|
||||||
// constructors.
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<bool>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<char>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<unsigned char>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<signed char>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<wchar_t>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<int>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<unsigned int>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<short>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<unsigned short>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<long>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<unsigned long>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<float>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<double>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<long double>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<string*>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<A*>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<const B*>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<C**>::value);
|
|
||||||
|
|
||||||
// Verify that pairs and arrays of such types have trivial
|
|
||||||
// copy constructors.
|
|
||||||
typedef int int10[10];
|
|
||||||
ASSERT_TRUE((GOOGLE_NAMESPACE::has_trivial_copy<pair<int, char*> >::value));
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<int10>::value);
|
|
||||||
|
|
||||||
// Verify that types without trivial copy constructors are
|
|
||||||
// correctly marked as such.
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::has_trivial_copy<string>::value);
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::has_trivial_copy<vector<int> >::value);
|
|
||||||
|
|
||||||
// Verify that pairs of types without trivial copy constructors
|
|
||||||
// are not marked as trivial.
|
|
||||||
ASSERT_FALSE((GOOGLE_NAMESPACE::has_trivial_copy<pair<int, string> >::value));
|
|
||||||
ASSERT_FALSE((GOOGLE_NAMESPACE::has_trivial_copy<pair<string, int> >::value));
|
|
||||||
|
|
||||||
// Verify that C, which we have declared to have a trivial
|
|
||||||
// copy constructor, is correctly marked as such.
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<C>::value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TestHasTrivialConstructor() {
|
|
||||||
// Verify that arithmetic types and pointers have trivial constructors.
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<bool>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<char>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<unsigned char>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<signed char>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<wchar_t>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<int>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<unsigned int>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<short>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<unsigned short>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<long>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<unsigned long>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<float>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<double>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<long double>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<string*>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<A*>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<const B*>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<C**>::value);
|
|
||||||
|
|
||||||
// Verify that pairs and arrays of such types have trivial
|
|
||||||
// constructors.
|
|
||||||
typedef int int10[10];
|
|
||||||
ASSERT_TRUE((GOOGLE_NAMESPACE::has_trivial_constructor<pair<int, char*> >::value));
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<int10>::value);
|
|
||||||
|
|
||||||
// Verify that pairs of types without trivial constructors
|
|
||||||
// are not marked as trivial.
|
|
||||||
ASSERT_FALSE((GOOGLE_NAMESPACE::has_trivial_constructor<pair<int, string> >::value));
|
|
||||||
ASSERT_FALSE((GOOGLE_NAMESPACE::has_trivial_constructor<pair<string, int> >::value));
|
|
||||||
|
|
||||||
// Verify that types without trivial constructors are
|
|
||||||
// correctly marked as such.
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::has_trivial_constructor<string>::value);
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::has_trivial_constructor<vector<int> >::value);
|
|
||||||
|
|
||||||
// Verify that E, which we have declared to have a trivial
|
|
||||||
// constructor, is correctly marked as such.
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<E>::value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TestHasTrivialAssign() {
|
|
||||||
// Verify that arithmetic types and pointers have trivial assignment
|
|
||||||
// operators.
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<bool>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<char>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<unsigned char>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<signed char>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<wchar_t>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<int>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<unsigned int>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<short>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<unsigned short>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<long>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<unsigned long>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<float>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<double>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<long double>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<string*>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<A*>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<const B*>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<C**>::value);
|
|
||||||
|
|
||||||
// Verify that pairs and arrays of such types have trivial
|
|
||||||
// assignment operators.
|
|
||||||
typedef int int10[10];
|
|
||||||
ASSERT_TRUE((GOOGLE_NAMESPACE::has_trivial_assign<pair<int, char*> >::value));
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<int10>::value);
|
|
||||||
|
|
||||||
// Verify that pairs of types without trivial assignment operators
|
|
||||||
// are not marked as trivial.
|
|
||||||
ASSERT_FALSE((GOOGLE_NAMESPACE::has_trivial_assign<pair<int, string> >::value));
|
|
||||||
ASSERT_FALSE((GOOGLE_NAMESPACE::has_trivial_assign<pair<string, int> >::value));
|
|
||||||
|
|
||||||
// Verify that types without trivial assignment operators are
|
|
||||||
// correctly marked as such.
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::has_trivial_assign<string>::value);
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::has_trivial_assign<vector<int> >::value);
|
|
||||||
|
|
||||||
// Verify that D, which we have declared to have a trivial
|
|
||||||
// assignment operator, is correctly marked as such.
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<D>::value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TestHasTrivialDestructor() {
|
|
||||||
// Verify that arithmetic types and pointers have trivial destructors.
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<bool>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<char>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<unsigned char>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<signed char>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<wchar_t>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<int>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<unsigned int>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<short>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<unsigned short>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<long>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<unsigned long>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<float>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<double>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<long double>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<string*>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<A*>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<const B*>::value);
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<C**>::value);
|
|
||||||
|
|
||||||
// Verify that pairs and arrays of such types have trivial
|
|
||||||
// destructors.
|
|
||||||
typedef int int10[10];
|
|
||||||
ASSERT_TRUE((GOOGLE_NAMESPACE::has_trivial_destructor<pair<int, char*> >::value));
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<int10>::value);
|
|
||||||
|
|
||||||
// Verify that pairs of types without trivial destructors
|
|
||||||
// are not marked as trivial.
|
|
||||||
ASSERT_FALSE((GOOGLE_NAMESPACE::has_trivial_destructor<pair<int, string> >::value));
|
|
||||||
ASSERT_FALSE((GOOGLE_NAMESPACE::has_trivial_destructor<pair<string, int> >::value));
|
|
||||||
|
|
||||||
// Verify that types without trivial destructors are
|
|
||||||
// correctly marked as such.
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::has_trivial_destructor<string>::value);
|
|
||||||
ASSERT_FALSE(GOOGLE_NAMESPACE::has_trivial_destructor<vector<int> >::value);
|
|
||||||
|
|
||||||
// Verify that F, which we have declared to have a trivial
|
|
||||||
// destructor, is correctly marked as such.
|
|
||||||
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<F>::value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests remove_pointer.
|
|
||||||
static void TestRemovePointer() {
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_pointer<int>::type);
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_pointer<int*>::type);
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(const int, GOOGLE_NAMESPACE::remove_pointer<const int*>::type);
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_pointer<int* const>::type);
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_pointer<int* volatile>::type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TestRemoveConst() {
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_const<int>::type);
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_const<const int>::type);
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(int *, GOOGLE_NAMESPACE::remove_const<int * const>::type);
|
|
||||||
// TR1 examples.
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(const int *, GOOGLE_NAMESPACE::remove_const<const int *>::type);
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(volatile int,
|
|
||||||
GOOGLE_NAMESPACE::remove_const<const volatile int>::type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TestRemoveVolatile() {
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_volatile<int>::type);
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_volatile<volatile int>::type);
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(int *, GOOGLE_NAMESPACE::remove_volatile<int * volatile>::type);
|
|
||||||
// TR1 examples.
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(volatile int *,
|
|
||||||
GOOGLE_NAMESPACE::remove_volatile<volatile int *>::type);
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(const int,
|
|
||||||
GOOGLE_NAMESPACE::remove_volatile<const volatile int>::type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TestRemoveReference() {
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_reference<int>::type);
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_reference<int&>::type);
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(const int, GOOGLE_NAMESPACE::remove_reference<const int&>::type);
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(int*, GOOGLE_NAMESPACE::remove_reference<int * &>::type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TestRemoveCV() {
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_cv<int>::type);
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_cv<volatile int>::type);
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_cv<const int>::type);
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(int *, GOOGLE_NAMESPACE::remove_cv<int * const volatile>::type);
|
|
||||||
// TR1 examples.
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(const volatile int *,
|
|
||||||
GOOGLE_NAMESPACE::remove_cv<const volatile int *>::type);
|
|
||||||
COMPILE_ASSERT_TYPES_EQ(int,
|
|
||||||
GOOGLE_NAMESPACE::remove_cv<const volatile int>::type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TestIsConvertible() {
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
ASSERT_TRUE((GOOGLE_NAMESPACE::is_convertible<int, int>::value));
|
|
||||||
ASSERT_TRUE((GOOGLE_NAMESPACE::is_convertible<int, long>::value));
|
|
||||||
ASSERT_TRUE((GOOGLE_NAMESPACE::is_convertible<long, int>::value));
|
|
||||||
|
|
||||||
ASSERT_TRUE((GOOGLE_NAMESPACE::is_convertible<int*, void*>::value));
|
|
||||||
ASSERT_FALSE((GOOGLE_NAMESPACE::is_convertible<void*, int*>::value));
|
|
||||||
|
|
||||||
ASSERT_TRUE((GOOGLE_NAMESPACE::is_convertible<Derived*, Base*>::value));
|
|
||||||
ASSERT_FALSE((GOOGLE_NAMESPACE::is_convertible<Base*, Derived*>::value));
|
|
||||||
ASSERT_TRUE((GOOGLE_NAMESPACE::is_convertible<Derived*, const Base*>::value));
|
|
||||||
ASSERT_FALSE((GOOGLE_NAMESPACE::is_convertible<const Derived*, Base*>::value));
|
|
||||||
#endif // #ifdef MSC_VER
|
|
||||||
}
|
|
||||||
|
|
||||||
}; // end class TypeTraitsTest
|
|
||||||
|
|
||||||
} // end anonymous namespace
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
TypeTraitsTest::TestIsInteger();
|
|
||||||
TypeTraitsTest::TestIsFloating();
|
|
||||||
TypeTraitsTest::TestIsReference();
|
|
||||||
TypeTraitsTest::TestIsPod();
|
|
||||||
TypeTraitsTest::TestHasTrivialCopy();
|
|
||||||
TypeTraitsTest::TestHasTrivialConstructor();
|
|
||||||
TypeTraitsTest::TestHasTrivialAssign();
|
|
||||||
TypeTraitsTest::TestHasTrivialDestructor();
|
|
||||||
TypeTraitsTest::TestRemovePointer();
|
|
||||||
TypeTraitsTest::TestRemoveConst();
|
|
||||||
TypeTraitsTest::TestRemoveVolatile();
|
|
||||||
TypeTraitsTest::TestRemoveReference();
|
|
||||||
TypeTraitsTest::TestRemoveCV();
|
|
||||||
TypeTraitsTest::TestIsConvertible();
|
|
||||||
printf("PASS\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,149 +0,0 @@
|
|||||||
#ifndef GOOGLE_SPARSEHASH_WINDOWS_CONFIG_H_
|
|
||||||
#define GOOGLE_SPARSEHASH_WINDOWS_CONFIG_H_
|
|
||||||
|
|
||||||
/* src/config.h.in. Generated from configure.ac by autoheader. */
|
|
||||||
|
|
||||||
/* Namespace for Google classes */
|
|
||||||
#define GOOGLE_NAMESPACE ::google
|
|
||||||
|
|
||||||
/* the location of the header defining hash functions */
|
|
||||||
#define HASH_FUN_H <hash_map>
|
|
||||||
|
|
||||||
/* the location of <unordered_map> or <hash_map> */
|
|
||||||
#define HASH_MAP_H <hash_map>
|
|
||||||
|
|
||||||
/* the namespace of the hash<> function */
|
|
||||||
#define HASH_NAMESPACE stdext
|
|
||||||
|
|
||||||
/* the location of <unordered_set> or <hash_set> */
|
|
||||||
#define HASH_SET_H <hash_set>
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <google/malloc_extension.h> header file. */
|
|
||||||
#undef HAVE_GOOGLE_MALLOC_EXTENSION_H
|
|
||||||
|
|
||||||
/* define if the compiler has hash_map */
|
|
||||||
#define HAVE_HASH_MAP 1
|
|
||||||
|
|
||||||
/* define if the compiler has hash_set */
|
|
||||||
#define HAVE_HASH_SET 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
|
||||||
#undef HAVE_INTTYPES_H
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `long long'. */
|
|
||||||
#define HAVE_LONG_LONG 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `memcpy' function. */
|
|
||||||
#define HAVE_MEMCPY 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `memmove' function. */
|
|
||||||
#define HAVE_MEMMOVE 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <memory.h> header file. */
|
|
||||||
#undef HAVE_MEMORY_H
|
|
||||||
|
|
||||||
/* define if the compiler implements namespaces */
|
|
||||||
#define HAVE_NAMESPACES 1
|
|
||||||
|
|
||||||
/* Define if you have POSIX threads libraries and header files. */
|
|
||||||
#undef HAVE_PTHREAD
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
|
||||||
#undef HAVE_STDINT_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
|
||||||
#define HAVE_STDLIB_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <strings.h> header file. */
|
|
||||||
#undef HAVE_STRINGS_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <string.h> header file. */
|
|
||||||
#define HAVE_STRING_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/resource.h> header file. */
|
|
||||||
#undef HAVE_SYS_RESOURCE_H
|
|
||||||
|
|
||||||
/* 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/time.h> header file. */
|
|
||||||
#undef HAVE_SYS_TIME_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
|
||||||
#define HAVE_SYS_TYPES_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/utsname.h> header file. */
|
|
||||||
#undef HAVE_SYS_UTSNAME_H
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uint16_t'. */
|
|
||||||
#undef HAVE_UINT16_T
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
|
||||||
#undef HAVE_UNISTD_H
|
|
||||||
|
|
||||||
/* define if the compiler supports unordered_{map,set} */
|
|
||||||
#undef HAVE_UNORDERED_MAP
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `u_int16_t'. */
|
|
||||||
#undef HAVE_U_INT16_T
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `__uint16'. */
|
|
||||||
#define HAVE___UINT16 1
|
|
||||||
|
|
||||||
/* Name of package */
|
|
||||||
#undef PACKAGE
|
|
||||||
|
|
||||||
/* Define to the address where bug reports for this package should be sent. */
|
|
||||||
#undef PACKAGE_BUGREPORT
|
|
||||||
|
|
||||||
/* Define to the full name of this package. */
|
|
||||||
#undef PACKAGE_NAME
|
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
|
||||||
#undef PACKAGE_STRING
|
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
|
||||||
#undef PACKAGE_TARNAME
|
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
|
||||||
#undef PACKAGE_VERSION
|
|
||||||
|
|
||||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
|
||||||
your system. */
|
|
||||||
#undef PTHREAD_CREATE_JOINABLE
|
|
||||||
|
|
||||||
/* The system-provided hash function including the namespace. */
|
|
||||||
#define SPARSEHASH_HASH HASH_NAMESPACE::hash_compare
|
|
||||||
|
|
||||||
/* The system-provided hash function, in namespace HASH_NAMESPACE. */
|
|
||||||
#define SPARSEHASH_HASH_NO_NAMESPACE hash_compare
|
|
||||||
|
|
||||||
/* Define to 1 if you have the ANSI C header files. */
|
|
||||||
#define STDC_HEADERS 1
|
|
||||||
|
|
||||||
/* the namespace where STL code like vector<> is defined */
|
|
||||||
#define STL_NAMESPACE std
|
|
||||||
|
|
||||||
/* Version number of package */
|
|
||||||
#undef VERSION
|
|
||||||
|
|
||||||
/* Stops putting the code inside the Google namespace */
|
|
||||||
#define _END_GOOGLE_NAMESPACE_ }
|
|
||||||
|
|
||||||
/* Puts following code inside the Google namespace */
|
|
||||||
#define _START_GOOGLE_NAMESPACE_ namespace google {
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
|
||||||
// Extra stuff not found in config.h.in
|
|
||||||
|
|
||||||
#define HAVE_WINDOWS_H 1 // used in time_hash_map
|
|
||||||
|
|
||||||
// This makes sure the definitions in config.h and sparseconfig.h match
|
|
||||||
// up. If they don't, the compiler will complain about redefinition.
|
|
||||||
#include <google/sparsehash/sparseconfig.h>
|
|
||||||
|
|
||||||
// TODO(csilvers): include windows/port.h in every relevant source file instead?
|
|
||||||
#include "windows/port.h"
|
|
||||||
|
|
||||||
#endif /* GOOGLE_SPARSEHASH_WINDOWS_CONFIG_H_ */
|
|
@ -1,32 +0,0 @@
|
|||||||
#ifndef SPARSEHASH_WINDOWS_SPARSECONFIG_H_
|
|
||||||
#define SPARSEHASH_WINDOWS_SPARSECONFIG_H_
|
|
||||||
|
|
||||||
/***
|
|
||||||
*** These are #defines that autoheader puts in config.h.in that we
|
|
||||||
*** want to show up in sparseconfig.h, the minimal config.h file
|
|
||||||
*** #included by all our .h files. The reason we don't take
|
|
||||||
*** everything that autoheader emits is that we have to include a
|
|
||||||
*** config.h in installed header files, and we want to minimize the
|
|
||||||
*** number of #defines we make so as to not pollute the namespace.
|
|
||||||
***/
|
|
||||||
/* NOTE: these are for internal use only. Don't use these
|
|
||||||
* #defines in your own programs!
|
|
||||||
*/
|
|
||||||
#define GOOGLE_NAMESPACE ::google
|
|
||||||
#define HASH_NAMESPACE stdext
|
|
||||||
#define HASH_FUN_H <hash_map>
|
|
||||||
#define SPARSEHASH_HASH HASH_NAMESPACE::hash_compare
|
|
||||||
#undef HAVE_UINT16_T
|
|
||||||
#undef HAVE_U_INT16_T
|
|
||||||
#define HAVE___UINT16 1
|
|
||||||
#define HAVE_LONG_LONG 1
|
|
||||||
#define HAVE_SYS_TYPES_H 1
|
|
||||||
#undef HAVE_STDINT_H
|
|
||||||
#undef HAVE_INTTYPES_H
|
|
||||||
#define HAVE_MEMCPY 1
|
|
||||||
#define STL_NAMESPACE std
|
|
||||||
#define _END_GOOGLE_NAMESPACE_ }
|
|
||||||
#define _START_GOOGLE_NAMESPACE_ namespace google {
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* SPARSEHASH_WINDOWS_SPARSECONFIG_H_ */
|
|
@ -1,63 +0,0 @@
|
|||||||
/* Copyright (c) 2007, Google Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are
|
|
||||||
* met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* * Redistributions in binary form must reproduce the above
|
|
||||||
* copyright notice, this list of conditions and the following disclaimer
|
|
||||||
* in the documentation and/or other materials provided with the
|
|
||||||
* distribution.
|
|
||||||
* * Neither the name of Google Inc. nor the names of its
|
|
||||||
* contributors may be used to endorse or promote products derived from
|
|
||||||
* this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* ---
|
|
||||||
* Author: Craig Silverstein
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
# error You should only be including windows/port.cc in a windows environment!
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include <stdarg.h> // for va_list, va_start, va_end
|
|
||||||
#include "port.h"
|
|
||||||
|
|
||||||
// Calls the windows _vsnprintf, but always NUL-terminate.
|
|
||||||
int snprintf(char *str, size_t size, const char *format, ...) {
|
|
||||||
if (size == 0) // not even room for a \0?
|
|
||||||
return -1; // not what C99 says to do, but what windows does
|
|
||||||
str[size-1] = '\0';
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, format);
|
|
||||||
const int r = _vsnprintf(str, size-1, format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string TmpFile(const char* basename) {
|
|
||||||
char tmppath_buffer[1024];
|
|
||||||
int tmppath_len = GetTempPathA(sizeof(tmppath_buffer), tmppath_buffer);
|
|
||||||
if (tmppath_len <= 0 || tmppath_len >= sizeof(tmppath_buffer)) {
|
|
||||||
return basename; // an error, so just bail on tmppath
|
|
||||||
}
|
|
||||||
snprintf(tmppath_buffer + tmppath_len, sizeof(tmppath_buffer) - tmppath_len,
|
|
||||||
"\\%s", basename);
|
|
||||||
return tmppath_buffer;
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
/* Copyright (c) 2007, Google Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are
|
|
||||||
* met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* * Redistributions in binary form must reproduce the above
|
|
||||||
* copyright notice, this list of conditions and the following disclaimer
|
|
||||||
* in the documentation and/or other materials provided with the
|
|
||||||
* distribution.
|
|
||||||
* * Neither the name of Google Inc. nor the names of its
|
|
||||||
* contributors may be used to endorse or promote products derived from
|
|
||||||
* this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* ---
|
|
||||||
* Author: Craig Silverstein
|
|
||||||
*
|
|
||||||
* These are some portability typedefs and defines to make it a bit
|
|
||||||
* easier to compile this code -- in particular, unittests -- under VC++.
|
|
||||||
* Other portability code is found in windows/google/sparsehash/sparseconfig.h.
|
|
||||||
*
|
|
||||||
* Several of these are taken from glib:
|
|
||||||
* http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SPARSEHASH_WINDOWS_PORT_H_
|
|
||||||
#define SPARSEHASH_WINDOWS_PORT_H_
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN /* We always want minimal includes */
|
|
||||||
#include <windows.h>
|
|
||||||
#include <io.h> /* because we so often use open/close/etc */
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
// 4996: Yes, we're ok using the "unsafe" functions like _vsnprintf and fopen
|
|
||||||
// 4127: We use "while (1)" sometimes: yes, we know it's a constant
|
|
||||||
#pragma warning(disable:4996 4127)
|
|
||||||
|
|
||||||
|
|
||||||
// file I/O
|
|
||||||
#define PATH_MAX 1024
|
|
||||||
#define access _access
|
|
||||||
#define getcwd _getcwd
|
|
||||||
#define open _open
|
|
||||||
#define read _read
|
|
||||||
#define write _write
|
|
||||||
#define lseek _lseek
|
|
||||||
#define close _close
|
|
||||||
#define unlink _unlink
|
|
||||||
#define popen _popen
|
|
||||||
#define pclose _pclose
|
|
||||||
|
|
||||||
#define strdup _strdup
|
|
||||||
|
|
||||||
// We can't just use _snprintf as a drop-in replacement, because it
|
|
||||||
// doesn't always NUL-terminate. :-(
|
|
||||||
extern int snprintf(char *str, size_t size, const char *format, ...);
|
|
||||||
|
|
||||||
extern std::string TmpFile(const char* basename); // used in hashtable_unittest
|
|
||||||
|
|
||||||
#endif /* WIN32 */
|
|
||||||
|
|
||||||
#endif /* SPARSEHASH_WINDOWS_PORT_H_ */
|
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
@ -1,185 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="Windows-1252"?>
|
|
||||||
<VisualStudioProject
|
|
||||||
ProjectType="Visual C++"
|
|
||||||
Version="7.10"
|
|
||||||
Name="hashtable_unittest"
|
|
||||||
ProjectGUID="{FCDB3718-F01C-4DE4-B9F5-E10F2C5C0535}"
|
|
||||||
Keyword="Win32Proj">
|
|
||||||
<Platforms>
|
|
||||||
<Platform
|
|
||||||
Name="Win32"/>
|
|
||||||
</Platforms>
|
|
||||||
<Configurations>
|
|
||||||
<Configuration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ConfigurationName)"
|
|
||||||
ConfigurationType="1"
|
|
||||||
CharacterSet="2">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
Optimization="0"
|
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
|
||||||
MinimalRebuild="TRUE"
|
|
||||||
BasicRuntimeChecks="3"
|
|
||||||
RuntimeLibrary="5"
|
|
||||||
UsePrecompiledHeader="0"
|
|
||||||
WarningLevel="3"
|
|
||||||
DebugInformationFormat="4"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLinkerTool"
|
|
||||||
OutputFile="$(OutDir)/hashtable_unittest.exe"
|
|
||||||
LinkIncremental="2"
|
|
||||||
GenerateDebugInformation="TRUE"
|
|
||||||
ProgramDatabaseFile="$(OutDir)/hashtable_unittest.pdb"
|
|
||||||
SubSystem="1"
|
|
||||||
TargetMachine="1"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebDeploymentTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedWrapperGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
|
||||||
</Configuration>
|
|
||||||
<Configuration
|
|
||||||
Name="Release|Win32"
|
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ConfigurationName)"
|
|
||||||
ConfigurationType="1"
|
|
||||||
CharacterSet="2">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
|
||||||
RuntimeLibrary="4"
|
|
||||||
UsePrecompiledHeader="0"
|
|
||||||
WarningLevel="3"
|
|
||||||
DebugInformationFormat="3"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLinkerTool"
|
|
||||||
OutputFile="$(OutDir)/hashtable_unittest.exe"
|
|
||||||
LinkIncremental="1"
|
|
||||||
GenerateDebugInformation="TRUE"
|
|
||||||
SubSystem="1"
|
|
||||||
OptimizeReferences="2"
|
|
||||||
EnableCOMDATFolding="2"
|
|
||||||
TargetMachine="1"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebDeploymentTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedWrapperGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
|
||||||
</Configuration>
|
|
||||||
</Configurations>
|
|
||||||
<References>
|
|
||||||
</References>
|
|
||||||
<Files>
|
|
||||||
<Filter
|
|
||||||
Name="Source Files"
|
|
||||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
|
||||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\hashtable_unittest.cc">
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\windows\port.cc">
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
<Filter
|
|
||||||
Name="Header Files"
|
|
||||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
|
||||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\windows\config.h">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\dense_hash_map">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\dense_hash_set">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\sparsehash\densehashtable.h">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\windows\port.h">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\sparse_hash_map">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\sparse_hash_set">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\windows\google\sparsehash\sparseconfig.h">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\sparsehash\sparsehashtable.h">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\sparsetable">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\type_traits.h">
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
</Files>
|
|
||||||
<Globals>
|
|
||||||
</Globals>
|
|
||||||
</VisualStudioProject>
|
|
@ -1,170 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="Windows-1252"?>
|
|
||||||
<VisualStudioProject
|
|
||||||
ProjectType="Visual C++"
|
|
||||||
Version="7.10"
|
|
||||||
Name="sparsetable_unittest"
|
|
||||||
ProjectGUID="{E420867B-8BFA-4739-99EC-E008AB762FF9}"
|
|
||||||
Keyword="Win32Proj">
|
|
||||||
<Platforms>
|
|
||||||
<Platform
|
|
||||||
Name="Win32"/>
|
|
||||||
</Platforms>
|
|
||||||
<Configurations>
|
|
||||||
<Configuration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ConfigurationName)"
|
|
||||||
ConfigurationType="1"
|
|
||||||
CharacterSet="2">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
Optimization="0"
|
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
|
||||||
MinimalRebuild="TRUE"
|
|
||||||
BasicRuntimeChecks="3"
|
|
||||||
RuntimeLibrary="5"
|
|
||||||
UsePrecompiledHeader="0"
|
|
||||||
WarningLevel="3"
|
|
||||||
DebugInformationFormat="4"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLinkerTool"
|
|
||||||
OutputFile="$(OutDir)/sparsetable_unittest.exe"
|
|
||||||
LinkIncremental="2"
|
|
||||||
GenerateDebugInformation="TRUE"
|
|
||||||
ProgramDatabaseFile="$(OutDir)/sparsetable_unittest.pdb"
|
|
||||||
SubSystem="1"
|
|
||||||
TargetMachine="1"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebDeploymentTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedWrapperGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
|
||||||
</Configuration>
|
|
||||||
<Configuration
|
|
||||||
Name="Release|Win32"
|
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ConfigurationName)"
|
|
||||||
ConfigurationType="1"
|
|
||||||
CharacterSet="2">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
|
||||||
RuntimeLibrary="4"
|
|
||||||
UsePrecompiledHeader="0"
|
|
||||||
WarningLevel="3"
|
|
||||||
DebugInformationFormat="3"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLinkerTool"
|
|
||||||
OutputFile="$(OutDir)/sparsetable_unittest.exe"
|
|
||||||
LinkIncremental="1"
|
|
||||||
GenerateDebugInformation="TRUE"
|
|
||||||
SubSystem="1"
|
|
||||||
OptimizeReferences="2"
|
|
||||||
EnableCOMDATFolding="2"
|
|
||||||
TargetMachine="1"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebDeploymentTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedWrapperGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
|
||||||
</Configuration>
|
|
||||||
</Configurations>
|
|
||||||
<References>
|
|
||||||
</References>
|
|
||||||
<Files>
|
|
||||||
<Filter
|
|
||||||
Name="Source Files"
|
|
||||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
|
||||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\windows\port.cc">
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\sparsetable_unittest.cc">
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
<Filter
|
|
||||||
Name="Header Files"
|
|
||||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
|
||||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\windows\config.h">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\windows\port.h">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\windows\google\sparsehash\sparseconfig.h">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\sparsehash\sparsehashtable.h">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\sparsetable">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\type_traits.h">
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
</Files>
|
|
||||||
<Globals>
|
|
||||||
</Globals>
|
|
||||||
</VisualStudioProject>
|
|
@ -1,185 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="Windows-1252"?>
|
|
||||||
<VisualStudioProject
|
|
||||||
ProjectType="Visual C++"
|
|
||||||
Version="7.10"
|
|
||||||
Name="time_hash_map"
|
|
||||||
ProjectGUID="{A74E5DB8-5295-487A-AB1D-23859F536F45}"
|
|
||||||
Keyword="Win32Proj">
|
|
||||||
<Platforms>
|
|
||||||
<Platform
|
|
||||||
Name="Win32"/>
|
|
||||||
</Platforms>
|
|
||||||
<Configurations>
|
|
||||||
<Configuration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ConfigurationName)"
|
|
||||||
ConfigurationType="1"
|
|
||||||
CharacterSet="2">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
Optimization="0"
|
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
|
||||||
MinimalRebuild="TRUE"
|
|
||||||
BasicRuntimeChecks="3"
|
|
||||||
RuntimeLibrary="5"
|
|
||||||
UsePrecompiledHeader="0"
|
|
||||||
WarningLevel="3"
|
|
||||||
DebugInformationFormat="4"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLinkerTool"
|
|
||||||
OutputFile="$(OutDir)/time_hash_map.exe"
|
|
||||||
LinkIncremental="2"
|
|
||||||
GenerateDebugInformation="TRUE"
|
|
||||||
ProgramDatabaseFile="$(OutDir)/time_hash_map.pdb"
|
|
||||||
SubSystem="1"
|
|
||||||
TargetMachine="1"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebDeploymentTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedWrapperGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
|
||||||
</Configuration>
|
|
||||||
<Configuration
|
|
||||||
Name="Release|Win32"
|
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ConfigurationName)"
|
|
||||||
ConfigurationType="1"
|
|
||||||
CharacterSet="2">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
|
||||||
RuntimeLibrary="4"
|
|
||||||
UsePrecompiledHeader="0"
|
|
||||||
WarningLevel="3"
|
|
||||||
DebugInformationFormat="3"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLinkerTool"
|
|
||||||
OutputFile="$(OutDir)/time_hash_map.exe"
|
|
||||||
LinkIncremental="1"
|
|
||||||
GenerateDebugInformation="TRUE"
|
|
||||||
SubSystem="1"
|
|
||||||
OptimizeReferences="2"
|
|
||||||
EnableCOMDATFolding="2"
|
|
||||||
TargetMachine="1"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebDeploymentTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedWrapperGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
|
||||||
</Configuration>
|
|
||||||
</Configurations>
|
|
||||||
<References>
|
|
||||||
</References>
|
|
||||||
<Files>
|
|
||||||
<Filter
|
|
||||||
Name="Source Files"
|
|
||||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
|
||||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\windows\port.cc">
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\time_hash_map.cc">
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
<Filter
|
|
||||||
Name="Header Files"
|
|
||||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
|
||||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\windows\config.h">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\dense_hash_map">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\dense_hash_set">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\sparsehash\densehashtable.h">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\windows\port.h">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\sparse_hash_map">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\sparse_hash_set">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\windows\google\sparsehash\sparseconfig.h">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\sparsehash\sparsehashtable.h">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\sparsetable">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\type_traits.h">
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
</Files>
|
|
||||||
<Globals>
|
|
||||||
</Globals>
|
|
||||||
</VisualStudioProject>
|
|
@ -1,167 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="Windows-1252"?>
|
|
||||||
<VisualStudioProject
|
|
||||||
ProjectType="Visual C++"
|
|
||||||
Version="7.10"
|
|
||||||
Name="type_traits_unittest"
|
|
||||||
ProjectGUID="{008CCFED-7D7B-46F8-8E13-03837A2258B3}"
|
|
||||||
Keyword="Win32Proj">
|
|
||||||
<Platforms>
|
|
||||||
<Platform
|
|
||||||
Name="Win32"/>
|
|
||||||
</Platforms>
|
|
||||||
<Configurations>
|
|
||||||
<Configuration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ConfigurationName)"
|
|
||||||
ConfigurationType="1"
|
|
||||||
CharacterSet="2">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
Optimization="0"
|
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
|
||||||
MinimalRebuild="TRUE"
|
|
||||||
BasicRuntimeChecks="3"
|
|
||||||
RuntimeLibrary="5"
|
|
||||||
UsePrecompiledHeader="0"
|
|
||||||
WarningLevel="3"
|
|
||||||
DebugInformationFormat="4"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLinkerTool"
|
|
||||||
OutputFile="$(OutDir)/type_traits_unittest.exe"
|
|
||||||
LinkIncremental="2"
|
|
||||||
GenerateDebugInformation="TRUE"
|
|
||||||
ProgramDatabaseFile="$(OutDir)/type_traits_unittest.pdb"
|
|
||||||
SubSystem="1"
|
|
||||||
TargetMachine="1"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebDeploymentTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedWrapperGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
|
||||||
</Configuration>
|
|
||||||
<Configuration
|
|
||||||
Name="Release|Win32"
|
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ConfigurationName)"
|
|
||||||
ConfigurationType="1"
|
|
||||||
CharacterSet="2">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
|
||||||
RuntimeLibrary="4"
|
|
||||||
UsePrecompiledHeader="0"
|
|
||||||
WarningLevel="3"
|
|
||||||
DebugInformationFormat="3"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLinkerTool"
|
|
||||||
OutputFile="$(OutDir)/type_traits_unittest.exe"
|
|
||||||
LinkIncremental="1"
|
|
||||||
GenerateDebugInformation="TRUE"
|
|
||||||
SubSystem="1"
|
|
||||||
OptimizeReferences="2"
|
|
||||||
EnableCOMDATFolding="2"
|
|
||||||
TargetMachine="1"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebDeploymentTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedWrapperGeneratorTool"/>
|
|
||||||
<Tool
|
|
||||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
|
||||||
</Configuration>
|
|
||||||
</Configurations>
|
|
||||||
<References>
|
|
||||||
</References>
|
|
||||||
<Files>
|
|
||||||
<Filter
|
|
||||||
Name="Source Files"
|
|
||||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
|
||||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\windows\port.cc">
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\type_traits_unittest.cc">
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|Win32">
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
<Filter
|
|
||||||
Name="Header Files"
|
|
||||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
|
||||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\windows\config.h">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\windows\port.h">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\windows\google\sparsehash\sparseconfig.h">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\sparsetable">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\google\type_traits.h">
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
</Files>
|
|
||||||
<Globals>
|
|
||||||
</Globals>
|
|
||||||
</VisualStudioProject>
|
|
Loading…
Reference in New Issue
Block a user