commit cddcd72e336afd2330d706ecaad004956e5dc6b8 Author: Mirko Lindner Date: Thu Feb 4 12:33:47 2010 +0100 initial commit - needs clean-up Signed-off-by: Mirko Lindner diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..d03ea90 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,3 @@ +Massimiliano "Ryo" Torromeo +Testers: PokeParadox, Tripmonkey_uk, Goemon4 PSyMastR +Translators: Yodaz, superfly, pedator, NightShadow, Jozef, Esslan, Micket, fusion_power, johnnysnet, Waldteufel, Jontte, Atte, cowai, XaMMaX90, claus \ No newline at end of file diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..5b6e7c6 --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..c2236c8 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,154 @@ +----------- +New in 0.10 +----------- +Raised default clock to 136Mhz for F200 models (minimum frequency for touchscreen) +Fixed bug in link navigation +Support for additional utf8 characters +Restructured the virtual keyboard dialog with touchscreen support +New translations: Basque, Catalan, Turkish +Added support for the touchscreen +Added support for f200 battery +Added internal explorer that can launch .gpu .gpe and .sh files +Added graphic indicators for switching sections +Added on screen help (keep pressed A, only on the main screen at the moment) +Cpu clock raised when loading manuals +Added support for bmp and jpg/jpeg files for manuals +Added preview of images when selecting icons +Added option to show the root folder in the selection dialogs +Fixed bug that prevented the use of the custom selected wallpaper on restart +Lots of fixes + +---------- +New in 0.9 +---------- +Added gamma setting (global and per-link) +Added option to tweak ram timings +Added skins support +Added link to activate tv-out +Added support for multiple wallpapers +Color of message dialogs changeable by skins +Automatic icon association for links with icons found in the skin "icons" directory +Adding a link to a file without gpu or gpe extension automatically enables the wrapper feature +Added support for translations (Italian, Danish, Dutch, Spanish, German, French, Finnish, Portuguese, Swedish, Slovak, Norwegian and Russian included) +Use of a new font code which supports (some) utf8 characters +Added graphics for gp2x buttons +Moved screenshot in the selector under the text +[selFullPath] is automatically added at the end of the params when using the selector and no [marker] is specified +Easier access to the last row of links +Moved manual indicator to the bottom bar +Save screenshot with A+L+R (only on the main screen) +SD corruption when using USB on certain setups should be fixed +Fixed half tv-out screen +Fixed flickering in various locations +Fixed bugs in the manuals navigation system +Other small changes + +------------ +New in 0.8.1 +------------ +Fixed crash on section creation. +Fixed moving links between sections. +Fixed creating links in the first section. +Fixed alpha support for font.png + +---------- +New in 0.8 +---------- +Added support for game manuals (.man.png, .man.txt or readmes) +Implemented link's output logs with a log viewer (Disabled by default) +Implemented a simple text reader used in various situations +Implemented volume control (per-link and globally) +Added some confirmation dialogs +Changed cancel button from A to X +Added link to mount nand on usb with a dialog notification if usb is used for networking +Implemented virtual links (gmenu2x settings, usb, log viewer, about) +Added messageboxes +Added links for firmware 2.1.x +Directories browseable from selector +Added a blending effect to selector screenshots. +Updated the README with basic instructions (website is still recommended) +Fixed some minor bugs. + +---------- +New in 0.7 +---------- +GMenu2X always returns to last section/game/selector used (until shutdown) +New params magic value: [selFullPath] which equals [selPath][selFile][selExt] +Params magic values ([selFile] & Co.) are now automatically escaped, so quotes are not needed (and may cause problems) +Added support for an optional alias file for the selector that display the full name of roms. +Fixed bug with links with special characters. +Removed some unneeded savings. +Number of rows and columns on the links page configurable. +Various little fixes and tweaks + +---------- +New in 0.6 +---------- +Implemented link scanner +Added options to links for using a selector with them +Initial support for usbnet, ftp, telnet, samba and web server +Battery led indicates disk writes (don't turn the gp2x off while the led is on) +L = PageUp, R = PageDown in lists +Raised maximum hardcoded clock to 325Mhz and default gmenu2x clock to 100Mhz +Improved virtual keyboard +Sorting functions are now case unsensitive (filebrowser, dirdialog, selector) +Wrapper script removed and fixed a related bugs (wrapper function is still available) +Link's section changeable +All link's features are configurable from the interface +Battery indicator refined +File selector starts from /mnt instead of /mnt/sd +Fixed support for fonts of different size + +---------- +New in 0.5 +---------- +Added context-menu option to change link icon +Added options to configure top bar, bottom bar and selection color separately. +Readded support for imgs/selection.png (used only if present) +GMenu2X is now working at 50Mhz (configurable) +Added ability to set the maximum overclock to use with links (hardcoded maximum remains 300Mhz) +Moved under/overclock functions in gmenu2x (no need for cpu_speed binary) +"Save last selection" feature disableable + +---------- +New in 0.4 +---------- +Fixed flickering in context menu +Fixed bug that prevented correct launch of some applications +Interface color configurable (START brings up an options menu) (removed img/selection.png) +Saves and restores last selected section and link +Added global config file +Sections with no icon are displayed with a default one (icons/section.png) +Added virtual keyboard for editing title and description of links +Links created through file browser are truncated if too long + +---------- +New in 0.3 +---------- +Links creatable in-menu using a file browser +Links deletable in-menu +Icon associated with gpu/gpe is used when no icon is specified +Dithered background +Added battery status indicator +Added a menu with options binded to the select button +Clock setting is saved when changed +Links area scrollable to allow more than 24 links per section +Fix for links with DOS line-endings +Increased space between icons + +------------ +New in 0.2.1 +------------ +No more crash in presence of a section with no valid links +Keys and values in links are now trimmed. This means that you can spaces before and after keys and values (IE: " exec = /path/to/link.gpe " is valid) +Split applications section in applications and settings and added settings/exit link that launches the original frontend. +L and R shoulder buttons swapped + +---------- +New in 0.2 +---------- +Interface completely redesigned, now there are 24 links visible at the same time. +Display of free space on sd +In-Menu Under/Overclocker using the included utility by god_at_hell, Hermes/PS2Reality, Robster, Vimacs (edit script/cpuspeed.sh to tweak other parameteres besides clock speed) +Any number of sections supported +Customisation made simplier (just replace bg.png with any wallpaper of size 320x240) diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..bac90c3 --- /dev/null +++ b/INSTALL @@ -0,0 +1,8 @@ +To compile the sourcecode you need to set the GP2XDEV environment variable and probably edit the Makefile present in the src folder. +This is an example environment: + +# export GP2XDEV="/usr/local/gp2xdev" +# export PATH="$PATH:${GP2XDEV}/bin" + +=== Installation === +Put the file "autorun.gpu" and the folder "gmenu2x" on the root of your sd, create the links as described on the documentation present on the website (http://gmenu2x.sourceforge.net) and boot your gp2x. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..948a117 --- /dev/null +++ b/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/README b/README new file mode 100644 index 0000000..e69de29 diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..140a2cf --- /dev/null +++ b/README.txt @@ -0,0 +1,26 @@ +[Introduction] +GMenu2X is a replacement for the official frontend for the gp2x released under the GNU GPL license. + +[Installation] +Copy the file autorun.gpu and the directory gmenu2x/ to the root of your sd card. +Verify that the autorun option in the standard gp2x interface is enabled. +(Re)Boot your gp2x and enjoy GMenu2X. + +[Controls] +X, Stick left: Goes up one directory in file browser. +X: Cancel action. +B, Stick press: Launch selected link / Confirm action. +L, R: Switch between sections - PageUp/PageDown on lists. +Y: Bring up the manual/readme. +VOLDOWN: Decrease cpu clock. +VOLUP: Increase cpu clock. +VOLDOWN+VOLUP: Reset clock. +A+VOLDOWN: Decrease volume for the selected link. +A+VOLUP: Increase volume for the selected link. +A+VOLDOWN+VOLUP: Reset volume for the selected link. +SELECT: Bring up the contextual menu. +START: GMenu2X options. + +[Contacts] +Developed by Massimiliano Torromeo +Visit the homepage at http://gmenu2x.sourceforge.net for more info. diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 0000000..38d8b0f --- /dev/null +++ b/acinclude.m4 @@ -0,0 +1,168 @@ +# Configure paths for SDL +# Sam Lantinga 9/21/99 +# stolen from Manish Singh +# stolen back from Frank Belew +# stolen from Manish Singh +# Shamelessly stolen from Owen Taylor + +dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS +dnl +AC_DEFUN(AM_PATH_SDL, +[dnl +dnl Get the cflags and libraries from the sdl-config script +dnl +AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)], + sdl_prefix="$withval", sdl_prefix="") +AC_ARG_WITH(sdl-exec-prefix,[ --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)], + sdl_exec_prefix="$withval", sdl_exec_prefix="") +AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run a test SDL program], + , enable_sdltest=yes) + + if test x$sdl_exec_prefix != x ; then + sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix" + if test x${SDL_CONFIG+set} != xset ; then + SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config + fi + fi + if test x$sdl_prefix != x ; then + sdl_args="$sdl_args --prefix=$sdl_prefix" + if test x${SDL_CONFIG+set} != xset ; then + SDL_CONFIG=$sdl_prefix/bin/sdl-config + fi + fi + + AC_PATH_PROG(SDL_CONFIG, sdl-config, no) + min_sdl_version=ifelse([$1], ,0.11.0,$1) + AC_MSG_CHECKING(for SDL - version >= $min_sdl_version) + no_sdl="" + if test "$SDL_CONFIG" = "no" ; then + no_sdl=yes + else + SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags` + SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs` + + sdl_major_version=`$SDL_CONFIG $sdl_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_sdltest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" +dnl +dnl Now check if the installed SDL is sufficiently new. (Also sanity +dnl checks the results of sdl-config to some extent +dnl + rm -f conf.sdltest + AC_TRY_RUN([ +#include +#include +#include +#include "SDL.h" + +char* +my_strdup (char *str) +{ + char *new_str; + + if (str) + { + new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char)); + strcpy (new_str, str); + } + else + new_str = NULL; + + return new_str; +} + +int main (int argc, char *argv[]) +{ + int major, minor, micro; + char *tmp_version; + + /* This hangs on some systems (?) + system ("touch conf.sdltest"); + */ + { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); } + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = my_strdup("$min_sdl_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_sdl_version"); + exit(1); + } + + if (($sdl_major_version > major) || + (($sdl_major_version == major) && ($sdl_minor_version > minor)) || + (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version); + printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro); + printf("*** best to upgrade to the required version.\n"); + printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n"); + printf("*** to point to the correct copy of sdl-config, and remove the file\n"); + printf("*** config.cache before re-running configure\n"); + return 1; + } +} + +],, no_sdl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_sdl" = x ; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$SDL_CONFIG" = "no" ; then + echo "*** The sdl-config script installed by SDL could not be found" + echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the SDL_CONFIG environment variable to the" + echo "*** full path to sdl-config." + else + if test -f conf.sdltest ; then + : + else + echo "*** Could not run SDL test program, checking why..." + CFLAGS="$CFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" + AC_TRY_LINK([ +#include +#include "SDL.h" +], [ return 0; ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding SDL or finding the wrong" + echo "*** version of SDL. If it is not finding SDL, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means SDL was incorrectly installed" + echo "*** or that you have moved SDL since it was installed. In the latter case, you" + echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + SDL_CFLAGS="" + SDL_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(SDL_CFLAGS) + AC_SUBST(SDL_LIBS) + rm -f conf.sdltest +]) diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..55ff843 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,952 @@ +# generated automatically by aclocal 1.11 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2007, 2008, 2009 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. + +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.64],, +[m4_warning([this file was generated for autoconf 2.64. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically `autoreconf'.])]) + +# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 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. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.11' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.11], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.11])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# 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, 2006, 2008 +# 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 9 + +# 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])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +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, 2006, 2009 +# 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 10 + +# 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], UPC, [depcc="$UPC" am_compiler_list=], + [$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 + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + 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 + + # 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. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + 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 + ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj 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])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 +# 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 5 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + 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. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/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"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2008, 2009 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 16 + +# 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.62])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 +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +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 +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, + [m4_fatal([AC_INIT should be called with package and version arguments])])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) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +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 +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES(OBJC)], + [define([AC_PROG_OBJC], + defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl +]) +_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl +dnl The `parallel-tests' driver may need to know about EXEEXT, so add the +dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro +dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl +]) + +dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + + +# 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_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001, 2003, 2005, 2008 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 +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +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, 2009 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_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.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 +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +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, 2004, 2005, 2008 +# 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 6 + +# 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 +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# 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, 2006 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 for `mkdir -p'. +AC_DEFUN([AM_PROG_MKDIR_P], +[AC_PREREQ([2.60])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, +dnl while keeping a definition of mkdir_p for backward compatibility. +dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. +dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of +dnl Makefile.ins that do not define MKDIR_P, so we do our own +dnl adjustment using top_builddir (which is defined more often than +dnl MKDIR_P). +AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl +case $mkdir_p in + [[\\/$]]* | ?:[[\\/]]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2008 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_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], +[m4_foreach_w([_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, 2008 +# 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 5 + +# 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 +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; +esac + +# 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="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006, 2008 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_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# 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 /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([acinclude.m4]) diff --git a/autorun.gpu b/autorun.gpu new file mode 100644 index 0000000..2e1f87a --- /dev/null +++ b/autorun.gpu @@ -0,0 +1,3 @@ +#!/bin/sh +cd /mnt/sd/gmenu2x +exec ./gmenu2x diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..07fb069 --- /dev/null +++ b/configure.in @@ -0,0 +1,30 @@ +AC_INIT(configure.in) +AM_INIT_AUTOMAKE(gmenu2x, 0.1) + +AC_ISC_POSIX +AC_PROG_CC +AC_HEADER_STDC +AC_PROG_CPP +AC_PROG_CXX +AC_PROG_CXXCPP + +AC_LANG_CPLUSPLUS + +# Check for SDL +SDL_VERSION=1.2.8 +AM_PATH_SDL($SDL_VERSION, :, + AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!])) + +AC_CHECK_LIB(SDL_image, IMG_LoadPNG_RW, , AC_MSG_ERROR([ +*** Unable to find SDL_image libary with PNG support +(http://www.libsdl.org/projects/SDL_image/) +])) + +AC_ARG_WITH(sdl-gfx-prefix, + [ --with-sdl-gfx-prefix=DIR specify where SDL_gfx library is installed], + [SDL_GFX_PREFIX="$withval"]) + +AC_CHECK_LIB(SDL_gfx, rotozoomSurfaceXY,,check_sdl_gfx="no") + + +AC_OUTPUT(Makefile src/Makefile) diff --git a/pandora/gmenu2x.conf b/pandora/gmenu2x.conf new file mode 100644 index 0000000..a50a59c --- /dev/null +++ b/pandora/gmenu2x.conf @@ -0,0 +1,18 @@ +lang="English" +tvoutEncoding="PAL" +wallpaper="skins/Default/wallpapers/pandora-nova-desat.png" +skin="Default" +resolutionX=800 +section=3 +menuClock=100 +resolutionY=480 +outputLogs=0 +maxClock=300 +link=0 +globalVolume=0 +globalVolume=67 +saveSelection=1 +globalVolume=0 +gamma=10 +globalVolume=0 +videoBpp=24 diff --git a/pandora/input.conf.gp2x b/pandora/input.conf.gp2x new file mode 100644 index 0000000..203b56b --- /dev/null +++ b/pandora/input.conf.gp2x @@ -0,0 +1,14 @@ +a=joystickbutton,0,12 +b=joystickbutton,0,13 +x=joystickbutton,0,14 +y=joystickbutton,0,15 +l=joystickbutton,0,10 +r=joystickbutton,0,11 +select=joystickbutton,0,9 +start=joystickbutton,0,8 +volup=joystickbutton,0,16 +voldown=joystickbutton,0,17 +up=joystickbutton,0,0 +down=joystickbutton,0,4 +left=joystickbutton,0,2 +right=joystickbutton,0,6 diff --git a/pandora/input.conf.xbox360 b/pandora/input.conf.xbox360 new file mode 100644 index 0000000..bc3e89f --- /dev/null +++ b/pandora/input.conf.xbox360 @@ -0,0 +1,23 @@ +a=joystickbutton,0,2 +b=joystickbutton,0,1 +b=keyboard,13 +b=keyboard,271 +x=joystickbutton,0,0 +x=keyboard,8 +y=joystickbutton,0,3 +l=joystickbutton,0,4 +l=keyboard,49 +r=joystickbutton,0,5 +r=keyboard,50 +select=joystickbutton,0,10 +start=joystickbutton,0,6 +volup=joystickaxys,0,5,10000 +voldown=joystickaxys,0,2,10000 +up=joystickaxys,0,1,-10000 +up=keyboard,273 +down=joystickaxys,0,1,10000 +down=keyboard,274 +left=joystickaxys,0,0,-10000 +left=keyboard,276 +right=joystickaxys,0,0,10000 +right=keyboard,275 \ No newline at end of file diff --git a/pandora/scripts/services.sh b/pandora/scripts/services.sh new file mode 100755 index 0000000..b8ddf37 --- /dev/null +++ b/pandora/scripts/services.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# $1 = ip +# $2 = inet +# $3 = samba +# $4 = web +insmod net2272 +insmod g_ether +ifconfig usb0 $1 netmask 255.255.255.0 up +# route add default gw $defaultgw +if [ $2 = "on" ]; then /etc/init.d/inet start; fi +if [ $3 = "on" ]; then smbd; fi +if [ $4 = "on" ]; then thttpd; fi diff --git a/pandora/scripts/usboff.sh b/pandora/scripts/usboff.sh new file mode 100755 index 0000000..4b230e0 --- /dev/null +++ b/pandora/scripts/usboff.sh @@ -0,0 +1,11 @@ +#!/bin/bash +export PATH=$PATH:/sbin +rmmod g_file_storage +rmmod net2272 +if [ $1 = "nand" ]; then + mount /mnt/nand || mount -o remount,rw /mnt/nand +elif [ $1 = "root" ]; then + mount -o remount,rw / +else + mount /mnt/sd || mount -o remount,rw /mnt/sd +fi diff --git a/pandora/scripts/usbon.sh b/pandora/scripts/usbon.sh new file mode 100755 index 0000000..2196730 --- /dev/null +++ b/pandora/scripts/usbon.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# $1 = sd|nand|root +# defaults to sd (compatible with previous versions) +export PATH=$PATH:/sbin +modprobe net2272 +if [ $1 = "nand" ]; then + umount /mnt/nand || mount -o remount,loop,ro /mnt/nand + modprobe g_file_storage file=/dev/loop/7 +elif [ $1 = "root" ]; then + mount -o remount,loop,ro / + modprobe g_file_storage file=/dev/mtdblock/3 +else + umount /mnt/sd || mount -o remount,loop,ro /mnt/sd + modprobe g_file_storage file=/dev/mmcsd/disc0/disc +fi diff --git a/pandora/sections/applications/ebook b/pandora/sections/applications/ebook new file mode 100644 index 0000000..7667546 --- /dev/null +++ b/pandora/sections/applications/ebook @@ -0,0 +1,6 @@ +title=eBook +icon=skin:icons/ebook.png +exec=/usr/gp2x/gp2xmenu +params=--disable-autorun --enable-terminate --view-ebook +clock=75 +wrapper=true diff --git a/pandora/sections/applications/mplayer b/pandora/sections/applications/mplayer new file mode 100644 index 0000000..17241b2 --- /dev/null +++ b/pandora/sections/applications/mplayer @@ -0,0 +1,5 @@ +title=Movies +icon=skin:icons/mplayer.png +exec=/usr/gp2x/mplayer +clock=200 +wrapper=true diff --git a/pandora/sections/applications/music b/pandora/sections/applications/music new file mode 100644 index 0000000..1f0ff6c --- /dev/null +++ b/pandora/sections/applications/music @@ -0,0 +1,5 @@ +title=Music +icon=skin:icons/music.png +exec=/usr/gp2x/gp2xmenu +params=--disable-autorun --enable-terminate --view-music +clock=75 diff --git a/pandora/sections/applications/photo b/pandora/sections/applications/photo new file mode 100644 index 0000000..9259b58 --- /dev/null +++ b/pandora/sections/applications/photo @@ -0,0 +1,6 @@ +title=Photo +icon=skin:icons/photo.png +exec=/usr/gp2x/gp2xmenu +params=--disable-autorun --enable-terminate --view-photo +clock=100 +wrapper=true diff --git a/pandora/sections/emulators/Amiga b/pandora/sections/emulators/Amiga new file mode 100755 index 0000000..9b291ff --- /dev/null +++ b/pandora/sections/emulators/Amiga @@ -0,0 +1,5 @@ +title=Amiga +description=UAE-2X +exec=/mnt/sd/uae2x_01alpha/uae2x-tweak.gpe +manual=fonttest.txt +clock=200 diff --git a/pandora/sections/emulators/GBAdvance b/pandora/sections/emulators/GBAdvance new file mode 100755 index 0000000..a560f65 --- /dev/null +++ b/pandora/sections/emulators/GBAdvance @@ -0,0 +1,9 @@ +title=gpSP +description=vba2xg +icon=/mnt/sd/Icons/Videogames/gba-purple.png +exec=/mnt/sd/vba2x/vba.gpe +clock=280 +selectordir=/mnt/sd/roms/gba/ +selectorfilter=.zip,.vba +selectorscreens=/mnt/sd/roms/gba +wrapper=true diff --git a/pandora/sections/emulators/GameBoy b/pandora/sections/emulators/GameBoy new file mode 100755 index 0000000..12b86fc --- /dev/null +++ b/pandora/sections/emulators/GameBoy @@ -0,0 +1,6 @@ +title=GameBoy +description=Gnuboy2x +icon=/mnt/sd/Icons/Videogames/gb-silver.png +exec=/mnt/sd/gnuboy2x/Gnuboy2x.gpe +manual=/mnt/sd/gnuboy2x/readme.txt +clock=180 diff --git a/pandora/sections/emulators/Genesis b/pandora/sections/emulators/Genesis new file mode 100755 index 0000000..e44c4d0 --- /dev/null +++ b/pandora/sections/emulators/Genesis @@ -0,0 +1,9 @@ +title=Genesis +description=PicoDrive +icon=/mnt/sd/Icons/Videogames/genesis.png +exec=/mnt/sd/PicoDrive/PicoDrive.gpe +params=-menu " " [selFullPath] +clock=160 +selectordir=/mnt/sd/roms/genesis/ +selectorscreens=/mnt/sd/screens/genesis +wrapper=true diff --git a/pandora/sections/emulators/Mame b/pandora/sections/emulators/Mame new file mode 100755 index 0000000..cc52062 --- /dev/null +++ b/pandora/sections/emulators/Mame @@ -0,0 +1,10 @@ +title=MAME +description=Multiple Arcade Machine Emulator +icon=/mnt/sd/mamegp2x/mame.png +exec=/mnt/sd/mamegp2x/mame.gpe +params=[selFile] +manual=/mnt/sd/mamegp2x/mame.man.png +clock=200 +selectordir=/mnt/sd/mamegp2x/roms/ +selectorscreens=/mnt/sd/mamegp2x/screen +selectoraliases=/mnt/sd/mame.alias diff --git a/pandora/sections/emulators/NK SNES b/pandora/sections/emulators/NK SNES new file mode 100755 index 0000000..179f850 --- /dev/null +++ b/pandora/sections/emulators/NK SNES @@ -0,0 +1,5 @@ +title=NK SNES +description=Super Nintendo Emulator +icon=/mnt/sd/Icons/Videogames/snes.png +exec=/mnt/sd/snes-mod/snesgp2x.gpe +clock=200 diff --git a/pandora/sections/emulators/NeoGeo b/pandora/sections/emulators/NeoGeo new file mode 100755 index 0000000..0081560 --- /dev/null +++ b/pandora/sections/emulators/NeoGeo @@ -0,0 +1,5 @@ +title=Neo Geo +description=GnGeo2X +icon=/mnt/sd/Icons/Videogames/neogeo.png +exec=/mnt/sd/neogeo/rage2x.gpe +clock=200 diff --git a/pandora/sections/emulators/NeoGeo Pocket b/pandora/sections/emulators/NeoGeo Pocket new file mode 100755 index 0000000..c616a9c --- /dev/null +++ b/pandora/sections/emulators/NeoGeo Pocket @@ -0,0 +1,9 @@ +title=NeoGeo Pocket +description=Race! +icon=/mnt/sd/Icons/Videogames/ngpc white.png +exec=/mnt/sd/ngpc/race +clock=160 +selectordir=/mnt/sd/roms/ngpc/ +selectorfilter=.ngp,.ngc +selectorscreens=/mnt/sd/screens/ngpc +wrapper=true diff --git a/pandora/sections/emulators/Nintendo b/pandora/sections/emulators/Nintendo new file mode 100755 index 0000000..9378657 --- /dev/null +++ b/pandora/sections/emulators/Nintendo @@ -0,0 +1,9 @@ +title=Nintendo +description=GpFCE +icon=/mnt/sd/Icons/Videogames/nes.png +exec=/mnt/sd/GpFce/gpfce +clock=200 +selectordir=/mnt/sd/roms/nes/ +selectorfilter=.nes,.zip +selectorscreens=/mnt/sd/screens/nes +wrapper=true diff --git a/pandora/sections/emulators/PcEngine b/pandora/sections/emulators/PcEngine new file mode 100755 index 0000000..644e59a --- /dev/null +++ b/pandora/sections/emulators/PcEngine @@ -0,0 +1,5 @@ +title=PcEngine +description=gp2xengine +icon=/mnt/sd/Icons/Videogames/tg16.png +exec=/mnt/sd/gp2xengine/gp2xengine.gpe +clock=200 diff --git a/pandora/sections/emulators/PlayStation b/pandora/sections/emulators/PlayStation new file mode 100755 index 0000000..ec48745 --- /dev/null +++ b/pandora/sections/emulators/PlayStation @@ -0,0 +1,5 @@ +title=PlayStation +description=psx4gp2x +icon=/mnt/sd/Icons/Videogames/psx.png +exec=/mnt/sd/psx4gp2x/psx4all.gpe +clock=200 diff --git a/pandora/sections/emulators/SSnes b/pandora/sections/emulators/SSnes new file mode 100755 index 0000000..3058bb2 --- /dev/null +++ b/pandora/sections/emulators/SSnes @@ -0,0 +1,9 @@ +title=SNES +description=SquidgeSnes +icon=/mnt/sd/Icons/Videogames/snes.png +exec=/mnt/sd/snes/squidgesnes.gpe +params=ntrd load=[selFullPath] +clock=240 +selectordir=/mnt/sd/roms/snes/ +selectorscreens=/mnt/sd/screens/snes +wrapper=true diff --git a/pandora/sections/emulators/fishyNES b/pandora/sections/emulators/fishyNES new file mode 100755 index 0000000..f70f035 --- /dev/null +++ b/pandora/sections/emulators/fishyNES @@ -0,0 +1,4 @@ +title=fishyNES +icon=/mnt/sd/Icons/Videogames/nes.png +exec=/mnt/sd/nes/fishyNES.gpe +clock=200 diff --git a/pandora/sections/emulators/hu6280 b/pandora/sections/emulators/hu6280 new file mode 100755 index 0000000..aeb3105 --- /dev/null +++ b/pandora/sections/emulators/hu6280 @@ -0,0 +1,5 @@ +title=HU6280 +description=PcEngine emulator +icon=/mnt/sd/Icons/Videogames/tg16.png +exec=/mnt/sd/pcengine/hu6280.gpe +clock=200 diff --git a/pandora/sections/games/Barrage b/pandora/sections/games/Barrage new file mode 100755 index 0000000..72ced33 --- /dev/null +++ b/pandora/sections/games/Barrage @@ -0,0 +1,3 @@ +title=Barrage +exec=/mnt/sd/barrage/Barrage.gpe +clock=200 diff --git a/pandora/sections/games/CDogs b/pandora/sections/games/CDogs new file mode 100755 index 0000000..5ad8b3b --- /dev/null +++ b/pandora/sections/games/CDogs @@ -0,0 +1,4 @@ +title=CDogs +icon=/mnt/sd/Icons/cdogssp2.png +exec=/mnt/sd/CDogs/CDogs.gpe +clock=200 diff --git a/pandora/sections/games/ClonkFront b/pandora/sections/games/ClonkFront new file mode 100755 index 0000000..6163d87 --- /dev/null +++ b/pandora/sections/games/ClonkFront @@ -0,0 +1,4 @@ +title=Clonk2X +icon=/mnt/sd/Icons/clonk.png +exec=/mnt/sd/Clonk2X/ClonkFront.gpe +clock=200 diff --git a/pandora/sections/games/Nethack b/pandora/sections/games/Nethack new file mode 100755 index 0000000..7c216df --- /dev/null +++ b/pandora/sections/games/Nethack @@ -0,0 +1,3 @@ +title=Nethack +icon=/mnt/sd/nethack/Nethack.png +exec=/mnt/sd/nethack/Nethack.gpe diff --git a/pandora/sections/games/PaybackDemo b/pandora/sections/games/PaybackDemo new file mode 100755 index 0000000..b44781f --- /dev/null +++ b/pandora/sections/games/PaybackDemo @@ -0,0 +1,5 @@ +title=Payback +icon=/mnt/sd/PaybackDemo/PaybackDemo.png +exec=/mnt/sd/PaybackDemo/PaybackDemo +clock=200 +wrapper=true diff --git a/pandora/sections/games/S-Tris 2 b/pandora/sections/games/S-Tris 2 new file mode 100755 index 0000000..a1d4bf8 --- /dev/null +++ b/pandora/sections/games/S-Tris 2 @@ -0,0 +1,2 @@ +title=S-Tris 2 +exec=/mnt/sd/s-tris/S-Tris 2.gpe diff --git a/pandora/sections/games/beat2x b/pandora/sections/games/beat2x new file mode 100755 index 0000000..8b2018a --- /dev/null +++ b/pandora/sections/games/beat2x @@ -0,0 +1,4 @@ +title=Beat2X +description=DanceDance style game +icon=/mnt/sd/beat2x/beat2x.png +exec=/mnt/sd/beat2x/beat2x.gpe diff --git a/pandora/sections/games/blazar b/pandora/sections/games/blazar new file mode 100755 index 0000000..276d345 --- /dev/null +++ b/pandora/sections/games/blazar @@ -0,0 +1,4 @@ +title=blazar +icon=/mnt/sd/Blazar/blazar.png +exec=/mnt/sd/Blazar/blazar.gpe +clock=199 diff --git a/pandora/sections/games/duke3d b/pandora/sections/games/duke3d new file mode 100755 index 0000000..80e79dc --- /dev/null +++ b/pandora/sections/games/duke3d @@ -0,0 +1,4 @@ +title=duke3d +icon=/mnt/sd/Icons/duke3ddp1.png +exec=/mnt/sd/duke2x/duke3d.gpe +clock=140 diff --git a/pandora/sections/games/hexahop b/pandora/sections/games/hexahop new file mode 100755 index 0000000..2b668d7 --- /dev/null +++ b/pandora/sections/games/hexahop @@ -0,0 +1,3 @@ +title=hexahop +icon=/mnt/sd/hex-a-hop/hexahop.png +exec=/mnt/sd/hex-a-hop/hexahop.gpe diff --git a/pandora/sections/games/ladykiller b/pandora/sections/games/ladykiller new file mode 100755 index 0000000..2736a08 --- /dev/null +++ b/pandora/sections/games/ladykiller @@ -0,0 +1,3 @@ +title=ladykiller +exec=/mnt/sd/ladykiller/ladykiller.gpe +clock=200 diff --git a/pandora/sections/games/myriad b/pandora/sections/games/myriad new file mode 100755 index 0000000..9849bb5 --- /dev/null +++ b/pandora/sections/games/myriad @@ -0,0 +1,3 @@ +title=myriad +icon=/mnt/sd/Myriad/myriad.png +exec=/mnt/sd/Myriad/myriad.gpe diff --git a/pandora/sections/games/openglad b/pandora/sections/games/openglad new file mode 100755 index 0000000..0f35550 --- /dev/null +++ b/pandora/sections/games/openglad @@ -0,0 +1,5 @@ +title=openglad +icon=/mnt/sd/Icons/exultsx6.png +exec=/mnt/sd/openglad2x/openglad +clock=200 +dontleave=true diff --git a/pandora/sections/games/openjazz b/pandora/sections/games/openjazz new file mode 100755 index 0000000..62f55c0 --- /dev/null +++ b/pandora/sections/games/openjazz @@ -0,0 +1,3 @@ +title=OpenJazz +description=Jazz Jazkrabbit Port +exec=/mnt/sd/openjazz/openjazz.gpe diff --git a/pandora/sections/games/puzzleland b/pandora/sections/games/puzzleland new file mode 100755 index 0000000..05b4232 --- /dev/null +++ b/pandora/sections/games/puzzleland @@ -0,0 +1,5 @@ +title=puzzleland +icon=/mnt/sd/puzzleland/puzzleland.png +exec=/mnt/sd/puzzleland/puzzleland +clock=200 +wrapper=true diff --git a/pandora/sections/games/rubido b/pandora/sections/games/rubido new file mode 100755 index 0000000..2571d2f --- /dev/null +++ b/pandora/sections/games/rubido @@ -0,0 +1,5 @@ +title=rubido +icon=/mnt/sd/rubido/rubido.png +exec=/mnt/sd/rubido/rubido.gpe +clock=200 +wrapper=true diff --git a/pandora/sections/games/scummvm b/pandora/sections/games/scummvm new file mode 100755 index 0000000..8f9c1d1 --- /dev/null +++ b/pandora/sections/games/scummvm @@ -0,0 +1,5 @@ +title=Scumm +description=Scumm emulator +icon=/mnt/sd/Icons/scummvmpq9.png +exec=/mnt/sd/scummvm/scummvm.gpe +clock=200 diff --git a/pandora/sections/games/smashgp b/pandora/sections/games/smashgp new file mode 100755 index 0000000..b87535f --- /dev/null +++ b/pandora/sections/games/smashgp @@ -0,0 +1,3 @@ +title=SmashGp2x +description=Super Smash Bros. Clone +exec=/mnt/sd/SmashGp2x.gpe diff --git a/pandora/sections/games/smw b/pandora/sections/games/smw new file mode 100755 index 0000000..56f93f1 --- /dev/null +++ b/pandora/sections/games/smw @@ -0,0 +1,6 @@ +title=SMW +description=Super Mario War +icon=/mnt/sd/Icons/Characters/Mario.png +exec=/mnt/sd/smw/smw.gpe +clock=200 +gamma=76 diff --git a/pandora/sections/games/sokoban b/pandora/sections/games/sokoban new file mode 100755 index 0000000..c260a84 --- /dev/null +++ b/pandora/sections/games/sokoban @@ -0,0 +1,5 @@ +title=sokoban +icon=/mnt/sd/sokoban/sokoban.png +exec=/mnt/sd/sokoban/sokoban.gpe +clock=200 +wrapper=true diff --git a/pandora/sections/games/supertux b/pandora/sections/games/supertux new file mode 100755 index 0000000..d84810b --- /dev/null +++ b/pandora/sections/games/supertux @@ -0,0 +1,4 @@ +title=SuperTux +description=Platform Jump 'n' Run +icon=/mnt/sd/supertux/supertux.png +exec=/mnt/sd/supertux/supertux.gpe diff --git a/pandora/sections/games/vektar b/pandora/sections/games/vektar new file mode 100755 index 0000000..0f0bfba --- /dev/null +++ b/pandora/sections/games/vektar @@ -0,0 +1,5 @@ +title=Vektar +description=Commercial version demo +icon=/mnt/sd/Vektar Commercial Demo/vektar.png +exec=/mnt/sd/Vektar Commercial Demo/vektar.gpe +clock=200 diff --git a/pandora/sections/settings/exit b/pandora/sections/settings/exit new file mode 100755 index 0000000..1c79af4 --- /dev/null +++ b/pandora/sections/settings/exit @@ -0,0 +1,6 @@ +title=Exit +description=Exit GMenu2X to the official frontend +icon=skin:icons/exit.png +exec=/usr/gp2x/gp2xmenu +params=--disable-autorun +clock=195 diff --git a/pandora/sections/settings/originalsettings b/pandora/sections/settings/originalsettings new file mode 100644 index 0000000..785eadf --- /dev/null +++ b/pandora/sections/settings/originalsettings @@ -0,0 +1,6 @@ +title=GP2X +description=Configure options from the original frontend +icon=skin:icons/configure.png +exec=/usr/gp2x/gp2xmenu +params=--disable-autorun --enable-terminate --view-setting +wrapper=true diff --git a/pandora/sections/settings/system b/pandora/sections/settings/system new file mode 100644 index 0000000..4f0d5e1 --- /dev/null +++ b/pandora/sections/settings/system @@ -0,0 +1,6 @@ +title=System +description=Configure options from the original frontend +icon=skin:icons/configure.png +exec=/usr/gp2x/gp2xmenu +params=--disable-autorun --enable-terminate --view-system +wrapper=true diff --git a/pandora/skins/Default/icons/about.png b/pandora/skins/Default/icons/about.png new file mode 100755 index 0000000..d56ba2c Binary files /dev/null and b/pandora/skins/Default/icons/about.png differ diff --git a/pandora/skins/Default/icons/configure.png b/pandora/skins/Default/icons/configure.png new file mode 100644 index 0000000..6f3b1f4 Binary files /dev/null and b/pandora/skins/Default/icons/configure.png differ diff --git a/pandora/skins/Default/icons/ebook.png b/pandora/skins/Default/icons/ebook.png new file mode 100755 index 0000000..89ef01b Binary files /dev/null and b/pandora/skins/Default/icons/ebook.png differ diff --git a/pandora/skins/Default/icons/exit.png b/pandora/skins/Default/icons/exit.png new file mode 100755 index 0000000..08e97b4 Binary files /dev/null and b/pandora/skins/Default/icons/exit.png differ diff --git a/pandora/skins/Default/icons/explorer.png b/pandora/skins/Default/icons/explorer.png new file mode 100755 index 0000000..86cd87b Binary files /dev/null and b/pandora/skins/Default/icons/explorer.png differ diff --git a/pandora/skins/Default/icons/generic.png b/pandora/skins/Default/icons/generic.png new file mode 100755 index 0000000..135fd11 Binary files /dev/null and b/pandora/skins/Default/icons/generic.png differ diff --git a/pandora/skins/Default/icons/mplayer.png b/pandora/skins/Default/icons/mplayer.png new file mode 100755 index 0000000..e2470fc Binary files /dev/null and b/pandora/skins/Default/icons/mplayer.png differ diff --git a/pandora/skins/Default/icons/music.png b/pandora/skins/Default/icons/music.png new file mode 100755 index 0000000..a5a8d14 Binary files /dev/null and b/pandora/skins/Default/icons/music.png differ diff --git a/pandora/skins/Default/icons/photo.png b/pandora/skins/Default/icons/photo.png new file mode 100755 index 0000000..b443e1d Binary files /dev/null and b/pandora/skins/Default/icons/photo.png differ diff --git a/pandora/skins/Default/icons/section.png b/pandora/skins/Default/icons/section.png new file mode 100755 index 0000000..bd433f4 Binary files /dev/null and b/pandora/skins/Default/icons/section.png differ diff --git a/pandora/skins/Default/icons/skin.png b/pandora/skins/Default/icons/skin.png new file mode 100644 index 0000000..cf1c60d Binary files /dev/null and b/pandora/skins/Default/icons/skin.png differ diff --git a/pandora/skins/Default/icons/tv.png b/pandora/skins/Default/icons/tv.png new file mode 100755 index 0000000..9ae5c96 Binary files /dev/null and b/pandora/skins/Default/icons/tv.png differ diff --git a/pandora/skins/Default/icons/usb.png b/pandora/skins/Default/icons/usb.png new file mode 100755 index 0000000..2433889 Binary files /dev/null and b/pandora/skins/Default/icons/usb.png differ diff --git a/pandora/skins/Default/icons/wallpaper.png b/pandora/skins/Default/icons/wallpaper.png new file mode 100755 index 0000000..1616367 Binary files /dev/null and b/pandora/skins/Default/icons/wallpaper.png differ diff --git a/pandora/skins/Default/imgs/battery/0.png b/pandora/skins/Default/imgs/battery/0.png new file mode 100755 index 0000000..9257060 Binary files /dev/null and b/pandora/skins/Default/imgs/battery/0.png differ diff --git a/pandora/skins/Default/imgs/battery/1.png b/pandora/skins/Default/imgs/battery/1.png new file mode 100755 index 0000000..94274fd Binary files /dev/null and b/pandora/skins/Default/imgs/battery/1.png differ diff --git a/pandora/skins/Default/imgs/battery/2.png b/pandora/skins/Default/imgs/battery/2.png new file mode 100755 index 0000000..89bfade Binary files /dev/null and b/pandora/skins/Default/imgs/battery/2.png differ diff --git a/pandora/skins/Default/imgs/battery/3.png b/pandora/skins/Default/imgs/battery/3.png new file mode 100755 index 0000000..5aad243 Binary files /dev/null and b/pandora/skins/Default/imgs/battery/3.png differ diff --git a/pandora/skins/Default/imgs/battery/4.png b/pandora/skins/Default/imgs/battery/4.png new file mode 100755 index 0000000..aa5abbf Binary files /dev/null and b/pandora/skins/Default/imgs/battery/4.png differ diff --git a/pandora/skins/Default/imgs/battery/5.png b/pandora/skins/Default/imgs/battery/5.png new file mode 100755 index 0000000..cade241 Binary files /dev/null and b/pandora/skins/Default/imgs/battery/5.png differ diff --git a/pandora/skins/Default/imgs/battery/ac.png b/pandora/skins/Default/imgs/battery/ac.png new file mode 100755 index 0000000..69c89a5 Binary files /dev/null and b/pandora/skins/Default/imgs/battery/ac.png differ diff --git a/pandora/skins/Default/imgs/bottombar.png b/pandora/skins/Default/imgs/bottombar.png new file mode 100644 index 0000000..f7ec0b4 Binary files /dev/null and b/pandora/skins/Default/imgs/bottombar.png differ diff --git a/pandora/skins/Default/imgs/buttons/a.png b/pandora/skins/Default/imgs/buttons/a.png new file mode 100755 index 0000000..e3400f9 Binary files /dev/null and b/pandora/skins/Default/imgs/buttons/a.png differ diff --git a/pandora/skins/Default/imgs/buttons/b.png b/pandora/skins/Default/imgs/buttons/b.png new file mode 100755 index 0000000..16de5be Binary files /dev/null and b/pandora/skins/Default/imgs/buttons/b.png differ diff --git a/pandora/skins/Default/imgs/buttons/down.png b/pandora/skins/Default/imgs/buttons/down.png new file mode 100755 index 0000000..19233c5 Binary files /dev/null and b/pandora/skins/Default/imgs/buttons/down.png differ diff --git a/pandora/skins/Default/imgs/buttons/l.png b/pandora/skins/Default/imgs/buttons/l.png new file mode 100755 index 0000000..210c714 Binary files /dev/null and b/pandora/skins/Default/imgs/buttons/l.png differ diff --git a/pandora/skins/Default/imgs/buttons/left.png b/pandora/skins/Default/imgs/buttons/left.png new file mode 100755 index 0000000..bb7f7e4 Binary files /dev/null and b/pandora/skins/Default/imgs/buttons/left.png differ diff --git a/pandora/skins/Default/imgs/buttons/r.png b/pandora/skins/Default/imgs/buttons/r.png new file mode 100755 index 0000000..f3abb56 Binary files /dev/null and b/pandora/skins/Default/imgs/buttons/r.png differ diff --git a/pandora/skins/Default/imgs/buttons/right.png b/pandora/skins/Default/imgs/buttons/right.png new file mode 100755 index 0000000..1022430 Binary files /dev/null and b/pandora/skins/Default/imgs/buttons/right.png differ diff --git a/pandora/skins/Default/imgs/buttons/sectionl.png b/pandora/skins/Default/imgs/buttons/sectionl.png new file mode 100755 index 0000000..210c714 Binary files /dev/null and b/pandora/skins/Default/imgs/buttons/sectionl.png differ diff --git a/pandora/skins/Default/imgs/buttons/sectionr.png b/pandora/skins/Default/imgs/buttons/sectionr.png new file mode 100755 index 0000000..f3abb56 Binary files /dev/null and b/pandora/skins/Default/imgs/buttons/sectionr.png differ diff --git a/pandora/skins/Default/imgs/buttons/select.png b/pandora/skins/Default/imgs/buttons/select.png new file mode 100755 index 0000000..a434bfa Binary files /dev/null and b/pandora/skins/Default/imgs/buttons/select.png differ diff --git a/pandora/skins/Default/imgs/buttons/start.png b/pandora/skins/Default/imgs/buttons/start.png new file mode 100755 index 0000000..89aa550 Binary files /dev/null and b/pandora/skins/Default/imgs/buttons/start.png differ diff --git a/pandora/skins/Default/imgs/buttons/stick.png b/pandora/skins/Default/imgs/buttons/stick.png new file mode 100755 index 0000000..49259c2 Binary files /dev/null and b/pandora/skins/Default/imgs/buttons/stick.png differ diff --git a/pandora/skins/Default/imgs/buttons/up.png b/pandora/skins/Default/imgs/buttons/up.png new file mode 100755 index 0000000..eddb453 Binary files /dev/null and b/pandora/skins/Default/imgs/buttons/up.png differ diff --git a/pandora/skins/Default/imgs/buttons/vol+.png b/pandora/skins/Default/imgs/buttons/vol+.png new file mode 100755 index 0000000..19cd6a9 Binary files /dev/null and b/pandora/skins/Default/imgs/buttons/vol+.png differ diff --git a/pandora/skins/Default/imgs/buttons/vol-.png b/pandora/skins/Default/imgs/buttons/vol-.png new file mode 100755 index 0000000..085522b Binary files /dev/null and b/pandora/skins/Default/imgs/buttons/vol-.png differ diff --git a/pandora/skins/Default/imgs/buttons/x.png b/pandora/skins/Default/imgs/buttons/x.png new file mode 100755 index 0000000..717d429 Binary files /dev/null and b/pandora/skins/Default/imgs/buttons/x.png differ diff --git a/pandora/skins/Default/imgs/buttons/y.png b/pandora/skins/Default/imgs/buttons/y.png new file mode 100755 index 0000000..759a2a7 Binary files /dev/null and b/pandora/skins/Default/imgs/buttons/y.png differ diff --git a/pandora/skins/Default/imgs/cpu.png b/pandora/skins/Default/imgs/cpu.png new file mode 100755 index 0000000..aabfca3 Binary files /dev/null and b/pandora/skins/Default/imgs/cpu.png differ diff --git a/pandora/skins/Default/imgs/file.png b/pandora/skins/Default/imgs/file.png new file mode 100755 index 0000000..c0584aa Binary files /dev/null and b/pandora/skins/Default/imgs/file.png differ diff --git a/pandora/skins/Default/imgs/folder.png b/pandora/skins/Default/imgs/folder.png new file mode 100755 index 0000000..086c13c Binary files /dev/null and b/pandora/skins/Default/imgs/folder.png differ diff --git a/pandora/skins/Default/imgs/font.png b/pandora/skins/Default/imgs/font.png new file mode 100755 index 0000000..cdccf51 Binary files /dev/null and b/pandora/skins/Default/imgs/font.png differ diff --git a/pandora/skins/Default/imgs/go-up.png b/pandora/skins/Default/imgs/go-up.png new file mode 100644 index 0000000..de8c391 Binary files /dev/null and b/pandora/skins/Default/imgs/go-up.png differ diff --git a/pandora/skins/Default/imgs/inet.png b/pandora/skins/Default/imgs/inet.png new file mode 100755 index 0000000..bb8a316 Binary files /dev/null and b/pandora/skins/Default/imgs/inet.png differ diff --git a/pandora/skins/Default/imgs/l_disabled.png b/pandora/skins/Default/imgs/l_disabled.png new file mode 100644 index 0000000..d9a7dbd Binary files /dev/null and b/pandora/skins/Default/imgs/l_disabled.png differ diff --git a/pandora/skins/Default/imgs/l_enabled.png b/pandora/skins/Default/imgs/l_enabled.png new file mode 100644 index 0000000..f300d91 Binary files /dev/null and b/pandora/skins/Default/imgs/l_enabled.png differ diff --git a/pandora/skins/Default/imgs/manual.png b/pandora/skins/Default/imgs/manual.png new file mode 100755 index 0000000..ecdc991 Binary files /dev/null and b/pandora/skins/Default/imgs/manual.png differ diff --git a/pandora/skins/Default/imgs/menu.png b/pandora/skins/Default/imgs/menu.png new file mode 100644 index 0000000..a4da1c1 Binary files /dev/null and b/pandora/skins/Default/imgs/menu.png differ diff --git a/pandora/skins/Default/imgs/mute.png b/pandora/skins/Default/imgs/mute.png new file mode 100644 index 0000000..e3c0ae2 Binary files /dev/null and b/pandora/skins/Default/imgs/mute.png differ diff --git a/pandora/skins/Default/imgs/phones.png b/pandora/skins/Default/imgs/phones.png new file mode 100644 index 0000000..e072b2b Binary files /dev/null and b/pandora/skins/Default/imgs/phones.png differ diff --git a/pandora/skins/Default/imgs/r_disabled.png b/pandora/skins/Default/imgs/r_disabled.png new file mode 100644 index 0000000..702ed6a Binary files /dev/null and b/pandora/skins/Default/imgs/r_disabled.png differ diff --git a/pandora/skins/Default/imgs/r_enabled.png b/pandora/skins/Default/imgs/r_enabled.png new file mode 100644 index 0000000..239a856 Binary files /dev/null and b/pandora/skins/Default/imgs/r_enabled.png differ diff --git a/pandora/skins/Default/imgs/samba.png b/pandora/skins/Default/imgs/samba.png new file mode 100755 index 0000000..f261e77 Binary files /dev/null and b/pandora/skins/Default/imgs/samba.png differ diff --git a/pandora/skins/Default/imgs/sd.png b/pandora/skins/Default/imgs/sd.png new file mode 100755 index 0000000..58590b8 Binary files /dev/null and b/pandora/skins/Default/imgs/sd.png differ diff --git a/pandora/skins/Default/imgs/selection.png b/pandora/skins/Default/imgs/selection.png new file mode 100644 index 0000000..024085c Binary files /dev/null and b/pandora/skins/Default/imgs/selection.png differ diff --git a/pandora/skins/Default/imgs/topbar.png b/pandora/skins/Default/imgs/topbar.png new file mode 100644 index 0000000..ccd9ea4 Binary files /dev/null and b/pandora/skins/Default/imgs/topbar.png differ diff --git a/pandora/skins/Default/imgs/volume.png b/pandora/skins/Default/imgs/volume.png new file mode 100755 index 0000000..6febf77 Binary files /dev/null and b/pandora/skins/Default/imgs/volume.png differ diff --git a/pandora/skins/Default/imgs/webserver.png b/pandora/skins/Default/imgs/webserver.png new file mode 100755 index 0000000..dd5ba69 Binary files /dev/null and b/pandora/skins/Default/imgs/webserver.png differ diff --git a/pandora/skins/Default/sections/applications.png b/pandora/skins/Default/sections/applications.png new file mode 100755 index 0000000..105d21e Binary files /dev/null and b/pandora/skins/Default/sections/applications.png differ diff --git a/pandora/skins/Default/sections/emulators.png b/pandora/skins/Default/sections/emulators.png new file mode 100755 index 0000000..3efef51 Binary files /dev/null and b/pandora/skins/Default/sections/emulators.png differ diff --git a/pandora/skins/Default/sections/games.png b/pandora/skins/Default/sections/games.png new file mode 100755 index 0000000..538e3ec Binary files /dev/null and b/pandora/skins/Default/sections/games.png differ diff --git a/pandora/skins/Default/sections/settings.png b/pandora/skins/Default/sections/settings.png new file mode 100755 index 0000000..f37127e Binary files /dev/null and b/pandora/skins/Default/sections/settings.png differ diff --git a/pandora/skins/Default/skin.conf b/pandora/skins/Default/skin.conf new file mode 100644 index 0000000..c98f25d --- /dev/null +++ b/pandora/skins/Default/skin.conf @@ -0,0 +1,9 @@ +messageBoxBorder=#505050ff +topBarBg=#ffffff80 +selectionBg=#ffffff80 +messageBoxBg=#00000080 +messageBoxSelection=#fffffff80 +bottomBarBg=#ffffff80 +topBarHeight=50 +linkHeight=50 +linkWidth=80 \ No newline at end of file diff --git a/pandora/skins/Default/wallpapers/pandora-nova-desat.png b/pandora/skins/Default/wallpapers/pandora-nova-desat.png new file mode 100644 index 0000000..d9f0f71 Binary files /dev/null and b/pandora/skins/Default/wallpapers/pandora-nova-desat.png differ diff --git a/pandora/translations/Basque b/pandora/translations/Basque new file mode 100644 index 0000000..1895e61 --- /dev/null +++ b/pandora/translations/Basque @@ -0,0 +1,129 @@ +Settings=Aukerak +Configure GMenu2X's options=GMenu2X aukerak konfiguratu +Activate Usb on SD=Sd-aren usb-a aktibatu +Activate Usb on Nand=Nand-aren usb-a aktibatu +Info about GMenu2X=GMenu2X-ri buruzkoak erakutsi +About=Honi buruz... +Add section=Sekzioa gehitu +Rename section=Sekzioaren izena aldatu +Delete section=Sekzioa ezabatu +Scan for applications and games=Jokuak eta programak bilatu +applications=Programak +Edit link=Esteka aldatu +Title=Izenburua +Link title=Estekaren izenburua +Description=Azalpena +Link description=Azalpenaren esteka +Section=sekzioa +The section this link belongs to=Esteka honen sekzioa da +Icon=Ikonoa +Select an icon for the link: $1=Estekarentzako ikonoa aukeratu: $1 +Manual=Eskuliburua +Select a graphic/textual manual or a readme=Aukeratu eskuliburua(testua edo grafikoa) +Cpu clock frequency to set when launching this link=Programa hau abiarazteko PUZ abiadura ezarri +Volume to set for this link=Esteka honentzako bolumena ezarri +Parameters=Parametroak +Parameters to pass to the application=Programara pasatuko diren parametroak +Selector Directory=Selektorearen karpeta +Directory to scan for the selector=Selektorearekin eskaneatuko den direktorioa +Selector Browser=Selektorearen arakatzailea +Allow the selector to change directory=Selektoreari direktorioz aldatzea baimendu +Selector Filter=Selektorearen iragazkia +Filter for the selector (Separate values with a comma)=Selektorearentzako iragazkiak(Balioak komekin banandu) +Selector Screenshots=Selektorearen pantaila-argazkia +Directory of the screenshots for the selector=Selektorearen pantaila-argazkien direktorioa +Selector Aliases=Selektorearen aliasak +File containing a list of aliases for the selector=Aliasen zerrenda duen artxiboaren izena +Don't Leave=Ez irten +Don't quit GMenu2X when launching this link=Lotura hau abiaraztean ez amaitu Gmenu2x +Save last selection=Azken aukera gogoratu +Save the last selected link and section on exit=Azken aukera eta esteka gorde irtetean +Clock for GMenu2X=GMenu2X-ren erlojua +Set the cpu working frequency when running GMenu2X=Gmenu2x-rentzako PUZ abiadura ezarri +Maximum overclock=Overclock muga +Set the maximum overclock for launching links=Ezarri daitekeen overclockik handiena +Global Volume=Bolumen orokorra +Set the default volume for the gp2x soundcard=Aurrezarritako bolumen maila +Output logs=log artxiboak +Logs the output of the links. Use the Log Viewer to read them.=esteken log-ak gorde. Log irakurlea erabili irakurtzeko. +Number of columns=Zutabe zenbakia +Set the number of columns of links to display on a page=Orri bakoitzeko erakutsiko diren zutabeak +Number of rows=Ilara zenbakia +Set the number of rows of links to display on a page=Orri bakoitzeko erakutsiko diren ilarak +Top Bar Color=Goiko barraren kolorea +Color of the top bar=Goian dagoen barraren kolorea +Bottom Bar Color=Beheko barraren kolorea +Color of the bottom bar=Behean dagoen barraren kolorea +Selection Color=aukeratutakoaren kolorea +Color of the selection and other interface details=Aukeratutako testuaren kolorea eta interfacearen beste aukera batzuk +You should disable Usb Networking to do this.=Usb sarea desaktibatu beharko zenuke. +Operation not permitted.=Baimendu gabeko operazioa. +Language=Hizkuntza +Set the language used by GMenu2X=Aukeratu Gmenu2x-ren hizkuntza +Increase=Handitu +Decrease=txikitu +Change color component=Kolore konponentea aldatu +Increase value=Balioa handitu +Decrease value=Balioa txikitu +Switch=Aldatu +Change value=Balioa aldatu +Edit=Editatu +Clear=Garbitu +Select a directory=Direktorioa aukeratu +Select a file=Artxiboa aukeratu ezazu +Clock (default: 200)=Maiztasuna (Aurrezarritakoa: 200) +Volume (default: -1)=bolumena (Aurrezarritakoa: -1) +Enter folder=Karpetan sartu +Confirm=Berretsi +Enter folder/Confirm=karpetan sartu/Berretsi +Up one folder=Karpeta bat gora +Select an application=Programa aukeratu +Space=espazio-barra +Shift=Shift +Cancel=Cancelar +OK=Ok +Backspace=Backspace +Skin=Maskara +Set the skin used by GMenu2X=GMenu2X-ren maskara aukeratu +Add link in $1=esteka sortu... $1 +Edit $1=Aldatu $1 +Delete $1 link=honen esteka ezabatu $1 +Deleting $1=Ezabatzen $1 +Are you sure?=Ziur zaude? +Insert a name for the new section=Sekzio berrirako izena sartu +Insert a new name for this section=Sekzio honetarako izen berria sartu +Yes=Bai +No=Ez +You will lose all the links in this section.=Sekzio honetako esteka guztiak galduko dira +Exit=Irten +Link Scanner=Esteka bilatzailea +Scanning SD filesystem...=SD txartela arakatzen... +Scanning NAND filesystem...=NAND memoria arakatzen... +$1 files found.=$1 aurkitutako artxiboak(s). +Creating links...=Estekak sortzen... +$1 links created.=$1 esteka sorturik(s). +Version $1 (Build date: $2)=Bertsioa $1 (data: $2) +Log Viewer=Log irakurlea +Displays last launched program's output=Abiarazitako azken programa erakutsi +Do you want to delete the log file?=Log-ak ezabatu nahi dituzu? +USB Enabled (SD)=USB-a piztuta (SD) +USB Enabled (Nand)=USB-a piztuta (Nand) +Turn off=Desaktibatu +Launching $1=Abiarazten $1 +Change page=Orria aldatu +Page=Orria +Scroll=scroll +Untitled=Izenburu gabekoa +Change GMenu2X wallpaper=GMenu2X-ren atzeko irudia aldatu +Activate/deactivate tv-out=Tv-out piztu/itzali +Select wallpaper=aukeratu atzekaldeko irudia +Gamma=Gama +Set gp2x gamma value (default: 10)=Gp2x-ren gama balioa ezarri (aurrezarritakoa: 10) +Tv-Out encoding=tv-out-ren kodeketa +Encoding of the tv-out signal=TV-out-ren seinalearen kodeketa +Tweak RAM Timings=Ram denborak hobetu +This usually speeds up the application at the cost of stability=programa azkarrago doa estabilitatearen truke. +Gamma (default: 0)=Gama (aurrezarritakoa: 0) +Gamma value to set when launching this link=Esteka hau abiarazteko erabiltzen den gama balioa +Wrapper=Itzuli +Explicitly relaunch GMenu2X after this link's execution ends=Amaitzerakoan gmenu2x birkargatu diff --git a/pandora/translations/Catalan b/pandora/translations/Catalan new file mode 100644 index 0000000..94a53db --- /dev/null +++ b/pandora/translations/Catalan @@ -0,0 +1,137 @@ +Settings=Preferències +Configure GMenu2X's options=Configura les opcions del GMenu2X +Activate Usb on SD=Activa USB per la SD +Activate Usb on Nand=Activa USB per la Nand +Info about GMenu2X=Informació del GMenu2X +About=Informació +Add section=Afegir secció +Rename section=Re anomenar secció +Delete section=Eliminar secció +Scan for applications and games=Buscar aplicacions i jocs +applications=Aplicacions +Edit link=Editar enllaç +Title=Títol +Link title=Títol de l'enllaç +Description=Descripció +Link description=Descripció de l'enllaç +Section=Secció +The section this link belongs to=Secció a la que pertany l'enllaç +Icon=Icona +Select an icon for the link: $1=Selecciona una icona per l'enllaç: $1 +Manual=Manual +Select a graphic/textual manual or a readme=Selecciona un manual gràfic/text o un "readme" +Cpu clock frequency to set when launching this link=Ajust del rellotge de la cpu per aquest enllaç +Volume to set for this link=Ajust del volum de l'enllaç +Parameters=Paràmetres +Parameters to pass to the application=Paràmetres que s'envien a l'aplicació +Selector Directory=Directori del Selector +Directory to scan for the selector=Directori a explorar amb el selector +Selector Browser=Explorador del selector +Allow the selector to change directory=Permetre al selector canviar de directori +Selector Filter=Filtre del selector +Filter for the selector (Separate values with a comma)=Filtre per el selector (Separar valors amb comes) +Selector Screenshots=Captures de pantalla del selector +Directory of the screenshots for the selector=Directori de captures de pantalla per el selector +Selector Aliases=Alias del selector +File containing a list of aliases for the selector=Fitxer que conté la llista d'alias per el selector +Explicitly relaunch GMenu2X after this link's execution ends=Força recarregar el GMenu2X a l'acabar l'execució de l'enllaç +Don't Leave=No sortir +Don't quit GMenu2X when launching this link=No tancar GMenu2X al carregar aquest enllaç +Save last selection=Recordar l'última selecció +Save the last selected link and section on exit=Recordar l'última secció i enllaç seleccionat al sortir +Clock for GMenu2X=Rellotge per al GMenu2X +Set the cpu working frequency when running GMenu2X=Ajustar la freqüència de treball de la cpu a l'executar GMenu2X +Maximum overclock=Overclock màxim +Set the maximum overclock for launching links=Ajustar al màxim overclock per a carregar enllaços +Global Volume=Volum global +Set the default volume for the gp2x soundcard=Ajusta el volum per defecte del so a la gp2x +Output logs=Fitxers de Log +Logs the output of the links. Use the Log Viewer to read them.=Enregistra els Logs dels enllaços. Usa el lector de registres per llegir-los. +Number of columns=Número de columnes +Set the number of columns of links to display on a page=Ajusta el número de columnes d'enllaços a mostrar per pàgina +Number of rows=Número de línies +Set the number of rows of links to display on a page=Ajusta el número de línies d'enllaços a mostrar per pàgina +Top Bar Color=Color de barra superior +Color of the top bar=Color de la barra superior +Bottom Bar Color=Color de barra inferior +Color of the bottom bar=Color de la barra inferior +Selection Color=Color selecció +Color of the selection and other interface details=Color de la selecció i altres detalls de la interfície +You should disable Usb Networking to do this.=Ha de desactivar la Xarxa per USB per fer això. +Operation not permitted.=Operació no permesa. +Language=Idioma +Set the language used by GMenu2X=Ajusta l'idioma utilitzat al GMenu2X +Increase=Augmentar +Decrease=Reduïr +Change color component=Canviar component cromàtic +Increase value=Incrementar valor +Decrease value=Reduir valor +Switch=Canviar +Change value=Canviar valor +Edit=Modificar +Clear=Netejar +Select a directory=Selecciona un directori +Select a file=Selecciona un fitxer +Clock (default: 200)=Freqüència (predeterminada: 200) +Volume (default: -1)=Volum (predeterminat: -1) +Enter folder=Entrar a la carpeta +Wrapper=Retornar +Confirm=Confirmar +Enter folder/Confirm=Entrar a la carpeta/Confirmar +Up one folder=Pujar una carpeta +Select an application=Selecciona un programa +Space=Espai +Shift=Majúscules +Cancel=Cancel·lar +OK=Acceptar +Backspace=Retrocés +Skin=Tema +Set the skin used by GMenu2X=Selecciona el tema a utilitzar al GMenu2X +Add link in $1=Afegir enllaç a $1 +Edit $1=Modificar $1 +Delete $1 link=Eliminar l'enllaç de $1 +Deleting $1=Eliminant $1 +Are you sure?=Estàs segur? +Insert a name for the new section=Introduir nom per a la nova secció +Insert a new name for this section=Introduir nou nom per a la secció +Yes=Si +No=No +You will lose all the links in this section.=Es perdran tots els enllaços d'aquesta secció. +Exit=Sortir +Link Scanner=Buscador d'enllaços +Scanning SD filesystem...=Explorant el sistema de fitxers de la SD... +Scanning NAND filesystem...=Explorant el sistema de fitxers de la NAND... +$1 files found.=$1 Fitxer(s) trobat(s). +Creating links...=Creant enllaços... +$1 links created.=$1 enllaç(os) creat(s). +Version $1 (Build date: $2)=Versió $1 (Compilació: $2) +Log Viewer=Visor de Logs +Displays last launched program's output=Mostra la sortida de l'últim programa executat +Do you want to delete the log file?=¿Desitja eliminar el fitxer de registre de successos? +USB Enabled (SD)=USB Activat (SD) +USB Enabled (Nand)=USB Activat (Nand) +Turn off=Desactivar +Launching $1=Executant $1 +Change page=Canviar pàgina +Page=Pàgina +Scroll=Desplaçament +Untitled=Sense títol +Change GMenu2X wallpaper=Canvia el fons del GMenu2X +Activate/deactivate tv-out=Activa/desactiva la sortida de TV +Select wallpaper=Selecciona la imatge de fons +Gamma=Gamma +Set gp2x gamma value (default: 10)=Ajustar el valor gama de la gp2x (predeterminat: 10) +Tv-Out encoding=Codificació de sortida de TV +Encoding of the tv-out signal=Codificació de la senyal de sortida de TV +Tweak RAM Timings=Modifica la sincronització de RAM +This usually speeds up the application at the cost of stability=Normalment accelera l'aplicació a costa de l'estabilitat +Gamma (default: 0)=Gamma (predeterminat: 0) +Gamma value to set when launching this link=Valor de gamma que utilitzarà a l'executar aquest enllaç +Wallpaper=Fons d'escriptori +Configure skin=Configura el Tema +Message Box Color=Color de caixa de text +Message Box Border Color=Color de la vora de la caixa de text +Message Box Selection Color=Color de la selecció de la caixa de text +Background color of the message box=Color de fons de la caixa de text +Border color of the message box=Color de la vora de la caixa de text +Color of the selection of the message box=Color de la selecció de la caixa de text diff --git a/pandora/translations/Danish b/pandora/translations/Danish new file mode 100644 index 0000000..ecd2099 --- /dev/null +++ b/pandora/translations/Danish @@ -0,0 +1,129 @@ +settings=Indstillinger +Configure GMenu2X's options=Konfigurer GMenu2X's Indstillinger +Activate Usb on SD=Aktiver Usb pÃ¥ SD +Activate Usb on Nand=Aktiver Usb pÃ¥ Nand +Info about GMenu2X=Information om GMenu2X +Activate/deactivate tv-out=Aktiver/deaktiver tv-udgang +Exit GMenu2X to the official frontend=Lukker GMenu2X +Change GMenu2X wallpaper=Skift baggrund +About=Om +Add section=Tilføj sektion +Rename section=Ændre navn pÃ¥ sektion +Delete section=Slet sektion +Scan for applications and games=Skan hukommelsen for applikationer og spil +applications=applikationer +Edit link=Rediger genveje +Title=Titel +Link title=Genvejs titel +Description=Beskrivelse +Link description=Genvejs beskrivelse +Section=Seektion +The section this link belongs to=Sektionen for denne genvej +Icon=Ikon +Select an icon for the link=Vælg et ikon til denne genvej +Manual=Manual +Select a graphic/textual manual or a readme=Vælg en grafisk/tekstbaseret manual eller en readme fil +Cpu clock frequency to set when launching this link=Cpu-clockfrekvens indstilling for denne genvej +Volume to set for this link=Lydstyrke indstilling for denne genvej +Parameters=Parametre +Parameters to pass to the application=Angiv parametre for applikationen +Selector Directory=Selector oversigt +Directory to scan for the selector=Angiv Mappe som selector skal skanne +Selector Browser=Selector Browser +Allow the selector to change directory=Tillad selector at ændre mappe +Selector Filter=Selector filter +Filter for the selector (Separate values with a comma)=Filter til selector (separer værdier med komma) +Selector Screenshots= Selector Screenshots +Directory of the screenshots for the selector=Mappe med Screenshots af selector +Selector Aliases=Selector alias +File containing a list of aliases for the selector=Fil som indeholder en liste over alias for selector +Explicitly relaunch GMenu2X after this link's execution ends=Tving GMenu2X til at genstarte nÃ¥r denne genvej køres +Don't Leave=Forlad ikke +Don't quit GMenu2X when launching this link=Afslut ikke GMenu2X nÃ¥r denne genvej startes +Save last selection=Gem sidste ændring +Save the last selected link and section on exit= Gem sidst valgte genvej og sektion ved afslutning +Clock for GMenu2X=Clockfrekvens for GMenu2X +Set the cpu working frequency when running GMenu2X=Indstil cpu-clockfrekvens for GMenu2X +Maximum overclock=Maksimal clockfrekvens +Set the maximum overclock for launching links=Indstil maksimal clockfrekvens ved opstart af genvej +Global Volume=Global lydstyrke +Set the default volume for the gp2x soundcard=Indstil standard lydstyrke for gp2x lydkort +Output logs=Vis logs +Logs the output of the links. Use the Log Viewer to read them.=Danner logs for genvejene. Anvend Vis log for at Ã¥bne dem. +Number of columns=Antal spalter +Set the number of columns of links to display on a page=Angiv antallet af spalter for genveje per side +Number of rows=Antal rækker +Set the number of rows of links to display on a page= Angiv antallet af rækker for genveje per side +Top Bar Color=Øverste bjælkes farve +Color of the top bar= Øverste bjælkes farve +Bottom Bar Color=Nederste bjælkes farve +Color of the bottom bar=Nederste bjælkes farve +Selection Color=Markørens farve +Color of the selection and other interface details= Markøren og grænseflades farve +You should disable Usb Networking to do this.=Du bør fravælge USB netværket nÃ¥ du vælger dette +Operation not permitted.=Dette er ikke tilladt. +Language=Sprog +Set the language used by GMenu2X=Indstil sprog der anvendes i GMenu2X +Increase=Op +Decrease=Ned +Change color component=Ændre farven pÃ¥ komponent +Increase value=Op +Decrease value=Ned +Switch=Ændre +Change value=Ændre værdi +Edit=Rediger +Clear=Ryd +Select a directory=Vælg en mappe +Select a file=Vælg en fil +Clock (default: 200)=Clockfrekvens (normal: 200) +Volume (default: -1)=Lydstyrke (normal: -1) +Wrapper=Wrapper +Enter folder=Ã…bn mappe +Confirm=Bekræft +Enter folder/Confirm=Ã…bn mappe/Bekræft +Up one folder=Tilbage +Select an application=Vælg en applikation +Space=Mellemrum +Shift=Skift +Cancel=Afbryd +OK=OK +Backspace=Slet +Skin=Tema +Set the skin used by GMenu2X =Angiv tema for GMenu2X +Add link in $1=Tilføj genvej i $1 +Edit $1=Rediger $1 +Delete $1 link=Slet $1 +Deleting $1=Sletter $1 +Are you sure?=Er du sikker? +Insert a name for the new section=Angiv navn for den nye sektion +Insert a new name for this section=Angiv nyt navn for denne sektion +Yes=Ja +No=Nej +You will lose all the links in this section.=Du vil miste alle genveje i denne sektion. +Exit=Afslut +Link Scanner=Skan genveje +Scanning SD filesystem...=Skanner SD filsystem... +Scanning NAND filesystem...=Skanner NAND filsystem... +$1 files found.=$1 fil(er) fundet. +Creating links...=Opretter genveje... +$1 links created.=$1 genvej(e) oprettet. +Version $1 (Build date: $2)=Version $1 (den: $2) +Log Viewer=Vis log +Displays last launched program's output=Vis log fra sidst kørte program +Do you want to delete the log file?=Vil du slette denne log fil? +USB Enabled (SD)=USB Aktiveret (SD) +USB Enabled (Nand)=USB Aktiveret (Nand) +Turn off=Afbryd +Launching $1=Starter $1 +Change page=Skift side +Page=Side +Scroll=Rulle +Untitled=Ikke navngivet +Wallpaper=Baggrund +Configure skin=Konfigurer tema +Message Box Color=Farve pÃ¥ Konfigurations vinduet +Message Box Border Color= Farve pÃ¥ Konfig vinduets kant +Message Box Selection Color=Konfig vinduets markør farve +Background color of the message box= Konfigurations vinduets baggrundsfarve +Border color of the message box=Farve pÃ¥ Konfigurations vinduets kant +Color of the selection of the message box=Farven pÃ¥ markøren i Konfigurations vinduet diff --git a/pandora/translations/Dutch b/pandora/translations/Dutch new file mode 100644 index 0000000..eaa3062 --- /dev/null +++ b/pandora/translations/Dutch @@ -0,0 +1,118 @@ +Settings=Instellingen +Configure GMenu2X's options=Instellingen van GMenu2X +Activate Usb on SD=Activeer USB op SD +Activate Usb on Nand=Activeer USB op Nand +Info about GMenu2X=Informatie over GMenu2X +About=Over +Add section=Groep toevoegen +Rename section=Groep hernoemen +Delete section=Groep verwijderen +Scan for applications and games=Zoek applicaties en spellen +applications=applicaties +Edit link=Wijzig snelkoppeling +Title=Naam +Link title=Naam van de snelkoppeling +Description=Omschrijving +Link description=Omschrijving van de snelkoppeling +Section=Groep +The section this link belongs to=De groep waartoe deze snelkoppeling behoort +Icon=Pictogram +Select an icon for the link: $1=Selecteer een pictogram voor de snelkoppeling: $1 +Manual=Handleiding +Select a graphic/textual manual or a readme=Selecteer een grafische/tekstuele handleiding of een readme/leesmij +Cpu clock frequency to set when launching this link=Kloksnelheid voor het starten van deze snelkoppeling +Volume to set for this link=Volume-instelling voor deze snelkoppeling +Parameters=Parameters +Parameters to pass to the application=Parameters om door te geven aan de applicatie +Selector Directory=Kiezer map +Directory to scan for the selector=Map met bestanden voor de kiezer +Selector Browser=Kiezer navigatie +Allow the selector to change directory=Wisselen van map mogelijk maken in kiezer +Selector Filter=Kiezer filter +Filter for the selector (Separate values with a comma)=Filter voor de kiezer (komma-gescheiden) +Selector Screenshots=Kiezer schermafdrukken +Directory of the screenshots for the selector=Map met schermafdrukken voor de kiezer +Selector Aliases=Kiezer aliassen +File containing a list of aliases for the selector=Bestand met aliassen voor de kiezer +Explicitly relaunch GMenu2X after this link's execution ends=GMenux2X altijd herstarten na uitvoeren snelkoppeling +Don't Leave=Niet verlaten +Don't quit GMenu2X when launching this link=GMenu2X niet verlaten bij uitvoeren snelkoppeling +Save last selection=Bewaar laatste keuze +Save the last selected link and section on exit=Bewaar de laatst gekozen snelkoppeling en groep +Clock for GMenu2X=Kloksnelheid voor GMenu2X +Set the cpu working frequency when running GMenu2X=Stel de kloksnelheid in voor het draaien van Gmenu2X +Maximum overclock=Maximale overkloksnelheid +Set the maximum overclock for launching links=Stel maximaal toegestane overkloksnelheid in +Global Volume=Hoofdvolume +Set the default volume for the gp2x soundcard=Stel het standaardvolume in voor de gp2x geluidskaart +Output logs=Uitvoer naar logboek +Logs the output of the links. Use the Log Viewer to read them.=Logt de uitvoer van snelkoppelingen. Gebruik de log viewer om de log te lezen. +Number of columns=Aantal kolommen +Set the number of columns of links to display on a page=Stel het aantal getoonde pictogrammen in (horizontaal) +Number of rows=Aantal rijen +Set the number of rows of links to display on a page=Stel het aantal getoonde pictogrammen in (verticaal) +Top Bar Color=Kleur bovenste balk +Color of the top bar=Kleur van de bovenste balk +Bottom Bar Color=Kleur onderste balk +Color of the bottom bar=Kleur van de onderste balk +Selection Color=Kleur selectie +Color of the selection and other interface details=Kleur van de selectie en andere interface details +You should disable Usb Networking to do this.=Zet USB Netwerk uit om dit te gebruiken. +Operation not permitted.=Handeling niet toegestaan. +Language=Taal +Set the language used by GMenu2X=Stel de taal van GMenu2X in +Increase=Verhoog +Decrease=Verlaag +Change color component=Wijzig kleur component +Increase value=Verhoog waarde +Decrease value=Verlaag waarde +Switch=Wissel +Change value=Wijzig waarde +Edit=Bewerk +Clear=Wis +Select a directory=Selecteer een map +Select a file=Selecteer een bestand +Clock (default: 200)=Kloksnelheid (standaard: 200) +Volume (default: -1)=Volume (standaard: -1) +Wrapper=Schil +Enter folder=Open map +Confirm=Bevestig +Enter folder/Confirm=Open map/Bevestig +Up one folder=Map omhoog +Select an application=Selecteer een applicatie +Space=Spatie +Shift=Shift +Cancel=Annuleer +OK=OK +Backspace=Backspace +Skin=Skin +Set the skin used by GMenu2X=Kies de skin voor GMenu2X +Add link in $1=Voeg snelkoppeling toe in $1 +Edit $1=Wijzig $1 +Delete $1 link=Verwijder snelkoppeling $1 +Deleting $1=Verwijdert $1 +Are you sure?=Weet u het zeker? +Insert a name for the new section=Geef een naam voor de nieuwe groep +Insert a new name for this section=Geef een nieuwe naam voor deze groep +Yes=Ja +No=Nee +You will lose all the links in this section.=Alle snelkoppelingen in deze groep worden gewist. +Exit=Verlaat +Link Scanner=Snelkoppeling-Scanner +Scanning SD filesystem...=Scant het SD-bestandssysteem... +Scanning NAND filesystem...=Scant het NAND-bestandssysteem... +$1 files found.=$1 bestand(en) gevonden. +Creating links...=Snelkoppelingen aanmaken... +$1 links created.=$1 Snelkoppeling(en) aangemaakt. +Version $1 (Build date: $2)=Versie $1 (Datum build: $2) +Log Viewer=Logbestand lezer +Displays last launched program's output=Toont de uitvoer van het laatst gestarte programma +Do you want to delete the log file?=Wilt u het logbestand verwijderen? +USB Enabled (SD)=USB geactiveerd (SD) +USB Enabled (Nand)=USB geactiveerd (Nand) +Turn off=Zet uit +Launching $1=Start $1 +Change page=Wijzig pagina +Page=Pagina +Scroll=Scroll +Untitled=Naamloos diff --git a/pandora/translations/Finnish b/pandora/translations/Finnish new file mode 100644 index 0000000..c01f595 --- /dev/null +++ b/pandora/translations/Finnish @@ -0,0 +1,117 @@ +Settings=Asetukset +Configure GMenu2X's options=Muuta GMenu2X:n asetuksia +Activate Usb on SD=Aktivoi USB SD-kortille +Activate Usb on Nand=Aktivoi USB NAND-muistille +Info about GMenu2X=Tietoa GMenu2X:st� +About=Tietoa +Add section=Lis�� v�lilehti +Rename section=Nime� v�lilehti uudelleen +Delete section=Poista v�lilehti +Scan for applications and games=Etsi ohjelmia ja pelej� +applications=ohjelmat +Edit link=Muokkaa linkki� +Title=Otsikko +Link title=Linkin otsikko +Description=Kuvaus +Link description=Linkin kuvaus +Section=V�lilehti +The section this link belongs to=V�lilehti johon t�m� linkki kuuluu +Icon=Kuvake +Select an icon for the link: $1=Valitse kuvake linkille: $1 +Manual=Ohjetiedosto +Select a graphic/textual manual or a readme=Valitse graafinen/tekstipohjainen ohjetiedosto +Cpu clock frequency to set when launching this link=CPU kellotaajuus t�m�n linkin k�ynnistyksess� +Volume to set for this link=��nenvoimakkuus t�lle linkille +Parameters=Parametrit +Parameters to pass to the application=Ohjelmalle annettavat parametrit +Selector Directory=Ohjelmanvalitsimen hakemisto +Directory to scan for the selector=Hakemisto joka skannataan ohjelmanvalitsimelle +Selector Browser=Ohjelmanvalitsimen selain +Allow the selector to change directory=Anna ohjelmanvalitsimen vaihtaa hakemistoa +Selector Filter=Ohjelmavalitsimen filtteri +Filter for the selector (Separate values with a comma)=Filtteri ohjelmanvalitsimelle (Eroita arvot pilkulla) +Selector Screenshots=Kuvakaappaukset ohjelmanvalitsimesta +Directory of the screenshots for the selector=Ohjelmanvalitsimen kuvakaappausten hakemisto +Selector Aliases=Ohjelmanvalitsimen peitenimet +File containing a list of aliases for the selector=Tiedosto, joka sis�lt�� listan peitenimist� ohjelmavalitsimelle +Explicitly relaunch GMenu2X after this link's execution ends=K�ynnist� GMenu2X uudelleen kun linkin ajo on suoritettu +Don't Leave=�l� poistu +Don't quit GMenu2X when launching this link=�l� sulje GMenu2X:�� kun linkki k�ynnistet��n +Save last selection=Muista viimeisin valinta +Save the last selected link and section on exit=Muista viimeisin valinta ja v�lilehti poistuttaessa +Clock for GMenu2X=Kellotaajuus GMenu2X:lle +Set the cpu working frequency when running GMenu2X=S��d� CPU kellotaajuutta GMenu2X:lle +Maximum overclock=Ylikellotusrajoitus +Set the maximum overclock for launching links=S��d� suurin mahdollinen ylikellotus k�ynnistett�ess� linkkej� +Global Volume=Yleinen ��nenvoimakkuus +Set the default volume fo the gp2x soundcard=S��d� perus��nenvoimakkuus gp2x:n ��nikortille +Output logs=Tulosteloki +Logs the output of the links. Use the Log Viewer to read them.=Kirjoita linkkien tuloste lokiin. K�yt� lokilukijaa niiden lukemiseen. +Number of columns=Sarakkeiden lukum��r� +Set the number of columns of links to display on a page=Aseta linkkisarakkeiden lukum��r� sivulla +Number of rows=Rivien lukum��r� +Set the number of rows of links to display on a page=Aseta linkkirivien lukum��r� sivulla +Top Bar Color=V�ri yl�palkille +Color of the top bar=Yl�palkin v�ri +Color of the bottom bar=Alapalkin v�ri +Selection Color=Valinnan v�ri +Color of the selection and other interface details=Valinnan ja muiden ykstiyiskohtien v�ri +You should disable Usb Networking to do this.=Usb Networking:in pit�� olla poissa k�yt�st� jotta voit tehd� t�m�n. +Operation not permitted.=Toiminto ei ole sallittu. +Language=Kieli +Set the language used by GMenu2X=Valitse GMenu2X:n k�ytt�m� kieli +Increase=Lis�� +Decrease=V�henn� +Change color component=Vaihda v�rikomponenttia +Increase value=Nosta arvoa +Decrease value=Laske arvoa +Switch=Vaihda +Change value=Vaihda arvoa +Edit=Muokkaa +Clear=Tyhjenn� +Select a directory=Valitse hakemisto +Select a file=Valitse tiedosto +Clock (default: 200)=Kellotaajuus (oletusarvo: 200) +Volume (default: -1)=��nenvoimakkuus (oletusarvo: -1) +Wrapper=Wrapperi +Enter folder=Avaa kansio +Confirm=Vahvista +Enter folder/Confirm=Avaa kansio/Vahvista +Up one folder=Yksi hakemisto yl�sp�in +Select an application=Valitse ohjelma +Space=V�lily�nti +Shift=Vaihto +Cancel=Peruuta +OK=OK +Backspace=Askelpalautin +Skin=Teema +Set the skin used by GMenu2X=Aseta GMenu2X:n k�ytt�m� teema +Add link in $1=Lis�� linkki v�lilehteen $1 +Edit $1=Muokkaa v�lilehte� $1 +Delete $1 link=Poista v�lilehti $1 +Deleting $1=Poistetaan v�lilehte� $1 +Are you sure?=Oletko varma? +Insert a name for the new section=Anna uuden v�lilehden nimi +Insert a new name for this section=Anna uusi nimi t�lle v�lilehdelle +Yes=Kyll� +No=Ei +You will lose all the links in this section.=Menet�t kaikki t�ss� v�lilehdess� olevat linkit. +Exit=Poistu +Link Scanner=Linkkiskanneri +Scanning SD filesystem...=Skannataan SD-tiedostoj�rjestelm��... +Scanning NAND filesystem...=Skannataan NAND-tiedostoj�rjestelm��... +$1 files found.=$1 tiedosto(a) l�ydetty. +Creating links...=Luodaan linkkej�... +$1 links created.=$1 linkki(�) luotu. +Version $1 (Build date: $2)=Versio $1 (K��nt�p�iv�m��r�: $2) +Log Viewer=Lokilukija +Displays last launched program's output=N�ytt�� viimeksi k�ynnistetyn ohjelman tulosteen +Do you want to delete the log file?=Haluatko poistaa logitiedoston? +USB Enabled (SD)=USB Aktivoitu (SD) +USB Enabled (Nand)=USB Aktivoitu (Nand) +Turn off=Sammuta +Launching $1=K�ynnistet��n $1 +Change page=Vaihda sivua +Page=Sivu +Scroll=Vierit� +Untitled=Nime�m�t�n diff --git a/pandora/translations/French b/pandora/translations/French new file mode 100644 index 0000000..f3d6081 --- /dev/null +++ b/pandora/translations/French @@ -0,0 +1,129 @@ +Settings=Configurations +Configure GMenu2X's options=Configurer les options de GMenu2X +Activate Usb on SD=Activer l'Usb sur la SD +Activate Usb on Nand=Activer l'Usb sur la Nand +Info about GMenu2X=Information sur GMenu2X +About=A propos de +Add section=Ajouter une section +Rename section=Renommer une section +Delete section=Supprimer une section +Scan for applications and games=Rechercher des applications et des jeux +applications=applications +Edit link=Editer un lien +Title=Titre +Link title=Titre du lien +Description=Description +Link description=Description du lien +Section=Section +The section this link belongs to=La section à laquelle appartient ce lien +Icon=Icône +Select an icon for the link: $1=Selectionner une icône pour le lien: $1 +Manual=Manuel +Select a graphic/textual manual or a readme=Selectionner un manuel graphique/textuel ou un readme +Cpu clock frequency to set when launching this link=Fréquence d'horloge CPU à définir lorsqu'on lance ce lien +Volume to set for this link=Volume à définir pour ce lien +Parameters=Paramètres +Parameters to pass to the application=Paramètres à donner à l'application +Selector Directory=Répertoire de Selector +Directory to scan for the selector=Répertoire à rechercher pour le selector +Selector Browser=Explorateur de Selector +Allow the selector to change directory=Laisser le Selector de changer le répertoire +Selector Filter=Filtre de Selector +Filter for the selector (Separate values with a comma)=Filtre pour le Selector (Séparer les valeurs avec une virgule) +Selector Screenshots=Les captures d'écran de Selector +Directory of the screenshots for the selector=Répertoire des captures d'écran pour le selector +Selector Aliases=Aliases de Selector +File containing a list of aliases for the selector=Fichier contenant une liste d'aliases pour selector +Explicitly relaunch GMenu2X after this link's execution ends=Relancer explicitement GMenu2X après la fin de l'execution de ce lien +Don't Leave=Ne quitter pas +Don't quit GMenu2X when launching this link=Ne pas quitter GMenu2X lorsqu'on lance ce lien +Save last selection=Sauvegarder la dernière sélection +Save the last selected link and section on exit=Sauvegarder le dernier lien sélectionné et section en sortant +Clock for GMenu2X=Horloge pour GMenu2X +Set the cpu working frequency when running GMenu2X=Définir la féquence de fonctionnement du CPU lorsqu'on utilise GMenu2X +Maximum overclock=Overclock maximum +Set the maximum overclock for launching links=Définir l'overclock maximum pour lancer des liens +Global Volume=Volume global +Set the default volume for the gp2x soundcard=Définir le volume par défaut pour la carte sonore de la GP2x +Output logs=Logs de sortie +Logs the output of the links. Use the Log Viewer to read them.=Loguer la sortie des liens. Utiliser le lecteur de log pour les lire +Number of columns=Nombre de colonnes +Set the number of columns of links to display on a page=Définir le nombre de colonnes de liens à afficher sur une page +Number of rows=Nombres de rangées +Set the number of rows of links to display on a page=Définir le nombre de rangées de liens à afficher sur une page +Top Bar Color=Couleur de la bar supérieur +Color of the top bar=Couleur de la bar supérieur +Bottom Bar Color=Couleur de la bar inférieur +Color of the bottom bar=Couleur de la bar inférieur +Selection Color=Couleur de sélection +Color of the selection and other interface details=Couleur de la sélection et des autres détails de l'interface +You should disable Usb Networking to do this.=Vous devez désactiver le réseau Usb pour faire ceci. +Operation not permitted.=Opération non permise +Language=Langue +Set the language used by GMenu2X=Définir la langue utilisée par GMenu2X +Increase=Augmenter +Decrease=Diminuer +Change color component=Changer la couleur composante +Increase value=Augmenter la valeur +Decrease value=Diminuer la valeur +Switch=Changer +Change value=Changer la valeur +Edit=Editer +Clear=Effacer +Select a directory=Sélectionner un répertoire +Select a file=Sélectionner un fichier +Clock (default: 200)=Fréquence (par défaut: 200) +Volume (default: -1)=Volume (par défaut: -1) +Wrapper=Wrapper +Enter folder=Enter dans le répertoire +Confirm=Confirmer +Enter folder/Confirm=Entrer un répertoire/Confirmer +Up one folder=Remonter d'un répertoire +Select an application=Sélectionner une application +Space=Espace +Shift=Majuscule +Cancel=Annuler +OK=OK +Backspace=Backspace +Skin=Skin +Set the skin used by GMenu2X=Définir la skin utilisé par GMenu2X +Add link in $1=Ajouter un lien dans $1 +Edit $1=Editer $1 +Delete $1 link=Effacer le lien $1 +Deleting $1=Effacement de $1 +Are you sure?=Êtes vous sûr? +Insert a name for the new section=Saisir un nom pour cette nouvelle section +Insert a new name for this section=Saisir un nouveau nom pour cette section +Yes=Oui +No=Non +You will lose all the links in this section.=Vous perdrez tous les liens dans cette section. +Exit=Quitter +Link Scanner=Scanneur de lien +Scanning SD filesystem...=Scanne du sytème de fichier de la SD... +Scanning NAND filesystem...=Scanne du sytème de fichier de la NAND... +$1 files found.=$1 fichiers trouvés. +Creating links...=Création de liens... +$1 links created.=$1 liens créés. +Version $1 (Build date: $2)=Version $1 (Date de compilation: $2) +Log Viewer=Visualisateur de log +Displays last launched program's output=Afficher la sortie du dernier programme lancé +Do you want to delete the log file?=Voulez vous effacer le fichier de log? +USB Enabled (SD)=USB Activé (SD) +USB Enabled (Nand)=USB Activé (Nand) +Turn off=Désactiver +Launching $1=Lancement de $1 +Change page=Changer de page +Page=Page +Scroll=Défilement +Untitled=Sans titre +Change GMenu2X wallpaper=Changer l'arrière-plan de GMenu2X +Activate/deactivate tv-out=Activer/desactiver la sortie TV. +Select wallpaper=Sélectionner l'arrière-plan +Gamma=Gamma +Set gp2x gamma value (default: 10)=Définir la valeur de gamma de la gp2x (par défaut: 10) +Tv-Out encoding=Encodage de la sortie TV +Encoding of the tv-out signal=Encodage du signal de la sortie TV +Tweak RAM Timings=Modification des timings de la RAM +This usually speeds up the application at the cost of stability=Ceci accélère, normalement, l'application mais en contre partie de la stabilité +Gamma (default: 0)=Gamma (par défaut: 0) +Gamma value to set when launching this link=Valeur de gamma à définir lors du lancement de ce lien \ No newline at end of file diff --git a/pandora/translations/German b/pandora/translations/German new file mode 100644 index 0000000..c34ba94 --- /dev/null +++ b/pandora/translations/German @@ -0,0 +1,129 @@ +Settings=Einstellungen +Configure GMenu2X's options=Optionen des GMenu2X konfigurieren +Activate Usb on SD=Aktiviert USB für die SD-Karte +Activate Usb on Nand=Aktiviert USB für den Nand-Speicher +Info about GMenu2X=Informationen über GMenu2X +About=Ãœber +Add section=Sektion hinzufügen +Rename section=Sektion umbenennen +Delete section=Sektion löschen +Scan for applications and games= Nach Anwendungen und Spielen scannen +applications=Anwendungen +Edit link=Link bearbeiten +Title=Titel +Link title=Linktitel +Description=Beschreibung +Link description=Beschreibung für diesen Link +Section=Sektion +The section this link belongs to=Zum Link gehörende Sektion +Icon=Icon +Select an icon for the link: $1=Icon für diesen Link wählen: $1 +Manual=Anleitung +Select a graphic/textual manual or a readme=Wähle eine Graphik/Text Anleitung oder Readme +Cpu clock frequency to set when launching this link=CPU-Takt, mit welchem dieser Link gestartet wird +Volume to set for this link=Lautstärke für diesen Link +Parameters=Parameter +Parameters to pass to the application=Parameter, die an die Anwendung übergeben werden +Selector Directory=Selector Verzeichnis +Directory to scan for the selector=Vom Selector zu scannendes Verzeichnis +Selector Browser=Selector Browser +Allow the selector to change directory=Erlaube dem Selector, das Verzeichnis zu wechseln +Selector Filter=Selector Filter +Filter for the selector (Separate values with a comma)=Filter für den Selector (Werte mit Komma trennen) +Selector Screenshots=Selector Screenshots +Directory of the screenshots for the selector=Screenshot-Verzeichnis für den Selector +Selector Aliases=Selector Alternativnamen +File containing a list of aliases for the selector=Datei mit Liste von Alternativnamen für den Selector +Explicitly relaunch GMenu2X after this link's execution ends=GMenu2X nach Beenden der Anwendung umgehend Neustarten +Don't Leave=Nicht verlassen +Don't quit GMenu2X when launching this link=Beim starten dieses Links GMenu2X nicht beenden +Save last selection=Letzte Auswahl speichern +Save the last selected link and section on exit=Speichert den zuletzt gewählten Link und die Sektion beim Beenden +Clock for GMenu2X=Taktfrequenz für GMenu2X +Set the cpu working frequency when running GMenu2X=Stellt den CPU Arbeitstakt für GMenu2X ein +Maximum overclock=Maximale Ãœbertaktung +Set the maximum overclock for launching links=Einstellen der maximalen Taktfrequenz zum Starten von Links +Global Volume=Allgemeine Lautstärke +Set the default volume for the gp2x soundcard=Einstellen der Standardlautstärke des GP2X Soundchips +Output logs=Ausgabeprotokolle +Logs the output of the links. Use the Log Viewer to read them.=Protokolliert Ausgabe der Links. Benutz den Log Viewer zum Lesen. +Number of columns=Anzahl der Spalten +Set the number of columns of links to display on a page=Anzahl der Spalten mit Links, pro Seite +Number of rows=Anzahl der Zeilen +Set the number of rows of links to display on a page=Anzahl der Zeilen mit Links, pro Seite +Top Bar Color=Farbe der Kopfleiste +Color of the top bar= Stellt Farbe und Transparenz der oberen Menüleiste ein +Bottom Bar Color=Farbe der Fußleiste +Color of the bottom bar=Stellt Farbe und Transparenz der unteren Menüleiste ein +Selection Color=Farbe der Auswahl +Color of the selection and other interface details=Farbe der Auswahl-Hervorhebung und anderer Interface-Details +You should disable Usb Networking to do this.=Du solltest USB Networking deaktivieren um dies zu tun. +Operation not permitted.=Operation nicht gestattet. +Language=Sprache +Set the language used by GMenu2X=Einstellen der GMenu2X-Sprache +Increase=Erhöhen +Decrease=Verringern +Change color component=Farbkomponente ändern +Increase value=Wert erhöhen +Decrease value=Wert verringern +Switch=Wechseln +Change value=Wert ändern +Edit=Bearbeiten +Clear=Leeren +Select a directory=Verzeichnis wählen +Select a file=Datei wählen +Clock (default: 200)=Taktfrequenz (Standard: 200) +Volume (default: -1)=Lautstärke (Standard: -1) +Wrapper=Wrapper +Enter folder=Ordner öffnen +Confirm=Bestätigen +Enter folder/Confirm=Ordner öffnen/Bestätigen +Up one folder=Einen Ordner Aufwärts +Select an application=Anwendung wählen +Space=Leer +Shift=Umschalt +Cancel=Abbrechen +OK=OK +Backspace=Rücktaste +Skin=Skin +Set the skin used by GMenu2X=Skin für GMenu2X auswählen +Add link in $1=Link in "$1" hinzufügen +Edit $1="$1" bearbeiten +Delete $1 link=Link "$1" löschen +Deleting $1="$1" wird gelöscht +Are you sure?=Sind Sie sicher? +Insert a name for the new section=Name für die neue Sektion +Insert a new name for this section=Neuer Name für diese Sektion +Yes=Ja +No=Nein +You will lose all the links in this section.=Alle Links in dieser Sektion gehen verloren. +Exit=Beenden +Link Scanner=Links suchen +Scanning SD filesystem...=SD-Karte wird durchsucht... +Scanning NAND filesystem...=NAND-Speicher wird durchsucht... +$1 files found.=$1 Datei(en) gefunden. +Creating links...=Verknüpfungen werden erstellt. +$1 links created.=$1 Verknüpfung(en) erstellt. +Version $1 (Build date: $2)=Version $1 vom $2 +Log Viewer=Log-Viewer +Displays last launched program's output=Zeigt die Ausgabe der zuletzt gestarteten Anwendung an +Do you want to delete the log file?=Möchten Sie diese Log-Datei löschen? +USB Enabled (SD)=USB aktiviert (SD) +USB Enabled (Nand)=USB aktiviert (Nand) +Turn off=Abschalten +Launching $1=$1 wird gestartet +Change page=Seite wechseln +Page=Seite +Scroll=Scrollen +Untitled=Unbenannt +Change GMenu2X wallpaper=Ändert das GMenu2X Hintergrundbild +Activate/deactivate tv-out=Aktiviert/deaktiviert TV-O ut +Select wallpaper=Hintergrundbild wählen +Gamma=Gamma +Set gp2x gamma value (default: 10)=Setzt den GP2X Gamma-Wert (Standard: 10) +Tv-Out encoding=TV-Out Signal +Encoding of the tv-out signal=Einstellen der TV-Out Fernsehnorm +Tweak RAM Timings=Schnellere RAM-Timings +This usually speeds up the application at the cost of stability=Kann Anwendung beschleunigen, auf Kosten der Stabilität +Gamma (default: 0)=Gamma (Standard: 0) +Gamma value to set when launching this link=Bein Starten dieses Links benutzter Gamma-Wert diff --git a/pandora/translations/Italian b/pandora/translations/Italian new file mode 100644 index 0000000..64488f5 --- /dev/null +++ b/pandora/translations/Italian @@ -0,0 +1,142 @@ +Settings=Impostazioni +Configure GMenu2X's options=Configura le opzioni di GMenu2X +Activate Usb on SD=Attiva USB sulla SD +Activate Usb on Nand=Attiva USB sulla Nand +Info about GMenu2X=Informazioni su GMenu2X +About=Informazioni +Add section=Aggiungi sezione +Rename section=Rinomina sezione +Delete section=Elimina sezione +Scan for applications and games=Cerca applicazioni e giochi +applications=applicazioni +Edit link: $1=Modifica collegamento: $1 +Title=Titolo +Link title=Titolo collegamento +Description=Descrizione +Link description=Descrizione collegamento +Section=Sezione +The section this link belongs to=La sezione alla quale appartiene questo collegamento +Icon=Icona +Select an icon for the link: $1=Seleziona un'icona per il collegamento: $1 +Manual=Manuale +Select a graphic/textual manual or a readme=Seleziona un manuale grafico/testuale o un readme +Cpu clock frequency to set when launching this link=Clock della cpu da impostare quando si lancia questo collegamento +Volume to set for this link=Volume da impostare per questo collegamento +Parameters=Parametri +Parameters to pass to the application=Parametri da passare all'applicazione +Selector Directory=Directory del selettore +Directory to scan for the selector=Directory da utilizzare con il selettore +Selector Browser=Browser del selettore +Allow the selector to change directory=Permetti al selettore di cambiare directory +Selector Filter=Filtro del selettore +Filter for the selector (Separate values with a comma)=Filtro per il selettore (Separa i valori con virgola) +Selector Screenshots=Screenshot del selettore +Directory of the screenshots for the selector=Directory contenente gli screenshot per il selettore +Selector Aliases=Alias del selettore +File containing a list of aliases for the selector=File contenente una lista di alias per il selettore +Explicitly relaunch GMenu2X after this link's execution ends=Rilancia esplicitamente GMenu2X dopo l'esecuzione del collegamento +Don't Leave=Non lasciare +Don't quit GMenu2X when launching this link=Non terminare GMenu2X quando viene lanciato questo collegamento +Save last selection=Salva ultima selezione +Save the last selected link and section on exit=Salva l'ultimo collegamento e sezione usati quando si esce +Clock for GMenu2X=Clock per GMenu2X +Set the cpu working frequency when running GMenu2X=Imposta la frequenza di lavoro per GMenu2X +Maximum overclock=Overclock massimo +Set the maximum overclock for launching links=Imposta la frequenza massima per i collegamenti +Global Volume=Volume globale +Set the default volume for the gp2x soundcard=Imposta il volume standard per la gp2x +Output logs=Log dell'output +Logs the output of the links. Use the Log Viewer to read them.=Tiene traccia dell'output dei collegamenti. Usa il Visualizzatore di Log per leggerlo. +Number of columns=Numero di colonne +Set the number of columns of links to display on a page=Imposta il numero di colonne di collegamenti da visualizzare in una pagina +Number of rows=Numero di righe +Set the number of rows of links to display on a page=Imposta il numero di righe di collegamenti da visualizzare in una pagina +Top Bar Color=Colore barra superiore +Color of the top bar=Colore della barra superiore +Bottom Bar Color=Colore barra inferiore +Color of the bottom bar=Colore della barra inferiore +Selection Color=Colore selezione +Color of the selection and other interface details=Colore della selezione e altri dettagli dell'interfaccia +You should disable Usb Networking to do this.=Dovresti disattivare le impostazioni di rete per farlo. +Operation not permitted.=Operazione non consentita. +Language=Lingua +Set the language used by GMenu2X=Imposta la lingua usata da GMenu2X +Increase=Aumenta +Decrease=Riduci +Change color component=Cambia componente cromatico +Increase value=Incrementa valore +Decrease value=Decrementa valore +Switch=Cambia +Change value=Cambia valore +Edit=Modifica +Clear=Svuota +Select a directory=Seleziona una directory +Select a file=Seleziona un file +Clock (default: 200)=Frequenza (predefinito: 200) +Volume (default: -1)=Volume (predefinito: -1) +Wrapper=Involucro +Enter folder=Entra nella cartella +Confirm=Conferma +Enter folder/Confirm=Entra nella cartella/Conferma +Up one folder=Sali di una cartella +Select an application=Seleziona un'applicazione +Space=Spazio +Shift=Maiusc +Cancel=Annulla +OK=OK +Backspace=Backspace +Skin=Skin +Set the skin used by GMenu2X=Imposta la skin usata da GMenu2X +Add link in $1=Aggiungi collegamento in $1 +Edit $1=Modifica $1 +Delete $1 link=Elimina il collegamento $1 +Deleting $1=Rimozione di $1 +Are you sure?=Sei sicuro? +Insert a name for the new section=Inserisci un nome per la nuova sezione +Insert a new name for this section=Inserisci un nuovo nome per questa sezione +Yes=Si +No=No +You will lose all the links in this section.=Perderai tutti i collegamenti in questa sezione. +Exit=Esci +Link Scanner=Scanner di collegamenti +Scanning SD filesystem...=Scansione del filesystem della SD... +Scanning NAND filesystem...=Scansione del filesystem della NAND... +$1 files found.=$1 file trovati. +Creating links...=Creazione collegamenti... +$1 links created.=$1 collegamenti creati. +Version $1 (Build date: $2)=Versione $1 (Data compilazione: $2) +Log Viewer=Visualizzatore di log +Displays last launched program's output=Visualizza l'output dell'ultimo programma eseguito +Do you want to delete the log file?=Vuoi eliminare il file di log? +USB Enabled (SD)=USB Attivata (SD) +USB Enabled (Nand)=USB Attivata (Nand) +Turn off=Disattiva +Launching $1=Esecuzione di $1 +Change page=Cambia pagina +Page=Pagina +Scroll=Scorri +Untitled=Senza titolo +Change GMenu2X wallpaper=Cambia lo sfondo di GMenu2X +Activate/deactivate tv-out=Attiva/disattiva tv-out +Select wallpaper=Seleziona sfondo +Gamma=Gamma +Set gp2x gamma value (default: 10)=Imposta il valore gamma della gp2x (predefinito: 10) +Tv-Out encoding=Codifica uscita tv +Encoding of the tv-out signal=Codifica del segnale dell'uscita tv +Tweak RAM Timings=Modifica i timings della RAM +This usually speeds up the application at the cost of stability=Comporta solitamente un miglioramento delle performance al costo di stabilit� +Gamma (default: 0)=Gamma (predefinito: 0) +Gamma value to set when launching this link=Valore di gamma da impostare quando si lancia questo collegamento +Wallpaper=Sfondo +Configure skin=Configura skin +Message Box Color=Colore Finestra Messaggi +Message Box Border Color=Colore Bordo Finestra Messaggi +Message Box Selection Color=Color Selezione Finestra Messaggi +Background color of the message box=Colore di sfondo della finestra dei messaggi +Border color of the message box=Colore del bordo della finestra dei messaggi +Color of the selection of the message box=Colore della selezione della finestra dei messaggi + +Show root=Mostra radice +Show root folder in the file selection dialogs=Mostra la cartella radice nelle finestre di selezione di file +Change keys=Cambia tasti +Launch an application=Esegue un'applicazione \ No newline at end of file diff --git a/pandora/translations/Norwegian b/pandora/translations/Norwegian new file mode 100644 index 0000000..ec61db7 --- /dev/null +++ b/pandora/translations/Norwegian @@ -0,0 +1,118 @@ +Settings=Instillinger +Configure GMenu2X's options=Konfigurer GMenu2X's innstillinger +Activate Usb on SD=Aktiver USB pÃ¥ SD +Activate Usb on Nand=Aktiver USB pÃ¥ Nand +Info about GMenu2X=Info om GMenu2X +About=Om +Add section=Legg til avdeling +Rename section=Gi nytt navn pÃ¥ avdelning +Delete section=Slett avdelning +Scan for applications and games=Skann etter applikasjoner +applications=applikasjoner +Edit link=Rediger link +Title=Tittel +Link title=Linktittel +Description=Beskrivelse +Link description=Linkbeskrivelse +Section=Avdeling +The section this link belongs to=Avdelningen som denne linken tilhører +Icon=Ikon +Select an icon for the link: $1=Velg et ikon til linken: $1 +Manual=Manual +Select a graphic/textual manual or a readme=Velg en grafisk/tekstbasert manual eller en readme +Cpu clock frequency to set when launching this link=CPU-klokk som skal settes nÃ¥r denne linken startes +Volume to set for this link=Volum som skal settes til denne linken +Parameters=Parametrer +Parameters to pass to the application=Parametrer som skal settes til applikasjonen +Selector Directory=Selectormappe +Directory to scan for the selector=Mappe som selector skal skanne +Selector Browser=Selectorutforsker +Allow the selector to change directory=Tillat selector Ã¥ bytte mappe +Selector Filter=Selectorfilter +Filter for the selector (Separate values with a comma)=Filter for selector (separer verdiene med et komma) +Selector Screenshots=Screenshots for Selector +Directory of the screenshots for the selector=Mappe med screenshots til selector +Selector Aliases=Selectoralias +File containing a list of aliases for the selector=Fil som inneholder en liste med alias for selector +Explicitly relaunch GMenu2X after this link's execution ends=Tving GMenu2X i Ã¥ starte nÃ¥r denne linken er ferdigkjørt +Don't Leave=Forlat ikke +Don't quit GMenu2X when launching this link=Ikke avslutt GMenu2X nÃ¥r denne linken kjøres +Save last selection=Husk siste markering +Save the last selected link and section on exit=Husk siste link og avdeling ved avslutning +Clock for GMenu2X=Klokkefrekvens for GMenu2X +Set the cpu working frequency when running GMenu2X=Sett CPU-frekvensen for GMenu2X +Maximum overclock=Maks overklokk +Set the maximum overclock for launching links=Sett maks overklokk for linker +Global Volume=Mastervolum +Set the default volume fo the gp2x soundcard=Sett overall mastervolum +Output logs=Skriv logg +Logs the output of the links. Use the Log Viewer to read them.=Skriver ut logg for linkene. Bruk loggleseren for Ã¥ lese dem. +Number of columns=Antall spalter +Set the number of columns of links to display on a page=Velg antall spalter med linker som skal vises per side +Number of rows=Antall rader +Set the number of rows of links to display on a page=Velg antall rader med linker som skal vises per side +Top Bar Color=Øverste felts farge +Color of the top bar=Farge pÃ¥ det øverste feltet +Bottom Bar Color=Nederste felts farge +Color of the bottom bar=Färge pÃ¥ det nederste feltet +Selection Color=Markørfarge +Color of the selection and other interface details=Farge pÃ¥ markøren og andre deler av grensesnittet +You should disable Usb Networking to do this.=Du bør slÃ¥ av USB-nettverket nÃ¥r du gjør dette. +Operation not permitted.=Utillat operasjon. +Language=SprÃ¥k +Set the language used by GMenu2X=Still inn sprÃ¥k for GMenu2X +Increase=Øk +Decrease=Minsk +Change color component=Endre fargekomponent +Increase value=Øk verdi +Decrease value=Minsk verdi +Switch=Endre +Change value=Endre verdi +Edit=Rediger +Clear=Rens +Select a directory=Velg en mappe +Select a file=Velg en fil +Clock (default: 200)=Klokkefrekvens (standard: 200) +Volume (default: -1)=Volum (standard: -1) +Wrapper=Wrapper +Enter folder=Ã…pne mappe +Confirm=Bekreft +Enter folder/Confirm=Ã…pne mappe/Bekrefte +Up one folder=Opp en mappe +Select an application=Velg en applikasjon +Space=Mellomrom +Shift=Skift +Cancel=Avbryt +OK=OK +Backspace=Backspace +Skin=Skin +Set the skin used by GMenu2X=Velg hvilket skin GMenu2X skal bruke +Add link in $1=Lag link i $1 +Edit $1=Rediger $1 +Delete $1 link=Slett $1 +Deleting $1=Sletter $1 +Are you sure?=Er du sikker? +Insert a name for the new section=Sett navn for den nye avdelningen +Insert a new name for this section=Sett navn for denne avdelningen +Yes=Ja +No=Nei +You will lose all the links in this section.=Du vil miste alle linkene i denne avdelingen. +Exit=Avslutt +Link Scanner=Linkskanner +Scanning SD filesystem...=Skanner igjennom minnekortet... +Scanning NAND filesystem...=Skanner igjennom NAND... +$1 files found.=$1 fil(er) funnet. +Creating links...=Lager linker... +$1 links created.=$1 link(er) er lagd. +Version $1 (Build date: $2)=Versjon $1 (Bygd den: $2) +Log Viewer=Loggleser +Displays last launched program's output=Vis utdata fra siste startede program +Do you want to delete the log file?=Vil du slette loggen? +USB Enabled (SD)=USB Aktivert (SD) +USB Enabled (Nand)=USB Aktivert (NAND) +Turn off=SlÃ¥ av +Launching $1=Starter $1 +Change page=Bytt side +Page=Side +Scroll=Rull +Untitled=Uten navn \ No newline at end of file diff --git a/pandora/translations/Portuguese (Portugal) b/pandora/translations/Portuguese (Portugal) new file mode 100644 index 0000000..70c9084 --- /dev/null +++ b/pandora/translations/Portuguese (Portugal) @@ -0,0 +1,118 @@ +Settings= Configurações +Configure GMenu2X's options=Configurar opções do GMenu2X +Activate Usb on SD=Activar USB para SD +Activate Usb on Nand=Activar USB para Nand +Info about GMenu2X=Informação sobre GMenu2X +About=Sobre +Add section=Adicionar Secção +Rename section= Renomear Secção +Delete section= Eliminar Secção +Scan for applications and games=Procurar aplicações e jogos +applications=aplicações +Edit link=Editar Link +Title=Título +Link title=Título do Link +Description=Descrição +Link description=Descrição do Link +Section=Secção +The section this link belongs to=A secção a que pertence este link +Icon=Ãcone +Select an icon for the link: $1=Seleccionar um ícone para o link: $1 +Manual=Manual +Select a graphic/textual manual or a readme=Seleccionar um manual gráfico e/ou de texto +Cpu clock frequency to set when launching this link=Frequência de relógio do CPU ao lançar este link +Volume to set for this link=Ajustar o volume para este link +Parameters=Parâmetros +Parameters to pass to the application=Parâmetros a enviar para a aplicação +Selector Directory=Directório do Selector +Directory to scan for the selector=Directório a explorar com o selector +Selector Browser=Explorador do selector +Allow the selector to change directory=Permitir ao selector que mude de directório +Selector Filter=Filtro do selector +Filter for the selector (Separate values with a comma)=Filtro do selector (Separar valores com virgulas) +Selector Screenshots=Capturas de ecrã do selector +Directory of the screenshots for the selector=Directório das capturas de ecrã do selector +Selector Aliases=Alias do selector +File containing a list of aliases for the selector=Arquivo que contém a lista de alias para o selector +Explicitly relaunch GMenu2X after this link's execution ends=Forçar relançamento do GMenu2x após fim da execução deste link +Don't Leave=Não Sair +Don't quit GMenu2X when launching this link=Não sair do GMenu2X ao lançar este link +Save last selection=Gravar a última selecção +Save the last selected link and section on exit=Recordar link e secção seleccionadas ao sair +Clock for GMenu2X=Relógio no GMenu2X +Set the cpu working frequency when running GMenu2X=Ajustar a frequência do CPU durante a execução do GMenu2X +Maximum overclock=Overclock máximo +Set the maximum overclock for launching links=Ajustar o overclock máximo ao lançar um link +Global Volume=Volume global +Set the default volume fo the gp2x soundcard=Ajustar o volume por defeito da gp2x +Output logs=Logs de Output +Logs the output of the links. Use the Log Viewer to read them.=Regista o output dos links. Usar o Leitor de Logs para consultar. +Number of columns=Número de colunas +Set the number of columns of links to display on a page=Ajustar o número de colunas (de links) por página +Number of rows=Número de filas +Set the number of rows of links to display on a page=Ajustar o número de filas (de links) por página +Top Bar Color=Cor da barra superior +Color of the top bar= Cor da barra superior +Bottom Bar Color= Cor da barra inferior +Color of the bottom bar= Cor da barra inferior +Selection Color=Cor da selecção +Color of the selection and other interface details=Cor da selecção e outros detalhes do interface +You should disable Usb Networking to do this.=Deve desactivar a função Networking por USB para executar este comando. +Operation not permitted.=Operação não permitida. +Language=Idioma +Set the language used by GMenu2X=Ajustar o idioma usado no GMenu2X +Increase=Aumentar +Decrease=Reduzir +Change color component=Alterar componente da cor +Increase value=Aumentar valor +Decrease value=Reduzir Valor +Switch=Mudar +Change value=Mudar Valor +Edit=Editar +Clear=Eliminar +Select a directory=Seleccionar directório +Select a file=Seleccionar ficheiro +Clock (default: 200)=Frequência (predefinido: 200) +Volume (default: -1)=Volume (predefinido: -1) +Wrapper=Invólucro +Enter folder=Entrar na Pasta +Confirm=Confirmar +Enter folder/Confirm=Entrar na Pasta/Confirmar +Up one folder=Subir uma pasta +Select an application=Seleccionar uma aplicação +Space=Espaço +Shift=Shift +Cancel=Cancelar +OK=OK +Backspace=Backspace +Skin=Skin +Set the skin used by GMenu2X=Seleccionar a Skin a usar pelo GMenu2X +Add link in $1=Adicionar link em $1 +Edit $1=Modificar $1 +Delete $1 link=Eliminar o link $1 +Deleting $1=Removendo $1 +Are you sure?=Tem a certeza? +Insert a name for the new section=Insira o nome da nova secção +Insert a new name for this section=Insira um novo nome para esta secção +Yes=Sim +No=Não +You will lose all the links in this section.=Perderá todos os links desta secção. +Exit=Sair +Link Scanner=Pesquisador de links +Scanning SD filesystem...=A pesquisar o filesystem do SD... +Scanning NAND filesystem...=A pesquisar o filesystem do NAND... +$1 files found.=$1 ficheiros encontrados. +Creating links...=A criar Links... +$1 links created.=$1 Links criados. +Version $1 (Build date: $2)=Versão $1 (Data de compilação: $2) +Log Viewer=Leitor de Logs +Displays last launched program's output=Mostra o output do último programa executado +Do you want to delete the log file?=Deseja eliminar o ficheiro de log? +USB Enabled (SD)=USB Activado (SD) +USB Enabled (Nand)=USB Activado (Nand) +Turn off=Desligar +Launching $1= A Executar $1 +Change page=Mudar página +Page=Página +Scroll=Scroll +Untitled=Sem título diff --git a/pandora/translations/Russian b/pandora/translations/Russian new file mode 100644 index 0000000..900cab0 --- /dev/null +++ b/pandora/translations/Russian @@ -0,0 +1,132 @@ +Settings=ÐаÑтройки +Configure GMenu2X's options=Изменить наÑтройки GMenu2X +Activate Usb on SD=Ðктивировать SD через USB +Activate Usb on Nand=Ðктивировать NAND через USB +Info about GMenu2X=Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ GMenu2X +About=Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ +Add section=Добавить Ñекцию +Rename section=Переименовать Ñекцию +Delete section=Удалить Ñекцию +Scan for applications and games= ПоиÑк игр и приложений +applications=ÐŸÑ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ +Edit link=Изменить ÑÑылку +Title=Заголовок +Link title=Ð˜Ð¼Ñ ÑÑылки +Description=ОпиÑание +Link description=ОпиÑание ÑÑылки +Section=Ð¡ÐµÐºÑ†Ð¸Ñ +The section this link belongs to=СекциÑ, которой принадлежит ÑÑылка +Icon=Иконка +Select an icon for the link: $1=Выберите иконку к ÑÑылке: $1 +Manual=ИнÑÑ‚Ñ€ÑƒÐºÑ†Ð¸Ñ +Select a graphic/textual manual or a readme=Выберите текÑтовую инÑтрукцию +Cpu clock frequency to set when launching this link=ЧаÑтота CPU при запуÑке данной ÑÑылки +Volume to set for this link=ГромкоÑÑ‚ÑŒ уÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ð°Ñ Ð´Ð»Ñ Ñтой ÑÑылки +Parameters=Параметры +Parameters to pass to the application=Параметры Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‡Ð¸ приложению +Selector Directory=Папка проводника +Directory to scan for the selector=Папка Ð´Ð»Ñ ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¾Ð²Ð¾Ð´Ð½Ð¸ÐºÐ¾Ð¼ +Selector Browser=Выбрать браузером +Allow the selector to change directory=Разрешить проводнику выбирать папку +Selector Filter=Выбрать фильтр +Filter for the selector (Separate values with a comma)=Фильтр Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²Ð¾Ð´Ð½Ð¸ÐºÐ° +Selector Screenshots=Обзор Ñкриншотов +Directory of the screenshots for the selector=Папка Ñ Ñкриншотами Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²Ð¾Ð´Ð½Ð¸ÐºÐ° +Selector Aliases=Обзор ÑпиÑков Ñ Ð¸Ð¼ÐµÐ½Ð°Ð¼Ð¸ +File containing a list of aliases for the selector=Файл, Ñодержащий ÑпиÑок имён-пÑевдонимов +Explicitly relaunch GMenu2X after this link's execution ends=ПерезапуÑк GMenu2X поÑле Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÑÑылки +Don't Leave=Ðе покидать +Don't quit GMenu2X when launching this link=Ðе выключать Gmenu2X когда запуÑкаетÑÑ Ñта ÑÑылка +Save last selection=СохранÑÑ‚ÑŒ поÑледней выбор +Save the last selected link and section on exit=Сохранение поÑледней выбранной ÑÑылки и Ñекции при выключение +Clock for GMenu2X=ЧаÑтота CPU Ð´Ð»Ñ Gmenu2X +Set the cpu working frequency when running GMenu2X=УÑтанавливает чаÑтоту CPU пока запущен Gmenu2X +Maximum overclock=МакÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ñ‡Ð°Ñтота CPU +Set the maximum overclock for launching links=МакÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ñ‡Ð°Ñтота CPU Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑка ÑÑылок +Global Volume=ГромкоÑÑ‚ÑŒ +Set the default volume for the gp2x soundcard=УÑтанавливает громкоÑÑ‚ÑŒ Ð´Ð»Ñ Ð·Ð²ÑƒÐºÐ¾Ð²Ð¾Ð¹ карты GP2X +Output logs=Отчёты +Logs the output of the links. Use the Log Viewer to read them.=Создавать отчёты ÑÑылок +Number of columns=КоличеÑтво Ñтолбцов +Set the number of columns of links to display on a page=УÑтановите количеÑтво Ñтолбцов Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð½Ð° Ñтранице +Number of rows=КоличеÑтво колонок +Set the number of rows of links to display on a page=УÑтановите количеÑтво колонок Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð½Ð° Ñтранице +Top Bar Color=Цвет панели Ñверху +Color of the top bar=Выберите цвет панели Ñверху +Bottom Bar Color=Цвет панели внизу +Color of the bottom bar= Выберите цвет панели внизу +Selection Color=Цвет панели выбора +Color of the selection and other interface details=Выберите цвет панели выбора +You should disable Usb Networking to do this.=Ð’Ñ‹ должны выключить USB Networking чтобы Ñделать Ñто. +Operation not permitted.=ÐžÐ¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½Ðµ разрешена. +Language=Язык +Set the language used by GMenu2X=Выберите Ñзык интерфейÑа +Increase=Прибавить +Decrease=Убавить +Change color component=Изменить компонент цвета +Increase value=Увеличить значение +Decrease value=Уменьшить значение +Switch=Переключить +Change value=Изменить значение +Edit=Изменить +Clear=ОчиÑтить +Select a directory=Выбрать папку +Select a file=Выбрать файл +Clock (default: 200)=ЧаÑтота CPU (Стандарт: 200) +Volume (default: -1)=ГромкоÑÑ‚ÑŒ (Стандарт: -1) +Wrapper=ПерезапуÑк +Enter folder=Открыть папку +Confirm=Подтвердить +Enter folder/Confirm=Выбрать папку/подтвердить +Up one folder=Ðазад на одну папку +Select an application=Выберите приложение +Space=Пробел +Shift=Shift +Cancel=Выход +OK=OK +Backspace=Стереть +Skin=Скин +Set the skin used by GMenu2X=Выберите Ñкин Ð´Ð»Ñ GMenu2X +Add link in $1=Добавить ÑÑылку в $1 +Edit $1=Именить $1 +Delete $1 link=Удалить ÑÑылку $1 +Deleting $1=Удаление $1 +Are you sure?=Ð’Ñ‹ уверены? +Insert a name for the new section=Впишите Ð¸Ð¼Ñ Ð´Ð»Ñ Ð½Ð¾Ð²Ð¾Ð¹ Ñекции +Insert a new name for this section=Впишите новое Ð¸Ð¼Ñ Ð´Ð»Ñ Ñтой Ñекции +Yes=Да +No=Ðет +You will lose all the links in this section.=Ð’Ñ‹ потерÑете вÑе ÑÑылки в Ñтой Ñекции +Exit=Выход +Link Scanner=ПоиÑк ÑÑылок +Scanning SD filesystem...=Сканирование SD... +Scanning NAND filesystem...=Сканирование NAND... +$1 files found.=$1 Файлов найдено. +Creating links...=Создание ÑÑылок... +$1 links created.=$1 ÑÑылок Ñоздано. +Version $1 (Build date: $2)=ВерÑÐ¸Ñ $1 (Дата Ñборки: $2) +Log Viewer=Отчёты +Displays last launched program's output=Отображает поÑледний запущенный отчёт программы +Do you want to delete the log file?=Ð’Ñ‹ хотите удалить Ñтот отчёт? +USB Enabled (SD)=USB включен (SD) +USB Enabled (Nand)=USB включен (Nand) +Turn off=Выключить +Launching $1=ЗапуÑк $1... +Change page=Изменить Ñтраницу +Page=Страница +Scroll=Прокрутка +Untitled=Ðе названный + + +Change GMenu2X wallpaper=Изменить обои Gmenu2X +Activate/deactivate tv-out=Ðктивировать/дезактивировать ТВ-выход +Select wallpaper=Выберите обои +Gamma=Гамма +Set gp2x gamma value (default: 10)=Значение гаммы Ñкрана GP2X (Ñтандарт: 10) +Tv-Out encoding=Ð¢ÐµÑ…Ð½Ð¾Ð»Ð¾Ð³Ð¸Ñ Ð²Ñ‹Ð²Ð¾Ð´Ð° на ТВ +Encoding of the tv-out signal=Шифровка ТВ Ñигнала +Tweak RAM Timings=Изменение параметров RAM +This usually speeds up the application at the cost of stability=Это обычно убыÑÑ‚Ñ€Ñет приложение +Gamma (default: 0)=Гамма (Ñтандарт: 0) +Gamma value to set when launching this link=Значение гаммы при запуÑке Ñтой ÑÑылки + diff --git a/pandora/translations/Slovak b/pandora/translations/Slovak new file mode 100644 index 0000000..15bda3a --- /dev/null +++ b/pandora/translations/Slovak @@ -0,0 +1,137 @@ +Settings=Nastavenia +Configure GMenu2X's options=NastaviÅ¥ voľby pre GMenu2X +Activate Usb on SD=AktivovaÅ¥ USB pre SD kartu +Activate Usb on Nand=AktivovaÅ¥ USB pre pamäť Nand +Info about GMenu2X=Informácie o GMenu2X +About=O programe +Add section=PridaÅ¥ sekciu +Rename section=PremenovaÅ¥ sekciu +Delete section=VymazaÅ¥ sekciu +Scan for applications and games= HľadaÅ¥ aplikácie a hry +applications=aplikácie +Edit link=UpraviÅ¥ odkaz +Title=Názov +Link title=Názov odkazu +Description=Popis +Link description=Popis pre odkaz +Section=Sekcia +The section this link belongs to=Sekcia, do ktorej patrí tento odkaz +Icon=Ikona +Select an icon for the link=Vyberte ikonu pre tento odkaz +Manual=Návod +Select a graphic/textual manual or a readme=Vyberte grafický/textový návod alebo readme +Cpu clock frequency to set when launching this link=Taktovacia frekvencia procesora, s ktorou bude spustený odkaz +Volume to set for this link=Nastavenie hlasitosti pre tento odkaz +Parameters=Parametre +Parameters to pass to the application=Parametre, ktoré majú byÅ¥ predané aplikácii +Selector Directory=Adresár selektora +Directory to scan for the selector=Adresár, v ktorom má byÅ¥ hľadaný selektor +Selector Browser=PrehliadaÄ selektora +Allow the selector to change directory=Povolí selektorovi zmeniÅ¥ adresár +Selector Filter=Filter pre selektor +Filter for the selector (Separate values with a comma)=Filter pre selektor (hodnoty oddeľujte Äiarkou) +Selector Screenshots=Snímky obrazovky selektora +Directory of the screenshots for the selector=Adresár so snímkami obrazovky selektora +Selector Aliases=Aliasy selektora +File containing a list of aliases for the selector=Súbor obsahujúci zoznam aliasov pre selektor +Explicitly relaunch GMenu2X after this link's execution ends=Explicitne opätovne spustiÅ¥ GMenu2X po ukonÄení spustenia tohto odkazu +Don't Leave=NeopúšťaÅ¥ +Don't quit GMenu2X when launching this link=NeukonÄovaÅ¥ GMenu2X pri spúšťaní tohto odkazu +Save last selection=Ulož posledný výber +Save the last selected link and section on exit=Ulož naposledy vybraný odkaz a sekciu pri ukonÄení +Clock for GMenu2X=Takt. frekvencia pre GMenu2X +Set the cpu working frequency when running GMenu2X=Nastavte frekvenciu cpu poÄas behu GMenu2X +Maximum overclock=Maximálne pretaktovanie +Set the maximum overclock for launching links=Nastavte maximálne pretaktovanie pre spúšťanie odkazov +Global Volume=Globálna hlasitosÅ¥ +Set the default volume for the gp2x soundcard=Nastavte východziu hlasitosÅ¥ pre zvukovú kartu gp2x +Output logs=Výstupné logy +Logs the output of the links. Use the Log Viewer to read them.=Loguje výstup odkazov. Na prezretie použite Log Viewer. +Number of columns=PoÄet stĺpcov +Set the number of columns of links to display on a page=Nastavte poÄet stĺpcov pre odkazy zobrazené na stránke +Number of rows=PoÄet riadkov +Set the number of rows of links to display on a page=PoÄet riadkov odkazov zobrazených na stránke +Top Bar Color=Farba hornej liÅ¡ty +Color of the top bar= Farba hornej liÅ¡ty +Bottom Bar Color=Farba spodnej liÅ¡ty +Color of the bottom bar=Farba spodnej liÅ¡ty +Selection Color=Farba výberu +Color of the selection and other interface details=Farba výberu a iných detailov interfacu +You should disable Usb Networking to do this.=Pre vykonanie tejto operácie by ste mali deaktivovaÅ¥ Usb sieÅ¥ovanie. +Operation not permitted.=Operácia nepovolená. +Language=Jazyk +Set the language used by GMenu2X=Nastavte jazyk pre GMenu2X +Increase=ZvýšiÅ¥ +Decrease=ZnížiÅ¥ +Change color component=ZmeniÅ¥ farebnú zložku +Increase value=ZvýšiÅ¥ hodnotu +Decrease value=ZnížiÅ¥ hodnotu +Switch=Prepnúť +Change value=ZmeniÅ¥ hodnotu +Edit=UpraviÅ¥ +Clear=VyÄistiÅ¥ +Select a directory=Vyberte adresár +Select a file=Vyberte súbor +Clock (default: 200)=Takt (Å¡tandardne: 200) +Volume (default: -1)=HlasitosÅ¥ (Å¡tandardne: -1) +Wrapper=ObaľovaÄ +Enter folder=Zadajte prieÄinok +Confirm=PotvrdiÅ¥ +Enter folder/Confirm=Zadajte prieÄinok/PotvrdiÅ¥ +Up one folder=O jeden prieÄinok vyÅ¡Å¡ie +Select an application=Vyberte aplikáciu +Space=Medzera +Shift=Shift +Cancel=ZruÅ¡iÅ¥ +OK=OK +Backspace=Backspace +Skin=Skin +Set the skin used by GMenu2X=Nastavte skin pre GMenu2X +Add link in $1=PridaÅ¥ odkaz do $1 +Edit $1=UpraviÅ¥ $1 +Delete $1 link=VymazaÅ¥ odkaz na $1 +Deleting $1=Mažem $1 +Are you sure?=Ste si istý? +Insert a name for the new section=Zadajte názov novej sekcie +Insert a new name for this section=Zadajte nový názov pre túto sekciu +Yes=Ãno +No=Nie +You will lose all the links in this section.=Stratíte vÅ¡etky odkazy v tejto sekcii. +Exit=UkonÄiÅ¥ +Link Scanner=VyhľadávaÄ odkazov +Scanning SD filesystem...=Prehľadávam súborový systém na SD karte... +Scanning NAND filesystem...=Prehľadávam súborový systém na pamäti NAND... +$1 files found.=$1 súbor(ov) nájdených. +Creating links...=Vytváram odkazy... +$1 links created.=$1 odkazov vytvorených. +Version $1 (Build date: $2)=Verzia $1 (dátum zostavenia: $2) +Log Viewer=PrehliadaÄ log súborov +Displays last launched program's output=Zobrazuje výstup naposledy spusteného súboru +Do you want to delete the log file?=Želáte si vymazaÅ¥ log súbor? +USB Enabled (SD)=USB aktivované (SD) +USB Enabled (Nand)=USB aktivované (Nand) +Turn off=Vypnúť +Launching $1=Spúšťam $1 +Change page=ZmeniÅ¥ stránku +Page=Stránka +Scroll=SkrolovaÅ¥ +Untitled=Bez mena +Change GMenu2X wallpaper=ZmeniÅ¥ pozadie GMenu2X +Activate/deactivate tv-out=AktivovaÅ¥/deaktivovaÅ¥ výstup na TV +Select wallpaper=Vyberte pozadie +Gamma=Gamma +Set gp2x gamma value (default: 10)=Nastavte hodnotu gamma (implic: 10) +Tv-Out encoding=Kódovanie výstupu na TV +Encoding of the tv-out signal=Kódovanie televízneho signálu +Tweak RAM Timings=UpraviÅ¥ Äasovanie RAM +This usually speeds up the application at the cost of stability=Toto nastavenie zvyÄajne zrýchli aplikáciu na úkor stability +Gamma (default: 0)=Gamma (implic: 0) +Gamma value to set when launching this link=Hodnota gamma pri spúšťaní tohto odkazu +Wallpaper=Pozadie +Configure skin=NastaviÅ¥ skin +Message Box Color=Farba textového okna +Message Box Border Color=Farba okraja textového okna +Message Box Selection Color=Farba výberu textového okna +Background color of the message box=Farba pozadia textového okna +Border color of the message box=Farba okraja textového okna +Color of the selection of the message box=Farba výberu textového okna diff --git a/pandora/translations/Spanish b/pandora/translations/Spanish new file mode 100644 index 0000000..74f5a8e --- /dev/null +++ b/pandora/translations/Spanish @@ -0,0 +1,129 @@ +Settings=Ajustes +Configure GMenu2X's options=Configura las opciones de GMenu2X +Activate Usb on SD=Activa USB para SD +Activate Usb on Nand=Activa USB para Nand +Info about GMenu2X=Información sobre GMenu2X +About=Información +Add section=Añadir sección +Rename section=Renombrar sección +Delete section=Eliminar sección +Scan for applications and games=Buscar aplicaciones y juegos +applications=aplicaciones +Edit link=Editar enlace +Title=Título +Link title=Título de enlace +Description=Descripción +Link description=Descripción de enlace +Section=Sección +The section this link belongs to=La sección a la que pertenece el enlace +Icon=Icono +Select an icon for the link: $1=Seleccione un icono para el enlace: $1 +Manual=Manual +Select a graphic/textual manual or a readme=Seleccione un manual gráfico/texto o un leeme +Cpu clock frequency to set when launching this link=Ajuste del reloj de la cpu para cargar este enlace +Volume to set for this link=Ajuste del volumen para este enlace +Parameters=Parámetros +Parameters to pass to the application=Parámetros que enviar a la aplicación +Selector Directory=Directorio del Selector +Directory to scan for the selector=Directorio que explorar con el selector +Selector Browser=Explorador del selector +Allow the selector to change directory=Permitir al selector cambiar de directorio +Selector Filter=Filtro del selector +Filter for the selector (Separate values with a comma)=Filtro para el selector (Separar valores con comas) +Selector Screenshots=Capturas de pantalla del selector +Directory of the screenshots for the selector=Directorio de capturas de pantalla para el selector +Selector Aliases=Alias del selector +File containing a list of aliases for the selector=Archivo contenedor de la lista de alias para el selector +Don't Leave=No salir +Don't quit GMenu2X when launching this link=No terminar GMenu2X al cargar este enlace +Save last selection=Recordar última selección +Save the last selected link and section on exit=Recordar última sección y enlace seleccionado al salir +Clock for GMenu2X=Reloj para GMenu2X +Set the cpu working frequency when running GMenu2X=Ajuste la frecuencia de trabajo de cpu al ejecutar GMenu2X +Maximum overclock=Overclock máximo +Set the maximum overclock for launching links=Ajuste el máximo overclock para cargar enlaces +Global Volume=Volumen global +Set the default volume for the gp2x soundcard=Ajuste el volumen por defecto del sonido en gp2x +Output logs=Archivos de registro de sucesos +Logs the output of the links. Use the Log Viewer to read them.=Registra los sucesos de los enlaces. Usa el lector de registros para leerlos. +Number of columns=Número de columnas +Set the number of columns of links to display on a page=Ajuste el número de columnas de enlaces que mostrar por página +Number of rows=Número de líneas +Set the number of rows of links to display on a page=Ajuste el número de líneas de enlaces que mostrar por página +Top Bar Color=Color de barra superior +Color of the top bar=Color de la barra superior +Bottom Bar Color=Color de barra inferior +Color of the bottom bar=Color de la barra inferior +Selection Color=Color de selección +Color of the selection and other interface details=Color de la selección y otros detalles del interfaz +You should disable Usb Networking to do this.=Debe desactivar Red por USB para hacer esto. +Operation not permitted.=Operación no permitida. +Language=Idioma +Set the language used by GMenu2X=Ajuste el idioma usado en GMenu2X +Increase=Aumentar +Decrease=Reducir +Change color component=Cambiar componente cromático +Increase value=Incrementar valor +Decrease value=Reducir valor +Switch=Cambiar +Change value=Cambiar valor +Edit=Modificar +Clear=Limpiar +Select a directory=Selecciona un directorio +Select a file=Selecciona un archivo +Clock (default: 200)=Frecuencia (predefinida: 200) +Volume (default: -1)=Volumen (predefinida: -1) +Enter folder=Entrar en carpeta +Confirm=Confirmar +Enter folder/Confirm=Entrar en carpeta/Confirmar +Up one folder=Subir una carpeta +Select an application=Seleccionar un programa +Space=Espacio +Shift=Mayúsculas +Cancel=Cancelar +OK=Aceptar +Backspace=Retroceso +Skin=Máscara +Set the skin used by GMenu2X=Seleccione la máscara usada en GMenu2X +Add link in $1=Añadir enlace en $1 +Edit $1=Modificar $1 +Delete $1 link=Eliminar el enlace de $1 +Deleting $1=Eliminando $1 +Are you sure?=¿Estás seguro? +Insert a name for the new section=Insertar nombre para la nueva sección +Insert a new name for this section=Insertar nuevo nombre para la sección +Yes=Si +No=No +You will lose all the links in this section.=Se perderán todos los enlaces de esta sección. +Exit=Salir +Link Scanner=Buscador de enlaces +Scanning SD filesystem...=Explorando sistema de archivos de SD... +Scanning NAND filesystem...=Explorando sistema de archivos de NAND... +$1 files found.=$1 archivo(s) encontrado(s). +Creating links...=Creando enlaces... +$1 links created.=$1 enlace(s) creado(s). +Version $1 (Build date: $2)=Versión $1 (Compilación: $2) +Log Viewer=Lector de Registro de Sucesos +Displays last launched program's output=Muestra la salida del último programa ejecutado +Do you want to delete the log file?=¿Desea eliminar el archivo de registro de sucesos? +USB Enabled (SD)=USB Activado (SD) +USB Enabled (Nand)=USB Activado (Nand) +Turn off=Desactivar +Launching $1=Ejecutando $1 +Change page=Cambiar página +Page=Página +Scroll=Desplazamiento +Untitled=Sin titulo +Change GMenu2X wallpaper=Cambia el fondo de GMenu2X +Activate/deactivate tv-out=Activa/desactiva salida de tv +Select wallpaper=Selecciona imagen de fondo +Gamma=Gama +Set gp2x gamma value (default: 10)=Ajusta el valor gama de la gp2x (predefinido: 10) +Tv-Out encoding=Codificación de salida de tv +Encoding of the tv-out signal=Codificación de la señal de salida de tv +Tweak RAM Timings=Modifica la sincronización de RAM +This usually speeds up the application at the cost of stability=Normalmente acelera la aplicación a costa de la estabilidad +Gamma (default: 0)=Gama (predefinido: 0) +Gamma value to set when launching this link=Valor de gama que usar al lanzar este enlace +Wrapper=Retornar +Explicitly relaunch GMenu2X after this link's execution ends=Forzar recarga de GMenu2X al terminar ejecución del enlace diff --git a/pandora/translations/Swedish b/pandora/translations/Swedish new file mode 100644 index 0000000..5501464 --- /dev/null +++ b/pandora/translations/Swedish @@ -0,0 +1,119 @@ +Settings=Inställningar +Configure GMenu2X's options=Konfigurera GMenu2X's inställningar +Activate Usb on SD=Aktivera Usb pÃ¥ SD +Activate Usb on Nand=Aktivera Usb pÃ¥ Nand +Info about GMenu2X=Info om GMenu2X +About=Om +Add section=Lägg till avdelning +Rename section=Byt namn pÃ¥ avdelning +Delete section=Ta bort avdelning +Scan for applications and games=Scanna efter applikationer +applications=applikationer +Edit link=Redigera länk +Title=Titel +Link title=Länktitel +Description=Beskrivning +Link description=Länkbeskrivning +Section=Avdelning +The section this link belongs to=Avdelningen som den här länken tillhör +Icon=Ikon +Select an icon for the link: $1=Välj en ikon till länken: $1 +Manual=Manual +Select a graphic/textual manual or a readme=Välj en grafisk/textbaserad manual eller en readme +Cpu clock frequency to set when launching this link=Cpu-klockfrekvens att ändra till när denna länk körs +Volume to set for this link=Volymen som skall sättas för den här länken +Parameters=Parametrar +Parameters to pass to the application=Parametrar som skall skickas till applikationen +Selector Directory=Selectorkatalog +Directory to scan for the selector=Katalog som selector skall scanna +Selector Browser=Selectorutforskare +Allow the selector to change directory=TillÃ¥t selector att byta katalog +Selector Filter=Selectorfilter +Filter for the selector (Separate values with a comma)=Filter för selector (separera värdena med kommatecken) +Selector Screenshots=Skärmdumpar till Selector +Directory of the screenshots for the selector=Katalog med skärmdumpar till selector +Selector Aliases=Selectoralias +File containing a list of aliases for the selector=Fil som innehÃ¥ller en lista med alias för selector +Explicitly relaunch GMenu2X after this link's execution ends=Tvinga GMenu2X att starta om när denna länk körts klart +Don't Leave=Lämna inte +Don't quit GMenu2X when launching this link=Avsluta inte GMenu2X när denna länk körs +Save last selection=Spara senaste markeringen +Save the last selected link and section on exit=Spara senaste länk och avdelning vid avslut +Clock for GMenu2X=Klockfrekvens för GMenu2X +Set the cpu working frequency when running GMenu2X=Ställ in cpu-klockfrekvensen för GMenu2X +Maximum overclock=Maximal överklockning +Set the maximum overclock for launching links=Sätt maximal överklockning vid start av länk +Global Volume=Global volym +Set the default volume fo the gp2x soundcard=Sätt förinställd volym pÃ¥ gp2x ljudkortet +Output logs=logg utskrift +Logs the output of the links. Use the Log Viewer to read them.=Skriver ut loggar för länkarna. Använd loggläsaren för att läsa dem. +Number of columns=Antal spalter +Set the number of columns of links to display on a page=Välj antal spalter med länkar som skall visas per sida +Number of rows=Antal rader +Set the number of rows of links to display on a page=Välj antal rader med länkar som skall visas per sida +Top Bar Color=Översta fältets färg +Color of the top bar=Färg pÃ¥ det översta fältet +Bottom Bar Color=Nedersta fältets färg +Color of the bottom bar=Färg pÃ¥ det nedersta fältet +Selection Color=Markörfärg +Color of the selection and other interface details=Färg pÃ¥ markören och andra delar av gränssnittet +You should disable Usb Networking to do this.=Du bör slÃ¥ av usb-nätverket när du gör detta. +Operation not permitted.=OtillÃ¥ten användning. +Language=SprÃ¥k +Set the language used by GMenu2X=Ställ in sprÃ¥k för GMenu2X +Increase=Öka +Decrease=Minska +Change color component=Ändra färg komponent +Increase value=Öka värde +Decrease value=Minska värde +Switch=Ändra +Change value=Ändra värde +Edit=Redigera +Clear=Rensa +Select a directory=Välj en katalog +Select a file=Välj en fil +Clock (default: 200)=Klockfrekvens (förinställd: 200) +Volume (default: -1)=Volym (förinställd: -1) +Wrapper=Wrapper +Enter folder=Öppna katalog +Confirm=Bekräfta +Enter folder/Confirm=Öppna katalog/Bekräfta +Up one folder=Upp en katalog +Select an application=Välj en applikation +Space=Mellanslag +Shift=Skift +Cancel=Avbryt +OK=OK +Backspace=Backsteg +Skin=Skin +Set the skin used by GMenu2X=Välj vilket skin GMenu2X ska använda +Add link in $1=Skapa länk i $1 +Edit $1=Redigera $1 +Delete $1 link=Ta bort $1 +Deleting $1=Tar bort $1 +Are you sure?=Är du säker? +Insert a name for the new section=Skriv in namn för den nya avdelningen +Insert a new name for this section=Skriv in namn för den här avdelningen +Yes=Ja +No=Nej +You will lose all the links in this section.=Du kommer att förlora alla länkar i den här +avdelningen. +Exit=Avsluta +Link Scanner=Länkscanner +Scanning SD filesystem...=Scannar SD filsystem... +Scanning NAND filesystem...=Scannar NAND filsystem... +$1 files found.=$1 fil(er) funna. +Creating links...=Skapar länkar... +$1 links created.=$1 länk(ar) skapade. +Version $1 (Build date: $2)=Version $1 (Skapad den: $2) +Log Viewer=Logg läsare +Displays last launched program's output=Visa utdata frÃ¥n senast körda program +Do you want to delete the log file?=Vill du ta bort logg filen? +USB Enabled (SD)=USB Aktiverad (SD) +USB Enabled (Nand)=USB Aktiverad (Nand) +Turn off=Stäng av +Launching $1=Startar $1 +Change page=Byt sida +Page=Sida +Scroll=Rulla +Untitled=Obetitlad diff --git a/pandora/translations/Turkish b/pandora/translations/Turkish new file mode 100644 index 0000000..7554ced --- /dev/null +++ b/pandora/translations/Turkish @@ -0,0 +1,133 @@ +Settings=Ayarlar +Configure GMenu2X's options=GMenu2X'in ayarlarini degistir +Activate Usb on SD=SD Karti için USB baglantisini aktive et +Activate Usb on Nand=Nand Bellegi için USB baglantisini aktive et +Info about GMenu2X=GMenu2X hakkinda bilgi +About=Hakkinda +Add section=Bölüm ekle +Rename section=Bölümü yeniden adlandir +Delete section=Bölümü sil +Scan for applications and games=Oyun ve program taramasi +applications=programlar +Edit link=Link'i düzenle +Title=Baslik +Link title=Link basligi +Description=Açiklama +Link description=Link açiklamasi +Section=Bölüm +The section this link belongs to=Bu linkin ait oldugu bölüm +Icon=Icon +Select an icon for the link: $1=$1 Linki için bir simge seçin: +Manual=Kullanim kilavuzu +Select a graphic/textual manual or a readme=Grafik/Text bir kullanim kilavuzu veya readme dosyasi seçin +Cpu clock frequency to set when launching this link=Bu linki baslatirken kullanilacak CPU hizi +Volume to set for this link=Bu linkin ses seviyesi +Parameters=Parametreler +Parameters to pass to the application=Programa baslatirken aktarilacak parametreler +Selector Directory=Seçim klasörü +Directory to scan for the selector=Seçim için taranacak klasör +Selector Browser=Dosya seçimi +Allow the selector to change directory=Dosyas seçiminin klasör degistirmesine izin ver +Selector Filter=Seçim filtresi +Filter for the selector (Separate values with a comma)=Seçim için filtre (Verileri virgül ile ayirin) +Selector Screenshots=Seçim Ekran görüntüleri +Directory of the screenshots for the selector=Seçim için ekran görüntülerinin klasörü +Selector Aliases=Seçim için alternatif isimler (alias) +File containing a list of aliases for the selector=Seçim için alternatif isimleri içeren dosya adi +Explicitly relaunch GMenu2X after this link's execution ends=GMenu2X'i bu linkin çalismasi bittiginde özellikle tekrar baslat +Don't Leave=Çikma +Don't quit GMenu2X when launching this link=Bu linki baslatirken GMenu2X'i durdurma +Save last selection=Son seçimi sakla +Save the last selected link and section on exit=Son seçilen link ve seçimi çikista sakla +Clock for GMenu2X=GMenu2X için CPU hizi +Set the cpu working frequency when running GMenu2X=GMenu2X'in çalistigi CPU hizi +Maximum overclock=Maksimum overclock hizi +Set the maximum overclock for launching links=Linkler baslatilirken kullanilacak en yüksek CPU hizini belirleyin +Global Volume=Genel ses seviyesi +Set the default volume for the gp2x soundcard=GP2X ses kartinin standart ses seviyesini belirleyin +Output logs=Çikti kayitlari +Logs the output of the links. Use the Log Viewer to read them.=Linklerin çiktilarini kaydeder. Kayit gösterici ile okuyabilirsiniz. +Number of columns=Sütun sayisi +Set the number of columns of links to display on a page=Bir sayfada gösterilecek sütun sayisini belirleyin +Number of rows=Satir sayisi +Set the number of rows of links to display on a page=Bir sayfada gösterilecek satir sayisini belirleyin +Top Bar Color=Baslik çubugunun rengi +Color of the top bar=Baslik çubugunun rengini ve saydamligini belirler +Bottom Bar Color=Statü çubugunun rengi +Color of the bottom bar=Statü çubugunun rengini ve saydamligini belirler +Selection Color=Seçim rengi +Color of the selection and other interface details=Seçim rengi ve baska arabirim detaylarinin rengi +You should disable Usb Networking to do this.=Bunu yapmadan önce USB-Ag destegini kapatmalisiniz. +Operation not permitted.=Isleme izin verilmedi. +Language=Dil +Set the language used by GMenu2X=GMenu2X'in kullanacagi dili seçin +Increase=Artir +Decrease=Azalt +Change color component=Renk ögesini degistirin +Increase value=Degeri artir +Decrease value=Degeri azalt +Switch=Degistir +Change value=Degeri degistir +Edit=Düzenle +Clear=Temizle +Select a directory=Bir klasör seç +Select a file=Bir dosya seç +Clock (default: 200)=Hiz (Standart: 200) +Volume (default: -1)=Ses seviyesi (Standart: -1) +Wrapper=GMenu2X'i Tekrar baslat +Enter folder=Klasöre gir +Confirm=Onayla +Enter folder/Confirm=Klasöre gir / Onayla +Up one folder=Bir klasör yukari +Select an application=Bir program seçin +Space=Bosluk +Shift=Shift +Cancel=Vazgeç +OK=OK +Backspace=Geri +Skin=Skin +Set the skin used by GMenu2X=GMenu2X'in kullanacagi Skin'i seçin +Add link in $1=$1 bölümüne link ekle +Edit $1=$1 linkini düzenle +Delete $1 link=$1 linkini sil +Deleting $1=$1 linki silinecek +Are you sure?=Emin misiniz? +Insert a name for the new section=Yeni bölüm için bir isim girin +Insert a new name for this section=Bu bölüm için yeni isim girin +Yes=Evet +No=Hayir +You will lose all the links in this section.=Bu bölümdeki tüm linkleri kaybedeceksiniz. +Exit=Çikis +Link Scanner=Link taramasi +Scanning SD filesystem...=SD karti taraniyor... +Scanning NAND filesystem...=NAND bellegi taraniyor... +$1 files found.=$1 dosya bulundu. +Creating links...=Linkler yaratiliyor. +$1 links created.=$1 link yaratildi. +Version $1 (Build date: $2)=Version $1 - Derleme: $2 +Log Viewer=Kayit Gösterici +Displays last launched program's output=Son çalistirilan programin çiktisini gösterir +Do you want to delete the log file?=Kayit dosyasini silmek istiyor musunuz? +USB Enabled (SD)=USB aktive edildi (SD) +USB Enabled (Nand)=USB aktive edildi (Nand) +Turn off=Kapat +Launching $1=$1 baslatiliyor +Change page=Sayfa degistir +Page=Sayfa +Scroll=Kaydir +Untitled=Basliksiz +Change GMenu2X wallpaper=GMenu2X arka plan resmini degistir +Activate/deactivate tv-out=TV-Out aktive/deaktive et +Select wallpaper=Arka plan resmi seç +Gamma=Gamma +Set gp2x gamma value (default: 10)=gp2x gamma degerini degistir (Standart: 10) +Tv-Out encoding=TV-Out Sinyali +Encoding of the tv-out signal=TV-Out formati ayari +Tweak RAM Timings=Hafiza hizlandirmasi +This usually speeds up the application at the cost of stability=Programlari hizlandirir ancak stabilitelerini düsürür +Gamma (default: 0)=Gamma (Standart: 0) +Gamma value to set when launching this link=Bu linki çalistirirken kullanilacak gamma degeri +ON=Açik +OFF=Kapali +File Browser=Dosya seçici +Directory Browser=Klasör seçici diff --git a/src/FastDelegate.h b/src/FastDelegate.h new file mode 100644 index 0000000..98c4b01 --- /dev/null +++ b/src/FastDelegate.h @@ -0,0 +1,2108 @@ +// FastDelegate.h +// Efficient delegates in C++ that generate only two lines of asm code! +// Documentation is found at http://www.codeproject.com/cpp/FastDelegate.asp +// +// - Don Clugston, Mar 2004. +// Major contributions were made by Jody Hagins. +// History: +// 24-Apr-04 1.0 * Submitted to CodeProject. +// 28-Apr-04 1.1 * Prevent most unsafe uses of evil static function hack. +// * Improved syntax for horrible_cast (thanks Paul Bludov). +// * Tested on Metrowerks MWCC and Intel ICL (IA32) +// * Compiled, but not run, on Comeau C++ and Intel Itanium ICL. +// 27-Jun-04 1.2 * Now works on Borland C++ Builder 5.5 +// * Now works on /clr "managed C++" code on VC7, VC7.1 +// * Comeau C++ now compiles without warnings. +// * Prevent the virtual inheritance case from being used on +// VC6 and earlier, which generate incorrect code. +// * Improved warning and error messages. Non-standard hacks +// now have compile-time checks to make them safer. +// * implicit_cast used instead of static_cast in many cases. +// * If calling a const member function, a const class pointer can be used. +// * MakeDelegate() global helper function added to simplify pass-by-value. +// * Added fastdelegate.clear() +// 16-Jul-04 1.2.1* Workaround for gcc bug (const member function pointers in templates) +// 30-Oct-04 1.3 * Support for (non-void) return values. +// * No more workarounds in client code! +// MSVC and Intel now use a clever hack invented by John Dlugosz: +// - The FASTDELEGATEDECLARE workaround is no longer necessary. +// - No more warning messages for VC6 +// * Less use of macros. Error messages should be more comprehensible. +// * Added include guards +// * Added FastDelegate::empty() to test if invocation is safe (Thanks Neville Franks). +// * Now tested on VS 2005 Express Beta, PGI C++ +// 24-Dec-04 1.4 * Added DelegateMemento, to allow collections of disparate delegates. +// * <,>,<=,>= comparison operators to allow storage in ordered containers. +// * Substantial reduction of code size, especially the 'Closure' class. +// * Standardised all the compiler-specific workarounds. +// * MFP conversion now works for CodePlay (but not yet supported in the full code). +// * Now compiles without warnings on _any_ supported compiler, including BCC 5.5.1 +// * New syntax: FastDelegate< int (char *, double) >. +// 14-Feb-05 1.4.1* Now treats =0 as equivalent to .clear(), ==0 as equivalent to .empty(). (Thanks elfric). +// * Now tested on Intel ICL for AMD64, VS2005 Beta for AMD64 and Itanium. +// 30-Mar-05 1.5 * Safebool idiom: "if (dg)" is now equivalent to "if (!dg.empty())" +// * Fully supported by CodePlay VectorC +// * Bugfix for Metrowerks: empty() was buggy because a valid MFP can be 0 on MWCC! +// * More optimal assignment,== and != operators for static function pointers. + +#ifndef FASTDELEGATE_H +#define FASTDELEGATE_H +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include // to allow <,> comparisons + +//////////////////////////////////////////////////////////////////////////////// +// Configuration options +// +//////////////////////////////////////////////////////////////////////////////// + +// Uncomment the following #define for optimally-sized delegates. +// In this case, the generated asm code is almost identical to the code you'd get +// if the compiler had native support for delegates. +// It will not work on systems where sizeof(dataptr) < sizeof(codeptr). +// Thus, it will not work for DOS compilers using the medium model. +// It will also probably fail on some DSP systems. +#define FASTDELEGATE_USESTATICFUNCTIONHACK + +// Uncomment the next line to allow function declarator syntax. +// It is automatically enabled for those compilers where it is known to work. +//#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +//////////////////////////////////////////////////////////////////////////////// +// Compiler identification for workarounds +// +//////////////////////////////////////////////////////////////////////////////// + +// Compiler identification. It's not easy to identify Visual C++ because +// many vendors fraudulently define Microsoft's identifiers. +#if defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__VECTOR_C) && !defined(__ICL) && !defined(__BORLANDC__) +#define FASTDLGT_ISMSVC + +#if (_MSC_VER <1300) // Many workarounds are required for VC6. +#define FASTDLGT_VC6 +#pragma warning(disable:4786) // disable this ridiculous warning +#endif + +#endif + +// Does the compiler uses Microsoft's member function pointer structure? +// If so, it needs special treatment. +// Metrowerks CodeWarrior, Intel, and CodePlay fraudulently define Microsoft's +// identifier, _MSC_VER. We need to filter Metrowerks out. +#if defined(_MSC_VER) && !defined(__MWERKS__) +#define FASTDLGT_MICROSOFT_MFP + +#if !defined(__VECTOR_C) +// CodePlay doesn't have the __single/multi/virtual_inheritance keywords +#define FASTDLGT_HASINHERITANCE_KEYWORDS +#endif +#endif + +// Does it allow function declarator syntax? The following compilers are known to work: +#if defined(FASTDLGT_ISMSVC) && (_MSC_VER >=1310) // VC 7.1 +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +// Gcc(2.95+), and versions of Digital Mars, Intel and Comeau in common use. +#if defined (__DMC__) || defined(__GNUC__) || defined(__ICL) || defined(__COMO__) +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +// It works on Metrowerks MWCC 3.2.2. From boost.Config it should work on earlier ones too. +#if defined (__MWERKS__) +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +#ifdef __GNUC__ // Workaround GCC bug #8271 + // At present, GCC doesn't recognize constness of MFPs in templates +#define FASTDELEGATE_GCC_BUG_8271 +#endif + + + +//////////////////////////////////////////////////////////////////////////////// +// General tricks used in this code +// +// (a) Error messages are generated by typdefing an array of negative size to +// generate compile-time errors. +// (b) Warning messages on MSVC are generated by declaring unused variables, and +// enabling the "variable XXX is never used" warning. +// (c) Unions are used in a few compiler-specific cases to perform illegal casts. +// (d) For Microsoft and Intel, when adjusting the 'this' pointer, it's cast to +// (char *) first to ensure that the correct number of *bytes* are added. +// +//////////////////////////////////////////////////////////////////////////////// +// Helper templates +// +//////////////////////////////////////////////////////////////////////////////// + + +namespace fastdelegate { +namespace detail { // we'll hide the implementation details in a nested namespace. + +// implicit_cast< > +// I believe this was originally going to be in the C++ standard but +// was left out by accident. It's even milder than static_cast. +// I use it instead of static_cast<> to emphasize that I'm not doing +// anything nasty. +// Usage is identical to static_cast<> +template +inline OutputClass implicit_cast(InputClass input){ + return input; +} + +// horrible_cast< > +// This is truly evil. It completely subverts C++'s type system, allowing you +// to cast from any class to any other class. Technically, using a union +// to perform the cast is undefined behaviour (even in C). But we can see if +// it is OK by checking that the union is the same size as each of its members. +// horrible_cast<> should only be used for compiler-specific workarounds. +// Usage is identical to reinterpret_cast<>. + +// This union is declared outside the horrible_cast because BCC 5.5.1 +// can't inline a function with a nested class, and gives a warning. +template +union horrible_union{ + OutputClass out; + InputClass in; +}; + +template +inline OutputClass horrible_cast(const InputClass input){ + horrible_union u; + // Cause a compile-time error if in, out and u are not the same size. + // If the compile fails here, it means the compiler has peculiar + // unions which would prevent the cast from working. + typedef int ERROR_CantUseHorrible_cast[sizeof(InputClass)==sizeof(u) + && sizeof(InputClass)==sizeof(OutputClass) ? 1 : -1]; + u.in = input; + return u.out; +} + +//////////////////////////////////////////////////////////////////////////////// +// Workarounds +// +//////////////////////////////////////////////////////////////////////////////// + +// Backwards compatibility: This macro used to be necessary in the virtual inheritance +// case for Intel and Microsoft. Now it just forward-declares the class. +#define FASTDELEGATEDECLARE(CLASSNAME) class CLASSNAME; + +// Prevent use of the static function hack with the DOS medium model. +#ifdef __MEDIUM__ +#undef FASTDELEGATE_USESTATICFUNCTIONHACK +#endif + +// DefaultVoid - a workaround for 'void' templates in VC6. +// +// (1) VC6 and earlier do not allow 'void' as a default template argument. +// (2) They also doesn't allow you to return 'void' from a function. +// +// Workaround for (1): Declare a dummy type 'DefaultVoid' which we use +// when we'd like to use 'void'. We convert it into 'void' and back +// using the templates DefaultVoidToVoid<> and VoidToDefaultVoid<>. +// Workaround for (2): On VC6, the code for calling a void function is +// identical to the code for calling a non-void function in which the +// return value is never used, provided the return value is returned +// in the EAX register, rather than on the stack. +// This is true for most fundamental types such as int, enum, void *. +// Const void * is the safest option since it doesn't participate +// in any automatic conversions. But on a 16-bit compiler it might +// cause extra code to be generated, so we disable it for all compilers +// except for VC6 (and VC5). +#ifdef FASTDLGT_VC6 +// VC6 workaround +typedef const void * DefaultVoid; +#else +// On any other compiler, just use a normal void. +typedef void DefaultVoid; +#endif + +// Translate from 'DefaultVoid' to 'void'. +// Everything else is unchanged +template +struct DefaultVoidToVoid { typedef T type; }; + +template <> +struct DefaultVoidToVoid { typedef void type; }; + +// Translate from 'void' into 'DefaultVoid' +// Everything else is unchanged +template +struct VoidToDefaultVoid { typedef T type; }; + +template <> +struct VoidToDefaultVoid { typedef DefaultVoid type; }; + + + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 1: +// +// Conversion of member function pointer to a standard form +// +//////////////////////////////////////////////////////////////////////////////// + +// GenericClass is a fake class, ONLY used to provide a type. +// It is vitally important that it is never defined, so that the compiler doesn't +// think it can optimize the invocation. For example, Borland generates simpler +// code if it knows the class only uses single inheritance. + +// Compilers using Microsoft's structure need to be treated as a special case. +#ifdef FASTDLGT_MICROSOFT_MFP + +#ifdef FASTDLGT_HASINHERITANCE_KEYWORDS + // For Microsoft and Intel, we want to ensure that it's the most efficient type of MFP + // (4 bytes), even when the /vmg option is used. Declaring an empty class + // would give 16 byte pointers in this case.... + class __single_inheritance GenericClass; +#endif + // ...but for Codeplay, an empty class *always* gives 4 byte pointers. + // If compiled with the /clr option ("managed C++"), the JIT compiler thinks + // it needs to load GenericClass before it can call any of its functions, + // (compiles OK but crashes at runtime!), so we need to declare an + // empty class to make it happy. + // Codeplay and VC4 can't cope with the unknown_inheritance case either. + class GenericClass {}; +#else + class GenericClass; +#endif + +// The size of a single inheritance member function pointer. +const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (GenericClass::*)()); + +// SimplifyMemFunc< >::Convert() +// +// A template function that converts an arbitrary member function pointer into the +// simplest possible form of member function pointer, using a supplied 'this' pointer. +// According to the standard, this can be done legally with reinterpret_cast<>. +// For (non-standard) compilers which use member function pointers which vary in size +// depending on the class, we need to use knowledge of the internal structure of a +// member function pointer, as used by the compiler. Template specialization is used +// to distinguish between the sizes. Because some compilers don't support partial +// template specialisation, I use full specialisation of a wrapper struct. + +// general case -- don't know how to convert it. Force a compile failure +template +struct SimplifyMemFunc { + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // Unsupported member function type -- force a compile failure. + // (it's illegal to have a array with negative size). + typedef char ERROR_Unsupported_member_function_pointer_on_this_compiler[N-100]; + return 0; + } +}; + +// For compilers where all member func ptrs are the same size, everything goes here. +// For non-standard compilers, only single_inheritance classes go here. +template <> +struct SimplifyMemFunc { + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { +#if defined __DMC__ + // Digital Mars doesn't allow you to cast between abitrary PMF's, + // even though the standard says you can. The 32-bit compiler lets you + // static_cast through an int, but the DOS compiler doesn't. + bound_func = horrible_cast(function_to_bind); +#else + bound_func = reinterpret_cast(function_to_bind); +#endif + return reinterpret_cast(pthis); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 1b: +// +// Workarounds for Microsoft and Intel +// +//////////////////////////////////////////////////////////////////////////////// + + +// Compilers with member function pointers which violate the standard (MSVC, Intel, Codeplay), +// need to be treated as a special case. +#ifdef FASTDLGT_MICROSOFT_MFP + +// We use unions to perform horrible_casts. I would like to use #pragma pack(push, 1) +// at the start of each function for extra safety, but VC6 seems to ICE +// intermittently if you do this inside a template. + +// __multiple_inheritance classes go here +// Nasty hack for Microsoft and Intel (IA32 and Itanium) +template<> +struct SimplifyMemFunc< SINGLE_MEMFUNCPTR_SIZE + sizeof(int) > { + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // We need to use a horrible_cast to do this conversion. + // In MSVC, a multiple inheritance member pointer is internally defined as: + union { + XFuncType func; + struct { + GenericMemFuncType funcaddress; // points to the actual member function + int delta; // #BYTES to be added to the 'this' pointer + }s; + } u; + // Check that the horrible_cast will work + typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s)? 1 : -1]; + u.func = function_to_bind; + bound_func = u.s.funcaddress; + return reinterpret_cast(reinterpret_cast(pthis) + u.s.delta); + } +}; + +// virtual inheritance is a real nuisance. It's inefficient and complicated. +// On MSVC and Intel, there isn't enough information in the pointer itself to +// enable conversion to a closure pointer. Earlier versions of this code didn't +// work for all cases, and generated a compile-time error instead. +// But a very clever hack invented by John M. Dlugosz solves this problem. +// My code is somewhat different to his: I have no asm code, and I make no +// assumptions about the calling convention that is used. + +// In VC++ and ICL, a virtual_inheritance member pointer +// is internally defined as: +struct MicrosoftVirtualMFP { + void (GenericClass::*codeptr)(); // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtable_index; // or 0 if no virtual inheritance +}; +// The CRUCIAL feature of Microsoft/Intel MFPs which we exploit is that the +// m_codeptr member is *always* called, regardless of the values of the other +// members. (This is *not* true for other compilers, eg GCC, which obtain the +// function address from the vtable if a virtual function is being called). +// Dlugosz's trick is to make the codeptr point to a probe function which +// returns the 'this' pointer that was used. + +// Define a generic class that uses virtual inheritance. +// It has a trival member function that returns the value of the 'this' pointer. +struct GenericVirtualClass : virtual public GenericClass +{ + typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)(); + GenericVirtualClass * GetThis() { return this; } +}; + +// __virtual_inheritance classes go here +template <> +struct SimplifyMemFunc +{ + + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + union { + XFuncType func; + GenericClass* (X::*ProbeFunc)(); + MicrosoftVirtualMFP s; + } u; + u.func = function_to_bind; + bound_func = reinterpret_cast(u.s.codeptr); + union { + GenericVirtualClass::ProbePtrType virtfunc; + MicrosoftVirtualMFP s; + } u2; + // Check that the horrible_cast<>s will work + typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s) + && sizeof(function_to_bind)==sizeof(u.ProbeFunc) + && sizeof(u2.virtfunc)==sizeof(u2.s) ? 1 : -1]; + // Unfortunately, taking the address of a MF prevents it from being inlined, so + // this next line can't be completely optimised away by the compiler. + u2.virtfunc = &GenericVirtualClass::GetThis; + u.s.codeptr = u2.s.codeptr; + return (pthis->*u.ProbeFunc)(); + } +}; + +#if (_MSC_VER <1300) + +// Nasty hack for Microsoft Visual C++ 6.0 +// unknown_inheritance classes go here +// There is a compiler bug in MSVC6 which generates incorrect code in this case!! +template <> +struct SimplifyMemFunc +{ + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // There is an apalling but obscure compiler bug in MSVC6 and earlier: + // vtable_index and 'vtordisp' are always set to 0 in the + // unknown_inheritance case! + // This means that an incorrect function could be called!!! + // Compiling with the /vmg option leads to potentially incorrect code. + // This is probably the reason that the IDE has a user interface for specifying + // the /vmg option, but it is disabled - you can only specify /vmg on + // the command line. In VC1.5 and earlier, the compiler would ICE if it ever + // encountered this situation. + // It is OK to use the /vmg option if /vmm or /vms is specified. + + // Fortunately, the wrong function is only called in very obscure cases. + // It only occurs when a derived class overrides a virtual function declared + // in a virtual base class, and the member function + // points to the *Derived* version of that function. The problem can be + // completely averted in 100% of cases by using the *Base class* for the + // member fpointer. Ie, if you use the base class as an interface, you'll + // stay out of trouble. + // Occasionally, you might want to point directly to a derived class function + // that isn't an override of a base class. In this case, both vtable_index + // and 'vtordisp' are zero, but a virtual_inheritance pointer will be generated. + // We can generate correct code in this case. To prevent an incorrect call from + // ever being made, on MSVC6 we generate a warning, and call a function to + // make the program crash instantly. + typedef char ERROR_VC6CompilerBug[-100]; + return 0; + } +}; + + +#else + +// Nasty hack for Microsoft and Intel (IA32 and Itanium) +// unknown_inheritance classes go here +// This is probably the ugliest bit of code I've ever written. Look at the casts! +// There is a compiler bug in MSVC6 which prevents it from using this code. +template <> +struct SimplifyMemFunc +{ + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // The member function pointer is 16 bytes long. We can't use a normal cast, but + // we can use a union to do the conversion. + union { + XFuncType func; + // In VC++ and ICL, an unknown_inheritance member pointer + // is internally defined as: + struct { + GenericMemFuncType m_funcaddress; // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtordisp; // #bytes to add to 'this' to find the vtable + int vtable_index; // or 0 if no virtual inheritance + } s; + } u; + // Check that the horrible_cast will work + typedef int ERROR_CantUsehorrible_cast[sizeof(XFuncType)==sizeof(u.s)? 1 : -1]; + u.func = function_to_bind; + bound_func = u.s.funcaddress; + int virtual_delta = 0; + if (u.s.vtable_index) { // Virtual inheritance is used + // First, get to the vtable. + // It is 'vtordisp' bytes from the start of the class. + const int * vtable = *reinterpret_cast( + reinterpret_cast(pthis) + u.s.vtordisp ); + + // 'vtable_index' tells us where in the table we should be looking. + virtual_delta = u.s.vtordisp + *reinterpret_cast( + reinterpret_cast(vtable) + u.s.vtable_index); + } + // The int at 'virtual_delta' gives us the amount to add to 'this'. + // Finally we can add the three components together. Phew! + return reinterpret_cast( + reinterpret_cast(pthis) + u.s.delta + virtual_delta); + }; +}; +#endif // MSVC 7 and greater + +#endif // MS/Intel hacks + +} // namespace detail + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 2: +// +// Define the delegate storage, and cope with static functions +// +//////////////////////////////////////////////////////////////////////////////// + +// DelegateMemento -- an opaque structure which can hold an arbitary delegate. +// It knows nothing about the calling convention or number of arguments used by +// the function pointed to. +// It supplies comparison operators so that it can be stored in STL collections. +// It cannot be set to anything other than null, nor invoked directly: +// it must be converted to a specific delegate. + +// Implementation: +// There are two possible implementations: the Safe method and the Evil method. +// DelegateMemento - Safe version +// +// This implementation is standard-compliant, but a bit tricky. +// A static function pointer is stored inside the class. +// Here are the valid values: +// +-- Static pointer --+--pThis --+-- pMemFunc-+-- Meaning------+ +// | 0 | 0 | 0 | Empty | +// | !=0 |(dontcare)| Invoker | Static function| +// | 0 | !=0 | !=0* | Method call | +// +--------------------+----------+------------+----------------+ +// * For Metrowerks, this can be 0. (first virtual function in a +// single_inheritance class). +// When stored stored inside a specific delegate, the 'dontcare' entries are replaced +// with a reference to the delegate itself. This complicates the = and == operators +// for the delegate class. + +// DelegateMemento - Evil version +// +// For compilers where data pointers are at least as big as code pointers, it is +// possible to store the function pointer in the this pointer, using another +// horrible_cast. In this case the DelegateMemento implementation is simple: +// +--pThis --+-- pMemFunc-+-- Meaning---------------------+ +// | 0 | 0 | Empty | +// | !=0 | !=0* | Static function or method call| +// +----------+------------+-------------------------------+ +// * For Metrowerks, this can be 0. (first virtual function in a +// single_inheritance class). +// Note that the Sun C++ and MSVC documentation explicitly state that they +// support static_cast between void * and function pointers. + +class DelegateMemento { +protected: + // the data is protected, not private, because many + // compilers have problems with template friends. + typedef void (detail::GenericClass::*GenericMemFuncType)(); // arbitrary MFP. + GenericMemFuncType m_pFunction; + detail::GenericClass *m_pthis; + +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + typedef void (*GenericFuncPtr)(); // arbitrary code pointer + GenericFuncPtr m_pStaticFunction; +#endif + +public: +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + DelegateMemento() : m_pthis(0), m_pFunction(0), m_pStaticFunction(0) {}; + void clear() { + m_pthis=0; m_pFunction=0; m_pStaticFunction=0; + } +#else + DelegateMemento() : m_pFunction(0), m_pthis(0) {}; + void clear() { m_pthis=0; m_pFunction=0; } +#endif +public: +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + inline bool IsEqual (const DelegateMemento &x) const{ + // We have to cope with the static function pointers as a special case + if (m_pFunction!=x.m_pFunction) return false; + // the static function ptrs must either both be equal, or both be 0. + if (m_pStaticFunction!=x.m_pStaticFunction) return false; + if (m_pStaticFunction!=0) return m_pthis==x.m_pthis; + else return true; + } +#else // Evil Method + inline bool IsEqual (const DelegateMemento &x) const{ + return m_pthis==x.m_pthis && m_pFunction==x.m_pFunction; + } +#endif + // Provide a strict weak ordering for DelegateMementos. + inline bool IsLess(const DelegateMemento &right) const { + // deal with static function pointers first +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + if (m_pStaticFunction !=0 || right.m_pStaticFunction!=0) + return m_pStaticFunction < right.m_pStaticFunction; +#endif + if (m_pthis !=right.m_pthis) return m_pthis < right.m_pthis; + // There are no ordering operators for member function pointers, + // but we can fake one by comparing each byte. The resulting ordering is + // arbitrary (and compiler-dependent), but it permits storage in ordered STL containers. + return memcmp(&m_pFunction, &right.m_pFunction, sizeof(m_pFunction)) < 0; + + } + // BUGFIX (Mar 2005): + // We can't just compare m_pFunction because on Metrowerks, + // m_pFunction can be zero even if the delegate is not empty! + inline bool operator ! () const // Is it bound to anything? + { return m_pthis==0 && m_pFunction==0; } + inline bool empty() const // Is it bound to anything? + { return m_pthis==0 && m_pFunction==0; } +public: + DelegateMemento & operator = (const DelegateMemento &right) { + SetMementoFrom(right); + return *this; + } + inline bool operator <(const DelegateMemento &right) { + return IsLess(right); + } + inline bool operator >(const DelegateMemento &right) { + return right.IsLess(*this); + } + DelegateMemento (const DelegateMemento &right) : + m_pFunction(right.m_pFunction), m_pthis(right.m_pthis) +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + , m_pStaticFunction (right.m_pStaticFunction) +#endif + {} +protected: + void SetMementoFrom(const DelegateMemento &right) { + m_pFunction = right.m_pFunction; + m_pthis = right.m_pthis; +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = right.m_pStaticFunction; +#endif + } +}; + + +// ClosurePtr<> +// +// A private wrapper class that adds function signatures to DelegateMemento. +// It's the class that does most of the actual work. +// The signatures are specified by: +// GenericMemFunc: must be a type of GenericClass member function pointer. +// StaticFuncPtr: must be a type of function pointer with the same signature +// as GenericMemFunc. +// UnvoidStaticFuncPtr: is the same as StaticFuncPtr, except on VC6 +// where it never returns void (returns DefaultVoid instead). + +// An outer class, FastDelegateN<>, handles the invoking and creates the +// necessary typedefs. +// This class does everything else. + +namespace detail { + +template < class GenericMemFunc, class StaticFuncPtr, class UnvoidStaticFuncPtr> +class ClosurePtr : public DelegateMemento { +public: + // These functions are for setting the delegate to a member function. + + // Here's the clever bit: we convert an arbitrary member function into a + // standard form. XMemFunc should be a member function of class X, but I can't + // enforce that here. It needs to be enforced by the wrapper class. + template < class X, class XMemFunc > + inline void bindmemfunc(X *pthis, XMemFunc function_to_bind ) { + m_pthis = SimplifyMemFunc< sizeof(function_to_bind) > + ::Convert(pthis, function_to_bind, m_pFunction); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } + // For const member functions, we only need a const class pointer. + // Since we know that the member function is const, it's safe to + // remove the const qualifier from the 'this' pointer with a const_cast. + // VC6 has problems if we just overload 'bindmemfunc', so we give it a different name. + template < class X, class XMemFunc> + inline void bindconstmemfunc(const X *pthis, XMemFunc function_to_bind) { + m_pthis= SimplifyMemFunc< sizeof(function_to_bind) > + ::Convert(const_cast(pthis), function_to_bind, m_pFunction); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } +#ifdef FASTDELEGATE_GCC_BUG_8271 // At present, GCC doesn't recognize constness of MFPs in templates + template < class X, class XMemFunc> + inline void bindmemfunc(const X *pthis, XMemFunc function_to_bind) { + bindconstmemfunc(pthis, function_to_bind); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } +#endif + // These functions are required for invoking the stored function + inline GenericClass *GetClosureThis() const { return m_pthis; } + inline GenericMemFunc GetClosureMemPtr() const { return reinterpret_cast(m_pFunction); } + +// There are a few ways of dealing with static function pointers. +// There's a standard-compliant, but tricky method. +// There's also a straightforward hack, that won't work on DOS compilers using the +// medium memory model. It's so evil that I can't recommend it, but I've +// implemented it anyway because it produces very nice asm code. + +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + +// ClosurePtr<> - Safe version +// +// This implementation is standard-compliant, but a bit tricky. +// I store the function pointer inside the class, and the delegate then +// points to itself. Whenever the delegate is copied, these self-references +// must be transformed, and this complicates the = and == operators. +public: + // The next two functions are for operator ==, =, and the copy constructor. + // We may need to convert the m_pthis pointers, so that + // they remain as self-references. + template< class DerivedClass > + inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &x) { + SetMementoFrom(x); + if (m_pStaticFunction!=0) { + // transform self references... + m_pthis=reinterpret_cast(pParent); + } + } + // For static functions, the 'static_function_invoker' class in the parent + // will be called. The parent then needs to call GetStaticFunction() to find out + // the actual function to invoke. + template < class DerivedClass, class ParentInvokerSig > + inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, + StaticFuncPtr function_to_bind ) { + if (function_to_bind==0) { // cope with assignment to 0 + m_pFunction=0; + } else { + bindmemfunc(pParent, static_function_invoker); + } + m_pStaticFunction=reinterpret_cast(function_to_bind); + } + inline UnvoidStaticFuncPtr GetStaticFunction() const { + return reinterpret_cast(m_pStaticFunction); + } +#else + +// ClosurePtr<> - Evil version +// +// For compilers where data pointers are at least as big as code pointers, it is +// possible to store the function pointer in the this pointer, using another +// horrible_cast. Invocation isn't any faster, but it saves 4 bytes, and +// speeds up comparison and assignment. If C++ provided direct language support +// for delegates, they would produce asm code that was almost identical to this. +// Note that the Sun C++ and MSVC documentation explicitly state that they +// support static_cast between void * and function pointers. + + template< class DerivedClass > + inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &right) { + SetMementoFrom(right); + } + // For static functions, the 'static_function_invoker' class in the parent + // will be called. The parent then needs to call GetStaticFunction() to find out + // the actual function to invoke. + // ******** EVIL, EVIL CODE! ******* + template < class DerivedClass, class ParentInvokerSig> + inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, + StaticFuncPtr function_to_bind) { + if (function_to_bind==0) { // cope with assignment to 0 + m_pFunction=0; + } else { + // We'll be ignoring the 'this' pointer, but we need to make sure we pass + // a valid value to bindmemfunc(). + bindmemfunc(pParent, static_function_invoker); + } + + // WARNING! Evil hack. We store the function in the 'this' pointer! + // Ensure that there's a compilation failure if function pointers + // and data pointers have different sizes. + // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK. + typedef int ERROR_CantUseEvilMethod[sizeof(GenericClass *)==sizeof(function_to_bind) ? 1 : -1]; + m_pthis = horrible_cast(function_to_bind); + // MSVC, SunC++ and DMC accept the following (non-standard) code: +// m_pthis = static_cast(static_cast(function_to_bind)); + // BCC32, Comeau and DMC accept this method. MSVC7.1 needs __int64 instead of long +// m_pthis = reinterpret_cast(reinterpret_cast(function_to_bind)); + } + // ******** EVIL, EVIL CODE! ******* + // This function will be called with an invalid 'this' pointer!! + // We're just returning the 'this' pointer, converted into + // a function pointer! + inline UnvoidStaticFuncPtr GetStaticFunction() const { + // Ensure that there's a compilation failure if function pointers + // and data pointers have different sizes. + // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK. + typedef int ERROR_CantUseEvilMethod[sizeof(UnvoidStaticFuncPtr)==sizeof(this) ? 1 : -1]; + return horrible_cast(this); + } +#endif // !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + + // Does the closure contain this static function? + inline bool IsEqualToStaticFuncPtr(StaticFuncPtr funcptr){ + if (funcptr==0) return empty(); + // For the Evil method, if it doesn't actually contain a static function, this will return an arbitrary + // value that is not equal to any valid function pointer. + else return funcptr==reinterpret_cast(GetStaticFunction()); + } +}; + + +} // namespace detail + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 3: +// +// Wrapper classes to ensure type safety +// +//////////////////////////////////////////////////////////////////////////////// + + +// Once we have the member function conversion templates, it's easy to make the +// wrapper classes. So that they will work with as many compilers as possible, +// the classes are of the form +// FastDelegate3 +// They can cope with any combination of parameters. The max number of parameters +// allowed is 8, but it is trivial to increase this limit. +// Note that we need to treat const member functions seperately. +// All this class does is to enforce type safety, and invoke the delegate with +// the correct list of parameters. + +// Because of the weird rule about the class of derived member function pointers, +// you sometimes need to apply a downcast to the 'this' pointer. +// This is the reason for the use of "implicit_cast(pthis)" in the code below. +// If CDerivedClass is derived from CBaseClass, but doesn't override SimpleVirtualFunction, +// without this trick you'd need to write: +// MyDelegate(static_cast(&d), &CDerivedClass::SimpleVirtualFunction); +// but with the trick you can write +// MyDelegate(&d, &CDerivedClass::SimpleVirtualFunction); + +// RetType is the type the compiler uses in compiling the template. For VC6, +// it cannot be void. DesiredRetType is the real type which is returned from +// all of the functions. It can be void. + +// Implicit conversion to "bool" is achieved using the safe_bool idiom, +// using member data pointers (MDP). This allows "if (dg)..." syntax +// Because some compilers (eg codeplay) don't have a unique value for a zero +// MDP, an extra padding member is added to the SafeBool struct. +// Some compilers (eg VC6) won't implicitly convert from 0 to an MDP, so +// in that case the static function constructor is not made explicit; this +// allows "if (dg==0) ..." to compile. + +//N=0 +template +class FastDelegate0 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(); + typedef RetType (*UnvoidStaticFunctionPtr)(); + typedef RetType (detail::GenericClass::*GenericMemFn)(); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate0 type; + + // Construction and comparison functions + FastDelegate0() { clear(); } + FastDelegate0(const FastDelegate0 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate0 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate0 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate0 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate0 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate0 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate0(Y *pthis, DesiredRetType (X::* function_to_bind)() ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)()) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate0(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate0(DesiredRetType (*function_to_bind)() ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)() ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)()) { + m_Closure.bindstaticfunc(this, &FastDelegate0::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() () const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction() const { + return (*(m_Closure.GetStaticFunction()))(); } +}; + +//N=1 +template +class FastDelegate1 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate1 type; + + // Construction and comparison functions + FastDelegate1() { clear(); } + FastDelegate1(const FastDelegate1 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate1 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate1 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate1 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate1 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate1 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate1(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate1(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate1(DesiredRetType (*function_to_bind)(Param1 p1) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1)) { + m_Closure.bindstaticfunc(this, &FastDelegate1::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1) const { + return (*(m_Closure.GetStaticFunction()))(p1); } +}; + +//N=2 +template +class FastDelegate2 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate2 type; + + // Construction and comparison functions + FastDelegate2() { clear(); } + FastDelegate2(const FastDelegate2 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate2 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate2 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate2 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate2 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate2 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate2(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate2(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate2(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2)) { + m_Closure.bindstaticfunc(this, &FastDelegate2::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2); } +}; + +//N=3 +template +class FastDelegate3 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate3 type; + + // Construction and comparison functions + FastDelegate3() { clear(); } + FastDelegate3(const FastDelegate3 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate3 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate3 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate3 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate3 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate3 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate3(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate3(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate3(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) { + m_Closure.bindstaticfunc(this, &FastDelegate3::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3); } +}; + +//N=4 +template +class FastDelegate4 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate4 type; + + // Construction and comparison functions + FastDelegate4() { clear(); } + FastDelegate4(const FastDelegate4 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate4 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate4 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate4 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate4 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate4 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate4(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate4(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate4(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + m_Closure.bindstaticfunc(this, &FastDelegate4::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4); } +}; + +//N=5 +template +class FastDelegate5 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate5 type; + + // Construction and comparison functions + FastDelegate5() { clear(); } + FastDelegate5(const FastDelegate5 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate5 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate5 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate5 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate5 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate5 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate5(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate5(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate5(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + m_Closure.bindstaticfunc(this, &FastDelegate5::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5); } +}; + +//N=6 +template +class FastDelegate6 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate6 type; + + // Construction and comparison functions + FastDelegate6() { clear(); } + FastDelegate6(const FastDelegate6 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate6 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate6 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate6 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate6 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate6 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate6(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate6(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate6(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + m_Closure.bindstaticfunc(this, &FastDelegate6::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6); } +}; + +//N=7 +template +class FastDelegate7 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate7 type; + + // Construction and comparison functions + FastDelegate7() { clear(); } + FastDelegate7(const FastDelegate7 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate7 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate7 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate7 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate7 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate7 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate7(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate7(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate7(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + m_Closure.bindstaticfunc(this, &FastDelegate7::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7); } +}; + +//N=8 +template +class FastDelegate8 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate8 type; + + // Construction and comparison functions + FastDelegate8() { clear(); } + FastDelegate8(const FastDelegate8 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate8 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate8 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate8 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate8 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate8 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate8(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate8(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate8(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + m_Closure.bindstaticfunc(this, &FastDelegate8::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8); } +}; + + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 4: +// +// FastDelegate<> class (Original author: Jody Hagins) +// Allows boost::function style syntax like: +// FastDelegate< double (int, long) > +// instead of: +// FastDelegate2< int, long, double > +// +//////////////////////////////////////////////////////////////////////////////// + +#ifdef FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +// Declare FastDelegate as a class template. It will be specialized +// later for all number of arguments. +template +class FastDelegate; + +//N=0 +// Specialization to allow use of +// FastDelegate< R ( ) > +// instead of +// FastDelegate0 < R > +template +class FastDelegate< R ( ) > + // Inherit from FastDelegate0 so that it can be treated just like a FastDelegate0 + : public FastDelegate0 < R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate0 < R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=1 +// Specialization to allow use of +// FastDelegate< R ( Param1 ) > +// instead of +// FastDelegate1 < Param1, R > +template +class FastDelegate< R ( Param1 ) > + // Inherit from FastDelegate1 so that it can be treated just like a FastDelegate1 + : public FastDelegate1 < Param1, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate1 < Param1, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=2 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2 ) > +// instead of +// FastDelegate2 < Param1, Param2, R > +template +class FastDelegate< R ( Param1, Param2 ) > + // Inherit from FastDelegate2 so that it can be treated just like a FastDelegate2 + : public FastDelegate2 < Param1, Param2, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate2 < Param1, Param2, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=3 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3 ) > +// instead of +// FastDelegate3 < Param1, Param2, Param3, R > +template +class FastDelegate< R ( Param1, Param2, Param3 ) > + // Inherit from FastDelegate3 so that it can be treated just like a FastDelegate3 + : public FastDelegate3 < Param1, Param2, Param3, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate3 < Param1, Param2, Param3, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=4 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4 ) > +// instead of +// FastDelegate4 < Param1, Param2, Param3, Param4, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4 ) > + // Inherit from FastDelegate4 so that it can be treated just like a FastDelegate4 + : public FastDelegate4 < Param1, Param2, Param3, Param4, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate4 < Param1, Param2, Param3, Param4, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=5 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) > +// instead of +// FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) > + // Inherit from FastDelegate5 so that it can be treated just like a FastDelegate5 + : public FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=6 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) > +// instead of +// FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) > + // Inherit from FastDelegate6 so that it can be treated just like a FastDelegate6 + : public FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=7 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > +// instead of +// FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > + // Inherit from FastDelegate7 so that it can be treated just like a FastDelegate7 + : public FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=8 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > +// instead of +// FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > + // Inherit from FastDelegate8 so that it can be treated just like a FastDelegate8 + : public FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + + +#endif //FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 5: +// +// MakeDelegate() helper function +// +// MakeDelegate(&x, &X::func) returns a fastdelegate of the type +// necessary for calling x.func() with the correct number of arguments. +// This makes it possible to eliminate many typedefs from user code. +// +//////////////////////////////////////////////////////////////////////////////// + +// Also declare overloads of a MakeDelegate() global function to +// reduce the need for typedefs. +// We need seperate overloads for const and non-const member functions. +// Also, because of the weird rule about the class of derived member function pointers, +// implicit downcasts may need to be applied later to the 'this' pointer. +// That's why two classes (X and Y) appear in the definitions. Y must be implicitly +// castable to X. + +// Workaround for VC6. VC6 needs void return types converted into DefaultVoid. +// GCC 3.2 and later won't compile this unless it's preceded by 'typename', +// but VC6 doesn't allow 'typename' in this context. +// So, I have to use a macro. + +#ifdef FASTDLGT_VC6 +#define FASTDLGT_RETTYPE detail::VoidToDefaultVoid::type +#else +#define FASTDLGT_RETTYPE RetType +#endif + +//N=0 +template +FastDelegate0 MakeDelegate(Y* x, RetType (X::*func)()) { + return FastDelegate0(x, func); +} + +template +FastDelegate0 MakeDelegate(Y* x, RetType (X::*func)() const) { + return FastDelegate0(x, func); +} + +//N=1 +template +FastDelegate1 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1)) { + return FastDelegate1(x, func); +} + +template +FastDelegate1 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1) const) { + return FastDelegate1(x, func); +} + +//N=2 +template +FastDelegate2 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2)) { + return FastDelegate2(x, func); +} + +template +FastDelegate2 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2) const) { + return FastDelegate2(x, func); +} + +//N=3 +template +FastDelegate3 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3)) { + return FastDelegate3(x, func); +} + +template +FastDelegate3 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3) const) { + return FastDelegate3(x, func); +} + +//N=4 +template +FastDelegate4 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + return FastDelegate4(x, func); +} + +template +FastDelegate4 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) { + return FastDelegate4(x, func); +} + +//N=5 +template +FastDelegate5 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + return FastDelegate5(x, func); +} + +template +FastDelegate5 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) { + return FastDelegate5(x, func); +} + +//N=6 +template +FastDelegate6 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + return FastDelegate6(x, func); +} + +template +FastDelegate6 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) { + return FastDelegate6(x, func); +} + +//N=7 +template +FastDelegate7 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + return FastDelegate7(x, func); +} + +template +FastDelegate7 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) { + return FastDelegate7(x, func); +} + +//N=8 +template +FastDelegate8 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + return FastDelegate8(x, func); +} + +template +FastDelegate8 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) { + return FastDelegate8(x, func); +} + + + // clean up after ourselves... +#undef FASTDLGT_RETTYPE + +} // namespace fastdelegate + +#endif // !defined(FASTDELEGATE_H) + diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..76d31f8 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,15 @@ +bin_PROGRAMS = gmenu2x +# +gmenu2x_SOURCES = asfont.cpp button.cpp cpu.cpp dirdialog.cpp filedialog.cpp filelister.cpp gmenu2x.cpp iconbutton.cpp imagedialog.cpp inputdialog.cpp inputmanager.cpp linkaction.cpp linkapp.cpp link.cpp listviewitem.cpp menu.cpp menusettingbool.cpp menusetting.cpp menusettingdir.cpp menusettingfile.cpp menusettingimage.cpp menusettingint.cpp menusettingmultistring.cpp menusettingrgba.cpp menusettingstring.cpp messagebox.cpp pxml.cpp selector.cpp selectordetector.cpp settingsdialog.cpp sfontplus.cpp surfacecollection.cpp surface.cpp textdialog.cpp textmanualdialog.cpp touchscreen.cpp translator.cpp utilities.cpp wallpaperdialog.cpp listview.cpp tinyxml/tinystr.cpp tinyxml/tinyxml.cpp tinyxml/tinyxmlerror.cpp tinyxml/tinyxmlparser.cpp + +noinst_HEADERS = asfont.h button.h cpu.h dirdialog.h FastDelegate.h filedialog.h filelister.h gmenu2x.h gp2x.h iconbutton.h imagedialog.h inputdialog.h inputmanager.h jz4740.h linkaction.h linkapp.h link.h listview.h listviewitem.h menu.h menusettingbool.h menusettingdir.h menusettingfile.h menusetting.h menusettingimage.h menusettingint.h menusettingmultistring.h menusettingrgba.h menusettingstring.h messagebox.h pxml.h selectordetector.h selector.h settingsdialog.h sfontplus.h surfacecollection.h surface.h textdialog.h textmanualdialog.h touchscreen.h translator.h utilities.h wallpaperdialog.h tinyxml/tinystr.h tinyxml/tinyxml.h + +AM_CFLAGS= @CFLAGS@ @SDL_CFLAGS@ + +AM_CXXFLAGS = @CXXFLAGS@ @SDL_CFLAGS@ + +gmenu2x_LDADD = @LIBS@ @SDL_LIBS@ + +gmenu2x_LDFLAGS = -L/home/vegyraupe/work/qi/NanoNote/Ben/sw/tinyxml + +gmenu2x_LIBS = @LIBS@ @SDL_LIBS@ -L./sparsehash/ -I./obj/gp2x/tinyxml/ \ No newline at end of file diff --git a/src/asfont.cpp b/src/asfont.cpp new file mode 100644 index 0000000..e6cfdbb --- /dev/null +++ b/src/asfont.cpp @@ -0,0 +1,124 @@ +#include "asfont.h" +#include "surface.h" +#include "utilities.h" + +#include + +using namespace std; + +ASFont::ASFont(SDL_Surface* font) { + this->font.initFont(font); + halfHeight = getHeight()/2; + halfLineHeight = getLineHeight()/2; +} + +ASFont::ASFont(Surface* font) { + this->font.initFont(font->raw); + halfHeight = getHeight()/2; + halfLineHeight = getLineHeight()/2; +} + +ASFont::ASFont(string font) { + this->font.initFont(font); + halfHeight = getHeight()/2; + halfLineHeight = getLineHeight()/2; +} + +ASFont::~ASFont() { + font.freeFont(); +} + +bool ASFont::utf8Code(unsigned char c) { + return font.utf8Code(c); +} + +void ASFont::write(SDL_Surface* surface, const char* text, int x, int y) { + font.write(surface, text, x, y); +} + +void ASFont::write(SDL_Surface* surface, const std::string& text, int x, int y, const unsigned short halign, const unsigned short valign) { + switch (halign) { + case SFontHAlignCenter: + x -= getTextWidth(text)/2; + break; + case SFontHAlignRight: + x -= getTextWidth(text); + break; + } + + switch (valign) { + case SFontVAlignMiddle: + y -= getHalfHeight(); + break; + case SFontVAlignBottom: + y -= getHeight(); + break; + } + + font.write(surface, text, x, y); +} +void ASFont::write(SDL_Surface* surface, vector *text, int x, int y, const unsigned short halign, const unsigned short valign) { + switch (valign) { + case SFontVAlignMiddle: + y -= getHalfHeight()*text->size(); + break; + case SFontVAlignBottom: + y -= getHeight()*text->size(); + break; + } + + for (uint i=0; isize(); i++) { + int ix = x; + switch (halign) { + case SFontHAlignCenter: + ix -= getTextWidth(text->at(i))/2; + break; + case SFontHAlignRight: + ix -= getTextWidth(text->at(i)); + break; + } + + font.write(surface, text->at(i), x, y+getHeight()*i); + } +} + +void ASFont::write(Surface* surface, const std::string& text, int x, int y, const unsigned short halign, const unsigned short valign) { + if (text.find("\n",0)!=string::npos) { + vector textArr; + split(textArr,text,"\n"); + write(surface->raw, &textArr, x, y, halign, valign); + } else + write(surface->raw, text, x, y, halign, valign); +} + +int ASFont::getHeight() { + return font.getHeight(); +} +int ASFont::getHalfHeight() { + return halfHeight; +} + +int ASFont::getLineHeight() { + return font.getLineHeight(); +} +int ASFont::getHalfLineHeight() { + return halfLineHeight; +} + +int ASFont::getTextWidth(const char* text) { + return font.getTextWidth(text); +} +int ASFont::getTextWidth(const std::string& text) { + if (text.find("\n",0)!=string::npos) { + vector textArr; + split(textArr,text,"\n"); + return getTextWidth(&textArr); + } else + return getTextWidth(text.c_str()); +} +int ASFont::getTextWidth(vector *text) { + int w = 0; + for (uint i=0; isize(); i++) + w = max( getTextWidth(text->at(i).c_str()), w ); + return w; +} diff --git a/src/asfont.h b/src/asfont.h new file mode 100644 index 0000000..b28efcb --- /dev/null +++ b/src/asfont.h @@ -0,0 +1,49 @@ +//Advanced SFont by Massimiliano Torromeo (cpp wrapper around SFont) + +#ifndef ASFONT_H +#define ASFONT_H + +#include +#include +#include +#include "sfontplus.h" + +using std::string; +using std::vector; + +const unsigned short SFontHAlignLeft = 0; +const unsigned short SFontHAlignRight = 1; +const unsigned short SFontHAlignCenter = 2; +const unsigned short SFontVAlignTop = 0; +const unsigned short SFontVAlignBottom = 1; +const unsigned short SFontVAlignMiddle = 2; + +class Surface; + +class ASFont { +public: + ASFont(SDL_Surface* font); + ASFont(Surface* font); + ASFont(string font); + ~ASFont(); + + bool utf8Code(unsigned char c); + + int getHeight(); + int getHalfHeight(); + int getLineHeight(); + int getHalfLineHeight(); + int getTextWidth(const char* text); + int getTextWidth(const string& text); + int getTextWidth(vector *text); + void write(SDL_Surface* surface, const char* text, int x, int y); + void write(SDL_Surface* surface, const std::string& text, int x, int y, const unsigned short halign = 0, const unsigned short valign = 0); + void write(SDL_Surface* surface, vector *text, int x, int y, const unsigned short halign = 0, const unsigned short valign = 0); + void write(Surface* surface, const std::string& text, int x, int y, const unsigned short halign = 0, const unsigned short valign = 0); + +private: + SFontPlus font; + int halfHeight, halfLineHeight; +}; + +#endif /* ASFONT_H */ diff --git a/src/button.cpp b/src/button.cpp new file mode 100644 index 0000000..ff61fae --- /dev/null +++ b/src/button.cpp @@ -0,0 +1,71 @@ +#include "button.h" +#include "gmenu2x.h" + +using namespace std; +using namespace fastdelegate; + +Button::Button(GMenu2X * gmenu2x, bool doubleClick) { + this->gmenu2x = gmenu2x; + this->doubleClick = doubleClick; + lastTick = 0; + action = MakeDelegate(this, &Button::voidAction); + rect.x = 0; + rect.y = 0; + rect.w = 0; + rect.h = 0; +} + +void Button::paint() { + if (gmenu2x->ts.inRect(rect)) + if (!paintHover()) return; +} + +bool Button::paintHover() { + return false; +} + +bool Button::isPressed() { + return gmenu2x->ts.pressed() && gmenu2x->ts.inRect(rect); +} + +bool Button::isReleased() { + return gmenu2x->ts.released() && gmenu2x->ts.inRect(rect); +} + +bool Button::handleTS() { + if (isReleased()) { + if (doubleClick) { + int tickNow = SDL_GetTicks(); + if (tickNow - lastTick < 400) + exec(); + lastTick = tickNow; + } else { + exec(); + } + return true; + } + return false; +} + +void Button::exec() { + gmenu2x->ts.setHandled(); + action(); +} + +SDL_Rect Button::getRect() { + return rect; +} + +void Button::setSize(int w, int h) { + rect.w = w; + rect.h = h; +} + +void Button::setPosition(int x, int y) { + rect.x = x; + rect.y = y; +} + +void Button::setAction(ButtonAction action) { + this->action = action; +} diff --git a/src/button.h b/src/button.h new file mode 100644 index 0000000..ae5e106 --- /dev/null +++ b/src/button.h @@ -0,0 +1,62 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef BUTTON_H_ +#define BUTTON_H_ + +#include +#include +#include "FastDelegate.h" + +using std::string; +using fastdelegate::FastDelegate0; + +typedef FastDelegate0<> ButtonAction; +class GMenu2X; + +class Button { +protected: + GMenu2X *gmenu2x; + ButtonAction action; + SDL_Rect rect; + bool doubleClick; + int lastTick; + +public: + string path; + Button(GMenu2X *gmenu2x, bool doubleClick = false); + virtual ~Button() {}; + + SDL_Rect getRect(); + void setSize(int w, int h); + void setPosition(int x, int y); + + virtual void paint(); + virtual bool paintHover(); + + bool isPressed(); + bool isReleased(); + bool handleTS(); + void exec(); + void voidAction() {}; + void setAction(ButtonAction action); +}; + +#endif /*BUTTON_H_*/ diff --git a/src/cpu.cpp b/src/cpu.cpp new file mode 100644 index 0000000..94168f7 --- /dev/null +++ b/src/cpu.cpp @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include +#include "jz4740.h" +#include "cpu.h" + +inline int sdram_convert(unsigned int pllin,unsigned int *sdram_freq) +{ + register unsigned int ns, tmp; + + ns = 1000000000 / pllin; + /* Set refresh registers */ + tmp = SDRAM_TREF/ns; + tmp = tmp/64 + 1; + if (tmp > 0xff) tmp = 0xff; + *sdram_freq = tmp; + + return 0; + +} + +void pll_init(unsigned int clock) +{ + register unsigned int cfcr, plcr1; + unsigned int sdramclock = 0; + int n2FR[33] = { + 0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, + 9 + }; + //int div[5] = {1, 4, 4, 4, 4}; /* divisors of I:S:P:L:M */ + int div[5] = {1, 3, 3, 3, 3}; /* divisors of I:S:P:L:M */ + int nf, pllout2; + + cfcr = CPM_CPCCR_CLKOEN | + (n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) | + (n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) | + (n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) | + (n2FR[div[3]] << CPM_CPCCR_MDIV_BIT) | + (n2FR[div[4]] << CPM_CPCCR_LDIV_BIT); + + pllout2 = (cfcr & CPM_CPCCR_PCS) ? clock : (clock / 2); + + /* Init UHC clock */ +// REG_CPM_UHCCDR = pllout2 / 48000000 - 1; + jz_cpmregl[0x6C>>2] = pllout2 / 48000000 - 1; + + nf = clock * 2 / CFG_EXTAL; + plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */ + (0 << CPM_CPPCR_PLLN_BIT) | /* RD=0, NR=2 */ + (0 << CPM_CPPCR_PLLOD_BIT) | /* OD=0, NO=1 */ + (0x20 << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */ + CPM_CPPCR_PLLEN; /* enable PLL */ + + /* init PLL */ +// REG_CPM_CPCCR = cfcr; +// REG_CPM_CPPCR = plcr1; + jz_cpmregl[0] = cfcr; + jz_cpmregl[0x10>>2] = plcr1; + + sdram_convert(clock,&sdramclock); + if(sdramclock > 0) + { +// REG_EMC_RTCOR = sdramclock; +// REG_EMC_RTCNT = sdramclock; + jz_emcregs[0x8C>>1] = sdramclock; + jz_emcregs[0x88>>1] = sdramclock; + + }else + { + printf("sdram init fail!\n"); + while(1); + } + +} + + +void jz_cpuspeed(unsigned clockspeed) +{ + if (clockspeed >= 200 && clockspeed <= 430) + { + jz_dev = open("/dev/mem", O_RDWR); + if(jz_dev) + { + jz_cpmregl=(unsigned long *)mmap(0, 0x80, PROT_READ|PROT_WRITE, MAP_SHARED, jz_dev, 0x10000000); + jz_emcregl=(unsigned long *)mmap(0, 0x90, PROT_READ|PROT_WRITE, MAP_SHARED, jz_dev, 0x13010000); + jz_emcregs=(unsigned short *)jz_emcregl; + pll_init(clockspeed*1000000); + munmap((void *)jz_cpmregl, 0x80); + munmap((void *)jz_emcregl, 0x90); + close(jz_dev); + } + else + printf("failed opening /dev/mem \n"); + } +} diff --git a/src/cpu.h b/src/cpu.h new file mode 100644 index 0000000..7a05c7e --- /dev/null +++ b/src/cpu.h @@ -0,0 +1,24 @@ +#ifndef CPU_H +#define CPU_H + +/* Define this to the CPU frequency */ +#define CPU_FREQ 336000000 /* CPU clock: 336 MHz */ +#define CFG_EXTAL 12000000 /* EXT clock: 12 Mhz */ + +// SDRAM Timings, unit: ns +#define SDRAM_TRAS 45 /* RAS# Active Time */ +#define SDRAM_RCD 20 /* RAS# to CAS# Delay */ +#define SDRAM_TPC 20 /* RAS# Precharge Time */ +#define SDRAM_TRWL 7 /* Write Latency Time */ +#define SDRAM_TREF 15625 /* Refresh period: 4096 refresh cycles/64ms */ +//#define SDRAM_TREF 7812 /* Refresh period: 8192 refresh cycles/64ms */ + +static unsigned long jz_dev; +static volatile unsigned long *jz_cpmregl, *jz_emcregl; +volatile unsigned short *jz_emcregs; + +void jz_cpuspeed(unsigned clockspeed); +void pll_init(unsigned int clock); +inline int sdram_convert(unsigned int pllin,unsigned int *sdram_freq); + +#endif diff --git a/src/dirdialog.cpp b/src/dirdialog.cpp new file mode 100644 index 0000000..c495a74 --- /dev/null +++ b/src/dirdialog.cpp @@ -0,0 +1,202 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include + +//for browsing the filesystem +#include +#include +#include + +#include "dirdialog.h" +#include "filelister.h" +#include "FastDelegate.h" + +using namespace std; +using namespace fastdelegate; + +DirDialog::DirDialog(GMenu2X *gmenu2x, string text, string dir) { + this->gmenu2x = gmenu2x; + this->text = text; + selRow = 0; + if (dir.empty()) + path = "/card"; + else + path = dir; + + //Delegates + ButtonAction actionUp = MakeDelegate(this, &DirDialog::up); + ButtonAction actionEnter = MakeDelegate(this, &DirDialog::enter); + ButtonAction actionConfirm = MakeDelegate(this, &DirDialog::confirm); + + btnUp = new IconButton(gmenu2x, "skin:imgs/buttons/x.png", gmenu2x->tr["Up one folder"]); + btnUp->setAction(actionUp); + + btnEnter = new IconButton(gmenu2x, "skin:imgs/buttons/b.png", gmenu2x->tr["Enter folder"]); + btnEnter->setAction(actionEnter); + + btnConfirm = new IconButton(gmenu2x, "skin:imgs/buttons/start.png", gmenu2x->tr["Confirm"]); + btnConfirm->setAction(actionConfirm); +} + +bool DirDialog::exec() { + bool ts_pressed = false; + uint i, firstElement = 0, iY, action; + + if (!fileExists(path)) + path = "/card"; + + fl = new FileLister(path,true,false); + fl->browse(); + + selected = 0; + close = false; + result = true; + + uint rowHeight = gmenu2x->font->getHeight()+1; // gp2x=15+1 / pandora=19+1 + uint numRows = (gmenu2x->resY-gmenu2x->skinConfInt["topBarHeight"]-20)/rowHeight; + SDL_Rect clipRect = {0, gmenu2x->skinConfInt["topBarHeight"]+1, gmenu2x->resX-9, gmenu2x->resY-gmenu2x->skinConfInt["topBarHeight"]-25}; + SDL_Rect touchRect = {2, gmenu2x->skinConfInt["topBarHeight"]+4, gmenu2x->resX-12, clipRect.h}; + while (!close) { + action = DirDialog::ACT_NONE; + if (gmenu2x->f200) gmenu2x->ts.poll(); + + gmenu2x->bg->blit(gmenu2x->s,0,0); + gmenu2x->drawTitleIcon("icons/explorer.png",true); + gmenu2x->writeTitle("Directory Browser"); + gmenu2x->writeSubTitle(text); + + gmenu2x->drawButton(btnConfirm, + gmenu2x->drawButton(btnUp, + gmenu2x->drawButton(btnEnter, 5))); + + if (selected>firstElement+numRows-1) firstElement=selected-numRows+1; + if (selectedskinConfInt["topBarHeight"]+1+(iY*rowHeight); + gmenu2x->s->box(2, iY, gmenu2x->resX-12, rowHeight-1, gmenu2x->skinConfColors["selectionBg"]); + + //Directories + gmenu2x->s->setClipRect(clipRect); + if (ts_pressed && !gmenu2x->ts.pressed()) { + action = DirDialog::ACT_SELECT; + ts_pressed = false; + } + if (gmenu2x->f200 && gmenu2x->ts.pressed() && !gmenu2x->ts.inRect(touchRect)) ts_pressed = false; + for (i=firstElement; isize() && isc.skinRes("imgs/folder.png")->blit(gmenu2x->s, 5, gmenu2x->skinConfInt["topBarHeight"]+1+(iY*rowHeight)); + gmenu2x->s->write(gmenu2x->font, fl->at(i), 24, gmenu2x->skinConfInt["topBarHeight"]+9+(iY*rowHeight), SFontHAlignLeft, SFontVAlignMiddle); + if (gmenu2x->f200 && gmenu2x->ts.pressed() && gmenu2x->ts.inRect(touchRect.x, touchRect.y+(iY*rowHeight), touchRect.w, rowHeight)) { + ts_pressed = true; + selected = i; + } + } + gmenu2x->s->clearClipRect(); + + gmenu2x->drawScrollBar(numRows,fl->size(),firstElement,clipRect.y,clipRect.h); + gmenu2x->s->flip(); + + btnConfirm->handleTS(); + btnUp->handleTS(); + btnEnter->handleTS(); + gmenu2x->input.update(); + if ( gmenu2x->input[ACTION_SELECT] ) action = DirDialog::ACT_CLOSE; + if ( gmenu2x->input[ACTION_UP ] ) action = DirDialog::ACT_UP; + if ( gmenu2x->input[ACTION_L ] ) action = DirDialog::ACT_SCROLLUP; + if ( gmenu2x->input[ACTION_DOWN ] ) action = DirDialog::ACT_DOWN; + if ( gmenu2x->input[ACTION_R ] ) action = DirDialog::ACT_SCROLLDOWN; + if ( gmenu2x->input[ACTION_X] || gmenu2x->input[ACTION_LEFT] ) action = DirDialog::ACT_GOUP; + if ( gmenu2x->input[ACTION_B ] ) action = DirDialog::ACT_SELECT; + if ( gmenu2x->input[ACTION_START ] ) action = DirDialog::ACT_CONFIRM; + + if (action == DirDialog::ACT_SELECT && fl->at(selected)=="..") action = DirDialog::ACT_GOUP; + switch (action) { + case DirDialog::ACT_CLOSE: { + close = true; + result = false; + } break; + case DirDialog::ACT_UP: { + if (selected==0) + selected = fl->size()-1; + else + selected -= 1; + } break; + case DirDialog::ACT_SCROLLUP: { + if ((int)(selected-(numRows-2))<0) { + selected = 0; + } else { + selected -= numRows-2; + } + } break; + case DirDialog::ACT_DOWN: { + if (selected+1>=fl->size()) + selected = 0; + else + selected += 1; + } break; + case DirDialog::ACT_SCROLLDOWN: { + if (selected+(numRows-2)>=fl->size()) { + selected = fl->size()-1; + } else { + selected += numRows-2; + } + } break; + case DirDialog::ACT_GOUP: { + up(); + } break; + case DirDialog::ACT_SELECT: { + enter(); + } break; + case DirDialog::ACT_CONFIRM: { + confirm(); + } break; + } + } + + delete(fl); + + return result; +} + +void DirDialog::up() { + string::size_type p = path.rfind("/"); + if (p==string::npos || path.substr(0,11)!="/card" || p<4) { + close = true; + result = false; + } else { + path = path.substr(0,p); + selected = 0; + fl->setPath(path); + } +} + +void DirDialog::enter() { + path += "/"+fl->at(selected); + selected = 0; + fl->setPath(path); +} + +void DirDialog::confirm() { + close = true; +} diff --git a/src/dirdialog.h b/src/dirdialog.h new file mode 100644 index 0000000..42fd927 --- /dev/null +++ b/src/dirdialog.h @@ -0,0 +1,64 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef DIRDIALOG_H_ +#define DIRDIALOG_H_ + +#include +#include "gmenu2x.h" + +class FileLister; + +using std::string; +using std::vector; + +class DirDialog { +protected: + static const uint ACT_NONE = 0; + static const uint ACT_SELECT = 1; + static const uint ACT_CLOSE = 2; + static const uint ACT_UP = 3; + static const uint ACT_DOWN = 4; + static const uint ACT_SCROLLUP = 5; + static const uint ACT_SCROLLDOWN = 6; + static const uint ACT_GOUP = 7; + static const uint ACT_CONFIRM = 8; + +private: + int selRow; + uint selected; + bool close, result; + FileLister *fl; + string text; + IconButton *btnUp, *btnEnter, *btnConfirm; + GMenu2X *gmenu2x; + + void up(); + void enter(); + void confirm(); + +public: + string path; + DirDialog(GMenu2X *gmenu2x, string text, string dir=""); + + bool exec(); +}; + +#endif /*INPUTDIALOG_H_*/ diff --git a/src/filedialog.cpp b/src/filedialog.cpp new file mode 100644 index 0000000..99abde9 --- /dev/null +++ b/src/filedialog.cpp @@ -0,0 +1,187 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include + +//for browsing the filesystem +#include +#include +#include + +#include "filedialog.h" + +using namespace std; + +FileDialog::FileDialog(GMenu2X *gmenu2x, string text, string filter, string file) { + this->gmenu2x = gmenu2x; + this->text = text; + this->filter = filter; + this->file = ""; + setPath("/card"); + title = "File Browser"; + if (!file.empty()) { + string::size_type pos = file.rfind("/"); + if (pos != string::npos) { + setPath( file.substr(0, pos) ); + this->file = file.substr(pos+1,file.length()); + } + } + selRow = 0; +} + +bool FileDialog::exec() { + bool close = false, result = true, ts_pressed = false; + if (!fileExists(path())) + setPath("/card"); + + fl.setFilter(filter); + fl.browse(); + + uint i, firstElement = 0, iY, action; + uint rowHeight = gmenu2x->font->getHeight()+1; // gp2x=15+1 / pandora=19+1 + uint numRows = (gmenu2x->resY-gmenu2x->skinConfInt["topBarHeight"]-20)/rowHeight; + SDL_Rect clipRect = {0, gmenu2x->skinConfInt["topBarHeight"]+1, gmenu2x->resX-9, gmenu2x->resY-gmenu2x->skinConfInt["topBarHeight"]-25}; + SDL_Rect touchRect = {2, gmenu2x->skinConfInt["topBarHeight"]+4, gmenu2x->resX-12, clipRect.h}; + + selected = 0; + while (!close) { + action = FD_NO_ACTION; + if (gmenu2x->f200) gmenu2x->ts.poll(); + + gmenu2x->bg->blit(gmenu2x->s,0,0); + gmenu2x->drawTitleIcon("icons/explorer.png",true); + gmenu2x->writeTitle(title); + gmenu2x->writeSubTitle(text); + + gmenu2x->drawButton(gmenu2x->s, "x", gmenu2x->tr["Up one folder"], + gmenu2x->drawButton(gmenu2x->s, "b", gmenu2x->tr["Enter folder/Confirm"], 5)); + + if (selected>firstElement+numRows-1) firstElement=selected-numRows+1; + if (selectedskinConfInt["topBarHeight"]+1+(iY*rowHeight); + gmenu2x->s->box(2, iY, gmenu2x->resX-12, rowHeight-1, gmenu2x->skinConfColors["selectionBg"]); + + beforeFileList(); + + //Files & Directories + gmenu2x->s->setClipRect(clipRect); + if (ts_pressed && !gmenu2x->ts.pressed()) { + action = FD_ACTION_SELECT; + ts_pressed = false; + } + if (gmenu2x->f200 && gmenu2x->ts.pressed() && !gmenu2x->ts.inRect(touchRect)) ts_pressed = false; + for (i=firstElement; isc.skinRes("imgs/go-up.png")->blit(gmenu2x->s, 5, gmenu2x->skinConfInt["topBarHeight"]+1+(iY*rowHeight)); + else + gmenu2x->sc.skinRes("imgs/folder.png")->blit(gmenu2x->s, 5, gmenu2x->skinConfInt["topBarHeight"]+1+(iY*rowHeight)); + } else { + gmenu2x->sc.skinRes("imgs/file.png")->blit(gmenu2x->s, 5, gmenu2x->skinConfInt["topBarHeight"]+1+(iY*rowHeight)); + } + gmenu2x->s->write(gmenu2x->font, fl[i], 24, gmenu2x->skinConfInt["topBarHeight"]+9+(iY*rowHeight), SFontHAlignLeft, SFontVAlignMiddle); + if (gmenu2x->f200 && gmenu2x->ts.pressed() && gmenu2x->ts.inRect(touchRect.x, touchRect.y+(iY*rowHeight), touchRect.w, rowHeight)) { + ts_pressed = true; + selected = i; + } + } + gmenu2x->s->clearClipRect(); + + gmenu2x->drawScrollBar(numRows,fl.size(),firstElement,clipRect.y,clipRect.h); + gmenu2x->s->flip(); + + gmenu2x->input.update(); + if ( gmenu2x->input[ACTION_SELECT] ) action = FD_ACTION_CLOSE; + if ( gmenu2x->input[ACTION_UP ] ) action = FD_ACTION_UP; + if ( gmenu2x->input[ACTION_L ] ) action = FD_ACTION_SCROLLUP; + if ( gmenu2x->input[ACTION_DOWN ] ) action = FD_ACTION_DOWN; + if ( gmenu2x->input[ACTION_R ] ) action = FD_ACTION_SCROLLDOWN; + if ( gmenu2x->input[ACTION_X] || gmenu2x->input[ACTION_LEFT] ) action = FD_ACTION_GOUP; + if ( gmenu2x->input[ACTION_B ] ) action = FD_ACTION_SELECT; + + if (action == FD_ACTION_SELECT && fl[selected]=="..") action = FD_ACTION_GOUP; + switch (action) { + case FD_ACTION_CLOSE: { + close = true; + result = false; + } break; + case FD_ACTION_UP: { + if (selected==0) + selected = fl.size()-1; + else + selected -= 1; + } break; + case FD_ACTION_SCROLLUP: { + if ((int)(selected-(numRows-2))<0) { + selected = 0; + } else { + selected -= numRows-2; + } + } break; + case FD_ACTION_DOWN: { + if (selected+1>=fl.size()) + selected = 0; + else + selected += 1; + } break; + case FD_ACTION_SCROLLDOWN: { + if (selected+(numRows-2)>=fl.size()) { + selected = fl.size()-1; + } else { + selected += numRows-2; + } + } break; + case FD_ACTION_GOUP: { + string::size_type p = path().rfind("/"); + if (p==string::npos || path().substr(0,11)!="/card" || p<4) + return false; + else + setPath( path().substr(0,p) ); + } break; + case FD_ACTION_SELECT: { + if (fl.isDirectory(selected)) { + setPath( path()+"/"+fl[selected] ); + } else { + if (fl.isFile(selected)) { + file = fl[selected]; + close = true; + } + } + } break; + } + } + + return result; +} + +void FileDialog::setPath(string path) { + path_v = path; + fl.setPath(path); + selected = 0; + onChangeDir(); +} + +void FileDialog::beforeFileList() {} +void FileDialog::onChangeDir() {} diff --git a/src/filedialog.h b/src/filedialog.h new file mode 100644 index 0000000..605d742 --- /dev/null +++ b/src/filedialog.h @@ -0,0 +1,65 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef FILEDIALOG_H_ +#define FILEDIALOG_H_ + +#include +#include "filelister.h" +#include "gmenu2x.h" + +#define FD_NO_ACTION 0 +#define FD_ACTION_CLOSE 1 +#define FD_ACTION_UP 2 +#define FD_ACTION_DOWN 3 +#define FD_ACTION_LEFT 4 +#define FD_ACTION_RIGHT 5 +#define FD_ACTION_SCROLLDOWN 6 +#define FD_ACTION_SCROLLUP 7 +#define FD_ACTION_GOUP 8 +#define FD_ACTION_SELECT 9 + +using std::string; +using std::vector; + +class FileDialog { +protected: + int selRow; + string text, title; + GMenu2X *gmenu2x; + string filter; + FileLister fl; + uint selected; + string path_v; + +public: + string file; + FileDialog(GMenu2X *gmenu2x, string text, string filter="", string file=""); + virtual ~FileDialog() {}; + + virtual string path() { return path_v; }; + virtual void setPath(string path); + + inline virtual void beforeFileList(); + inline virtual void onChangeDir(); + bool exec(); +}; + +#endif /*INPUTDIALOG_H_*/ diff --git a/src/filelister.cpp b/src/filelister.cpp new file mode 100644 index 0000000..1b43c25 --- /dev/null +++ b/src/filelister.cpp @@ -0,0 +1,136 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +//for browsing the filesystem +#include +#include +#include +#include +#include + +#include "filelister.h" +#include "utilities.h" + +using namespace std; + +FileLister::FileLister(string startPath, bool showDirectories, bool showFiles) { + this->showDirectories = showDirectories; + this->showFiles = showFiles; + setPath(startPath,false); +} + +string FileLister::getPath() { + return path; +} +void FileLister::setPath(string path, bool doBrowse) { + if (path[path.length()-1]!='/') path += "/"; + this->path = path; + if (doBrowse) + browse(); +} + +string FileLister::getFilter() { + return filter; +} +void FileLister::setFilter(string filter) { + this->filter = filter; +} + +void FileLister::browse() { + directories.clear(); + files.clear(); + + if (showDirectories || showFiles) { + DIR *dirp; + if ((dirp = opendir(path.c_str())) == NULL) { + cout << "Error: opendir(" << path << ")" << endl; + return; + } + + vector vfilter; + split(vfilter,getFilter(),","); + + string filepath, file; + struct stat st; + struct dirent *dptr; + + while ((dptr = readdir(dirp))) { + file = dptr->d_name; + if (file[0]=='.' && file!="..") continue; + filepath = path+file; + int statRet = stat(filepath.c_str(), &st); + if (statRet == -1) { + cout << "\033[0;34mGMENU2X:\033[0;31m stat failed on '" << filepath << "' with error '" << strerror(errno) << "'\033[0m" << endl; + continue; + } + + if (find(exclude.begin(), exclude.end(), file) != exclude.end()) + continue; + + if (S_ISDIR(st.st_mode)) { + if (!showDirectories) continue; +#ifdef TARGET_GP2X +// if (!(path=="/card/" && (file!="sd" && file!="ext" && file!="nand"))) +#endif + directories.push_back(file); + } else { + if (!showFiles) continue; + bool filterOk = false; + for (uint i = 0; i=directories.size() && x +#include + +using std::string; +using std::vector; + +class FileLister { +private: + string path, filter; + bool showDirectories, showFiles; + +public: + FileLister(string startPath = "/boot/local", bool showDirectories = true, bool showFiles = true); + void browse(); + + vector directories, files, exclude; + uint size(); + uint dirCount(); + uint fileCount(); + string operator[](uint); + string at(uint); + bool isFile(uint); + bool isDirectory(uint); + + string getPath(); + void setPath(string path, bool doBrowse=true); + string getFilter(); + void setFilter(string filter); +}; + +#endif /*FILELISTER_H_*/ diff --git a/src/font-14.xcf b/src/font-14.xcf new file mode 100644 index 0000000..3f22547 Binary files /dev/null and b/src/font-14.xcf differ diff --git a/src/font.xcf b/src/font.xcf new file mode 100644 index 0000000..ab21020 Binary files /dev/null and b/src/font.xcf differ diff --git a/src/gmenu2x.cpp b/src/gmenu2x.cpp new file mode 100644 index 0000000..18dfaba --- /dev/null +++ b/src/gmenu2x.cpp @@ -0,0 +1,1979 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "gp2x.h" +#include //for battery + +//for browsing the filesystem +#include +#include +#include + +//for soundcard +#include +#include + +#include "linkapp.h" +#include "linkaction.h" +#include "menu.h" +#include "asfont.h" +#include "sfontplus.h" +#include "surface.h" +#include "filedialog.h" +#include "gmenu2x.h" +#include "filelister.h" + +#include "iconbutton.h" +#include "messagebox.h" +#include "inputdialog.h" +#include "settingsdialog.h" +#include "wallpaperdialog.h" +#include "textdialog.h" +#include "menusettingint.h" +#include "menusettingbool.h" +#include "menusettingrgba.h" +#include "menusettingstring.h" +#include "menusettingmultistring.h" +#include "menusettingfile.h" +#include "menusettingimage.h" +#include "menusettingdir.h" + +#include + +#ifdef TARGET_PANDORA +//#include +//#include +//#include +#endif + +using namespace std; +using namespace fastdelegate; + +int main(int argc, char *argv[]) { + cout << "----" << endl; + cout << "GMenu2X starting: If you read this message in the logs, check http://gmenu2x.sourceforge.net/page/Troubleshooting for a solution" << endl; + cout << "----" << endl; + + signal(SIGINT,&exit); + GMenu2X app(argc,argv); + return 0; +} + +void GMenu2X::gp2x_init() { +#ifdef TARGET_GP2X +/* gp2x_mem = open("/dev/mem", O_RDWR); + gp2x_memregs=(unsigned short *)mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, gp2x_mem, 0xc0000000); + MEM_REG=&gp2x_memregs[0]; + if (f200) { + //if wm97xx fails to open, set f200 to false to prevent any further access to the touchscreen + f200 = ts.init(); + }*/ + batteryHandle = fopen("/sys/class/power_supply/battery/capacity", "r"); + usbHandle = fopen("/sys/class/power_supply/usb/online", "r"); + acHandle = fopen("/sys/class/power_supply/ac/online", "r"); + backlightHandle = fopen("/proc/jz/lcd_backlight","w+"); +#endif +} + +void GMenu2X::gp2x_deinit() { +#ifdef TARGET_GP2X +/* if (gp2x_mem!=0) { + gp2x_memregs[0x28DA>>1]=0x4AB; + gp2x_memregs[0x290C>>1]=640; + close(gp2x_mem); + } + + if (f200) ts.deinit();*/ +#endif + if (batteryHandle) fclose(batteryHandle); + if (backlightHandle) fclose(backlightHandle); + if (usbHandle) fclose(usbHandle); + if (acHandle) fclose(acHandle); +} + +void GMenu2X::gp2x_tvout_on(bool pal) { +#ifdef TARGET_GP2X +/* if (gp2x_mem!=0) { +// Ioctl_Dummy_t *msg; +// int TVHandle = ioctl(SDL_videofd, FBMMSP2CTRL, msg); + if (cx25874!=0) gp2x_tvout_off(); + //if tv-out is enabled without cx25874 open, stop + //if (gp2x_memregs[0x2800>>1]&0x100) return; + cx25874 = open("/dev/cx25874",O_RDWR); + ioctl(cx25874, _IOW('v', 0x02, unsigned char), pal ? 4 : 3); + gp2x_memregs[0x2906>>1]=512; + gp2x_memregs[0x28E4>>1]=gp2x_memregs[0x290C>>1]; + gp2x_memregs[0x28E8>>1]=239; + }*/ +#endif +} + +void GMenu2X::gp2x_tvout_off() { +#ifdef TARGET_GP2X +/* if (gp2x_mem!=0) { + close(cx25874); + cx25874 = 0; + gp2x_memregs[0x2906>>1]=1024; + }*/ +#endif +} + +GMenu2X::GMenu2X(int argc, char *argv[]) { + //Detect firmware version and type + if (fileExists("/etc/open2x")) { + fwType = "open2x"; + fwVersion = ""; + } else { + fwType = "gph"; + fwVersion = ""; + } +#ifdef TARGET_GP2X + f200 = fileExists("/dev/touchscreen/wm97xx"); +#else + f200 = true; +#endif + + confStr.set_empty_key(" "); + confStr.set_deleted_key(""); + confInt.set_empty_key(" "); + confInt.set_deleted_key(""); + skinConfInt.set_empty_key(" "); + skinConfInt.set_deleted_key(""); + skinConfStr.set_empty_key(" "); + skinConfStr.set_deleted_key(""); + skinConfColors.set_empty_key(" "); + skinConfColors.set_deleted_key(""); + + //open2x + savedVolumeMode = 0; + volumeMode = VOLUME_MODE_NORMAL; + volumeScalerNormal = VOLUME_SCALER_NORMAL; + volumeScalerPhones = VOLUME_SCALER_PHONES; + + o2x_usb_net_on_boot = false; + o2x_usb_net_ip = ""; + o2x_ftp_on_boot = false; + o2x_telnet_on_boot = false; + o2x_gp2xjoy_on_boot = false; + o2x_usb_host_on_boot = false; + o2x_usb_hid_on_boot = false; + o2x_usb_storage_on_boot = false; + + usbnet = samba = inet = web = false; + useSelectionPng = false; + + //load config data + readConfig(); + if (fwType=="open2x") { + readConfigOpen2x(); + // VOLUME MODIFIER + switch(volumeMode) { + case VOLUME_MODE_MUTE: setVolumeScaler(VOLUME_SCALER_MUTE); break; + case VOLUME_MODE_PHONES: setVolumeScaler(volumeScalerPhones); break; + case VOLUME_MODE_NORMAL: setVolumeScaler(volumeScalerNormal); break; + } + } else + readCommonIni(); + + halfX = resX/2; + halfY = resY/2; + bottomBarIconY = resY-18; + bottomBarTextY = resY-10; + + path = ""; + getExePath(); + +#ifdef TARGET_GP2X + gp2x_mem = 0; + cx25874 = 0; + batteryHandle = 0; + backlightHandle = 0; + usbHandle = 0; + acHandle = 0; + + gp2x_init(); + + //Fix tv-out +/* if (gp2x_mem!=0) { + if (gp2x_memregs[0x2800>>1]&0x100) { + gp2x_memregs[0x2906>>1]=512; + //gp2x_memregs[0x290C>>1]=640; + gp2x_memregs[0x28E4>>1]=gp2x_memregs[0x290C>>1]; + } + gp2x_memregs[0x28E8>>1]=239; + }*/ +#endif + + //Screen + if( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_JOYSTICK)<0 ) { + cout << "\033[0;34mGMENU2X:\033[0;31m Could not initialize SDL:\033[0m " << SDL_GetError() << endl; + quit(); + } + + s = new Surface(); +#ifdef TARGET_GP2X + { + //I use a tmp variable to hide the cursor as soon as possible (and create the double buffer surface only after that) + //I'm forced to use SW surfaces since with HW there are issuse with changing the clock frequency + SDL_Surface *tmps = SDL_SetVideoMode(resX, resY, confInt["videoBpp"], SDL_SWSURFACE); + SDL_ShowCursor(0); + s->enableVirtualDoubleBuffer(tmps); + } +#else + s->raw = SDL_SetVideoMode(resX, resY, confInt["videoBpp"], SDL_HWSURFACE|SDL_DOUBLEBUF); +#endif + + bg = NULL; + font = NULL; + menu = NULL; + setSkin(confStr["skin"], false); + initMenu(); + + if (!fileExists(confStr["wallpaper"])) { +#ifdef DEBUG + cout << "Searching wallpaper" << endl; +#endif + FileLister fl("skins/"+confStr["skin"]+"/wallpapers",false,true); + fl.setFilter(".png,.jpg,.jpeg,.bmp"); + fl.browse(); + if (fl.files.size()<=0 && confStr["skin"] != "Default") + fl.setPath("skins/Default/wallpapers",true); + if (fl.files.size()>0) + confStr["wallpaper"] = fl.getPath()+fl.files[0]; + } + + initBG(); + input.init(path+"input.conf"); + setInputSpeed(); + initServices(); + setBacklight(confInt["backlight"]); + setVolume(confInt["globalVolume"]); + applyDefaultTimings(); + setClock(confInt["menuClock"]); + //recover last session + readTmp(); + if (lastSelectorElement>-1 && menu->selLinkApp()!=NULL && (!menu->selLinkApp()->getSelectorDir().empty() || !lastSelectorDir.empty())) + menu->selLinkApp()->selector(lastSelectorElement,lastSelectorDir); + +#ifdef DEBUG + cout << "Starting main()" << endl; +#endif + main(); + writeConfig(); + if (fwType=="open2x") writeConfigOpen2x(); + + quit(); + exit(0); +} + +GMenu2X::~GMenu2X() { + free(menu); + free(s); + free(font); +} + +void GMenu2X::quit() { + fflush(NULL); + sc.clear(); + s->free(); + SDL_Quit(); +#ifdef TARGET_GP2X +/* if (gp2x_mem!=0) { + //Fix tv-out + if (gp2x_memregs[0x2800>>1]&0x100) { + gp2x_memregs[0x2906>>1]=512; + gp2x_memregs[0x28E4>>1]=gp2x_memregs[0x290C>>1]; + } + gp2x_deinit(); + }*/ +#endif +} + +void GMenu2X::initBG() { + sc.del("bgmain"); + + if (bg != NULL) free(bg); + + if (!fileExists(confStr["wallpaper"])) { + bg = new Surface(s); + bg->box(0,0,resX,resY,0,0,0); + } else { + bg = new Surface(confStr["wallpaper"],false); + } + + drawTopBar(bg); + drawBottomBar(bg); + + Surface *bgmain = new Surface(bg); + sc.add(bgmain,"bgmain"); + + Surface sd("imgs/sd.png", confStr["skin"]); + Surface cpu("imgs/cpu.png", confStr["skin"]); + Surface volume("imgs/volume.png", confStr["skin"]); + string df = getDiskFree(); + + cout << "after diskfree" << endl; + + sd.blit( sc["bgmain"], 3, bottomBarIconY ); + sc["bgmain"]->write( font, df, 22, bottomBarTextY, SFontHAlignLeft, SFontVAlignMiddle ); + volumeX = 27+font->getTextWidth(df); + cout << "3 lines after diskfree" << endl; + volume.blit( sc["bgmain"], volumeX, bottomBarIconY ); + volumeX += 19; + cpuX = volumeX+font->getTextWidth("100")+5; + cpu.blit( sc["bgmain"], cpuX, bottomBarIconY ); + cpuX += 19; + manualX = cpuX+font->getTextWidth("300Mhz")+5; + + int serviceX = resX-38; + if (usbnet) { + if (web) { + Surface webserver("imgs/webserver.png", confStr["skin"]); + webserver.blit( sc["bgmain"], serviceX, bottomBarIconY ); + serviceX -= 19; + } + if (samba) { + Surface sambaS("imgs/samba.png", confStr["skin"]); + sambaS.blit( sc["bgmain"], serviceX, bottomBarIconY ); + serviceX -= 19; + } + if (inet) { + Surface inetS("imgs/inet.png", confStr["skin"]); + inetS.blit( sc["bgmain"], serviceX, bottomBarIconY ); + serviceX -= 19; + } + } + cout << "after usbnet if" << endl; +} + +void GMenu2X::initFont() { + if (font != NULL) { + free(font); + font = NULL; + } + + string fontFile = sc.getSkinFilePath("imgs/font.png"); + if (fontFile.empty()) { + cout << "Font png not found!" << endl; + quit(); + exit(-1); + } + font = new ASFont(fontFile); +} + +void GMenu2X::initMenu() { + //Menu structure handler + menu = new Menu(this); + for (uint i=0; isections.size(); i++) { + //Add virtual links in the applications section + if (menu->sections[i]=="applications") { + menu->addActionLink(i,"Explorer",MakeDelegate(this,&GMenu2X::explorer),tr["Launch an application"],"skin:icons/explorer.png"); + } + + //Add virtual links in the setting section + else if (menu->sections[i]=="settings") { + menu->addActionLink(i,"GMenu2X",MakeDelegate(this,&GMenu2X::options),tr["Configure GMenu2X's options"],"skin:icons/configure.png"); + if (fwType=="open2x") + menu->addActionLink(i,"Open2x",MakeDelegate(this,&GMenu2X::settingsOpen2x),tr["Configure Open2x system settings"],"skin:icons/o2xconfigure.png"); + menu->addActionLink(i,tr["Skin"],MakeDelegate(this,&GMenu2X::skinMenu),tr["Configure skin"],"skin:icons/skin.png"); + menu->addActionLink(i,tr["Wallpaper"],MakeDelegate(this,&GMenu2X::changeWallpaper),tr["Change GMenu2X wallpaper"],"skin:icons/wallpaper.png"); +#ifdef TARGET_GP2X +/* menu->addActionLink(i,"TV",MakeDelegate(this,&GMenu2X::toggleTvOut),tr["Activate/deactivate tv-out"],"skin:icons/tv.png"); + menu->addActionLink(i,"USB Sd",MakeDelegate(this,&GMenu2X::activateSdUsb),tr["Activate Usb on SD"],"skin:icons/usb.png"); + if (fwType=="gph" && !f200) + menu->addActionLink(i,"USB Nand",MakeDelegate(this,&GMenu2X::activateNandUsb),tr["Activate Usb on Nand"],"skin:icons/usb.png"); + //menu->addActionLink(i,"USB Root",MakeDelegate(this,&GMenu2X::activateRootUsb),tr["Activate Usb on the root of the Gp2x Filesystem"],"skin:icons/usb.png");*/ +#endif + if (fileExists(path+"log.txt")) + menu->addActionLink(i,tr["Log Viewer"],MakeDelegate(this,&GMenu2X::viewLog),tr["Displays last launched program's output"],"skin:icons/ebook.png"); + menu->addActionLink(i,tr["About"],MakeDelegate(this,&GMenu2X::about),tr["Info about GMenu2X"],"skin:icons/about.png"); + } + } + + menu->setSectionIndex(confInt["section"]); + menu->setLinkIndex(confInt["link"]); + + menu->loadIcons(); + + //DEBUG + //menu->addLink( "/card", "sample.pxml", "applications" ); +} + +void GMenu2X::about() { + vector text; + split(text,"GMenu2X is developed by Massimiliano \"Ryo\" Torromeo, and is released under the GPL-v2 license.\n\ +Website: http://gmenu2x.sourceforge.net\n\ +E-Mail & PayPal account: massimiliano.torromeo@gmail.com\n\ +\n\ +Thanks goes to...\n\ +\n\ + Contributors\n\ +----\n\ +NoidZ for his gp2x' buttons graphics\n\ +\n\ + Beta testers\n\ +----\n\ +Goemon4, PokeParadox, PSyMastR and Tripmonkey_uk\n\ +\n\ + Translators\n\ +----\n\ +English & Italian by me\n\ +French by Yodaz\n\ +Danish by claus\n\ +Dutch by superfly\n\ +Spanish by pedator\n\ +Portuguese (Portugal) by NightShadow\n\ +Slovak by Jozef\n\ +Swedish by Esslan and Micket\n\ +German by fusion_power, johnnysnet and Waldteufel\n\ +Finnish by Jontte and Atte\n\ +Norwegian by cowai\n\ +Russian by XaMMaX90\n\ +\n\ + Donors\n\ +----\n\ +EvilDragon (www.gp2x.de)\n\ +Tecnologie Creative (www.tecnologiecreative.it)\n\ +TelcoLou\n\ +gaterooze\n\ +deepmenace\n\ +superfly\n\ +halo9\n\ +sbock\n\ +b._.o._.b\n\ +Jacopastorius\n\ +lorystorm90\n\ +and all the anonymous donors...\n\ +(If I missed to list you or if you want to be removed, contact me.)","\n"); + TextDialog td(this, "GMenu2X", tr.translate("Version $1 (Build date: $2)","0.10-test4",__DATE__,NULL), "icons/about.png", &text); + td.exec(); +} + +void GMenu2X::viewLog() { + string logfile = path+"log.txt"; + if (fileExists(logfile)) { + ifstream inf(logfile.c_str(), ios_base::in); + if (inf.is_open()) { + vector log; + + string line; + while (getline(inf, line, '\n')) + log.push_back(line); + inf.close(); + + TextDialog td(this, tr["Log Viewer"], tr["Displays last launched program's output"], "icons/ebook.png", &log); + td.exec(); + + MessageBox mb(this, tr["Do you want to delete the log file?"], "icons/ebook.png"); + mb.buttons[ACTION_B] = tr["Yes"]; + mb.buttons[ACTION_X] = tr["No"]; + if (mb.exec() == ACTION_B) { + ledOn(); + unlink(logfile.c_str()); + sync(); + menu->deleteSelectedLink(); + ledOff(); + } + } + } +} + +void GMenu2X::readConfig() { + string conffile = path+"gmenu2x.conf"; + if (fileExists(conffile)) { + ifstream inf(conffile.c_str(), ios_base::in); + if (inf.is_open()) { + string line; + while (getline(inf, line, '\n')) { + string::size_type pos = line.find("="); + string name = trim(line.substr(0,pos)); + string value = trim(line.substr(pos+1,line.length())); + + if (value.length()>1 && value.at(0)=='"' && value.at(value.length()-1)=='"') + confStr[name] = value.substr(1,value.length()-2); + else + confInt[name] = atoi(value.c_str()); + } + inf.close(); + } + } + if (!confStr["lang"].empty()) tr.setLang(confStr["lang"]); + if (!confStr["wallpaper"].empty() && !fileExists(confStr["wallpaper"])) confStr["wallpaper"] = ""; + if (confStr["skin"].empty() || !fileExists("skins/"+confStr["skin"])) confStr["skin"] = "Default"; + + evalIntConf( &confInt["outputLogs"], 0, 0,1 ); + evalIntConf( &confInt["maxClock"], 430, 200,430 ); + evalIntConf( &confInt["menuClock"], 200, 200,430 ); + evalIntConf( &confInt["globalVolume"], 67, 0,100 ); + evalIntConf( &confInt["backlight"], 100, 5,100 ); + evalIntConf( &confInt["videoBpp"], 32,32,32 ); // 8,16 + + if (confStr["tvoutEncoding"] != "PAL") confStr["tvoutEncoding"] = "NTSC"; + resX = constrain( confInt["resolutionX"], 320,1920 ); + resY = constrain( confInt["resolutionY"], 240,1200 ); +} + +void GMenu2X::writeConfig() { + ledOn(); + string conffile = path+"gmenu2x.conf"; + ofstream inf(conffile.c_str()); + if (inf.is_open()) { + ConfStrHash::iterator endS = confStr.end(); + for(ConfStrHash::iterator curr = confStr.begin(); curr != endS; curr++) + inf << curr->first << "=\"" << curr->second << "\"" << endl; + + ConfIntHash::iterator endI = confInt.end(); + for(ConfIntHash::iterator curr = confInt.begin(); curr != endI; curr++) + inf << curr->first << "=" << curr->second << endl; + + inf.close(); + sync(); + } + ledOff(); +} + + +void GMenu2X::readConfigOpen2x() { + string conffile = "/etc/config/open2x.conf"; + if (fileExists(conffile)) { + ifstream inf(conffile.c_str(), ios_base::in); + if (inf.is_open()) { + string line; + while (getline(inf, line, '\n')) { + string::size_type pos = line.find("="); + string name = trim(line.substr(0,pos)); + string value = trim(line.substr(pos+1,line.length())); + + if (name=="USB_NET_ON_BOOT") o2x_usb_net_on_boot = value == "y" ? true : false; + else if (name=="USB_NET_IP") o2x_usb_net_ip = value; + else if (name=="TELNET_ON_BOOT") o2x_telnet_on_boot = value == "y" ? true : false; + else if (name=="FTP_ON_BOOT") o2x_ftp_on_boot = value == "y" ? true : false; + else if (name=="GP2XJOY_ON_BOOT") o2x_gp2xjoy_on_boot = value == "y" ? true : false; + else if (name=="USB_HOST_ON_BOOT") o2x_usb_host_on_boot = value == "y" ? true : false; + else if (name=="USB_HID_ON_BOOT") o2x_usb_hid_on_boot = value == "y" ? true : false; + else if (name=="USB_STORAGE_ON_BOOT") o2x_usb_storage_on_boot = value == "y" ? true : false; + else if (name=="VOLUME_MODE") volumeMode = savedVolumeMode = constrain( atoi(value.c_str()), 0, 2); + else if (name=="PHONES_VALUE") volumeScalerPhones = constrain( atoi(value.c_str()), 0, 100); + else if (name=="NORMAL_VALUE") volumeScalerNormal = constrain( atoi(value.c_str()), 0, 150); + } + inf.close(); + } + } +} +void GMenu2X::writeConfigOpen2x() { + ledOn(); + string conffile = "/etc/config/open2x.conf"; + ofstream inf(conffile.c_str()); + if (inf.is_open()) { + inf << "USB_NET_ON_BOOT=" << ( o2x_usb_net_on_boot ? "y" : "n" ) << endl; + inf << "USB_NET_IP=" << o2x_usb_net_ip << endl; + inf << "TELNET_ON_BOOT=" << ( o2x_telnet_on_boot ? "y" : "n" ) << endl; + inf << "FTP_ON_BOOT=" << ( o2x_ftp_on_boot ? "y" : "n" ) << endl; + inf << "GP2XJOY_ON_BOOT=" << ( o2x_gp2xjoy_on_boot ? "y" : "n" ) << endl; + inf << "USB_HOST_ON_BOOT=" << ( (o2x_usb_host_on_boot || o2x_usb_hid_on_boot || o2x_usb_storage_on_boot) ? "y" : "n" ) << endl; + inf << "USB_HID_ON_BOOT=" << ( o2x_usb_hid_on_boot ? "y" : "n" ) << endl; + inf << "USB_STORAGE_ON_BOOT=" << ( o2x_usb_storage_on_boot ? "y" : "n" ) << endl; + inf << "VOLUME_MODE=" << volumeMode << endl; + if (volumeScalerPhones != VOLUME_SCALER_PHONES) inf << "PHONES_VALUE=" << volumeScalerPhones << endl; + if (volumeScalerNormal != VOLUME_SCALER_NORMAL) inf << "NORMAL_VALUE=" << volumeScalerNormal << endl; + inf.close(); + sync(); + } + ledOff(); +} + +void GMenu2X::writeSkinConfig() { + ledOn(); + string conffile = path+"skins/"+confStr["skin"]+"/skin.conf"; + ofstream inf(conffile.c_str()); + if (inf.is_open()) { + ConfStrHash::iterator endS = skinConfStr.end(); + for(ConfStrHash::iterator curr = skinConfStr.begin(); curr != endS; curr++) + inf << curr->first << "=\"" << curr->second << "\"" << endl; + + ConfIntHash::iterator endI = skinConfInt.end(); + for(ConfIntHash::iterator curr = skinConfInt.begin(); curr != endI; curr++) + inf << curr->first << "=" << curr->second << endl; + + ConfRGBAHash::iterator endC = skinConfColors.end(); + for(ConfRGBAHash::iterator curr = skinConfColors.begin(); curr != endC; curr++) + inf << curr->first << "=#" << hex << curr->second.r << hex << curr->second.g << hex << curr->second.b << hex << curr->second.a << endl; + + inf.close(); + sync(); + } + ledOff(); +} + +void GMenu2X::readCommonIni() { + if (fileExists("/usr/gp2x/common.ini")) { + ifstream inf("/usr/gp2x/common.ini", ios_base::in); + if (inf.is_open()) { + string line; + string section = ""; + while (getline(inf, line, '\n')) { + line = trim(line); + if (line[0]=='[' && line[line.length()-1]==']') { + section = line.substr(1,line.length()-2); + } else { + string::size_type pos = line.find("="); + string name = trim(line.substr(0,pos)); + string value = trim(line.substr(pos+1,line.length())); + + if (section=="usbnet") { + if (name=="enable") + usbnet = value=="true" ? true : false; + else if (name=="ip") + ip = value; + + } else if (section=="server") { + if (name=="inet") + inet = value=="true" ? true : false; + else if (name=="samba") + samba = value=="true" ? true : false; + else if (name=="web") + web = value=="true" ? true : false; + } + } + } + inf.close(); + } + } +} + +void GMenu2X::writeCommonIni() {} + +void GMenu2X::readTmp() { + lastSelectorElement = -1; + if (fileExists("/tmp/gmenu2x.tmp")) { + ifstream inf("/tmp/gmenu2x.tmp", ios_base::in); + if (inf.is_open()) { + string line; + string section = ""; + while (getline(inf, line, '\n')) { + string::size_type pos = line.find("="); + string name = trim(line.substr(0,pos)); + string value = trim(line.substr(pos+1,line.length())); + + if (name=="section") + menu->setSectionIndex(atoi(value.c_str())); + else if (name=="link") + menu->setLinkIndex(atoi(value.c_str())); + else if (name=="selectorelem") + lastSelectorElement = atoi(value.c_str()); + else if (name=="selectordir") + lastSelectorDir = value; + } + inf.close(); + } + } +} + +void GMenu2X::writeTmp(int selelem, string selectordir) { + string conffile = "/tmp/gmenu2x.tmp"; + ofstream inf(conffile.c_str()); + if (inf.is_open()) { + inf << "section=" << menu->selSectionIndex() << endl; + inf << "link=" << menu->selLinkIndex() << endl; + if (selelem>-1) + inf << "selectorelem=" << selelem << endl; + if (selectordir!="") + inf << "selectordir=" << selectordir << endl; + inf.close(); + sync(); + } +} + +void GMenu2X::initServices() { +#ifdef TARGET_GP2X +/* if (usbnet) { + string services = "scripts/services.sh "+ip+" "+(inet?"on":"off")+" "+(samba?"on":"off")+" "+(web?"on":"off")+" &"; + system(services.c_str()); + }*/ +#endif +} + +void GMenu2X::ledOn() { +#ifdef TARGET_GP2X +// if (gp2x_mem!=0 && !f200) gp2x_memregs[0x106E >> 1] ^= 16; + //SDL_SYS_JoystickGp2xSys(joy.joystick, BATT_LED_ON); +#endif +} + +void GMenu2X::ledOff() { +#ifdef TARGET_GP2X +// if (gp2x_mem!=0 && !f200) gp2x_memregs[0x106E >> 1] ^= 16; + //SDL_SYS_JoystickGp2xSys(joy.joystick, BATT_LED_OFF); +#endif +} + +void GMenu2X::setBacklight(int val) +{ + if ((val >= 0) && (val <=100)) + { + if (backlightHandle) + { + stringstream valsstr; + string valstr = ""; + if (val < 10) + valsstr << "00"; + else if (val < 100) + valsstr << "0" ; + valsstr << val; + valsstr >> valstr; + fprintf(backlightHandle,"%s",valstr.c_str()); + rewind(backlightHandle); + } + } +} + +int GMenu2X::getBackLight() +{ + int val = 100; + if (backlightHandle) + { + char valcstring[4]; + fscanf(backlightHandle,"%s",&valcstring); + rewind(backlightHandle); + val = atoi(valcstring); + } + return val; +} + +int GMenu2X::main() { + uint linksPerPage = linkColumns*linkRows; + int linkSpacingX = (resX-10 - linkColumns*skinConfInt["linkWidth"])/linkColumns; + int linkSpacingY = (resY-35 - skinConfInt["topBarHeight"] - linkRows*skinConfInt["linkHeight"])/linkRows; + uint sectionLinkPadding = (skinConfInt["topBarHeight"] - 32 - font->getLineHeight()) / 3; + + bool quit = false; + int x,y, offset = menu->sectionLinks()->size()>linksPerPage ? 2 : 6, helpBoxHeight = fwType=="open2x" ? 154 : 139; + uint i; + long tickBattery = -60000, tickNow; + string batteryIcon = "imgs/battery/0.png"; + stringstream ss; + uint sectionsCoordX = 24; + SDL_Rect re = {0,0,0,0}; + bool helpDisplayed = false; +#ifdef DEBUG + //framerate + long tickFPS = SDL_GetTicks(); + int drawn_frames = 0; + string fps = ""; +#endif + + IconButton btnContextMenu(this,"skin:imgs/menu.png"); + btnContextMenu.setPosition(resX-38, bottomBarIconY); + btnContextMenu.setAction(MakeDelegate(this, &GMenu2X::contextMenu)); + + while (!quit) { + tickNow = SDL_GetTicks(); + + //Background + sc["bgmain"]->blit(s,0,0); + + //Sections + sectionsCoordX = halfX - (constrain((uint)menu->sections.size(), 0 , linkColumns) * skinConfInt["linkWidth"]) / 2; + if (menu->firstDispSection()>0) + sc.skinRes("imgs/l_enabled.png")->blit(s,0,0); + else + sc.skinRes("imgs/l_disabled.png")->blit(s,0,0); + if (menu->firstDispSection()+linkColumnssections.size()) + sc.skinRes("imgs/r_enabled.png")->blit(s,resX-10,0); + else + sc.skinRes("imgs/r_disabled.png")->blit(s,resX-10,0); + for (i=menu->firstDispSection(); isections.size() && ifirstDispSection()+linkColumns; i++) { + string sectionIcon = "skin:sections/"+menu->sections[i]+".png"; + x = (i-menu->firstDispSection())*skinConfInt["linkWidth"]+sectionsCoordX; + if (menu->selSectionIndex()==(int)i) + s->box(x, 0, skinConfInt["linkWidth"], skinConfInt["topBarHeight"], skinConfColors["selectionBg"]); + x += skinConfInt["linkWidth"]/2; + if (sc.exists(sectionIcon)) + sc[sectionIcon]->blit(s,x-16,sectionLinkPadding,32,32); + else + sc.skinRes("icons/section.png")->blit(s,x-16,sectionLinkPadding); + s->write( font, menu->sections[i], x, skinConfInt["topBarHeight"]-sectionLinkPadding, SFontHAlignCenter, SFontVAlignBottom ); + } + + //Links + s->setClipRect(offset,skinConfInt["topBarHeight"],resX-9,resY-74); //32*2+10 + for (i=menu->firstDispRow()*linkColumns; i<(menu->firstDispRow()*linkColumns)+linksPerPage && isectionLinks()->size(); i++) { + int ir = i-menu->firstDispRow()*linkColumns; + x = (ir%linkColumns)*(skinConfInt["linkWidth"]+linkSpacingX)+offset; + y = ir/linkColumns*(skinConfInt["linkHeight"]+linkSpacingY)+skinConfInt["topBarHeight"]+2; + menu->sectionLinks()->at(i)->setPosition(x,y); + + if (i==(uint)menu->selLinkIndex()) + menu->sectionLinks()->at(i)->paintHover(); + + menu->sectionLinks()->at(i)->paint(); + } + s->clearClipRect(); + + drawScrollBar(linkRows,menu->sectionLinks()->size()/linkColumns + ((menu->sectionLinks()->size()%linkColumns==0) ? 0 : 1),menu->firstDispRow(),43,resY-81); + + switch(volumeMode) { + case VOLUME_MODE_MUTE: sc.skinRes("imgs/mute.png")->blit(s,279,bottomBarIconY); break; + case VOLUME_MODE_PHONES: sc.skinRes("imgs/phones.png")->blit(s,279,bottomBarIconY); break; + default: sc.skinRes("imgs/volume.png")->blit(s,279,bottomBarIconY); break; + } + + if (menu->selLink()!=NULL) { + s->write ( font, menu->selLink()->getDescription(), halfX, resY-19, SFontHAlignCenter, SFontVAlignBottom ); + if (menu->selLinkApp()!=NULL) { + s->write ( font, menu->selLinkApp()->clockStr(confInt["maxClock"]), cpuX, bottomBarTextY, SFontHAlignLeft, SFontVAlignMiddle ); + s->write ( font, menu->selLinkApp()->volumeStr(), volumeX, bottomBarTextY, SFontHAlignLeft, SFontVAlignMiddle ); + //Manual indicator + if (!menu->selLinkApp()->getManual().empty()) + sc.skinRes("imgs/manual.png")->blit(s,manualX,bottomBarIconY); + } + } + + if (f200) { + btnContextMenu.paint(); + } + //check battery status every 60 seconds + if (tickNow-tickBattery >= 60000) { + tickBattery = tickNow; + unsigned short battlevel = getBatteryLevel(); + if (battlevel>5) { + batteryIcon = "imgs/battery/ac.png"; + } else { + ss.clear(); + ss << battlevel; + ss >> batteryIcon; + batteryIcon = "imgs/battery/"+batteryIcon+".png"; + } + } + sc.skinRes(batteryIcon)->blit( s, resX-19, bottomBarIconY ); + //s->write( font, tr[batstr.c_str()], 20, 170 ); + //On Screen Help + + if(input[ACTION_A] ) + helpDisplayed = ! helpDisplayed; + + if (helpDisplayed) { + s->box(10,50,300,143, skinConfColors["messageBoxBg"]); + s->rectangle( 12,52,296,helpBoxHeight, skinConfColors["messageBoxBorder"] ); + s->write( font, tr["CONTROLS"], 20, 60 ); + s->write( font, tr["B, Stick press: Launch link / Confirm action"], 20, 80 ); + s->write( font, tr["L, R: Change section"], 20, 95 ); + s->write( font, tr["Y: Show manual/readme"], 20, 110 ); + s->write( font, tr["VOLUP, VOLDOWN: Change cpu clock"], 20, 125 ); + s->write( font, tr["A+VOLUP, A+VOLDOWN: Change volume"], 20, 140 ); + s->write( font, tr["SELECT: Show contextual menu"], 20, 155 ); + s->write( font, tr["START: Show options menu"], 20, 170 ); + if (fwType=="open2x") s->write( font, tr["X: Toggle speaker mode"], 20, 185 ); + + } + +#ifdef DEBUG + //framerate + drawn_frames++; + if (tickNow-tickFPS>=1000) { + ss.clear(); + ss << drawn_frames*(tickNow-tickFPS+1)/1000; + ss >> fps; + tickFPS = tickNow; + drawn_frames = 0; + } + s->write( font, fps+" FPS", resX-1,1 ,SFontHAlignRight ); +#endif + + s->flip(); + + //touchscreen + if (f200) { + ts.poll(); + btnContextMenu.handleTS(); + re.x = 0; re.y = 0; re.h = skinConfInt["topBarHeight"]; re.w = resX; + if (ts.pressed() && ts.inRect(re)) { + re.w = skinConfInt["linkWidth"]; + for (i=menu->firstDispSection(); !ts.handled() && isections.size() && ifirstDispSection()+linkColumns; i++) { + sectionsCoordX = halfX - (constrain((uint)(linkColumns-menu->sections.size()), 0 , linkColumns) * skinConfInt["linkWidth"]) / 2; + re.x = (i-menu->firstDispSection())*re.w+sectionsCoordX; + + if (ts.inRect(re)) { + menu->setSectionIndex(i); + ts.setHandled(); + } + } + } + + i=menu->firstDispRow()*linkColumns; + while ( i<(menu->firstDispRow()*linkColumns)+linksPerPage && isectionLinks()->size()) { + if (menu->sectionLinks()->at(i)->isPressed()) + menu->setLinkIndex(i); + if (menu->sectionLinks()->at(i)->handleTS()) + i = menu->sectionLinks()->size(); + i++; + } + } + +//#ifdef TARGET_GP2X + input.update(); + if ( input[ACTION_B] && menu->selLink()!=NULL ) menu->selLink()->run(); + else if ( input[ACTION_START] ) options(); + else if ( input[ACTION_SELECT] ) contextMenu(); + // VOLUME SCALE MODIFIER + else if ( fwType=="open2x" && input[ACTION_X] ) { + volumeMode = constrain(volumeMode-1, -VOLUME_MODE_MUTE-1, VOLUME_MODE_NORMAL); + if(volumeMode < VOLUME_MODE_MUTE) + volumeMode = VOLUME_MODE_NORMAL; + switch(volumeMode) { + case VOLUME_MODE_MUTE: setVolumeScaler(VOLUME_SCALER_MUTE); break; + case VOLUME_MODE_PHONES: setVolumeScaler(volumeScalerPhones); break; + case VOLUME_MODE_NORMAL: setVolumeScaler(volumeScalerNormal); break; + } + setVolume(confInt["globalVolume"]); + } + // LINK NAVIGATION + else if ( input[ACTION_LEFT ] ) menu->linkLeft(); + else if ( input[ACTION_RIGHT] ) menu->linkRight(); + else if ( input[ACTION_UP ] ) menu->linkUp(); + else if ( input[ACTION_DOWN ] ) menu->linkDown(); + // SELLINKAPP SELECTED + else if (menu->selLinkApp()!=NULL) { + if ( input[ACTION_Y] ) menu->selLinkApp()->showManual(); + else if ( input.isActive(ACTION_A) ) { + // VOLUME + if ( input[ACTION_VOLDOWN] && !input.isActive(ACTION_VOLUP) ) + menu->selLinkApp()->setVolume( constrain(menu->selLinkApp()->volume()-1,0,100) ); + if ( input[ACTION_VOLUP] && !input.isActive(ACTION_VOLDOWN) ) + menu->selLinkApp()->setVolume( constrain(menu->selLinkApp()->volume()+1,0,100) );; + if ( input.isActive(ACTION_VOLUP) && input.isActive(ACTION_VOLDOWN) ) menu->selLinkApp()->setVolume(-1); + } else { + // CLOCK + if ( input[ACTION_VOLDOWN] && !input.isActive(ACTION_VOLUP) ) + menu->selLinkApp()->setClock( constrain(menu->selLinkApp()->clock()-1,200,confInt["maxClock"]) ); + if ( input[ACTION_VOLUP] && !input.isActive(ACTION_VOLDOWN) ) + menu->selLinkApp()->setClock( constrain(menu->selLinkApp()->clock()+1,200,confInt["maxClock"]) ); + if ( input.isActive(ACTION_VOLUP) && input.isActive(ACTION_VOLDOWN) ) menu->selLinkApp()->setClock(336); + } + } + if ( input.isActive(ACTION_A) ) { + if (input.isActive(ACTION_L) && input.isActive(ACTION_R)) + saveScreenshot(); + } else { + // SECTIONS + if ( input[ACTION_L ] ) { + menu->decSectionIndex(); + offset = menu->sectionLinks()->size()>linksPerPage ? 2 : 6; + } else if ( input[ACTION_R ] ) { + menu->incSectionIndex(); + offset = menu->sectionLinks()->size()>linksPerPage ? 2 : 6; + } + } + + usleep(LOOP_DELAY); + } + + return -1; +} + +void GMenu2X::explorer() { + FileDialog fd(this,tr["Select an application"],".gpu,.dge,.sh"); + if (fd.exec()) { + if (confInt["saveSelection"] && (confInt["section"]!=menu->selSectionIndex() || confInt["link"]!=menu->selLinkIndex())) + writeConfig(); + if (fwType == "open2x" && savedVolumeMode != volumeMode) + writeConfigOpen2x(); + + //string command = cmdclean(fd.path()+"/"+fd.file) + "; sync & cd "+cmdclean(getExePath())+"; exec ./gmenu2x"; + string command = cmdclean(fd.path()+"/"+fd.file); + chdir(fd.path().c_str()); + quit(); + setClock(200); + execlp("/bin/sh","/bin/sh","-c",command.c_str(),NULL); + + //if execution continues then something went wrong and as we already called SDL_Quit we cannot continue + //try relaunching gmenu2x + fprintf(stderr, "Error executing selected application, re-launching gmenu2x\n"); + chdir(getExePath().c_str()); + execlp("./gmenu2x", "./gmenu2x", NULL); + } +} + +void GMenu2X::options() { + int curMenuClock = confInt["menuClock"]; + int curGlobalVolume = confInt["globalVolume"]; + //G + int prevbacklight = confInt["backlight"]; + bool showRootFolder = fileExists("/card"); + + FileLister fl_tr("translations"); + fl_tr.browse(); + fl_tr.files.insert(fl_tr.files.begin(),"English"); + string lang = tr.lang(); + + vector encodings; + encodings.push_back("NTSC"); + encodings.push_back("PAL"); + + SettingsDialog sd(this,tr["Settings"]); + sd.addSetting(new MenuSettingMultiString(this,tr["Language"],tr["Set the language used by GMenu2X"],&lang,&fl_tr.files)); + sd.addSetting(new MenuSettingBool(this,tr["Save last selection"],tr["Save the last selected link and section on exit"],&confInt["saveSelection"])); + sd.addSetting(new MenuSettingInt(this,tr["Clock for GMenu2X"],tr["Set the cpu working frequency when running GMenu2X"],&confInt["menuClock"],200,430)); + sd.addSetting(new MenuSettingInt(this,tr["Maximum overclock"],tr["Set the maximum overclock for launching links"],&confInt["maxClock"],200,430)); + sd.addSetting(new MenuSettingInt(this,tr["Global Volume"],tr["Set the default volume for the gp2x soundcard"],&confInt["globalVolume"],0,100)); + sd.addSetting(new MenuSettingBool(this,tr["Output logs"],tr["Logs the output of the links. Use the Log Viewer to read them."],&confInt["outputLogs"])); + //G + sd.addSetting(new MenuSettingInt(this,tr["Lcd Backlight"],tr["Set dingoo's Lcd Backlight value (default: 100)"],&confInt["backlight"],5,100)); +// sd.addSetting(new MenuSettingMultiString(this,tr["Tv-Out encoding"],tr["Encoding of the tv-out signal"],&confStr["tvoutEncoding"],&encodings)); + sd.addSetting(new MenuSettingBool(this,tr["Show root"],tr["Show root folder in the file selection dialogs"],&showRootFolder)); + + if (sd.exec() && sd.edited()) { + //G + if (prevbacklight != confInt["backlight"]) setBacklight(confInt["backlight"]); + if (curMenuClock!=confInt["menuClock"]) setClock(confInt["menuClock"]); + if (curGlobalVolume!=confInt["globalVolume"]) setVolume(confInt["globalVolume"]); + if (lang == "English") lang = ""; + if (lang != tr.lang()) tr.setLang(lang); + if (fileExists("/card") && !showRootFolder) + unlink("/card"); + else if (!fileExists("/card") && showRootFolder) + symlink("/","/card"); + writeConfig(); + } +} + +void GMenu2X::settingsOpen2x() { + SettingsDialog sd(this,tr["Open2x Settings"]); + sd.addSetting(new MenuSettingBool(this,tr["USB net on boot"],tr["Allow USB networking to be started at boot time"],&o2x_usb_net_on_boot)); + sd.addSetting(new MenuSettingString(this,tr["USB net IP"],tr["IP address to be used for USB networking"],&o2x_usb_net_ip)); + sd.addSetting(new MenuSettingBool(this,tr["Telnet on boot"],tr["Allow telnet to be started at boot time"],&o2x_telnet_on_boot)); + sd.addSetting(new MenuSettingBool(this,tr["FTP on boot"],tr["Allow FTP to be started at boot time"],&o2x_ftp_on_boot)); + sd.addSetting(new MenuSettingBool(this,tr["GP2XJOY on boot"],tr["Create a js0 device for GP2X controls"],&o2x_gp2xjoy_on_boot)); + sd.addSetting(new MenuSettingBool(this,tr["USB host on boot"],tr["Allow USB host to be started at boot time"],&o2x_usb_host_on_boot)); + sd.addSetting(new MenuSettingBool(this,tr["USB HID on boot"],tr["Allow USB HID to be started at boot time"],&o2x_usb_hid_on_boot)); + sd.addSetting(new MenuSettingBool(this,tr["USB storage on boot"],tr["Allow USB storage to be started at boot time"],&o2x_usb_storage_on_boot)); + //sd.addSetting(new MenuSettingInt(this,tr["Speaker Mode on boot"],tr["Set Speaker mode. 0 = Mute, 1 = Phones, 2 = Speaker"],&volumeMode,0,2)); + sd.addSetting(new MenuSettingInt(this,tr["Speaker Scaler"],tr["Set the Speaker Mode scaling 0-150\% (default is 100\%)"],&volumeScalerNormal,0,150)); + sd.addSetting(new MenuSettingInt(this,tr["Headphones Scaler"],tr["Set the Headphones Mode scaling 0-100\% (default is 65\%)"],&volumeScalerPhones,0,100)); + + if (sd.exec() && sd.edited()) { + writeConfigOpen2x(); + switch(volumeMode) { + case VOLUME_MODE_MUTE: setVolumeScaler(VOLUME_SCALER_MUTE); break; + case VOLUME_MODE_PHONES: setVolumeScaler(volumeScalerPhones); break; + case VOLUME_MODE_NORMAL: setVolumeScaler(volumeScalerNormal); break; + } + setVolume(confInt["globalVolume"]); + } +} + +void GMenu2X::skinMenu() { + FileLister fl_sk("skins",true,false); + fl_sk.exclude.push_back(".."); + fl_sk.browse(); + string curSkin = confStr["skin"]; + + SettingsDialog sd(this,tr["Skin"]); + sd.addSetting(new MenuSettingMultiString(this,tr["Skin"],tr["Set the skin used by GMenu2X"],&confStr["skin"],&fl_sk.directories)); + sd.addSetting(new MenuSettingRGBA(this,tr["Top Bar Color"],tr["Color of the top bar"],&skinConfColors["topBarBg"])); + sd.addSetting(new MenuSettingRGBA(this,tr["Bottom Bar Color"],tr["Color of the bottom bar"],&skinConfColors["bottomBarBg"])); + sd.addSetting(new MenuSettingRGBA(this,tr["Selection Color"],tr["Color of the selection and other interface details"],&skinConfColors["selectionBg"])); + sd.addSetting(new MenuSettingRGBA(this,tr["Message Box Color"],tr["Background color of the message box"],&skinConfColors["messageBoxBg"])); + sd.addSetting(new MenuSettingRGBA(this,tr["Message Box Border Color"],tr["Border color of the message box"],&skinConfColors["messageBoxBorder"])); + sd.addSetting(new MenuSettingRGBA(this,tr["Message Box Selection Color"],tr["Color of the selection of the message box"],&skinConfColors["messageBoxSelection"])); + + if (sd.exec() && sd.edited()) { + if (curSkin != confStr["skin"]) { + setSkin(confStr["skin"]); + writeConfig(); + } + writeSkinConfig(); + initBG(); + } +} + +void GMenu2X::toggleTvOut() { +#ifdef TARGET_GP2X +/* if (cx25874!=0) + gp2x_tvout_off(); + else + gp2x_tvout_on(confStr["tvoutEncoding"] == "PAL");*/ +#endif +} + +void GMenu2X::setSkin(string skin, bool setWallpaper) { + confStr["skin"] = skin; + + //Clear previous skin settings + skinConfColors.clear(); + skinConfStr.clear(); + skinConfInt.clear(); + + //clear collection and change the skin path + sc.clear(); + sc.setSkin(skin); + + //reset colors to the default values + skinConfColors["topBarBg"] = (RGBAColor){255,255,255,130}; + skinConfColors["bottomBarBg"] = (RGBAColor){255,255,255,130}; + skinConfColors["selectionBg"] = (RGBAColor){255,255,255,130}; + skinConfColors["messageBoxBg"] = (RGBAColor){255,255,255,255}; + skinConfColors["messageBoxBorder"] = (RGBAColor){80,80,80,255}; + skinConfColors["messageBoxSelection"] = (RGBAColor){160,160,160,255}; + + //load skin settings + string skinconfname = "skins/"+skin+"/skin.conf"; + if (fileExists(skinconfname)) { + ifstream skinconf(skinconfname.c_str(), ios_base::in); + if (skinconf.is_open()) { + string line; + while (getline(skinconf, line, '\n')) { + line = trim(line); + cout << "skinconf: " << line << endl; + string::size_type pos = line.find("="); + string name = trim(line.substr(0,pos)); + string value = trim(line.substr(pos+1,line.length())); + + if (value.length()>0) { + if (value.length()>1 && value.at(0)=='"' && value.at(value.length()-1)=='"') + skinConfStr[name] = value.substr(1,value.length()-2); + else if (value.at(0) == '#') + skinConfColors[name] = strtorgba( value.substr(1,value.length()) ); + else + skinConfInt[name] = atoi(value.c_str()); + } + } + skinconf.close(); + + if (setWallpaper && !skinConfStr["wallpaper"].empty() && fileExists("skins/"+skin+"/wallpapers/"+skinConfStr["wallpaper"])) + confStr["wallpaper"] = "skins/"+skin+"/wallpapers/"+skinConfStr["wallpaper"]; + } + } + + evalIntConf( &skinConfInt["topBarHeight"], 40, 32,120 ); + evalIntConf( &skinConfInt["linkHeight"], 40, 32,120 ); + evalIntConf( &skinConfInt["linkWidth"], 60, 32,120 ); + + //recalculate some coordinates based on the new element sizes + linkColumns = (resX-10)/skinConfInt["linkWidth"]; + linkRows = (resY-35-skinConfInt["topBarHeight"])/skinConfInt["linkHeight"]; + + if (menu != NULL) menu->loadIcons(); + + //Selection png + useSelectionPng = sc.addSkinRes("imgs/selection.png") != NULL; + + //font + initFont(); +} + +void GMenu2X::activateSdUsb() { + if (usbnet) { + MessageBox mb(this,tr["Operation not permitted."]+"\n"+tr["You should disable Usb Networking to do this."]); + mb.exec(); + } else { + system("scripts/usbon.sh sd"); + MessageBox mb(this,tr["USB Enabled (SD)"],"icons/usb.png"); + mb.buttons[ACTION_B] = tr["Turn off"]; + mb.exec(); + system("scripts/usboff.sh sd"); + } +} + +void GMenu2X::activateNandUsb() { + if (usbnet) { + MessageBox mb(this,tr["Operation not permitted."]+"\n"+tr["You should disable Usb Networking to do this."]); + mb.exec(); + } else { + system("scripts/usbon.sh nand"); + MessageBox mb(this,tr["USB Enabled (Nand)"],"icons/usb.png"); + mb.buttons[ACTION_B] = tr["Turn off"]; + mb.exec(); + system("scripts/usboff.sh nand"); + } +} + +void GMenu2X::activateRootUsb() { + if (usbnet) { + MessageBox mb(this,tr["Operation not permitted."]+"\n"+tr["You should disable Usb Networking to do this."]); + mb.exec(); + } else { + system("scripts/usbon.sh root"); + MessageBox mb(this,tr["USB Enabled (Root)"],"icons/usb.png"); + mb.buttons[ACTION_B] = tr["Turn off"]; + mb.exec(); + system("scripts/usboff.sh root"); + } +} + +void GMenu2X::contextMenu() { + vector voices; + { + MenuOption opt = {tr.translate("Add link in $1",menu->selSection().c_str(),NULL), MakeDelegate(this, &GMenu2X::addLink)}; + voices.push_back(opt); + } + + if (menu->selLinkApp()!=NULL) { + { + MenuOption opt = {tr.translate("Edit $1",menu->selLink()->getTitle().c_str(),NULL), MakeDelegate(this, &GMenu2X::editLink)}; + voices.push_back(opt); + }{ + MenuOption opt = {tr.translate("Delete $1 link",menu->selLink()->getTitle().c_str(),NULL), MakeDelegate(this, &GMenu2X::deleteLink)}; + voices.push_back(opt); + } + } + + { + MenuOption opt = {tr["Add section"], MakeDelegate(this, &GMenu2X::addSection)}; + voices.push_back(opt); + }{ + MenuOption opt = {tr["Rename section"], MakeDelegate(this, &GMenu2X::renameSection)}; + voices.push_back(opt); + }{ + MenuOption opt = {tr["Delete section"], MakeDelegate(this, &GMenu2X::deleteSection)}; + voices.push_back(opt); + }{ + MenuOption opt = {tr["Scan for applications and games"], MakeDelegate(this, &GMenu2X::scanner)}; + voices.push_back(opt); + } + + bool close = false; + uint i, sel=0, fadeAlpha=0; + + int h = font->getHeight(); + int h2 = font->getHalfHeight(); + SDL_Rect box; + box.h = (h+2)*voices.size()+8; + box.w = 0; + for (i=0; igetTextWidth(voices[i].text); + if (w>box.w) box.w = w; + } + box.w += 23; + box.x = halfX - box.w/2; + box.y = halfY - box.h/2; + + SDL_Rect selbox = {box.x+4, 0, box.w-8, h+2}; + long tickNow, tickStart = SDL_GetTicks(); + + Surface bg(s); + /*//Darken background + bg.box(0, 0, resX, resY, 0,0,0,150); + bg.box(box.x, box.y, box.w, box.h, skinConfColors["messageBoxBg"]); + bg.rectangle( box.x+2, box.y+2, box.w-4, box.h-4, skinConfColors["messageBoxBorder"] );*/ + while (!close) { + tickNow = SDL_GetTicks(); + + selbox.y = box.y+4+(h+2)*sel; + bg.blit(s,0,0); + + if (fadeAlpha<200) fadeAlpha = intTransition(0,200,tickStart,500,tickNow); + s->box(0, 0, resX, resY, 0,0,0,fadeAlpha); + s->box(box.x, box.y, box.w, box.h, skinConfColors["messageBoxBg"]); + s->rectangle( box.x+2, box.y+2, box.w-4, box.h-4, skinConfColors["messageBoxBorder"] ); + + + //draw selection rect + s->box( selbox.x, selbox.y, selbox.w, selbox.h, skinConfColors["messageBoxSelection"] ); + for (i=0; iwrite( font, voices[i].text, box.x+12, box.y+h2+5+(h+2)*i, SFontHAlignLeft, SFontVAlignMiddle ); + s->flip(); + + //touchscreen + if (f200) { + ts.poll(); + if (ts.released()) { + if (!ts.inRect(box)) + close = true; + else if (ts.x>=selbox.x && ts.x<=selbox.x+selbox.w) + for (i=0; i=selbox.y && ts.y<=selbox.y+selbox.h) { + voices[i].action(); + close = true; + i = voices.size(); + } + } + } else if (ts.pressed() && ts.inRect(box)) { + for (i=0; i=selbox.y && ts.y<=selbox.y+selbox.h) { + sel = i; + i = voices.size(); + } + } + } + } + + input.update(); + if ( input[ACTION_SELECT] ) close = true; + if ( input[ACTION_UP ] ) sel = max(0, sel-1); + if ( input[ACTION_DOWN ] ) sel = min((int)voices.size()-1, sel+1); + if ( input[ACTION_B] ) { voices[sel].action(); close = true; } + } +} + +void GMenu2X::changeWallpaper() { + WallpaperDialog wp(this); + if (wp.exec() && confStr["wallpaper"] != wp.wallpaper) { + confStr["wallpaper"] = wp.wallpaper; + initBG(); + writeConfig(); + } +} + +void GMenu2X::saveScreenshot() { + ledOn(); + uint x = 0; + stringstream ss; + string fname; + do { + x++; + fname = ""; + ss.clear(); + ss << x; + ss >> fname; + fname = "screen"+fname+".bmp"; + } while (fileExists(fname)); + SDL_SaveBMP(s->raw,fname.c_str()); + sync(); + ledOff(); +} + +void GMenu2X::addLink() { + FileDialog fd(this,tr["Select an application"]); + if (fd.exec()) { + ledOn(); + menu->addLink(fd.path(), fd.file); + sync(); + ledOff(); + } +} + +void GMenu2X::editLink() { + if (menu->selLinkApp()==NULL) return; + + vector pathV; + split(pathV,menu->selLinkApp()->file,"/"); + string oldSection = ""; + if (pathV.size()>1) + oldSection = pathV[pathV.size()-2]; + string newSection = oldSection; + + string linkTitle = menu->selLinkApp()->getTitle(); + string linkDescription = menu->selLinkApp()->getDescription(); + string linkIcon = menu->selLinkApp()->getIcon(); + string linkManual = menu->selLinkApp()->getManual(); + string linkParams = menu->selLinkApp()->getParams(); + string linkSelFilter = menu->selLinkApp()->getSelectorFilter(); + string linkSelDir = menu->selLinkApp()->getSelectorDir(); + bool linkSelBrowser = menu->selLinkApp()->getSelectorBrowser(); + bool linkUseRamTimings = menu->selLinkApp()->getUseRamTimings(); + string linkSelScreens = menu->selLinkApp()->getSelectorScreens(); + string linkSelAliases = menu->selLinkApp()->getAliasFile(); + int linkClock = menu->selLinkApp()->clock(); + int linkVolume = menu->selLinkApp()->volume(); + //G + int linkGamma = menu->selLinkApp()->gamma(); + int linkBacklight = menu->selLinkApp()->backlight(); + + string diagTitle = tr.translate("Edit link: $1",linkTitle.c_str(),NULL); + string diagIcon = menu->selLinkApp()->getIconPath(); + + SettingsDialog sd(this,diagTitle,diagIcon); + sd.addSetting(new MenuSettingString(this,tr["Title"],tr["Link title"],&linkTitle, diagTitle,diagIcon)); + sd.addSetting(new MenuSettingString(this,tr["Description"],tr["Link description"],&linkDescription, diagTitle,diagIcon)); + sd.addSetting(new MenuSettingMultiString(this,tr["Section"],tr["The section this link belongs to"],&newSection,&menu->sections)); + sd.addSetting(new MenuSettingImage(this,tr["Icon"],tr.translate("Select an icon for the link: $1",linkTitle.c_str(),NULL),&linkIcon,".png,.bmp,.jpg,.jpeg")); + sd.addSetting(new MenuSettingFile(this,tr["Manual"],tr["Select a graphic/textual manual or a readme"],&linkManual,".man.png,.txt")); + sd.addSetting(new MenuSettingInt(this,tr["Clock (default: 336)"],tr["Cpu clock frequency to set when launching this link"],&linkClock,200,confInt["maxClock"])); +// sd.addSetting(new MenuSettingBool(this,tr["Tweak RAM Timings"],tr["This usually speeds up the application at the cost of stability"],&linkUseRamTimings)); + sd.addSetting(new MenuSettingInt(this,tr["Volume (default: -1)"],tr["Volume to set for this link"],&linkVolume,-1,100)); + sd.addSetting(new MenuSettingInt(this,tr["Backlight (default: 100)"],tr["LCD backlight value to set when launching this link"],&linkBacklight,5,100)); + sd.addSetting(new MenuSettingString(this,tr["Parameters"],tr["Parameters to pass to the application"],&linkParams, diagTitle,diagIcon)); + sd.addSetting(new MenuSettingDir(this,tr["Selector Directory"],tr["Directory to scan for the selector"],&linkSelDir)); + sd.addSetting(new MenuSettingBool(this,tr["Selector Browser"],tr["Allow the selector to change directory"],&linkSelBrowser)); + sd.addSetting(new MenuSettingString(this,tr["Selector Filter"],tr["Filter for the selector (Separate values with a comma)"],&linkSelFilter, diagTitle,diagIcon)); + sd.addSetting(new MenuSettingDir(this,tr["Selector Screenshots"],tr["Directory of the screenshots for the selector"],&linkSelScreens)); + sd.addSetting(new MenuSettingFile(this,tr["Selector Aliases"],tr["File containing a list of aliases for the selector"],&linkSelAliases)); + //G + sd.addSetting(new MenuSettingBool(this,tr["Wrapper"],tr["Explicitly relaunch GMenu2X after this link's execution ends"],&menu->selLinkApp()->wrapper)); + sd.addSetting(new MenuSettingBool(this,tr["Don't Leave"],tr["Don't quit GMenu2X when launching this link"],&menu->selLinkApp()->dontleave)); + + if (sd.exec() && sd.edited()) { + ledOn(); + + menu->selLinkApp()->setTitle(linkTitle); + menu->selLinkApp()->setDescription(linkDescription); + menu->selLinkApp()->setIcon(linkIcon); + menu->selLinkApp()->setManual(linkManual); + menu->selLinkApp()->setParams(linkParams); + menu->selLinkApp()->setSelectorFilter(linkSelFilter); + menu->selLinkApp()->setSelectorDir(linkSelDir); + menu->selLinkApp()->setSelectorBrowser(linkSelBrowser); + menu->selLinkApp()->setUseRamTimings(linkUseRamTimings); + menu->selLinkApp()->setSelectorScreens(linkSelScreens); + menu->selLinkApp()->setAliasFile(linkSelAliases); + menu->selLinkApp()->setClock(linkClock); + menu->selLinkApp()->setVolume(linkVolume); + //G + menu->selLinkApp()->setBacklight(linkBacklight); + +#ifdef DEBUG + cout << "New Section: " << newSection << endl; +#endif + //if section changed move file and update link->file + if (oldSection!=newSection) { + vector::iterator newSectionIndex = find(menu->sections.begin(),menu->sections.end(),newSection); + if (newSectionIndex==menu->sections.end()) return; + string newFileName = "sections/"+newSection+"/"+linkTitle; + uint x=2; + while (fileExists(newFileName)) { + string id = ""; + stringstream ss; ss << x; ss >> id; + newFileName = "sections/"+newSection+"/"+linkTitle+id; + x++; + } + rename(menu->selLinkApp()->file.c_str(),newFileName.c_str()); + menu->selLinkApp()->file = newFileName; +#ifdef DEBUG + cout << "New section index: " << newSectionIndex - menu->sections.begin() << endl; +#endif + menu->linkChangeSection(menu->selLinkIndex(), menu->selSectionIndex(), newSectionIndex - menu->sections.begin()); + } + menu->selLinkApp()->save(); + sync(); + + ledOff(); + } +} + +void GMenu2X::deleteLink() { + if (menu->selLinkApp()!=NULL) { + MessageBox mb(this, tr.translate("Deleting $1",menu->selLink()->getTitle().c_str(),NULL)+"\n"+tr["Are you sure?"], menu->selLink()->getIconPath()); + mb.buttons[ACTION_B] = tr["Yes"]; + mb.buttons[ACTION_X] = tr["No"]; + if (mb.exec() == ACTION_B) { + ledOn(); + menu->deleteSelectedLink(); + sync(); + ledOff(); + } + } +} + +void GMenu2X::addSection() { + InputDialog id(this,tr["Insert a name for the new section"]); + if (id.exec()) { + //only if a section with the same name does not exist + if (find(menu->sections.begin(),menu->sections.end(),id.input)==menu->sections.end()) { + //section directory doesn't exists + ledOn(); + if (menu->addSection(id.input)) { + menu->setSectionIndex( menu->sections.size()-1 ); //switch to the new section + sync(); + } + ledOff(); + } + } +} + +void GMenu2X::renameSection() { + InputDialog id(this,tr["Insert a new name for this section"],menu->selSection()); + if (id.exec()) { + //only if a section with the same name does not exist & !samename + if (menu->selSection()!=id.input && find(menu->sections.begin(),menu->sections.end(),id.input)==menu->sections.end()) { + //section directory doesn't exists + string newsectiondir = "sections/"+id.input; + string sectiondir = "sections/"+menu->selSection(); + ledOn(); + if (rename(sectiondir.c_str(), "tmpsection")==0 && rename("tmpsection", newsectiondir.c_str())==0) { + string oldpng = sectiondir+".png", newpng = newsectiondir+".png"; + string oldicon = sc.getSkinFilePath(oldpng), newicon = sc.getSkinFilePath(newpng); + if (!oldicon.empty() && newicon.empty()) { + newicon = oldicon; + newicon.replace(newicon.find(oldpng), oldpng.length(), newpng); + + if (!fileExists(newicon)) { + rename(oldicon.c_str(), "tmpsectionicon"); + rename("tmpsectionicon", newicon.c_str()); + sc.move("skin:"+oldpng, "skin:"+newpng); + } + } + menu->sections[menu->selSectionIndex()] = id.input; + sync(); + } + ledOff(); + } + } +} + +void GMenu2X::deleteSection() { + MessageBox mb(this,tr["You will lose all the links in this section."]+"\n"+tr["Are you sure?"]); + mb.buttons[ACTION_B] = tr["Yes"]; + mb.buttons[ACTION_X] = tr["No"]; + if (mb.exec() == ACTION_B) { + ledOn(); + if (rmtree(path+"sections/"+menu->selSection())) { + menu->deleteSelectedSection(); + sync(); + } + ledOff(); + } +} + +void GMenu2X::scanner() { + Surface scanbg(bg); + drawButton(&scanbg, "x", tr["Exit"], + drawButton(&scanbg, "b", "", 5)-10); + scanbg.write(font,tr["Link Scanner"],halfX,7,SFontHAlignCenter,SFontVAlignMiddle); + + uint lineY = 42; + +#ifdef _TARGET_PANDORA + //char *configpath = pnd_conf_query_searchpath(); +#else + if (confInt["menuClock"]<430) { + setClock(336); + scanbg.write(font,tr["Raising cpu clock to 336Mhz"],5,lineY); + scanbg.blit(s,0,0); + s->flip(); + lineY += 26; + } + + scanbg.write(font,tr["Scanning SD filesystem..."],5,lineY); + scanbg.blit(s,0,0); + s->flip(); + lineY += 26; + + vector files; + scanPath("/card",&files); + + //Onyl gph firmware has nand +/* if (fwType=="gph" && !f200) { + scanbg.write(font,tr["Scanning NAND filesystem..."],5,lineY); + scanbg.blit(s,0,0); + s->flip(); + lineY += 26; + scanPath("/boot/local/nand",&files); + } +*/ + stringstream ss; + ss << files.size(); + string str = ""; + ss >> str; + scanbg.write(font,tr.translate("$1 files found.",str.c_str(),NULL),5,lineY); + lineY += 26; + scanbg.write(font,tr["Creating links..."],5,lineY); + scanbg.blit(s,0,0); + s->flip(); + lineY += 26; + + string path, file; + string::size_type pos; + uint linkCount = 0; + + ledOn(); + for (uint i = 0; i0) { + path = files[i].substr(0, pos+1); + file = files[i].substr(pos+1, files[i].length()); + if (menu->addLink(path,file,"found "+file.substr(file.length()-3,3))) + linkCount++; + } + } + + ss.clear(); + ss << linkCount; + ss >> str; + scanbg.write(font,tr.translate("$1 links created.",str.c_str(),NULL),5,lineY); + scanbg.blit(s,0,0); + s->flip(); + lineY += 26; + + if (confInt["menuClock"]<430) { + setClock(confInt["menuClock"]); + scanbg.write(font,tr["Decreasing cpu clock"],5,lineY); + scanbg.blit(s,0,0); + s->flip(); + lineY += 26; + } + + sync(); + ledOff(); +#endif + + bool close = false; + while (!close) { + input.update(); + if (input[ACTION_START] || input[ACTION_B] || input[ACTION_X]) close = true; + usleep(30000); + } +} + +void GMenu2X::scanPath(string path, vector *files) { + DIR *dirp; + struct stat st; + struct dirent *dptr; + string filepath, ext; + + if (path[path.length()-1]!='/') path += "/"; + if ((dirp = opendir(path.c_str())) == NULL) return; + + while ((dptr = readdir(dirp))) { + if (dptr->d_name[0]=='.') + continue; + filepath = path+dptr->d_name; + int statRet = stat(filepath.c_str(), &st); + if (S_ISDIR(st.st_mode)) + scanPath(filepath, files); + if (statRet != -1) { + ext = filepath.substr(filepath.length()-4,4); +#ifdef TARGET_GP2X + if (ext==".gpu" || ext==".dge") +#else + if (ext==".pxml") +#endif + files->push_back(filepath); + } + } + + closedir(dirp); +} + +unsigned short GMenu2X::getBatteryLevel() { +#ifdef TARGET_GP2X +/* if (batteryHandle<=0) return 0; + + if (f200) { + MMSP2ADC val; + read(batteryHandle, &val, sizeof(MMSP2ADC)); + + if (val.batt==0) return 5; + if (val.batt==1) return 3; + if (val.batt==2) return 1; + if (val.batt==3) return 0; + } else { + int battval = 0; + unsigned short cbv, min=900, max=0; + + for (int i = 0; i < BATTERY_READS; i ++) { + if ( read(batteryHandle, &cbv, 2) == 2) { + battval += cbv; + if (cbv>max) max = cbv; + if (cbv=850) return 6; + if (battval>780) return 5; + if (battval>740) return 4; + if (battval>700) return 3; + if (battval>690) return 2; + if (battval>680) return 1; + }*/ + if (!batteryHandle) return 0; + int battval = 0; + char battvalcstr[5]; + fscanf(batteryHandle,"%s",&battvalcstr); + rewind(batteryHandle); + battval = atoi(battvalcstr); + if (battval>90) return 5; + if (battval>70) return 4; + if (battval>50) return 3; + if (battval>30) return 2; + if (battval>10) return 1; + + if (!usbHandle) return 0; + int usbval = 0; + char usbvalcstr[5]; + fscanf(usbHandle,"%s",&usbvalcstr); + rewind(usbHandle); + usbval = atoi(usbvalcstr); + if (usbval==1) return 6; + + return 0; +//#else +// return 6; //AC Power +#endif +} + +void GMenu2X::setInputSpeed() { + input.setInterval(150); + input.setInterval(30, ACTION_VOLDOWN); + input.setInterval(30, ACTION_VOLUP ); + input.setInterval(30, ACTION_A ); + input.setInterval(500, ACTION_START ); + input.setInterval(500, ACTION_SELECT ); + input.setInterval(300, ACTION_X ); + input.setInterval(300, ACTION_Y ); + input.setInterval(1000,ACTION_B ); + //joy.setInterval(1000,ACTION_CLICK ); + input.setInterval(300, ACTION_L ); + input.setInterval(300, ACTION_R ); + SDL_EnableKeyRepeat(1,150); +} + +void GMenu2X::applyRamTimings() { +#ifdef TARGET_GP2X + // 6 4 1 1 1 2 2 +/* if (gp2x_mem!=0) { + int tRC = 5, tRAS = 3, tWR = 0, tMRD = 0, tRFC = 0, tRP = 1, tRCD = 1; + gp2x_memregs[0x3802>>1] = ((tMRD & 0xF) << 12) | ((tRFC & 0xF) << 8) | ((tRP & 0xF) << 4) | (tRCD & 0xF); + gp2x_memregs[0x3804>>1] = ((tRC & 0xF) << 8) | ((tRAS & 0xF) << 4) | (tWR & 0xF); + }*/ +#endif +} + +void GMenu2X::applyDefaultTimings() { +#ifdef TARGET_GP2X + // 8 16 3 8 8 8 8 +/* if (gp2x_mem!=0) { + int tRC = 7, tRAS = 15, tWR = 2, tMRD = 7, tRFC = 7, tRP = 7, tRCD = 7; + gp2x_memregs[0x3802>>1] = ((tMRD & 0xF) << 12) | ((tRFC & 0xF) << 8) | ((tRP & 0xF) << 4) | (tRCD & 0xF); + gp2x_memregs[0x3804>>1] = ((tRC & 0xF) << 8) | ((tRAS & 0xF) << 4) | (tWR & 0xF); + }*/ +#endif +} + + + +void GMenu2X::setClock(unsigned mhz) { + mhz = constrain(mhz,200,confInt["maxClock"]); +#ifdef TARGET_GP2X +/* if (gp2x_mem!=0) { + unsigned v; + unsigned mdiv,pdiv=3,scale=0; + mhz*=1000000; + mdiv=(mhz*pdiv)/GP2X_CLK_FREQ; + mdiv=((mdiv-8)<<8) & 0xff00; + pdiv=((pdiv-2)<<2) & 0xfc; + scale&=3; + v=mdiv | pdiv | scale; + MEM_REG[0x910>>1]=v; + }*/ + jz_cpuspeed(mhz); +#endif +} + +void GMenu2X::setGamma(int gamma) { +#ifdef TARGET_GP2X +/* float fgamma = (float)constrain(gamma,1,100)/10; + fgamma = 1 / fgamma; + MEM_REG[0x2880>>1]&=~(1<<12); + MEM_REG[0x295C>>1]=0; + + for (int i=0; i<256; i++) { + unsigned char g = (unsigned char)(255.0*pow(i/255.0,fgamma)); + unsigned short s = (g<<8) | g; + MEM_REG[0x295E>>1]= s; + MEM_REG[0x295E>>1]= g; + }*/ +#endif +} + +int GMenu2X::getVolume() { + unsigned long mixer; + int basevolume = -1; + mixer = open("/dev/mixer", O_RDONLY); + if(mixer) + { + if (ioctl(mixer, SOUND_MIXER_READ_VOLUME, &basevolume) == -1) { + fprintf(stderr, "Failed opening mixer for read - VOLUME\n"); + } + close(mixer); + if(basevolume != -1) + return (basevolume>>8) & basevolume ; + } + return basevolume; +} + +void GMenu2X::setVolume(int vol) { + unsigned long mixer; + int newvolume = vol; + int oss_volume = newvolume | (newvolume << 8); // set volume for both channels + mixer = open("/dev/mixer", O_WRONLY); + if(mixer) + { + if (ioctl(mixer, SOUND_MIXER_WRITE_VOLUME, &oss_volume) == -1) { + fprintf(stderr, "Failed opening mixer for write - VOLUME\n"); + } + close(mixer); + } + +} + +void GMenu2X::setVolumeScaler(int scale) { + scale = constrain(scale,0,MAX_VOLUME_SCALE_FACTOR); + unsigned long soundDev = open("/dev/mixer", O_WRONLY); + if (soundDev) { + ioctl(soundDev, SOUND_MIXER_PRIVATE2, &scale); + close(soundDev); + } +} + +int GMenu2X::getVolumeScaler() { + int currentscalefactor = -1; + unsigned long soundDev = open("/dev/mixer", O_RDONLY); + if (soundDev) { + ioctl(soundDev, SOUND_MIXER_PRIVATE1, ¤tscalefactor); + close(soundDev); + } + return currentscalefactor; +} + +string GMenu2X::getExePath() { + if (path.empty()) { + char buf[255]; + int l = readlink("/proc/self/exe",buf,255); + + path = buf; + path = path.substr(0,l); + l = path.rfind("/"); + path = path.substr(0,l+1); + } + return path; +} + +string GMenu2X::getDiskFree() { + stringstream ss; + string df = ""; + struct statvfs b; + +// int ret = statvfs("/card/gmenu2x", &b); + int ret = statvfs("/home/vegyraupe/work/qi/NanoNote/Ben/sw/gmenu2x/pandora/gmenu2x", &b); + if (ret==0) { + /*unsigned long free = b.f_bfree*b.f_frsize/1048576; + unsigned long total = b.f_blocks*b.f_frsize/1048576; + ss << free << "/" << total << "MB";*/ + double free = (double)b.f_bfree * (double)b.f_bsize / 1048576.0; + double total = (double)b.f_blocks * (double)b.f_frsize / 1048576.0; + ss << (unsigned long)free << "/" << (unsigned long)total << "MB"; + ss >> df; + } else cout << "\033[0;34mGMENU2X:\033[0;31m statvfs failed with error '" << strerror(errno) << "'\033[0m" << endl; + return df; +} + +int GMenu2X::drawButton(IconButton *btn, int x, int y) { + if (y<0) y = resY+y; + btn->setPosition(x, y-7); + btn->paint(); + return x+btn->getRect().w+6; +} + +int GMenu2X::drawButton(Surface *s, string btn, string text, int x, int y) { + if (y<0) y = resY+y; + SDL_Rect re = {x, y-7, 0, 16}; + if (sc.skinRes("imgs/buttons/"+btn+".png") != NULL) { + sc["imgs/buttons/"+btn+".png"]->blit(s, x, y-7); + re.w = sc["imgs/buttons/"+btn+".png"]->raw->w+3; + s->write(font, text, x+re.w, y, SFontHAlignLeft, SFontVAlignMiddle); + re.w += font->getTextWidth(text); + } + return x+re.w+6; +} + +int GMenu2X::drawButtonRight(Surface *s, string btn, string text, int x, int y) { + if (y<0) y = resY+y; + if (sc.skinRes("imgs/buttons/"+btn+".png") != NULL) { + x -= 16; + sc["imgs/buttons/"+btn+".png"]->blit(s, x, y-7); + x -= 3; + s->write(font, text, x, y, SFontHAlignRight, SFontVAlignMiddle); + return x-6-font->getTextWidth(text); + } + return x-6; +} + +void GMenu2X::drawScrollBar(uint pagesize, uint totalsize, uint pagepos, uint top, uint height) { + if (totalsize<=pagesize) return; + + s->rectangle(resX-8, top, 7, height, skinConfColors["selectionBg"]); + + //internal bar total height = height-2 + //bar size + uint bs = (height-2) * pagesize / totalsize; + //bar y position + uint by = (height-2) * pagepos / totalsize; + by = top+2+by; + if (by+bs>top+height-2) by = top+height-2-bs; + + + s->box(resX-6, by, 3, bs, skinConfColors["selectionBg"]); +} + +void GMenu2X::drawTitleIcon(string icon, bool skinRes, Surface *s) { + if (s==NULL) s = this->s; + + Surface *i = NULL; + if (!icon.empty()) { + if (skinRes) + i = sc.skinRes(icon); + else + i = sc[icon]; + } + + if (i==NULL) + i = sc.skinRes("icons/generic.png"); + + i->blit(s,4,(skinConfInt["topBarHeight"]-32)/2); +} + +void GMenu2X::writeTitle(string title, Surface *s) { + if (s==NULL) s = this->s; + s->write(font,title,40, skinConfInt["topBarHeight"]/4, SFontHAlignLeft, SFontVAlignMiddle); +} + +void GMenu2X::writeSubTitle(string subtitle, Surface *s) { + if (s==NULL) s = this->s; + s->write(font,subtitle,40, skinConfInt["topBarHeight"]/4*3, SFontHAlignLeft, SFontVAlignMiddle); +} + +void GMenu2X::drawTopBar(Surface *s) { + if (s==NULL) s = this->s; + + Surface *bar = sc.skinRes("imgs/topbar.png"); + if (bar != NULL) + bar->blit(s, 0, 0); + else + s->box(0, 0, resX, skinConfInt["topBarHeight"], skinConfColors["topBarBg"]); +} + +void GMenu2X::drawBottomBar(Surface *s) { + if (s==NULL) s = this->s; + + Surface *bar = sc.skinRes("imgs/bottombar.png"); + if (bar != NULL) + bar->blit(s, 0, resY-bar->raw->h); + else + s->box(0, resY-20, resX, 20, skinConfColors["bottomBarBg"]); +} diff --git a/src/gmenu2x.h b/src/gmenu2x.h new file mode 100644 index 0000000..8c0d46c --- /dev/null +++ b/src/gmenu2x.h @@ -0,0 +1,242 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef GMENU2X_H +#define GMENU2X_H + +#include +#include +#include + +#include "surfacecollection.h" +#include "iconbutton.h" +#include "translator.h" +#include "FastDelegate.h" +#include "utilities.h" +#include "touchscreen.h" +#include "inputmanager.h" + +const int MAX_VOLUME_SCALE_FACTOR = 200; +// Default values - going to add settings adjustment, saving, loading and such +const int VOLUME_SCALER_MUTE = 0; +const int VOLUME_SCALER_PHONES = 65; +const int VOLUME_SCALER_NORMAL = 100; +const int VOLUME_MODE_MUTE = 0; +const int VOLUME_MODE_PHONES = 1; +const int VOLUME_MODE_NORMAL = 2; +const int BATTERY_READS = 10; + +const int LOOP_DELAY=30000; + +extern void jz_cpuspeed(unsigned clockspeed); + +using std::string; +using fastdelegate::FastDelegate0; +using google::dense_hash_map; + +typedef FastDelegate0<> MenuAction; +typedef dense_hash_map > ConfStrHash; +typedef dense_hash_map > ConfIntHash; +typedef dense_hash_map > ConfRGBAHash; + +typedef struct { + unsigned short batt; + unsigned short remocon; +} MMSP2ADC; + +struct MenuOption { + string text; + MenuAction action; +}; + +class Menu; + +class GMenu2X { +private: + string path; //!< Contains the working directory of GMenu2X + /*! + Retrieves the free disk space on the sd + @return String containing a human readable representation of the free disk space + */ + string getDiskFree(); + unsigned short cpuX; //!< Offset for displaying cpu clock information + unsigned short volumeX; //!< Offset for displaying volume level + unsigned short manualX; //!< Offset for displaying the manual indicator in the taskbar + /*! + Reads the current battery state and returns a number representing it's level of charge + @return A number representing battery charge. 0 means fully discharged. 5 means fully charged. 6 represents a gp2x using AC power. + */ + unsigned short getBatteryLevel(); + FILE* batteryHandle, *backlightHandle, *usbHandle, *acHandle; + void browsePath(string path, vector* directories, vector* files); + /*! + Starts the scanning of the nand and sd filesystems, searching for dge and gpu files and creating the links in 2 dedicated sections. + */ + void scanner(); + /*! + Performs the actual scan in the given path and populates the files vector with the results. The creation of the links is not performed here. + @see scanner + */ + void scanPath(string path, vector *files); + + /*! + Displays a selector and launches the specified executable file + */ + void explorer(); + + bool inet, //!< Represents the configuration of the basic network services. @see readCommonIni @see usbnet @see samba @see web + usbnet, + samba, + web; + string ip, defaultgw, lastSelectorDir; + int lastSelectorElement; + void readConfig(); + void readConfigOpen2x(); + void readTmp(); + void readCommonIni(); + void writeCommonIni(); + + void initServices(); + void initFont(); + void initMenu(); + +#ifdef TARGET_GP2X + unsigned long gp2x_mem; + unsigned short *gp2x_memregs; + volatile unsigned short *MEM_REG; + int cx25874; //tv-out +#endif + void gp2x_tvout_on(bool pal); + void gp2x_tvout_off(); + void gp2x_init(); + void gp2x_deinit(); + void toggleTvOut(); + +public: + GMenu2X(int argc, char *argv[]); + ~GMenu2X(); + void quit(); + + /* + * Variables needed for elements disposition + */ + uint resX, resY, halfX, halfY; + uint bottomBarIconY, bottomBarTextY, linkColumns, linkRows; + + /*! + Retrieves the parent directory of GMenu2X. + This functions is used to initialize the "path" variable. + @see path + @return String containing the parent directory + */ + string getExePath(); + + InputManager input; + Touchscreen ts; + + //Configuration hashes + ConfStrHash confStr, skinConfStr; + ConfIntHash confInt, skinConfInt; + ConfRGBAHash skinConfColors; + + //Configuration settings + bool useSelectionPng; + void setSkin(string skin, bool setWallpaper = true); + //firmware type and version + string fwType, fwVersion; + //gp2x type + bool f200; + + // Open2x settings --------------------------------------------------------- + bool o2x_usb_net_on_boot, o2x_ftp_on_boot, o2x_telnet_on_boot, o2x_gp2xjoy_on_boot, o2x_usb_host_on_boot, o2x_usb_hid_on_boot, o2x_usb_storage_on_boot; + string o2x_usb_net_ip; + int volumeMode, savedVolumeMode; // just use the const int scale values at top of source + + // Volume scaling values to store from config files + int volumeScalerPhones; + int volumeScalerNormal; + //-------------------------------------------------------------------------- + + SurfaceCollection sc; + Translator tr; + Surface *s, *bg; + ASFont *font; + + //Status functions + int main(); + void options(); + void settingsOpen2x(); + void skinMenu(); + void activateSdUsb(); + void activateNandUsb(); + void activateRootUsb(); + void about(); + void viewLog(); + void contextMenu(); + void changeWallpaper(); + void saveScreenshot(); + + void applyRamTimings(); + void applyDefaultTimings(); + + void setClock(unsigned mhz); + void setGamma(int gamma); + + void setVolume(int vol); + int getVolume(); + void setVolumeScaler(int scaler); + int getVolumeScaler(); + + void setBacklight(int val); + int getBackLight(); + + void setInputSpeed(); + + void writeConfig(); + void writeConfigOpen2x(); + void writeSkinConfig(); + void writeTmp(int selelem=-1, string selectordir=""); + + void ledOn(); + void ledOff(); + + void addLink(); + void editLink(); + void deleteLink(); + void addSection(); + void renameSection(); + void deleteSection(); + + void initBG(); + int drawButton(IconButton *btn, int x=5, int y=-10); + int drawButton(Surface *s, string btn, string text, int x=5, int y=-10); + int drawButtonRight(Surface *s, string btn, string text, int x=5, int y=-10); + void drawScrollBar(uint pagesize, uint totalsize, uint pagepos, uint top, uint height); + + void drawTitleIcon(string icon, bool skinRes=true, Surface *s=NULL); + void writeTitle(string title, Surface *s=NULL); + void writeSubTitle(string subtitle, Surface *s=NULL); + void drawTopBar(Surface *s=NULL); + void drawBottomBar(Surface *s=NULL); + + Menu* menu; +}; + +#endif diff --git a/src/gp2x.h b/src/gp2x.h new file mode 100644 index 0000000..3adb7d3 --- /dev/null +++ b/src/gp2x.h @@ -0,0 +1,53 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#define GP2X_CLK_FREQ 7372800 + +#define GP2X_BUTTON_UP (0) +#define GP2X_BUTTON_DOWN (4) +#define GP2X_BUTTON_LEFT (2) +#define GP2X_BUTTON_RIGHT (6) +#define GP2X_BUTTON_UPLEFT (1) +#define GP2X_BUTTON_UPRIGHT (7) +#define GP2X_BUTTON_DOWNLEFT (3) +#define GP2X_BUTTON_DOWNRIGHT (5) +#define GP2X_BUTTON_CLICK (18) +#define GP2X_BUTTON_A (12) +#define GP2X_BUTTON_B (13) +#define GP2X_BUTTON_START (8) +#define GP2X_BUTTON_SELECT (9) +#define GP2X_BUTTON_VOLUP (16) +#define GP2X_BUTTON_VOLDOWN (17) + +#ifdef GP2X_OLDSDL_FIX + #define GP2X_BUTTON_X (15) + #define GP2X_BUTTON_Y (14) + #define GP2X_BUTTON_L (11) + #define GP2X_BUTTON_R (10) +#else + #define GP2X_BUTTON_X (14) + #define GP2X_BUTTON_Y (15) + #define GP2X_BUTTON_L (10) + #define GP2X_BUTTON_R (11) +#endif + +#define FBMMSP2CTRL 0x4619 diff --git a/src/iconbutton.cpp b/src/iconbutton.cpp new file mode 100644 index 0000000..bca0050 --- /dev/null +++ b/src/iconbutton.cpp @@ -0,0 +1,121 @@ +#include "iconbutton.h" +#include "gmenu2x.h" + +using namespace std; +using namespace fastdelegate; + +IconButton::IconButton(GMenu2X *gmenu2x, string icon, string label) : Button(gmenu2x) { + this->gmenu2x = gmenu2x; + this->icon = icon; + labelPosition = IconButton::DISP_RIGHT; + labelMargin = 2; + this->setLabel(label); +} + +void IconButton::setPosition(int x, int y) { + if (rect.x != x && rect.y != y) { + Button::setPosition(x,y); + recalcSize(); + } +} + +void IconButton::paint() { + uint margin = labelMargin; + if (gmenu2x->sc[icon] == NULL || label == "") + margin = 0; + if (gmenu2x->sc[icon] != NULL) + gmenu2x->sc[icon]->blit(gmenu2x->s,iconRect); + if (label != "") + gmenu2x->s->write(gmenu2x->font, label, labelRect.x, labelRect.y, labelHAlign, labelVAlign); +} + +bool IconButton::paintHover() { + return true; +} + +void IconButton::recalcSize() { + uint h = 0, w = 0; + uint margin = labelMargin; + + if (gmenu2x->sc[icon] == NULL || label == "") + margin = 0; + + if (gmenu2x->sc[icon] != NULL) { + w += gmenu2x->sc[icon]->raw->w; + h += gmenu2x->sc[icon]->raw->h; + iconRect.w = w; + iconRect.h = h; + iconRect.x = rect.x; + iconRect.y = rect.y; + } else { + iconRect.x = 0; + iconRect.y = 0; + iconRect.w = 0; + iconRect.h = 0; + } + + if (label != "") { + labelRect.w = gmenu2x->font->getTextWidth(label); + labelRect.h = gmenu2x->font->getHeight(); + if (labelPosition == IconButton::DISP_LEFT || labelPosition == IconButton::DISP_RIGHT) { + w += margin + labelRect.w; + //if (labelRect.h > h) h = labelRect.h; + labelHAlign = SFontHAlignLeft; + labelVAlign = SFontVAlignMiddle; + } else { + h += margin + labelRect.h; + //if (labelRect.w > w) w = labelRect.w; + labelHAlign = SFontHAlignCenter; + labelVAlign = SFontVAlignTop; + } + + switch (labelPosition) { + case IconButton::DISP_BOTTOM: + labelRect.x = iconRect.x + iconRect.w/2; + labelRect.y = iconRect.y + iconRect.h + margin; + break; + case IconButton::DISP_TOP: + labelRect.x = iconRect.x + iconRect.w/2; + labelRect.y = rect.y; + iconRect.y += labelRect.h + margin; + break; + case IconButton::DISP_LEFT: + labelRect.x = rect.x; + labelRect.y = rect.y+h/2; + iconRect.x += labelRect.w + margin; + break; + default: + labelRect.x = iconRect.x + iconRect.w + margin; + labelRect.y = rect.y+h/2; + break; + } + } + setSize(w, h); +} + +string IconButton::getLabel() { + return label; +} + +void IconButton::setLabel(string label) { + this->label = label; +} + +void IconButton::setLabelPosition(int pos, int margin) { + labelPosition = pos; + labelMargin = margin; + recalcSize(); +} + +string IconButton::getIcon() { + return icon; +} + +void IconButton::setIcon(string icon) { + this->icon = icon; + recalcSize(); +} + +void IconButton::setAction(ButtonAction action) { + this->action = action; +} diff --git a/src/iconbutton.h b/src/iconbutton.h new file mode 100644 index 0000000..7397c1b --- /dev/null +++ b/src/iconbutton.h @@ -0,0 +1,43 @@ +#ifndef ICONBUTTON_H +#define ICONBUTTON_H + +#include +#include "button.h" + +using std::string; + +class GMenu2X; + +class IconButton : public Button { +protected: + string icon, label; + int labelPosition, labelMargin; + unsigned short labelHAlign, labelVAlign; + void recalcSize(); + SDL_Rect iconRect, labelRect; + +public: + static const int DISP_RIGHT = 0; + static const int DISP_LEFT = 1; + static const int DISP_TOP = 2; + static const int DISP_BOTTOM = 3; + + IconButton(GMenu2X *gmenu2x, string icon, string label=""); + virtual ~IconButton() {}; + + virtual void paint(); + virtual bool paintHover(); + + void setPosition(int x, int y); + + string getLabel(); + void setLabel(string label); + void setLabelPosition(int pos, int margin); + + string getIcon(); + void setIcon(string icon); + + void setAction(ButtonAction action); +}; + +#endif diff --git a/src/imagedialog.cpp b/src/imagedialog.cpp new file mode 100644 index 0000000..4bfdd31 --- /dev/null +++ b/src/imagedialog.cpp @@ -0,0 +1,64 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include + +//for browsing the filesystem +#include +#include +#include + +#include "imagedialog.h" +#include "filelister.h" + +using namespace std; + +ImageDialog::ImageDialog(GMenu2X *gmenu2x, string text, string filter, string file) : FileDialog(gmenu2x, text, filter, file) { + this->gmenu2x = gmenu2x; + this->text = text; + this->filter = filter; + this->file = ""; + setPath("/card"); + title = "Image Browser"; + if (!file.empty()) { + file = strreplace(file,"skin:",gmenu2x->getExePath()+"skins/"+gmenu2x->confStr["skin"]+"/"); + string::size_type pos = file.rfind("/"); + if (pos != string::npos) { + setPath( file.substr(0, pos) ); + cout << "ib: " << path() << endl; + this->file = file.substr(pos+1,file.length()); + } + } + selRow = 0; +} + +ImageDialog::~ImageDialog() { + previews.clear(); +} + +void ImageDialog::beforeFileList() { + if (fl.isFile(selected) && fileExists(path()+"/"+fl[selected])) + previews[path()+"/"+fl[selected]]->blitRight(gmenu2x->s, 310, 43); +} + +void ImageDialog::onChangeDir() { + previews.clear(); +} diff --git a/src/imagedialog.h b/src/imagedialog.h new file mode 100644 index 0000000..2d0652a --- /dev/null +++ b/src/imagedialog.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef IMAGEDIALOG_H_ +#define IMAGEDIALOG_H_ + +#include +#include "filedialog.h" + +using std::string; +using std::vector; + +class ImageDialog : public FileDialog { +protected: + SurfaceCollection previews; +public: + ImageDialog(GMenu2X *gmenu2x, string text, string filter="", string file=""); + virtual ~ImageDialog(); + inline virtual void beforeFileList(); + inline virtual void onChangeDir(); +}; + +#endif /*IMAGEDIALOG_H_*/ diff --git a/src/inputdialog.cpp b/src/inputdialog.cpp new file mode 100644 index 0000000..c802207 --- /dev/null +++ b/src/inputdialog.cpp @@ -0,0 +1,302 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include + +#include "inputdialog.h" + +using namespace std; +using namespace fastdelegate; + +InputDialog::InputDialog(GMenu2X *gmenu2x, string text, string startvalue, string title, string icon) { + this->gmenu2x = gmenu2x; + if (title=="") { + this->title = text; + this->text = ""; + } else { + this->title = title; + this->text = text; + } + this->icon = ""; + if (icon!="" && gmenu2x->sc[icon] != NULL) + this->icon = icon; + + input = startvalue; + selCol = 0; + selRow = 0; + keyboard.resize(7); + + keyboard[0].push_back("abcdefghijklm"); + keyboard[0].push_back("nopqrstuvwxyz"); + keyboard[0].push_back("0123456789. "); + + keyboard[1].push_back("ABCDEFGHIJKLM"); + keyboard[1].push_back("NOPQRSTUVWXYZ"); + keyboard[1].push_back("_\"'`.,:;!? "); + + + keyboard[2].push_back("¡¿*+-/\\&<=>|"); + keyboard[2].push_back("()[]{}@#$%^~"); + keyboard[2].push_back("_\"'`.,:;!? "); + + + keyboard[3].push_back("àáèéìíòóùúýäõ"); + keyboard[3].push_back("ëïöüÿâêîôûåãñ"); + keyboard[3].push_back("ÄÄěľĺňôřŕšťůž"); + keyboard[3].push_back("ąćęłńśżź "); + + keyboard[4].push_back("ÀÃÈÉÌÃÒÓÙÚÃÄÕ"); + keyboard[4].push_back("ËÃÖÜŸÂÊÎÔÛÅÃÑ"); + keyboard[4].push_back("ČĎĚĽĹŇÔŘŔŠŤŮŽ"); + keyboard[4].push_back("ĄĆĘÅŃŚŻŹ "); + + + keyboard[5].push_back("æçабвгдеёжзий "); + keyboard[5].push_back("клмнопрÑтуфхцч"); + keyboard[5].push_back("шщъыьÑÑŽÑøðßÃÞþ"); + + keyboard[6].push_back("ÆÇÐБВГДЕÐЖЗИЙ "); + keyboard[6].push_back("КЛМÐОПРСТУФХЦЧ"); + keyboard[6].push_back("ШЩЪЫЬЭЮЯØðßÃÞþ"); + + setKeyboard(0); + + ButtonAction actBackspace = MakeDelegate(this, &InputDialog::backspace); + + btnBackspaceX = new IconButton(gmenu2x, "skin:imgs/buttons/x.png"); + btnBackspaceX->setAction(actBackspace); + + btnBackspaceL = new IconButton(gmenu2x, "skin:imgs/buttons/l.png", gmenu2x->tr["Backspace"]); + btnBackspaceL->setAction(actBackspace); + + btnSpace = new IconButton(gmenu2x, "skin:imgs/buttons/r.png", gmenu2x->tr["Space"]); + btnSpace->setAction(MakeDelegate(this, &InputDialog::space)); + + btnConfirm = new IconButton(gmenu2x, "skin:imgs/buttons/b.png", gmenu2x->tr["Confirm"]); + btnConfirm->setAction(MakeDelegate(this, &InputDialog::confirm)); + + btnChangeKeys = new IconButton(gmenu2x, "skin:imgs/buttons/y.png", gmenu2x->tr["Change keys"]); + btnChangeKeys->setAction(MakeDelegate(this, &InputDialog::changeKeys)); +} + +void InputDialog::setKeyboard(int kb) { + kb = constrain(kb,0,keyboard.size()-1); + curKeyboard = kb; + this->kb = &(keyboard[kb]); + kbLength = this->kb->at(0).length(); + for (int x = 0, l = kbLength; xfont->utf8Code(this->kb->at(0)[x])) { + kbLength--; + x++; + } + + kbLeft = 160 - kbLength*KEY_WIDTH/2; + kbWidth = kbLength*KEY_WIDTH+3; + kbHeight = (this->kb->size()+1)*KEY_HEIGHT+3; + + kbRect.x = kbLeft-3; + kbRect.y = KB_TOP-2; + kbRect.w = kbWidth; + kbRect.h = kbHeight; +} + +bool InputDialog::exec() { + SDL_Rect box = {0, 60, 0, gmenu2x->font->getHeight()+4}; + + Uint32 caretTick = 0, curTick; + bool caretOn = true; + + uint action; + close = false; + ok = true; + while (!close) { + gmenu2x->bg->blit(gmenu2x->s,0,0); + gmenu2x->writeTitle(title); + gmenu2x->writeSubTitle(text); + gmenu2x->drawTitleIcon(icon); + + gmenu2x->drawButton(gmenu2x->s, "y", gmenu2x->tr["Change keys"], + gmenu2x->drawButton(gmenu2x->s, "b", gmenu2x->tr["Confirm"], + gmenu2x->drawButton(gmenu2x->s, "r", gmenu2x->tr["Space"], + gmenu2x->drawButton(btnBackspaceL, + gmenu2x->drawButton(btnBackspaceX)-6)))); + + box.w = gmenu2x->font->getTextWidth(input)+18; + box.x = 160-box.w/2; + gmenu2x->s->box(box.x, box.y, box.w, box.h, gmenu2x->skinConfColors["selectionBg"]); + gmenu2x->s->rectangle(box.x, box.y, box.w, box.h, gmenu2x->skinConfColors["selectionBg"]); + + gmenu2x->s->write(gmenu2x->font, input, box.x+5, box.y+box.h-2, SFontHAlignLeft, SFontVAlignBottom); + + curTick = SDL_GetTicks(); + if (curTick-caretTick>=600) { + caretOn = !caretOn; + caretTick = curTick; + } + + if (caretOn) gmenu2x->s->box(box.x+box.w-12, box.y+3, 8, box.h-6, gmenu2x->skinConfColors["selectionBg"]); + + if (gmenu2x->f200) gmenu2x->ts.poll(); + action = drawVirtualKeyboard(); + gmenu2x->s->flip(); + + gmenu2x->input.update(); + if ( gmenu2x->input[ACTION_START] ) action = ID_ACTION_CLOSE; + if ( gmenu2x->input[ACTION_UP ] ) action = ID_ACTION_UP; + if ( gmenu2x->input[ACTION_DOWN ] ) action = ID_ACTION_DOWN; + if ( gmenu2x->input[ACTION_LEFT ] ) action = ID_ACTION_LEFT; + if ( gmenu2x->input[ACTION_RIGHT] ) action = ID_ACTION_RIGHT; + if ( gmenu2x->input[ACTION_B] ) action = ID_ACTION_SELECT; + if ( gmenu2x->input[ACTION_Y] ) action = ID_ACTION_KB_CHANGE; + if ( gmenu2x->input[ACTION_X] || gmenu2x->input[ACTION_L] ) action = ID_ACTION_BACKSPACE; + if ( gmenu2x->input[ACTION_R ] ) action = ID_ACTION_SPACE; + + switch (action) { + case ID_ACTION_CLOSE: { + ok = false; + close = true; + } break; + case ID_ACTION_UP: { + selRow--; + } break; + case ID_ACTION_DOWN: { + selRow++; + if (selRow==(int)kb->size()) selCol = selCol<8 ? 0 : 1; + } break; + case ID_ACTION_LEFT: { + selCol--; + } break; + case ID_ACTION_RIGHT: { + selCol++; + } break; + case ID_ACTION_BACKSPACE: backspace(); break; + case ID_ACTION_SPACE: space(); break; + case ID_ACTION_KB_CHANGE: changeKeys(); break; + case ID_ACTION_SELECT: confirm(); break; + } + } + + return ok; +} + +void InputDialog::backspace() { + // check for utf8 characters + input = input.substr(0,input.length()-( gmenu2x->font->utf8Code(input[input.length()-2]) ? 2 : 1 )); +} + +void InputDialog::space() { + // check for utf8 characters + input += " "; +} + +void InputDialog::confirm() { + if (selRow==(int)kb->size()) { + if (selCol==0) + ok = false; + close = true; + } else { + bool utf8; + int xc=0; + for (uint x=0; xat(selRow).length(); x++) { + utf8 = gmenu2x->font->utf8Code(kb->at(selRow)[x]); + if (xc==selCol) input += kb->at(selRow).substr(x, utf8 ? 2 : 1); + if (utf8) x++; + xc++; + } + } +} + +void InputDialog::changeKeys() { + if (curKeyboard==6) + setKeyboard(0); + else + setKeyboard(curKeyboard+1); +} + +int InputDialog::drawVirtualKeyboard() { + int action = ID_NO_ACTION; + + //keyboard border + gmenu2x->s->rectangle(kbRect, gmenu2x->skinConfColors["selectionBg"]); + + if (selCol<0) selCol = selRow==(int)kb->size() ? 1 : kbLength-1; + if (selCol>=(int)kbLength) selCol = 0; + if (selRow<0) selRow = kb->size()-1; + if (selRow>(int)kb->size()) selRow = 0; + + //selection + if (selRow<(int)kb->size()) + gmenu2x->s->box(kbLeft+selCol*KEY_WIDTH-1, KB_TOP+selRow*KEY_HEIGHT, KEY_WIDTH-1, KEY_HEIGHT-2, gmenu2x->skinConfColors["selectionBg"]); + else { + if (selCol>1) selCol = 0; + if (selCol<0) selCol = 1; + gmenu2x->s->box(kbLeft+selCol*kbLength*KEY_WIDTH/2-1, KB_TOP+kb->size()*KEY_HEIGHT, kbLength*KEY_WIDTH/2-1, KEY_HEIGHT-1, gmenu2x->skinConfColors["selectionBg"]); + } + + //keys + for (uint l=0; lsize(); l++) { + string line = kb->at(l); + for (uint x=0, xc=0; xfont->utf8Code(line[x])) { + charX = line.substr(x,2); + x++; + } else + charX = line[x]; + + SDL_Rect re = {kbLeft+xc*KEY_WIDTH-1, KB_TOP+l*KEY_HEIGHT, KEY_WIDTH-1, KEY_HEIGHT-2}; + + //if ts on rect, change selection + if (gmenu2x->f200 && gmenu2x->ts.pressed() && gmenu2x->ts.inRect(re)) { + selCol = xc; + selRow = l; + } + + gmenu2x->s->rectangle(re, gmenu2x->skinConfColors["selectionBg"]); + gmenu2x->s->write(gmenu2x->font, charX, kbLeft+xc*KEY_WIDTH+KEY_WIDTH/2-1, KB_TOP+l*KEY_HEIGHT+KEY_HEIGHT/2, SFontHAlignCenter, SFontVAlignMiddle); + xc++; + } + } + + //Ok/Cancel + SDL_Rect re = {kbLeft-1, KB_TOP+kb->size()*KEY_HEIGHT, kbLength*KEY_WIDTH/2-1, KEY_HEIGHT-1}; + gmenu2x->s->rectangle(re, gmenu2x->skinConfColors["selectionBg"]); + if (gmenu2x->f200 && gmenu2x->ts.pressed() && gmenu2x->ts.inRect(re)) { + selCol = 0; + selRow = kb->size(); + } + gmenu2x->s->write(gmenu2x->font, gmenu2x->tr["Cancel"], (int)(160-kbLength*KEY_WIDTH/4), KB_TOP+kb->size()*KEY_HEIGHT+KEY_HEIGHT/2, SFontHAlignCenter, SFontVAlignMiddle); + + re.x = kbLeft+kbLength*KEY_WIDTH/2-1; + gmenu2x->s->rectangle(re, gmenu2x->skinConfColors["selectionBg"]); + if (gmenu2x->f200 && gmenu2x->ts.pressed() && gmenu2x->ts.inRect(re)) { + selCol = 1; + selRow = kb->size(); + } + gmenu2x->s->write(gmenu2x->font, gmenu2x->tr["OK"], (int)(160+kbLength*KEY_WIDTH/4), KB_TOP+kb->size()*KEY_HEIGHT+KEY_HEIGHT/2, SFontHAlignCenter, SFontVAlignMiddle); + + //if ts released + if (gmenu2x->f200 && gmenu2x->ts.wasPressed && !gmenu2x->ts.pressed() && gmenu2x->ts.inRect(kbRect)) + action = ID_ACTION_SELECT; + + return action; +} diff --git a/src/inputdialog.h b/src/inputdialog.h new file mode 100644 index 0000000..2cdb060 --- /dev/null +++ b/src/inputdialog.h @@ -0,0 +1,76 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef INPUTDIALOG_H_ +#define INPUTDIALOG_H_ + +#define KEY_WIDTH 20 +#define KEY_HEIGHT 20 +#define KB_TOP 90 + +#define ID_NO_ACTION 0 +#define ID_ACTION_CLOSE 1 +#define ID_ACTION_UP 2 +#define ID_ACTION_DOWN 3 +#define ID_ACTION_LEFT 4 +#define ID_ACTION_RIGHT 5 +#define ID_ACTION_BACKSPACE 6 +#define ID_ACTION_SPACE 7 +#define ID_ACTION_GOUP 8 +#define ID_ACTION_SELECT 9 +#define ID_ACTION_KB_CHANGE 10 + +#include +#include "gmenu2x.h" + +using std::string; +using std::vector; + +typedef vector stringlist; + +class InputDialog { +private: + int selRow, selCol; + bool close, ok; + string title, text, icon; + GMenu2X *gmenu2x; + short curKeyboard; + vector keyboard; + stringlist *kb; + int kbLength, kbWidth, kbHeight, kbLeft; + SDL_Rect kbRect; + IconButton *btnBackspaceX, *btnBackspaceL, *btnSpace, *btnConfirm, *btnChangeKeys; + + void backspace(); + void space(); + void confirm(); + void changeKeys(); + + int drawVirtualKeyboard(); + void setKeyboard(int); + +public: + InputDialog(GMenu2X *gmenu2x, string text, string startvalue="", string title="", string icon=""); + + string input; + bool exec(); +}; + +#endif /*INPUTDIALOG_H_*/ diff --git a/src/inputmanager.cpp b/src/inputmanager.cpp new file mode 100644 index 0000000..93e2529 --- /dev/null +++ b/src/inputmanager.cpp @@ -0,0 +1,198 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include "inputmanager.h" +#include "utilities.h" + +using namespace std; + +InputManager::InputManager() {} + +InputManager::~InputManager() { + for (uint x=0; x values; + + while (getline(inf, line, '\n')) { + pos = line.find("="); + name = trim(line.substr(0,pos)); + value = trim(line.substr(pos+1,line.length())); + int action = -1; + + if (name=="up") action = ACTION_UP; + else if (name=="down") action = ACTION_DOWN; + else if (name=="left") action = ACTION_LEFT; + else if (name=="right") action = ACTION_RIGHT; + else if (name=="a") action = ACTION_A; + else if (name=="b") action = ACTION_B; + else if (name=="x") action = ACTION_X; + else if (name=="y") action = ACTION_Y; + else if (name=="l") action = ACTION_L; + else if (name=="r") action = ACTION_R; + else if (name=="start") action = ACTION_START; + else if (name=="select") action = ACTION_SELECT; + else if (name=="volup") action = ACTION_VOLUP; + else if (name=="voldown") action = ACTION_VOLDOWN; + + if (action >= 0) { + split(values, value, ","); + if (values.size() >= 2) { + + if (values[0] == "joystickbutton" && values.size()==3) { + InputMap map; + map.type = InputManager::MAPPING_TYPE_BUTTON; + map.num = atoi(values[1].c_str()); + map.value = atoi(values[2].c_str()); + map.treshold = 0; + mappings[action].push_back(map); + } else if (values[0] == "joystickaxys" && values.size()==4) { + InputMap map; + map.type = InputManager::MAPPING_TYPE_AXYS; + map.num = atoi(values[1].c_str()); + map.value = atoi(values[2].c_str()); + map.treshold = atoi(values[3].c_str()); + mappings[action].push_back(map); + } else if (values[0] == "keyboard") { + InputMap map; + map.type = InputManager::MAPPING_TYPE_KEYPRESS; + map.value = atoi(values[1].c_str()); + mappings[action].push_back(map); + } + + } + } + } + inf.close(); + } + } +} + +void InputManager::setActionsCount(int count) { + actions.clear(); + actionTick.clear(); + interval.clear(); + for (int x=0; xinterval[x]) { + actions[x] = true; + actionTick[x] = tick; + } + } else { + actionTick[x] = 0; + } + } +} + +int InputManager::count() { + return actions.size(); +} + +void InputManager::setInterval(int ms, int action) { + if (action<0) + for (uint x=0; x=actions.size()) return false; + return actions[action]; +} + +bool InputManager::isActive(int action) { + for (uint x=0; x0 && axyspos > map.treshold) return true; + } + break; + case InputManager::MAPPING_TYPE_KEYPRESS: + for (uint ex=0; ex +#include +#include +#include + +using std::vector; +using std::string; + +typedef struct { + int type; + uint num; + int value; + int treshold; +} InputMap; + +typedef vector MappingList; +typedef vector SDLEventList; + +/** +Manages all input peripherals +@author Massimiliano Torromeo +*/ +class InputManager { +private: + InputMap getInputMapping(int action); + vector actionTick; + vector interval; + SDLEventList events; + +public: + static const int MAPPING_TYPE_UNDEFINED = -1; + static const int MAPPING_TYPE_BUTTON = 0; + static const int MAPPING_TYPE_AXYS = 1; + static const int MAPPING_TYPE_KEYPRESS = 2; + + InputManager(); + ~InputManager(); + void init(string conffile = "input.conf"); + + vector joysticks; + vector actions; + vector mappings; + + void update(); + int count(); + void setActionsCount(int count); + void setInterval(int ms, int action = -1); + bool operator[](int action); + bool isActive(int action); +}; + +#endif diff --git a/src/jz4740.h b/src/jz4740.h new file mode 100644 index 0000000..1ca84d3 --- /dev/null +++ b/src/jz4740.h @@ -0,0 +1,5212 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2008 by Maurus Cuelenaere + * Copyright (C) 2006-2007 by Ingenic Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +/* + * linux/include/asm-mips/mach-jz4740/jz4740.h + * + * JZ4740 common definition. + * + * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. + * + * Author: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Include file for Ingenic Semiconductor's JZ4740 CPU. + */ +#ifndef __JZ4740_H__ +#define __JZ4740_H__ + +#ifndef __ASSEMBLY__ + +#define REG8(addr) (*(volatile unsigned char *)(addr)) +#define REG16(addr) (*(volatile unsigned short *)(addr)) +#define REG32(addr) (*(volatile unsigned int *)(addr)) + +#endif /* !ASSEMBLY */ + +/************************************************************************* + * Boot ROM Specification + */ + +/* NOR Boot config */ +#define JZ4740_NORBOOT_8BIT 0x00000000 /* 8-bit data bus flash */ +#define JZ4740_NORBOOT_16BIT 0x10101010 /* 16-bit data bus flash */ +#define JZ4740_NORBOOT_32BIT 0x20202020 /* 32-bit data bus flash */ + +/* NAND Boot config */ +#define JZ4740_NANDBOOT_B8R3 0xffffffff /* 8-bit bus & 3 row cycles */ +#define JZ4740_NANDBOOT_B8R2 0xf0f0f0f0 /* 8-bit bus & 2 row cycles */ +#define JZ4740_NANDBOOT_B16R3 0x0f0f0f0f /* 16-bit bus & 3 row cycles */ +#define JZ4740_NANDBOOT_B16R2 0x00000000 /* 16-bit bus & 2 row cycles */ + + +/************************************************************************* + * Register Definitions + */ +#define CPM_BASE 0xB0000000 +#define INTC_BASE 0xB0001000 +#define TCU_BASE 0xB0002000 +#define WDT_BASE 0xB0002000 +#define RTC_BASE 0xB0003000 +#define GPIO_BASE 0xB0010000 +#define AIC_BASE 0xB0020000 +#define ICDC_BASE 0xB0020000 +#define MSC_BASE 0xB0021000 +#define UART0_BASE 0xB0030000 +#define I2C_BASE 0xB0042000 +#define SSI_BASE 0xB0043000 +#define SADC_BASE 0xB0070000 +#define EMC_BASE 0xB3010000 +#define DMAC_BASE 0xB3020000 +#define UHC_BASE 0xB3030000 +#define UDC_BASE 0xB3040000 +#define LCD_BASE 0xB3050000 +#define SLCD_BASE 0xB3050000 +#define CIM_BASE 0xB3060000 +#define ETH_BASE 0xB3100000 + + +/************************************************************************* + * INTC (Interrupt Controller) + *************************************************************************/ +#define INTC_ISR (INTC_BASE + 0x00) +#define INTC_IMR (INTC_BASE + 0x04) +#define INTC_IMSR (INTC_BASE + 0x08) +#define INTC_IMCR (INTC_BASE + 0x0c) +#define INTC_IPR (INTC_BASE + 0x10) + +#define REG_INTC_ISR REG32(INTC_ISR) +#define REG_INTC_IMR REG32(INTC_IMR) +#define REG_INTC_IMSR REG32(INTC_IMSR) +#define REG_INTC_IMCR REG32(INTC_IMCR) +#define REG_INTC_IPR REG32(INTC_IPR) + +// 1st-level interrupts +#define IRQ_I2C 1 +#define IRQ_EMC 2 +#define IRQ_UHC 3 +#define IRQ_UART0 9 +#define IRQ_SADC 12 +#define IRQ_MSC 14 +#define IRQ_RTC 15 +#define IRQ_SSI 16 +#define IRQ_CIM 17 +#define IRQ_AIC 18 +#define IRQ_ETH 19 +#define IRQ_DMAC 20 +#define IRQ_TCU2 21 +#define IRQ_TCU1 22 +#define IRQ_TCU0 23 +#define IRQ_UDC 24 +#define IRQ_GPIO3 25 +#define IRQ_GPIO2 26 +#define IRQ_GPIO1 27 +#define IRQ_GPIO0 28 +#define IRQ_IPU 29 +#define IRQ_LCD 30 + +// 2nd-level interrupts +#define IRQ_DMA_0 32 /* 32 to 37 for DMAC channel 0 to 5 */ +#define IRQ_GPIO_0 48 /* 48 to 175 for GPIO pin 0 to 127 */ + + +/************************************************************************* + * RTC + *************************************************************************/ +#define RTC_RCR (RTC_BASE + 0x00) /* RTC Control Register */ +#define RTC_RSR (RTC_BASE + 0x04) /* RTC Second Register */ +#define RTC_RSAR (RTC_BASE + 0x08) /* RTC Second Alarm Register */ +#define RTC_RGR (RTC_BASE + 0x0c) /* RTC Regulator Register */ + +#define RTC_HCR (RTC_BASE + 0x20) /* Hibernate Control Register */ +#define RTC_HWFCR (RTC_BASE + 0x24) /* Hibernate Wakeup Filter Counter Reg */ +#define RTC_HRCR (RTC_BASE + 0x28) /* Hibernate Reset Counter Register */ +#define RTC_HWCR (RTC_BASE + 0x2c) /* Hibernate Wakeup Control Register */ +#define RTC_HWRSR (RTC_BASE + 0x30) /* Hibernate Wakeup Status Register */ +#define RTC_HSPR (RTC_BASE + 0x34) /* Hibernate Scratch Pattern Register */ + +#define REG_RTC_RCR REG32(RTC_RCR) +#define REG_RTC_RSR REG32(RTC_RSR) +#define REG_RTC_RSAR REG32(RTC_RSAR) +#define REG_RTC_RGR REG32(RTC_RGR) +#define REG_RTC_HCR REG32(RTC_HCR) +#define REG_RTC_HWFCR REG32(RTC_HWFCR) +#define REG_RTC_HRCR REG32(RTC_HRCR) +#define REG_RTC_HWCR REG32(RTC_HWCR) +#define REG_RTC_HWRSR REG32(RTC_HWRSR) +#define REG_RTC_HSPR REG32(RTC_HSPR) + +/* RTC Control Register */ +#define RTC_RCR_WRDY (1 << 7) /* Write Ready Flag */ +#define RTC_RCR_HZ (1 << 6) /* 1Hz Flag */ +#define RTC_RCR_HZIE (1 << 5) /* 1Hz Interrupt Enable */ +#define RTC_RCR_AF (1 << 4) /* Alarm Flag */ +#define RTC_RCR_AF_BIT 4 /* Alarm Flag */ +#define RTC_RCR_AIE (1 << 3) /* Alarm Interrupt Enable */ +#define RTC_RCR_AE (1 << 2) /* Alarm Enable */ +#define RTC_RCR_RTCE (1 << 0) /* RTC Enable */ + +/* RTC Regulator Register */ +#define RTC_RGR_LOCK (1 << 31) /* Lock Bit */ +#define RTC_RGR_ADJC_BIT 16 +#define RTC_RGR_ADJC_MASK (0x3ff << RTC_RGR_ADJC_BIT) +#define RTC_RGR_NC1HZ_BIT 0 +#define RTC_RGR_NC1HZ_MASK (0xffff << RTC_RGR_NC1HZ_BIT) + +/* Hibernate Control Register */ +#define RTC_HCR_PD (1 << 0) /* Power Down */ + +/* Hibernate Wakeup Filter Counter Register */ +#define RTC_HWFCR_BIT 5 +#define RTC_HWFCR_MASK (0x7ff << RTC_HWFCR_BIT) + +/* Hibernate Reset Counter Register */ +#define RTC_HRCR_BIT 5 +#define RTC_HRCR_MASK (0x7f << RTC_HRCR_BIT) + +/* Hibernate Wakeup Control Register */ +#define RTC_HWCR_EALM (1 << 0) /* RTC alarm wakeup enable */ + +/* Hibernate Wakeup Status Register */ +#define RTC_HWRSR_HR (1 << 5) /* Hibernate reset */ +#define RTC_HWRSR_PPR (1 << 4) /* PPR reset */ +#define RTC_HWRSR_PIN (1 << 1) /* Wakeup pin status bit */ +#define RTC_HWRSR_ALM (1 << 0) /* RTC alarm status bit */ + + +/************************************************************************* + * CPM (Clock reset and Power control Management) + *************************************************************************/ +#define CPM_CPCCR (CPM_BASE+0x00) +#define CPM_CPPCR (CPM_BASE+0x10) +#define CPM_I2SCDR (CPM_BASE+0x60) +#define CPM_LPCDR (CPM_BASE+0x64) +#define CPM_MSCCDR (CPM_BASE+0x68) +#define CPM_UHCCDR (CPM_BASE+0x6C) + +#define CPM_LCR (CPM_BASE+0x04) +#define CPM_CLKGR (CPM_BASE+0x20) +#define CPM_SCR (CPM_BASE+0x24) + +#define CPM_HCR (CPM_BASE+0x30) +#define CPM_HWFCR (CPM_BASE+0x34) +#define CPM_HRCR (CPM_BASE+0x38) +#define CPM_HWCR (CPM_BASE+0x3c) +#define CPM_HWSR (CPM_BASE+0x40) +#define CPM_HSPR (CPM_BASE+0x44) + +#define CPM_RSR (CPM_BASE+0x08) + + +#define REG_CPM_CPCCR REG32(CPM_CPCCR) +#define REG_CPM_CPPCR REG32(CPM_CPPCR) +#define REG_CPM_I2SCDR REG32(CPM_I2SCDR) +#define REG_CPM_LPCDR REG32(CPM_LPCDR) +#define REG_CPM_MSCCDR REG32(CPM_MSCCDR) +#define REG_CPM_UHCCDR REG32(CPM_UHCCDR) + +#define REG_CPM_LCR REG32(CPM_LCR) +#define REG_CPM_CLKGR REG32(CPM_CLKGR) +#define REG_CPM_SCR REG32(CPM_SCR) +#define REG_CPM_HCR REG32(CPM_HCR) +#define REG_CPM_HWFCR REG32(CPM_HWFCR) +#define REG_CPM_HRCR REG32(CPM_HRCR) +#define REG_CPM_HWCR REG32(CPM_HWCR) +#define REG_CPM_HWSR REG32(CPM_HWSR) +#define REG_CPM_HSPR REG32(CPM_HSPR) + +#define REG_CPM_RSR REG32(CPM_RSR) + + +/* Clock Control Register */ +#define CPM_CPCCR_I2CS (1 << 31) +#define CPM_CPCCR_CLKOEN (1 << 30) +#define CPM_CPCCR_UCS (1 << 29) +#define CPM_CPCCR_UDIV_BIT 23 +#define CPM_CPCCR_UDIV_MASK (0x3f << CPM_CPCCR_UDIV_BIT) +#define CPM_CPCCR_CE (1 << 22) +#define CPM_CPCCR_PCS (1 << 21) +#define CPM_CPCCR_LDIV_BIT 16 +#define CPM_CPCCR_LDIV_MASK (0x1f << CPM_CPCCR_LDIV_BIT) +#define CPM_CPCCR_MDIV_BIT 12 +#define CPM_CPCCR_MDIV_MASK (0x0f << CPM_CPCCR_MDIV_BIT) +#define CPM_CPCCR_PDIV_BIT 8 +#define CPM_CPCCR_PDIV_MASK (0x0f << CPM_CPCCR_PDIV_BIT) +#define CPM_CPCCR_HDIV_BIT 4 +#define CPM_CPCCR_HDIV_MASK (0x0f << CPM_CPCCR_HDIV_BIT) +#define CPM_CPCCR_CDIV_BIT 0 +#define CPM_CPCCR_CDIV_MASK (0x0f << CPM_CPCCR_CDIV_BIT) + +/* I2S Clock Divider Register */ +#define CPM_I2SCDR_I2SDIV_BIT 0 +#define CPM_I2SCDR_I2SDIV_MASK (0x1ff << CPM_I2SCDR_I2SDIV_BIT) + +/* LCD Pixel Clock Divider Register */ +#define CPM_LPCDR_PIXDIV_BIT 0 +#define CPM_LPCDR_PIXDIV_MASK (0x1ff << CPM_LPCDR_PIXDIV_BIT) + +/* MSC Clock Divider Register */ +#define CPM_MSCCDR_MSCDIV_BIT 0 +#define CPM_MSCCDR_MSCDIV_MASK (0x1f << CPM_MSCCDR_MSCDIV_BIT) + +/* PLL Control Register */ +#define CPM_CPPCR_PLLM_BIT 23 +#define CPM_CPPCR_PLLM_MASK (0x1ff << CPM_CPPCR_PLLM_BIT) +#define CPM_CPPCR_PLLN_BIT 18 +#define CPM_CPPCR_PLLN_MASK (0x1f << CPM_CPPCR_PLLN_BIT) +#define CPM_CPPCR_PLLOD_BIT 16 +#define CPM_CPPCR_PLLOD_MASK (0x03 << CPM_CPPCR_PLLOD_BIT) +#define CPM_CPPCR_PLLS (1 << 10) +#define CPM_CPPCR_PLLBP (1 << 9) +#define CPM_CPPCR_PLLEN (1 << 8) +#define CPM_CPPCR_PLLST_BIT 0 +#define CPM_CPPCR_PLLST_MASK (0xff << CPM_CPPCR_PLLST_BIT) + +/* Low Power Control Register */ +#define CPM_LCR_DOZE_DUTY_BIT 3 +#define CPM_LCR_DOZE_DUTY_MASK (0x1f << CPM_LCR_DOZE_DUTY_BIT) +#define CPM_LCR_DOZE_ON (1 << 2) +#define CPM_LCR_LPM_BIT 0 +#define CPM_LCR_LPM_MASK (0x3 << CPM_LCR_LPM_BIT) + #define CPM_LCR_LPM_IDLE (0x0 << CPM_LCR_LPM_BIT) + #define CPM_LCR_LPM_SLEEP (0x1 << CPM_LCR_LPM_BIT) + +/* Clock Gate Register */ +#define CPM_CLKGR_UART1 (1 << 15) +#define CPM_CLKGR_UHC (1 << 14) +#define CPM_CLKGR_IPU (1 << 13) +#define CPM_CLKGR_DMAC (1 << 12) +#define CPM_CLKGR_UDC (1 << 11) +#define CPM_CLKGR_LCD (1 << 10) +#define CPM_CLKGR_CIM (1 << 9) +#define CPM_CLKGR_SADC (1 << 8) +#define CPM_CLKGR_MSC (1 << 7) +#define CPM_CLKGR_AIC1 (1 << 6) +#define CPM_CLKGR_AIC2 (1 << 5) +#define CPM_CLKGR_SSI (1 << 4) +#define CPM_CLKGR_I2C (1 << 3) +#define CPM_CLKGR_RTC (1 << 2) +#define CPM_CLKGR_TCU (1 << 1) +#define CPM_CLKGR_UART0 (1 << 0) + +/* Sleep Control Register */ +#define CPM_SCR_O1ST_BIT 8 +#define CPM_SCR_O1ST_MASK (0xff << CPM_SCR_O1ST_BIT) +#define CPM_SCR_USBHOST_SUSPEND (1 << 7) +#define CPM_SCR_USBPHY_ENABLE (1 << 6) +#define CPM_SCR_OSC_ENABLE (1 << 4) + +/* Hibernate Control Register */ +#define CPM_HCR_PD (1 << 0) + +/* Wakeup Filter Counter Register in Hibernate Mode */ +#define CPM_HWFCR_TIME_BIT 0 +#define CPM_HWFCR_TIME_MASK (0x3ff << CPM_HWFCR_TIME_BIT) + +/* Reset Counter Register in Hibernate Mode */ +#define CPM_HRCR_TIME_BIT 0 +#define CPM_HRCR_TIME_MASK (0x7f << CPM_HRCR_TIME_BIT) + +/* Wakeup Control Register in Hibernate Mode */ +#define CPM_HWCR_WLE_LOW (0 << 2) +#define CPM_HWCR_WLE_HIGH (1 << 2) +#define CPM_HWCR_PIN_WAKEUP (1 << 1) +#define CPM_HWCR_RTC_WAKEUP (1 << 0) + +/* Wakeup Status Register in Hibernate Mode */ +#define CPM_HWSR_WSR_PIN (1 << 1) +#define CPM_HWSR_WSR_RTC (1 << 0) + +/* Reset Status Register */ +#define CPM_RSR_HR (1 << 2) +#define CPM_RSR_WR (1 << 1) +#define CPM_RSR_PR (1 << 0) + + +/************************************************************************* + * TCU (Timer Counter Unit) + *************************************************************************/ +#define TCU_TSR (TCU_BASE + 0x1C) /* Timer Stop Register */ +#define TCU_TSSR (TCU_BASE + 0x2C) /* Timer Stop Set Register */ +#define TCU_TSCR (TCU_BASE + 0x3C) /* Timer Stop Clear Register */ +#define TCU_TER (TCU_BASE + 0x10) /* Timer Counter Enable Register */ +#define TCU_TESR (TCU_BASE + 0x14) /* Timer Counter Enable Set Register */ +#define TCU_TECR (TCU_BASE + 0x18) /* Timer Counter Enable Clear Register */ +#define TCU_TFR (TCU_BASE + 0x20) /* Timer Flag Register */ +#define TCU_TFSR (TCU_BASE + 0x24) /* Timer Flag Set Register */ +#define TCU_TFCR (TCU_BASE + 0x28) /* Timer Flag Clear Register */ +#define TCU_TMR (TCU_BASE + 0x30) /* Timer Mask Register */ +#define TCU_TMSR (TCU_BASE + 0x34) /* Timer Mask Set Register */ +#define TCU_TMCR (TCU_BASE + 0x38) /* Timer Mask Clear Register */ +#define TCU_TDFR0 (TCU_BASE + 0x40) /* Timer Data Full Register */ +#define TCU_TDHR0 (TCU_BASE + 0x44) /* Timer Data Half Register */ +#define TCU_TCNT0 (TCU_BASE + 0x48) /* Timer Counter Register */ +#define TCU_TCSR0 (TCU_BASE + 0x4C) /* Timer Control Register */ +#define TCU_TDFR1 (TCU_BASE + 0x50) +#define TCU_TDHR1 (TCU_BASE + 0x54) +#define TCU_TCNT1 (TCU_BASE + 0x58) +#define TCU_TCSR1 (TCU_BASE + 0x5C) +#define TCU_TDFR2 (TCU_BASE + 0x60) +#define TCU_TDHR2 (TCU_BASE + 0x64) +#define TCU_TCNT2 (TCU_BASE + 0x68) +#define TCU_TCSR2 (TCU_BASE + 0x6C) +#define TCU_TDFR3 (TCU_BASE + 0x70) +#define TCU_TDHR3 (TCU_BASE + 0x74) +#define TCU_TCNT3 (TCU_BASE + 0x78) +#define TCU_TCSR3 (TCU_BASE + 0x7C) +#define TCU_TDFR4 (TCU_BASE + 0x80) +#define TCU_TDHR4 (TCU_BASE + 0x84) +#define TCU_TCNT4 (TCU_BASE + 0x88) +#define TCU_TCSR4 (TCU_BASE + 0x8C) +#define TCU_TDFR5 (TCU_BASE + 0x90) +#define TCU_TDHR5 (TCU_BASE + 0x94) +#define TCU_TCNT5 (TCU_BASE + 0x98) +#define TCU_TCSR5 (TCU_BASE + 0x9C) + +#define REG_TCU_TSR REG32(TCU_TSR) +#define REG_TCU_TSSR REG32(TCU_TSSR) +#define REG_TCU_TSCR REG32(TCU_TSCR) +#define REG_TCU_TER REG8(TCU_TER) +#define REG_TCU_TESR REG8(TCU_TESR) +#define REG_TCU_TECR REG8(TCU_TECR) +#define REG_TCU_TFR REG32(TCU_TFR) +#define REG_TCU_TFSR REG32(TCU_TFSR) +#define REG_TCU_TFCR REG32(TCU_TFCR) +#define REG_TCU_TMR REG32(TCU_TMR) +#define REG_TCU_TMSR REG32(TCU_TMSR) +#define REG_TCU_TMCR REG32(TCU_TMCR) +#define REG_TCU_TDFR0 REG16(TCU_TDFR0) +#define REG_TCU_TDHR0 REG16(TCU_TDHR0) +#define REG_TCU_TCNT0 REG16(TCU_TCNT0) +#define REG_TCU_TCSR0 REG16(TCU_TCSR0) +#define REG_TCU_TDFR1 REG16(TCU_TDFR1) +#define REG_TCU_TDHR1 REG16(TCU_TDHR1) +#define REG_TCU_TCNT1 REG16(TCU_TCNT1) +#define REG_TCU_TCSR1 REG16(TCU_TCSR1) +#define REG_TCU_TDFR2 REG16(TCU_TDFR2) +#define REG_TCU_TDHR2 REG16(TCU_TDHR2) +#define REG_TCU_TCNT2 REG16(TCU_TCNT2) +#define REG_TCU_TCSR2 REG16(TCU_TCSR2) +#define REG_TCU_TDFR3 REG16(TCU_TDFR3) +#define REG_TCU_TDHR3 REG16(TCU_TDHR3) +#define REG_TCU_TCNT3 REG16(TCU_TCNT3) +#define REG_TCU_TCSR3 REG16(TCU_TCSR3) +#define REG_TCU_TDFR4 REG16(TCU_TDFR4) +#define REG_TCU_TDHR4 REG16(TCU_TDHR4) +#define REG_TCU_TCNT4 REG16(TCU_TCNT4) +#define REG_TCU_TCSR4 REG16(TCU_TCSR4) + +// n = 0,1,2,3,4,5,6,7 +#define TCU_TDFR(n) (TCU_BASE + (0x40 + (n)*0x10)) /* Timer Data Full Reg */ +#define TCU_TDHR(n) (TCU_BASE + (0x44 + (n)*0x10)) /* Timer Data Half Reg */ +#define TCU_TCNT(n) (TCU_BASE + (0x48 + (n)*0x10)) /* Timer Counter Reg */ +#define TCU_TCSR(n) (TCU_BASE + (0x4C + (n)*0x10)) /* Timer Control Reg */ + +#define REG_TCU_TDFR(n) REG16(TCU_TDFR((n))) +#define REG_TCU_TDHR(n) REG16(TCU_TDHR((n))) +#define REG_TCU_TCNT(n) REG16(TCU_TCNT((n))) +#define REG_TCU_TCSR(n) REG16(TCU_TCSR((n))) + +// Register definitions +#define TCU_TCSR_PWM_SD (1 << 9) +#define TCU_TCSR_PWM_INITL_HIGH (1 << 8) +#define TCU_TCSR_PWM_EN (1 << 7) +#define TCU_TCSR_PRESCALE_BIT 3 +#define TCU_TCSR_PRESCALE_MASK (0x7 << TCU_TCSR_PRESCALE_BIT) + #define TCU_TCSR_PRESCALE1 (0x0 << TCU_TCSR_PRESCALE_BIT) + #define TCU_TCSR_PRESCALE4 (0x1 << TCU_TCSR_PRESCALE_BIT) + #define TCU_TCSR_PRESCALE16 (0x2 << TCU_TCSR_PRESCALE_BIT) + #define TCU_TCSR_PRESCALE64 (0x3 << TCU_TCSR_PRESCALE_BIT) + #define TCU_TCSR_PRESCALE256 (0x4 << TCU_TCSR_PRESCALE_BIT) + #define TCU_TCSR_PRESCALE1024 (0x5 << TCU_TCSR_PRESCALE_BIT) +#define TCU_TCSR_EXT_EN (1 << 2) +#define TCU_TCSR_RTC_EN (1 << 1) +#define TCU_TCSR_PCK_EN (1 << 0) + +#define TCU_TER_TCEN5 (1 << 5) +#define TCU_TER_TCEN4 (1 << 4) +#define TCU_TER_TCEN3 (1 << 3) +#define TCU_TER_TCEN2 (1 << 2) +#define TCU_TER_TCEN1 (1 << 1) +#define TCU_TER_TCEN0 (1 << 0) + +#define TCU_TESR_TCST5 (1 << 5) +#define TCU_TESR_TCST4 (1 << 4) +#define TCU_TESR_TCST3 (1 << 3) +#define TCU_TESR_TCST2 (1 << 2) +#define TCU_TESR_TCST1 (1 << 1) +#define TCU_TESR_TCST0 (1 << 0) + +#define TCU_TECR_TCCL5 (1 << 5) +#define TCU_TECR_TCCL4 (1 << 4) +#define TCU_TECR_TCCL3 (1 << 3) +#define TCU_TECR_TCCL2 (1 << 2) +#define TCU_TECR_TCCL1 (1 << 1) +#define TCU_TECR_TCCL0 (1 << 0) + +#define TCU_TFR_HFLAG5 (1 << 21) +#define TCU_TFR_HFLAG4 (1 << 20) +#define TCU_TFR_HFLAG3 (1 << 19) +#define TCU_TFR_HFLAG2 (1 << 18) +#define TCU_TFR_HFLAG1 (1 << 17) +#define TCU_TFR_HFLAG0 (1 << 16) +#define TCU_TFR_FFLAG5 (1 << 5) +#define TCU_TFR_FFLAG4 (1 << 4) +#define TCU_TFR_FFLAG3 (1 << 3) +#define TCU_TFR_FFLAG2 (1 << 2) +#define TCU_TFR_FFLAG1 (1 << 1) +#define TCU_TFR_FFLAG0 (1 << 0) + +#define TCU_TFSR_HFLAG5 (1 << 21) +#define TCU_TFSR_HFLAG4 (1 << 20) +#define TCU_TFSR_HFLAG3 (1 << 19) +#define TCU_TFSR_HFLAG2 (1 << 18) +#define TCU_TFSR_HFLAG1 (1 << 17) +#define TCU_TFSR_HFLAG0 (1 << 16) +#define TCU_TFSR_FFLAG5 (1 << 5) +#define TCU_TFSR_FFLAG4 (1 << 4) +#define TCU_TFSR_FFLAG3 (1 << 3) +#define TCU_TFSR_FFLAG2 (1 << 2) +#define TCU_TFSR_FFLAG1 (1 << 1) +#define TCU_TFSR_FFLAG0 (1 << 0) + +#define TCU_TFCR_HFLAG5 (1 << 21) +#define TCU_TFCR_HFLAG4 (1 << 20) +#define TCU_TFCR_HFLAG3 (1 << 19) +#define TCU_TFCR_HFLAG2 (1 << 18) +#define TCU_TFCR_HFLAG1 (1 << 17) +#define TCU_TFCR_HFLAG0 (1 << 16) +#define TCU_TFCR_FFLAG5 (1 << 5) +#define TCU_TFCR_FFLAG4 (1 << 4) +#define TCU_TFCR_FFLAG3 (1 << 3) +#define TCU_TFCR_FFLAG2 (1 << 2) +#define TCU_TFCR_FFLAG1 (1 << 1) +#define TCU_TFCR_FFLAG0 (1 << 0) + +#define TCU_TMR_HMASK5 (1 << 21) +#define TCU_TMR_HMASK4 (1 << 20) +#define TCU_TMR_HMASK3 (1 << 19) +#define TCU_TMR_HMASK2 (1 << 18) +#define TCU_TMR_HMASK1 (1 << 17) +#define TCU_TMR_HMASK0 (1 << 16) +#define TCU_TMR_FMASK5 (1 << 5) +#define TCU_TMR_FMASK4 (1 << 4) +#define TCU_TMR_FMASK3 (1 << 3) +#define TCU_TMR_FMASK2 (1 << 2) +#define TCU_TMR_FMASK1 (1 << 1) +#define TCU_TMR_FMASK0 (1 << 0) + +#define TCU_TMSR_HMST5 (1 << 21) +#define TCU_TMSR_HMST4 (1 << 20) +#define TCU_TMSR_HMST3 (1 << 19) +#define TCU_TMSR_HMST2 (1 << 18) +#define TCU_TMSR_HMST1 (1 << 17) +#define TCU_TMSR_HMST0 (1 << 16) +#define TCU_TMSR_FMST5 (1 << 5) +#define TCU_TMSR_FMST4 (1 << 4) +#define TCU_TMSR_FMST3 (1 << 3) +#define TCU_TMSR_FMST2 (1 << 2) +#define TCU_TMSR_FMST1 (1 << 1) +#define TCU_TMSR_FMST0 (1 << 0) + +#define TCU_TMCR_HMCL5 (1 << 21) +#define TCU_TMCR_HMCL4 (1 << 20) +#define TCU_TMCR_HMCL3 (1 << 19) +#define TCU_TMCR_HMCL2 (1 << 18) +#define TCU_TMCR_HMCL1 (1 << 17) +#define TCU_TMCR_HMCL0 (1 << 16) +#define TCU_TMCR_FMCL5 (1 << 5) +#define TCU_TMCR_FMCL4 (1 << 4) +#define TCU_TMCR_FMCL3 (1 << 3) +#define TCU_TMCR_FMCL2 (1 << 2) +#define TCU_TMCR_FMCL1 (1 << 1) +#define TCU_TMCR_FMCL0 (1 << 0) + +#define TCU_TSR_WDTS (1 << 16) +#define TCU_TSR_STOP5 (1 << 5) +#define TCU_TSR_STOP4 (1 << 4) +#define TCU_TSR_STOP3 (1 << 3) +#define TCU_TSR_STOP2 (1 << 2) +#define TCU_TSR_STOP1 (1 << 1) +#define TCU_TSR_STOP0 (1 << 0) + +#define TCU_TSSR_WDTSS (1 << 16) +#define TCU_TSSR_STPS5 (1 << 5) +#define TCU_TSSR_STPS4 (1 << 4) +#define TCU_TSSR_STPS3 (1 << 3) +#define TCU_TSSR_STPS2 (1 << 2) +#define TCU_TSSR_STPS1 (1 << 1) +#define TCU_TSSR_STPS0 (1 << 0) + +#define TCU_TSSR_WDTSC (1 << 16) +#define TCU_TSSR_STPC5 (1 << 5) +#define TCU_TSSR_STPC4 (1 << 4) +#define TCU_TSSR_STPC3 (1 << 3) +#define TCU_TSSR_STPC2 (1 << 2) +#define TCU_TSSR_STPC1 (1 << 1) +#define TCU_TSSR_STPC0 (1 << 0) + + +/************************************************************************* + * WDT (WatchDog Timer) + *************************************************************************/ +#define WDT_TDR (WDT_BASE + 0x00) +#define WDT_TCER (WDT_BASE + 0x04) +#define WDT_TCNT (WDT_BASE + 0x08) +#define WDT_TCSR (WDT_BASE + 0x0C) + +#define REG_WDT_TDR REG16(WDT_TDR) +#define REG_WDT_TCER REG8(WDT_TCER) +#define REG_WDT_TCNT REG16(WDT_TCNT) +#define REG_WDT_TCSR REG16(WDT_TCSR) + +// Register definition +#define WDT_TCSR_PRESCALE_BIT 3 +#define WDT_TCSR_PRESCALE_MASK (0x7 << WDT_TCSR_PRESCALE_BIT) + #define WDT_TCSR_PRESCALE1 (0x0 << WDT_TCSR_PRESCALE_BIT) + #define WDT_TCSR_PRESCALE4 (0x1 << WDT_TCSR_PRESCALE_BIT) + #define WDT_TCSR_PRESCALE16 (0x2 << WDT_TCSR_PRESCALE_BIT) + #define WDT_TCSR_PRESCALE64 (0x3 << WDT_TCSR_PRESCALE_BIT) + #define WDT_TCSR_PRESCALE256 (0x4 << WDT_TCSR_PRESCALE_BIT) + #define WDT_TCSR_PRESCALE1024 (0x5 << WDT_TCSR_PRESCALE_BIT) +#define WDT_TCSR_EXT_EN (1 << 2) +#define WDT_TCSR_RTC_EN (1 << 1) +#define WDT_TCSR_PCK_EN (1 << 0) + +#define WDT_TCER_TCEN (1 << 0) + + +/************************************************************************* + * DMAC (DMA Controller) + *************************************************************************/ + +#define MAX_DMA_NUM 6 /* max 6 channels */ + +#define DMAC_DSAR(n) (DMAC_BASE + (0x00 + (n) * 0x20)) /* DMA source address */ +#define DMAC_DTAR(n) (DMAC_BASE + (0x04 + (n) * 0x20)) /* DMA target address */ +#define DMAC_DTCR(n) (DMAC_BASE + (0x08 + (n) * 0x20)) /* DMA transfer count */ +#define DMAC_DRSR(n) (DMAC_BASE + (0x0c + (n) * 0x20)) /* DMA request source */ +#define DMAC_DCCSR(n) (DMAC_BASE + (0x10 + (n) * 0x20)) /* DMA control/status */ +#define DMAC_DCMD(n) (DMAC_BASE + (0x14 + (n) * 0x20)) /* DMA command */ +#define DMAC_DDA(n) (DMAC_BASE + (0x18 + (n) * 0x20)) /* DMA descriptor address */ +#define DMAC_DMACR (DMAC_BASE + 0x0300) /* DMA control register */ +#define DMAC_DMAIPR (DMAC_BASE + 0x0304) /* DMA interrupt pending */ +#define DMAC_DMADBR (DMAC_BASE + 0x0308) /* DMA doorbell */ +#define DMAC_DMADBSR (DMAC_BASE + 0x030C) /* DMA doorbell set */ + +// channel 0 +#define DMAC_DSAR0 DMAC_DSAR(0) +#define DMAC_DTAR0 DMAC_DTAR(0) +#define DMAC_DTCR0 DMAC_DTCR(0) +#define DMAC_DRSR0 DMAC_DRSR(0) +#define DMAC_DCCSR0 DMAC_DCCSR(0) +#define DMAC_DCMD0 DMAC_DCMD(0) +#define DMAC_DDA0 DMAC_DDA(0) + +// channel 1 +#define DMAC_DSAR1 DMAC_DSAR(1) +#define DMAC_DTAR1 DMAC_DTAR(1) +#define DMAC_DTCR1 DMAC_DTCR(1) +#define DMAC_DRSR1 DMAC_DRSR(1) +#define DMAC_DCCSR1 DMAC_DCCSR(1) +#define DMAC_DCMD1 DMAC_DCMD(1) +#define DMAC_DDA1 DMAC_DDA(1) + +// channel 2 +#define DMAC_DSAR2 DMAC_DSAR(2) +#define DMAC_DTAR2 DMAC_DTAR(2) +#define DMAC_DTCR2 DMAC_DTCR(2) +#define DMAC_DRSR2 DMAC_DRSR(2) +#define DMAC_DCCSR2 DMAC_DCCSR(2) +#define DMAC_DCMD2 DMAC_DCMD(2) +#define DMAC_DDA2 DMAC_DDA(2) + +// channel 3 +#define DMAC_DSAR3 DMAC_DSAR(3) +#define DMAC_DTAR3 DMAC_DTAR(3) +#define DMAC_DTCR3 DMAC_DTCR(3) +#define DMAC_DRSR3 DMAC_DRSR(3) +#define DMAC_DCCSR3 DMAC_DCCSR(3) +#define DMAC_DCMD3 DMAC_DCMD(3) +#define DMAC_DDA3 DMAC_DDA(3) + +// channel 4 +#define DMAC_DSAR4 DMAC_DSAR(4) +#define DMAC_DTAR4 DMAC_DTAR(4) +#define DMAC_DTCR4 DMAC_DTCR(4) +#define DMAC_DRSR4 DMAC_DRSR(4) +#define DMAC_DCCSR4 DMAC_DCCSR(4) +#define DMAC_DCMD4 DMAC_DCMD(4) +#define DMAC_DDA4 DMAC_DDA(4) + +// channel 5 +#define DMAC_DSAR5 DMAC_DSAR(5) +#define DMAC_DTAR5 DMAC_DTAR(5) +#define DMAC_DTCR5 DMAC_DTCR(5) +#define DMAC_DRSR5 DMAC_DRSR(5) +#define DMAC_DCCSR5 DMAC_DCCSR(5) +#define DMAC_DCMD5 DMAC_DCMD(5) +#define DMAC_DDA5 DMAC_DDA(5) + +#define REG_DMAC_DSAR(n) REG32(DMAC_DSAR((n))) +#define REG_DMAC_DTAR(n) REG32(DMAC_DTAR((n))) +#define REG_DMAC_DTCR(n) REG32(DMAC_DTCR((n))) +#define REG_DMAC_DRSR(n) REG32(DMAC_DRSR((n))) +#define REG_DMAC_DCCSR(n) REG32(DMAC_DCCSR((n))) +#define REG_DMAC_DCMD(n) REG32(DMAC_DCMD((n))) +#define REG_DMAC_DDA(n) REG32(DMAC_DDA((n))) +#define REG_DMAC_DMACR REG32(DMAC_DMACR) +#define REG_DMAC_DMAIPR REG32(DMAC_DMAIPR) +#define REG_DMAC_DMADBR REG32(DMAC_DMADBR) +#define REG_DMAC_DMADBSR REG32(DMAC_DMADBSR) + +// DMA request source register +#define DMAC_DRSR_RS_BIT 0 +#define DMAC_DRSR_RS_MASK (0x1f << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_AUTO (8 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_UART0OUT (20 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_UART0IN (21 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_SSIOUT (22 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_SSIIN (23 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_AICOUT (24 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_AICIN (25 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_MSCOUT (26 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_MSCIN (27 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_TCU (28 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_SADC (29 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_SLCD (30 << DMAC_DRSR_RS_BIT) + +// DMA channel control/status register +#define DMAC_DCCSR_NDES (1 << 31) /* descriptor (0) or not (1) ? */ +#define DMAC_DCCSR_CDOA_BIT 16 /* copy of DMA offset address */ +#define DMAC_DCCSR_CDOA_MASK (0xff << DMAC_DCCSR_CDOA_BIT) +#define DMAC_DCCSR_INV (1 << 6) /* descriptor invalid */ +#define DMAC_DCCSR_AR (1 << 4) /* address error */ +#define DMAC_DCCSR_TT (1 << 3) /* transfer terminated */ +#define DMAC_DCCSR_HLT (1 << 2) /* DMA halted */ +#define DMAC_DCCSR_CT (1 << 1) /* count terminated */ +#define DMAC_DCCSR_EN (1 << 0) /* channel enable bit */ + +// DMA channel command register +#define DMAC_DCMD_SAI (1 << 23) /* source address increment */ +#define DMAC_DCMD_DAI (1 << 22) /* dest address increment */ +#define DMAC_DCMD_RDIL_BIT 16 /* request detection interval length */ +#define DMAC_DCMD_RDIL_MASK (0x0f << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_IGN (0 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_2 (1 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_4 (2 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_8 (3 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_12 (4 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_16 (5 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_20 (6 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_24 (7 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_28 (8 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_32 (9 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_48 (10 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_60 (11 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_64 (12 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_124 (13 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_128 (14 << DMAC_DCMD_RDIL_BIT) + #define DMAC_DCMD_RDIL_200 (15 << DMAC_DCMD_RDIL_BIT) +#define DMAC_DCMD_SWDH_BIT 14 /* source port width */ +#define DMAC_DCMD_SWDH_MASK (0x03 << DMAC_DCMD_SWDH_BIT) + #define DMAC_DCMD_SWDH_32 (0 << DMAC_DCMD_SWDH_BIT) + #define DMAC_DCMD_SWDH_8 (1 << DMAC_DCMD_SWDH_BIT) + #define DMAC_DCMD_SWDH_16 (2 << DMAC_DCMD_SWDH_BIT) +#define DMAC_DCMD_DWDH_BIT 12 /* dest port width */ +#define DMAC_DCMD_DWDH_MASK (0x03 << DMAC_DCMD_DWDH_BIT) + #define DMAC_DCMD_DWDH_32 (0 << DMAC_DCMD_DWDH_BIT) + #define DMAC_DCMD_DWDH_8 (1 << DMAC_DCMD_DWDH_BIT) + #define DMAC_DCMD_DWDH_16 (2 << DMAC_DCMD_DWDH_BIT) +#define DMAC_DCMD_DS_BIT 8 /* transfer data size of a data unit */ +#define DMAC_DCMD_DS_MASK (0x07 << DMAC_DCMD_DS_BIT) + #define DMAC_DCMD_DS_32BIT (0 << DMAC_DCMD_DS_BIT) + #define DMAC_DCMD_DS_8BIT (1 << DMAC_DCMD_DS_BIT) + #define DMAC_DCMD_DS_16BIT (2 << DMAC_DCMD_DS_BIT) + #define DMAC_DCMD_DS_16BYTE (3 << DMAC_DCMD_DS_BIT) + #define DMAC_DCMD_DS_32BYTE (4 << DMAC_DCMD_DS_BIT) +#define DMAC_DCMD_TM (1 << 7) /* transfer mode: 0-single 1-block */ +#define DMAC_DCMD_DES_V (1 << 4) /* descriptor valid flag */ +#define DMAC_DCMD_DES_VM (1 << 3) /* descriptor valid mask: 1:support V-bit */ +#define DMAC_DCMD_DES_VIE (1 << 2) /* DMA valid error interrupt enable */ +#define DMAC_DCMD_TIE (1 << 1) /* DMA transfer interrupt enable */ +#define DMAC_DCMD_LINK (1 << 0) /* descriptor link enable */ + +// DMA descriptor address register +#define DMAC_DDA_BASE_BIT 12 /* descriptor base address */ +#define DMAC_DDA_BASE_MASK (0x0fffff << DMAC_DDA_BASE_BIT) +#define DMAC_DDA_OFFSET_BIT 4 /* descriptor offset address */ +#define DMAC_DDA_OFFSET_MASK (0x0ff << DMAC_DDA_OFFSET_BIT) + +// DMA control register +#define DMAC_DMACR_PR_BIT 8 /* channel priority mode */ +#define DMAC_DMACR_PR_MASK (0x03 << DMAC_DMACR_PR_BIT) + #define DMAC_DMACR_PR_012345 (0 << DMAC_DMACR_PR_BIT) + #define DMAC_DMACR_PR_023145 (1 << DMAC_DMACR_PR_BIT) + #define DMAC_DMACR_PR_201345 (2 << DMAC_DMACR_PR_BIT) + #define DMAC_DMACR_PR_RR (3 << DMAC_DMACR_PR_BIT) /* round robin */ +#define DMAC_DMACR_HLT (1 << 3) /* DMA halt flag */ +#define DMAC_DMACR_AR (1 << 2) /* address error flag */ +#define DMAC_DMACR_DMAE (1 << 0) /* DMA enable bit */ + +// DMA doorbell register +#define DMAC_DMADBR_DB5 (1 << 5) /* doorbell for channel 5 */ +#define DMAC_DMADBR_DB4 (1 << 5) /* doorbell for channel 4 */ +#define DMAC_DMADBR_DB3 (1 << 5) /* doorbell for channel 3 */ +#define DMAC_DMADBR_DB2 (1 << 5) /* doorbell for channel 2 */ +#define DMAC_DMADBR_DB1 (1 << 5) /* doorbell for channel 1 */ +#define DMAC_DMADBR_DB0 (1 << 5) /* doorbell for channel 0 */ + +// DMA doorbell set register +#define DMAC_DMADBSR_DBS5 (1 << 5) /* enable doorbell for channel 5 */ +#define DMAC_DMADBSR_DBS4 (1 << 5) /* enable doorbell for channel 4 */ +#define DMAC_DMADBSR_DBS3 (1 << 5) /* enable doorbell for channel 3 */ +#define DMAC_DMADBSR_DBS2 (1 << 5) /* enable doorbell for channel 2 */ +#define DMAC_DMADBSR_DBS1 (1 << 5) /* enable doorbell for channel 1 */ +#define DMAC_DMADBSR_DBS0 (1 << 5) /* enable doorbell for channel 0 */ + +// DMA interrupt pending register +#define DMAC_DMAIPR_CIRQ5 (1 << 5) /* irq pending status for channel 5 */ +#define DMAC_DMAIPR_CIRQ4 (1 << 4) /* irq pending status for channel 4 */ +#define DMAC_DMAIPR_CIRQ3 (1 << 3) /* irq pending status for channel 3 */ +#define DMAC_DMAIPR_CIRQ2 (1 << 2) /* irq pending status for channel 2 */ +#define DMAC_DMAIPR_CIRQ1 (1 << 1) /* irq pending status for channel 1 */ +#define DMAC_DMAIPR_CIRQ0 (1 << 0) /* irq pending status for channel 0 */ + + +/************************************************************************* + * GPIO (General-Purpose I/O Ports) + *************************************************************************/ +#define MAX_GPIO_NUM 128 + +//n = 0,1,2,3 +#define GPIO_PXPIN(n) (GPIO_BASE + (0x00 + (n)*0x100)) /* PIN Level Register */ +#define GPIO_PXDAT(n) (GPIO_BASE + (0x10 + (n)*0x100)) /* Port Data Register */ +#define GPIO_PXDATS(n) (GPIO_BASE + (0x14 + (n)*0x100)) /* Port Data Set Register */ +#define GPIO_PXDATC(n) (GPIO_BASE + (0x18 + (n)*0x100)) /* Port Data Clear Register */ +#define GPIO_PXIM(n) (GPIO_BASE + (0x20 + (n)*0x100)) /* Interrupt Mask Register */ +#define GPIO_PXIMS(n) (GPIO_BASE + (0x24 + (n)*0x100)) /* Interrupt Mask Set Reg */ +#define GPIO_PXIMC(n) (GPIO_BASE + (0x28 + (n)*0x100)) /* Interrupt Mask Clear Reg */ +#define GPIO_PXPE(n) (GPIO_BASE + (0x30 + (n)*0x100)) /* Pull Enable Register */ +#define GPIO_PXPES(n) (GPIO_BASE + (0x34 + (n)*0x100)) /* Pull Enable Set Reg. */ +#define GPIO_PXPEC(n) (GPIO_BASE + (0x38 + (n)*0x100)) /* Pull Enable Clear Reg. */ +#define GPIO_PXFUN(n) (GPIO_BASE + (0x40 + (n)*0x100)) /* Function Register */ +#define GPIO_PXFUNS(n) (GPIO_BASE + (0x44 + (n)*0x100)) /* Function Set Register */ +#define GPIO_PXFUNC(n) (GPIO_BASE + (0x48 + (n)*0x100)) /* Function Clear Register */ +#define GPIO_PXSEL(n) (GPIO_BASE + (0x50 + (n)*0x100)) /* Select Register */ +#define GPIO_PXSELS(n) (GPIO_BASE + (0x54 + (n)*0x100)) /* Select Set Register */ +#define GPIO_PXSELC(n) (GPIO_BASE + (0x58 + (n)*0x100)) /* Select Clear Register */ +#define GPIO_PXDIR(n) (GPIO_BASE + (0x60 + (n)*0x100)) /* Direction Register */ +#define GPIO_PXDIRS(n) (GPIO_BASE + (0x64 + (n)*0x100)) /* Direction Set Register */ +#define GPIO_PXDIRC(n) (GPIO_BASE + (0x68 + (n)*0x100)) /* Direction Clear Register */ +#define GPIO_PXTRG(n) (GPIO_BASE + (0x70 + (n)*0x100)) /* Trigger Register */ +#define GPIO_PXTRGS(n) (GPIO_BASE + (0x74 + (n)*0x100)) /* Trigger Set Register */ +#define GPIO_PXTRGC(n) (GPIO_BASE + (0x78 + (n)*0x100)) /* Trigger Set Register */ +#define GPIO_PXFLG(n) (GPIO_BASE + (0x80 + (n)*0x100)) /* Port Flag Register */ +#define GPIO_PXFLGC(n) (GPIO_BASE + (0x14 + (n)*0x100)) /* Port Flag clear Register */ + +#define REG_GPIO_PXPIN(n) REG32(GPIO_PXPIN((n))) /* PIN level */ +#define REG_GPIO_PXDAT(n) REG32(GPIO_PXDAT((n))) /* 1: interrupt pending */ +#define REG_GPIO_PXDATS(n) REG32(GPIO_PXDATS((n))) +#define REG_GPIO_PXDATC(n) REG32(GPIO_PXDATC((n))) +#define REG_GPIO_PXIM(n) REG32(GPIO_PXIM((n))) /* 1: mask pin interrupt */ +#define REG_GPIO_PXIMS(n) REG32(GPIO_PXIMS((n))) +#define REG_GPIO_PXIMC(n) REG32(GPIO_PXIMC((n))) +#define REG_GPIO_PXPE(n) REG32(GPIO_PXPE((n))) /* 1: disable pull up/down */ +#define REG_GPIO_PXPES(n) REG32(GPIO_PXPES((n))) +#define REG_GPIO_PXPEC(n) REG32(GPIO_PXPEC((n))) +#define REG_GPIO_PXFUN(n) REG32(GPIO_PXFUN((n))) /* 0:GPIO or intr, 1:FUNC */ +#define REG_GPIO_PXFUNS(n) REG32(GPIO_PXFUNS((n))) +#define REG_GPIO_PXFUNC(n) REG32(GPIO_PXFUNC((n))) +#define REG_GPIO_PXSEL(n) REG32(GPIO_PXSEL((n))) /* 0:GPIO/Fun0,1:intr/fun1*/ +#define REG_GPIO_PXSELS(n) REG32(GPIO_PXSELS((n))) +#define REG_GPIO_PXSELC(n) REG32(GPIO_PXSELC((n))) +#define REG_GPIO_PXDIR(n) REG32(GPIO_PXDIR((n))) /* 0:input/low-level-trig/falling-edge-trig, 1:output/high-level-trig/rising-edge-trig */ +#define REG_GPIO_PXDIRS(n) REG32(GPIO_PXDIRS((n))) +#define REG_GPIO_PXDIRC(n) REG32(GPIO_PXDIRC((n))) +#define REG_GPIO_PXTRG(n) REG32(GPIO_PXTRG((n))) /* 0:level-trigger, 1:edge-trigger */ +#define REG_GPIO_PXTRGS(n) REG32(GPIO_PXTRGS((n))) +#define REG_GPIO_PXTRGC(n) REG32(GPIO_PXTRGC((n))) +#define REG_GPIO_PXFLG(n) REG32(GPIO_PXFLG((n))) /* interrupt flag */ +#define REG_GPIO_PXFLGC(n) REG32(GPIO_PXFLGC((n))) /* interrupt flag */ + + +/************************************************************************* + * UART + *************************************************************************/ + +#define IRDA_BASE UART0_BASE +#define UART_BASE UART0_BASE +#define UART_OFF 0x1000 + +/* Register Offset */ +#define OFF_RDR (0x00) /* R 8b H'xx */ +#define OFF_TDR (0x00) /* W 8b H'xx */ +#define OFF_DLLR (0x00) /* RW 8b H'00 */ +#define OFF_DLHR (0x04) /* RW 8b H'00 */ +#define OFF_IER (0x04) /* RW 8b H'00 */ +#define OFF_ISR (0x08) /* R 8b H'01 */ +#define OFF_FCR (0x08) /* W 8b H'00 */ +#define OFF_LCR (0x0C) /* RW 8b H'00 */ +#define OFF_MCR (0x10) /* RW 8b H'00 */ +#define OFF_LSR (0x14) /* R 8b H'00 */ +#define OFF_MSR (0x18) /* R 8b H'00 */ +#define OFF_SPR (0x1C) /* RW 8b H'00 */ +#define OFF_SIRCR (0x20) /* RW 8b H'00, UART0 */ +#define OFF_UMR (0x24) /* RW 8b H'00, UART M Register */ +#define OFF_UACR (0x28) /* RW 8b H'00, UART Add Cycle Register */ + +/* Register Address */ +#define UART0_RDR (UART0_BASE + OFF_RDR) +#define UART0_TDR (UART0_BASE + OFF_TDR) +#define UART0_DLLR (UART0_BASE + OFF_DLLR) +#define UART0_DLHR (UART0_BASE + OFF_DLHR) +#define UART0_IER (UART0_BASE + OFF_IER) +#define UART0_ISR (UART0_BASE + OFF_ISR) +#define UART0_FCR (UART0_BASE + OFF_FCR) +#define UART0_LCR (UART0_BASE + OFF_LCR) +#define UART0_MCR (UART0_BASE + OFF_MCR) +#define UART0_LSR (UART0_BASE + OFF_LSR) +#define UART0_MSR (UART0_BASE + OFF_MSR) +#define UART0_SPR (UART0_BASE + OFF_SPR) +#define UART0_SIRCR (UART0_BASE + OFF_SIRCR) +#define UART0_UMR (UART0_BASE + OFF_UMR) +#define UART0_UACR (UART0_BASE + OFF_UACR) + +/* + * Define macros for UART_IER + * UART Interrupt Enable Register + */ +#define UART_IER_RIE (1 << 0) /* 0: receive fifo "full" interrupt disable */ +#define UART_IER_TIE (1 << 1) /* 0: transmit fifo "empty" interrupt disable */ +#define UART_IER_RLIE (1 << 2) /* 0: receive line status interrupt disable */ +#define UART_IER_MIE (1 << 3) /* 0: modem status interrupt disable */ +#define UART_IER_RTIE (1 << 4) /* 0: receive timeout interrupt disable */ + +/* + * Define macros for UART_ISR + * UART Interrupt Status Register + */ +#define UART_ISR_IP (1 << 0) /* 0: interrupt is pending 1: no interrupt */ +#define UART_ISR_IID (7 << 1) /* Source of Interrupt */ +#define UART_ISR_IID_MSI (0 << 1) /* Modem status interrupt */ +#define UART_ISR_IID_THRI (1 << 1) /* Transmitter holding register empty */ +#define UART_ISR_IID_RDI (2 << 1) /* Receiver data interrupt */ +#define UART_ISR_IID_RLSI (3 << 1) /* Receiver line status interrupt */ +#define UART_ISR_FFMS (3 << 6) /* FIFO mode select, set when UART_FCR.FE is set to 1 */ +#define UART_ISR_FFMS_NO_FIFO (0 << 6) +#define UART_ISR_FFMS_FIFO_MODE (3 << 6) + +/* + * Define macros for UART_FCR + * UART FIFO Control Register + */ +#define UART_FCR_FE (1 << 0) /* 0: non-FIFO mode 1: FIFO mode */ +#define UART_FCR_RFLS (1 << 1) /* write 1 to flush receive FIFO */ +#define UART_FCR_TFLS (1 << 2) /* write 1 to flush transmit FIFO */ +#define UART_FCR_DMS (1 << 3) /* 0: disable DMA mode */ +#define UART_FCR_UUE (1 << 4) /* 0: disable UART */ +#define UART_FCR_RTRG (3 << 6) /* Receive FIFO Data Trigger */ +#define UART_FCR_RTRG_1 (0 << 6) +#define UART_FCR_RTRG_4 (1 << 6) +#define UART_FCR_RTRG_8 (2 << 6) +#define UART_FCR_RTRG_15 (3 << 6) + +/* + * Define macros for UART_LCR + * UART Line Control Register + */ +#define UART_LCR_WLEN (3 << 0) /* word length */ +#define UART_LCR_WLEN_5 (0 << 0) +#define UART_LCR_WLEN_6 (1 << 0) +#define UART_LCR_WLEN_7 (2 << 0) +#define UART_LCR_WLEN_8 (3 << 0) +#define UART_LCR_STOP (1 << 2) /* 0: 1 stop bit when word length is 5,6,7,8 + 1: 1.5 stop bits when 5; 2 stop bits when 6,7,8 */ +#define UART_LCR_STOP_1 (0 << 2) /* 0: 1 stop bit when word length is 5,6,7,8 + 1: 1.5 stop bits when 5; 2 stop bits when 6,7,8 */ +#define UART_LCR_STOP_2 (1 << 2) /* 0: 1 stop bit when word length is 5,6,7,8 + 1: 1.5 stop bits when 5; 2 stop bits when 6,7,8 */ + +#define UART_LCR_PE (1 << 3) /* 0: parity disable */ +#define UART_LCR_PROE (1 << 4) /* 0: even parity 1: odd parity */ +#define UART_LCR_SPAR (1 << 5) /* 0: sticky parity disable */ +#define UART_LCR_SBRK (1 << 6) /* write 0 normal, write 1 send break */ +#define UART_LCR_DLAB (1 << 7) /* 0: access UART_RDR/TDR/IER 1: access UART_DLLR/DLHR */ + +/* + * Define macros for UART_LSR + * UART Line Status Register + */ +#define UART_LSR_DR (1 << 0) /* 0: receive FIFO is empty 1: receive data is ready */ +#define UART_LSR_ORER (1 << 1) /* 0: no overrun error */ +#define UART_LSR_PER (1 << 2) /* 0: no parity error */ +#define UART_LSR_FER (1 << 3) /* 0; no framing error */ +#define UART_LSR_BRK (1 << 4) /* 0: no break detected 1: receive a break signal */ +#define UART_LSR_TDRQ (1 << 5) /* 1: transmit FIFO half "empty" */ +#define UART_LSR_TEMT (1 << 6) /* 1: transmit FIFO and shift registers empty */ +#define UART_LSR_RFER (1 << 7) /* 0: no receive error 1: receive error in FIFO mode */ + +/* + * Define macros for UART_MCR + * UART Modem Control Register + */ +#define UART_MCR_DTR (1 << 0) /* 0: DTR_ ouput high */ +#define UART_MCR_RTS (1 << 1) /* 0: RTS_ output high */ +#define UART_MCR_OUT1 (1 << 2) /* 0: UART_MSR.RI is set to 0 and RI_ input high */ +#define UART_MCR_OUT2 (1 << 3) /* 0: UART_MSR.DCD is set to 0 and DCD_ input high */ +#define UART_MCR_LOOP (1 << 4) /* 0: normal 1: loopback mode */ +#define UART_MCR_MCE (1 << 7) /* 0: modem function is disable */ + +/* + * Define macros for UART_MSR + * UART Modem Status Register + */ +#define UART_MSR_DCTS (1 << 0) /* 0: no change on CTS_ pin since last read of UART_MSR */ +#define UART_MSR_DDSR (1 << 1) /* 0: no change on DSR_ pin since last read of UART_MSR */ +#define UART_MSR_DRI (1 << 2) /* 0: no change on RI_ pin since last read of UART_MSR */ +#define UART_MSR_DDCD (1 << 3) /* 0: no change on DCD_ pin since last read of UART_MSR */ +#define UART_MSR_CTS (1 << 4) /* 0: CTS_ pin is high */ +#define UART_MSR_DSR (1 << 5) /* 0: DSR_ pin is high */ +#define UART_MSR_RI (1 << 6) /* 0: RI_ pin is high */ +#define UART_MSR_DCD (1 << 7) /* 0: DCD_ pin is high */ + +/* + * Define macros for SIRCR + * Slow IrDA Control Register + */ +#define SIRCR_TSIRE (1 << 0) /* 0: transmitter is in UART mode 1: IrDA mode */ +#define SIRCR_RSIRE (1 << 1) /* 0: receiver is in UART mode 1: IrDA mode */ +#define SIRCR_TPWS (1 << 2) /* 0: transmit 0 pulse width is 3/16 of bit length + 1: 0 pulse width is 1.6us for 115.2Kbps */ +#define SIRCR_TXPL (1 << 3) /* 0: encoder generates a positive pulse for 0 */ +#define SIRCR_RXPL (1 << 4) /* 0: decoder interprets positive pulse as 0 */ + + +/************************************************************************* + * AIC (AC97/I2S Controller) + *************************************************************************/ +#define AIC_FR (AIC_BASE + 0x000) +#define AIC_CR (AIC_BASE + 0x004) +#define AIC_ACCR1 (AIC_BASE + 0x008) +#define AIC_ACCR2 (AIC_BASE + 0x00C) +#define AIC_I2SCR (AIC_BASE + 0x010) +#define AIC_SR (AIC_BASE + 0x014) +#define AIC_ACSR (AIC_BASE + 0x018) +#define AIC_I2SSR (AIC_BASE + 0x01C) +#define AIC_ACCAR (AIC_BASE + 0x020) +#define AIC_ACCDR (AIC_BASE + 0x024) +#define AIC_ACSAR (AIC_BASE + 0x028) +#define AIC_ACSDR (AIC_BASE + 0x02C) +#define AIC_I2SDIV (AIC_BASE + 0x030) +#define AIC_DR (AIC_BASE + 0x034) + +#define REG_AIC_FR REG32(AIC_FR) +#define REG_AIC_CR REG32(AIC_CR) +#define REG_AIC_ACCR1 REG32(AIC_ACCR1) +#define REG_AIC_ACCR2 REG32(AIC_ACCR2) +#define REG_AIC_I2SCR REG32(AIC_I2SCR) +#define REG_AIC_SR REG32(AIC_SR) +#define REG_AIC_ACSR REG32(AIC_ACSR) +#define REG_AIC_I2SSR REG32(AIC_I2SSR) +#define REG_AIC_ACCAR REG32(AIC_ACCAR) +#define REG_AIC_ACCDR REG32(AIC_ACCDR) +#define REG_AIC_ACSAR REG32(AIC_ACSAR) +#define REG_AIC_ACSDR REG32(AIC_ACSDR) +#define REG_AIC_I2SDIV REG32(AIC_I2SDIV) +#define REG_AIC_DR REG32(AIC_DR) + +/* AIC Controller Configuration Register (AIC_FR) */ + +#define AIC_FR_RFTH_BIT 12 /* Receive FIFO Threshold */ +#define AIC_FR_RFTH_MASK (0xf << AIC_FR_RFTH_BIT) +#define AIC_FR_TFTH_BIT 8 /* Transmit FIFO Threshold */ +#define AIC_FR_TFTH_MASK (0xf << AIC_FR_TFTH_BIT) +#define AIC_FR_ICDC (1 << 5) /* External(0) or Internal CODEC(1) */ +#define AIC_FR_AUSEL (1 << 4) /* AC97(0) or I2S/MSB-justified(1) */ +#define AIC_FR_RST (1 << 3) /* AIC registers reset */ +#define AIC_FR_BCKD (1 << 2) /* I2S BIT_CLK direction, 0:input,1:output */ +#define AIC_FR_SYNCD (1 << 1) /* I2S SYNC direction, 0:input,1:output */ +#define AIC_FR_ENB (1 << 0) /* AIC enable bit */ + +/* AIC Controller Common Control Register (AIC_CR) */ + +#define AIC_CR_OSS_BIT 19 /* Output Sample Size from memory (AIC V2 only) */ +#define AIC_CR_OSS_MASK (0x7 << AIC_CR_OSS_BIT) + #define AIC_CR_OSS_8BIT (0x0 << AIC_CR_OSS_BIT) + #define AIC_CR_OSS_16BIT (0x1 << AIC_CR_OSS_BIT) + #define AIC_CR_OSS_18BIT (0x2 << AIC_CR_OSS_BIT) + #define AIC_CR_OSS_20BIT (0x3 << AIC_CR_OSS_BIT) + #define AIC_CR_OSS_24BIT (0x4 << AIC_CR_OSS_BIT) +#define AIC_CR_ISS_BIT 16 /* Input Sample Size from memory (AIC V2 only) */ +#define AIC_CR_ISS_MASK (0x7 << AIC_CR_ISS_BIT) + #define AIC_CR_ISS_8BIT (0x0 << AIC_CR_ISS_BIT) + #define AIC_CR_ISS_16BIT (0x1 << AIC_CR_ISS_BIT) + #define AIC_CR_ISS_18BIT (0x2 << AIC_CR_ISS_BIT) + #define AIC_CR_ISS_20BIT (0x3 << AIC_CR_ISS_BIT) + #define AIC_CR_ISS_24BIT (0x4 << AIC_CR_ISS_BIT) +#define AIC_CR_RDMS (1 << 15) /* Receive DMA enable */ +#define AIC_CR_TDMS (1 << 14) /* Transmit DMA enable */ +#define AIC_CR_M2S (1 << 11) /* Mono to Stereo enable */ +#define AIC_CR_ENDSW (1 << 10) /* Endian switch enable */ +#define AIC_CR_AVSTSU (1 << 9) /* Signed <-> Unsigned toggle enable */ +#define AIC_CR_FLUSH (1 << 8) /* Flush FIFO */ +#define AIC_CR_EROR (1 << 6) /* Enable ROR interrupt */ +#define AIC_CR_ETUR (1 << 5) /* Enable TUR interrupt */ +#define AIC_CR_ERFS (1 << 4) /* Enable RFS interrupt */ +#define AIC_CR_ETFS (1 << 3) /* Enable TFS interrupt */ +#define AIC_CR_ENLBF (1 << 2) /* Enable Loopback Function */ +#define AIC_CR_ERPL (1 << 1) /* Enable Playback Function */ +#define AIC_CR_EREC (1 << 0) /* Enable Record Function */ + +/* AIC Controller AC-link Control Register 1 (AIC_ACCR1) */ + +#define AIC_ACCR1_RS_BIT 16 /* Receive Valid Slots */ +#define AIC_ACCR1_RS_MASK (0x3ff << AIC_ACCR1_RS_BIT) + #define AIC_ACCR1_RS_SLOT12 (1 << 25) /* Slot 12 valid bit */ + #define AIC_ACCR1_RS_SLOT11 (1 << 24) /* Slot 11 valid bit */ + #define AIC_ACCR1_RS_SLOT10 (1 << 23) /* Slot 10 valid bit */ + #define AIC_ACCR1_RS_SLOT9 (1 << 22) /* Slot 9 valid bit, LFE */ + #define AIC_ACCR1_RS_SLOT8 (1 << 21) /* Slot 8 valid bit, Surround Right */ + #define AIC_ACCR1_RS_SLOT7 (1 << 20) /* Slot 7 valid bit, Surround Left */ + #define AIC_ACCR1_RS_SLOT6 (1 << 19) /* Slot 6 valid bit, PCM Center */ + #define AIC_ACCR1_RS_SLOT5 (1 << 18) /* Slot 5 valid bit */ + #define AIC_ACCR1_RS_SLOT4 (1 << 17) /* Slot 4 valid bit, PCM Right */ + #define AIC_ACCR1_RS_SLOT3 (1 << 16) /* Slot 3 valid bit, PCM Left */ +#define AIC_ACCR1_XS_BIT 0 /* Transmit Valid Slots */ +#define AIC_ACCR1_XS_MASK (0x3ff << AIC_ACCR1_XS_BIT) + #define AIC_ACCR1_XS_SLOT12 (1 << 9) /* Slot 12 valid bit */ + #define AIC_ACCR1_XS_SLOT11 (1 << 8) /* Slot 11 valid bit */ + #define AIC_ACCR1_XS_SLOT10 (1 << 7) /* Slot 10 valid bit */ + #define AIC_ACCR1_XS_SLOT9 (1 << 6) /* Slot 9 valid bit, LFE */ + #define AIC_ACCR1_XS_SLOT8 (1 << 5) /* Slot 8 valid bit, Surround Right */ + #define AIC_ACCR1_XS_SLOT7 (1 << 4) /* Slot 7 valid bit, Surround Left */ + #define AIC_ACCR1_XS_SLOT6 (1 << 3) /* Slot 6 valid bit, PCM Center */ + #define AIC_ACCR1_XS_SLOT5 (1 << 2) /* Slot 5 valid bit */ + #define AIC_ACCR1_XS_SLOT4 (1 << 1) /* Slot 4 valid bit, PCM Right */ + #define AIC_ACCR1_XS_SLOT3 (1 << 0) /* Slot 3 valid bit, PCM Left */ + +/* AIC Controller AC-link Control Register 2 (AIC_ACCR2) */ + +#define AIC_ACCR2_ERSTO (1 << 18) /* Enable RSTO interrupt */ +#define AIC_ACCR2_ESADR (1 << 17) /* Enable SADR interrupt */ +#define AIC_ACCR2_ECADT (1 << 16) /* Enable CADT interrupt */ +#define AIC_ACCR2_OASS_BIT 8 /* Output Sample Size for AC-link */ +#define AIC_ACCR2_OASS_MASK (0x3 << AIC_ACCR2_OASS_BIT) + #define AIC_ACCR2_OASS_20BIT (0 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 20-bit */ + #define AIC_ACCR2_OASS_18BIT (1 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 18-bit */ + #define AIC_ACCR2_OASS_16BIT (2 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 16-bit */ + #define AIC_ACCR2_OASS_8BIT (3 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 8-bit */ +#define AIC_ACCR2_IASS_BIT 6 /* Output Sample Size for AC-link */ +#define AIC_ACCR2_IASS_MASK (0x3 << AIC_ACCR2_IASS_BIT) + #define AIC_ACCR2_IASS_20BIT (0 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 20-bit */ + #define AIC_ACCR2_IASS_18BIT (1 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 18-bit */ + #define AIC_ACCR2_IASS_16BIT (2 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 16-bit */ + #define AIC_ACCR2_IASS_8BIT (3 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 8-bit */ +#define AIC_ACCR2_SO (1 << 3) /* SDATA_OUT output value */ +#define AIC_ACCR2_SR (1 << 2) /* RESET# pin level */ +#define AIC_ACCR2_SS (1 << 1) /* SYNC pin level */ +#define AIC_ACCR2_SA (1 << 0) /* SYNC and SDATA_OUT alternation */ + +/* AIC Controller I2S/MSB-justified Control Register (AIC_I2SCR) */ + +#define AIC_I2SCR_STPBK (1 << 12) /* Stop BIT_CLK for I2S/MSB-justified */ +#define AIC_I2SCR_WL_BIT 1 /* Input/Output Sample Size for I2S/MSB-justified */ +#define AIC_I2SCR_WL_MASK (0x7 << AIC_I2SCR_WL_BIT) + #define AIC_I2SCR_WL_24BIT (0 << AIC_I2SCR_WL_BIT) /* Word Length is 24 bit */ + #define AIC_I2SCR_WL_20BIT (1 << AIC_I2SCR_WL_BIT) /* Word Length is 20 bit */ + #define AIC_I2SCR_WL_18BIT (2 << AIC_I2SCR_WL_BIT) /* Word Length is 18 bit */ + #define AIC_I2SCR_WL_16BIT (3 << AIC_I2SCR_WL_BIT) /* Word Length is 16 bit */ + #define AIC_I2SCR_WL_8BIT (4 << AIC_I2SCR_WL_BIT) /* Word Length is 8 bit */ +#define AIC_I2SCR_AMSL (1 << 0) /* 0:I2S, 1:MSB-justified */ + +/* AIC Controller FIFO Status Register (AIC_SR) */ + +#define AIC_SR_RFL_BIT 24 /* Receive FIFO Level */ +#define AIC_SR_RFL_MASK (0x3f << AIC_SR_RFL_BIT) +#define AIC_SR_TFL_BIT 8 /* Transmit FIFO level */ +#define AIC_SR_TFL_MASK (0x3f << AIC_SR_TFL_BIT) +#define AIC_SR_ROR (1 << 6) /* Receive FIFO Overrun */ +#define AIC_SR_TUR (1 << 5) /* Transmit FIFO Underrun */ +#define AIC_SR_RFS (1 << 4) /* Receive FIFO Service Request */ +#define AIC_SR_TFS (1 << 3) /* Transmit FIFO Service Request */ + +/* AIC Controller AC-link Status Register (AIC_ACSR) */ + +#define AIC_ACSR_SLTERR (1 << 21) /* Slot Error Flag */ +#define AIC_ACSR_CRDY (1 << 20) /* External CODEC Ready Flag */ +#define AIC_ACSR_CLPM (1 << 19) /* External CODEC low power mode flag */ +#define AIC_ACSR_RSTO (1 << 18) /* External CODEC regs read status timeout */ +#define AIC_ACSR_SADR (1 << 17) /* External CODEC regs status addr and data received */ +#define AIC_ACSR_CADT (1 << 16) /* Command Address and Data Transmitted */ + +/* AIC Controller I2S/MSB-justified Status Register (AIC_I2SSR) */ + +#define AIC_I2SSR_BSY (1 << 2) /* AIC Busy in I2S/MSB-justified format */ + +/* AIC Controller AC97 codec Command Address Register (AIC_ACCAR) */ + +#define AIC_ACCAR_CAR_BIT 0 +#define AIC_ACCAR_CAR_MASK (0xfffff << AIC_ACCAR_CAR_BIT) + +/* AIC Controller AC97 codec Command Data Register (AIC_ACCDR) */ + +#define AIC_ACCDR_CDR_BIT 0 +#define AIC_ACCDR_CDR_MASK (0xfffff << AIC_ACCDR_CDR_BIT) + +/* AIC Controller AC97 codec Status Address Register (AIC_ACSAR) */ + +#define AIC_ACSAR_SAR_BIT 0 +#define AIC_ACSAR_SAR_MASK (0xfffff << AIC_ACSAR_SAR_BIT) + +/* AIC Controller AC97 codec Status Data Register (AIC_ACSDR) */ + +#define AIC_ACSDR_SDR_BIT 0 +#define AIC_ACSDR_SDR_MASK (0xfffff << AIC_ACSDR_SDR_BIT) + +/* AIC Controller I2S/MSB-justified Clock Divider Register (AIC_I2SDIV) */ + +#define AIC_I2SDIV_DIV_BIT 0 +#define AIC_I2SDIV_DIV_MASK (0x7f << AIC_I2SDIV_DIV_BIT) + #define AIC_I2SDIV_BITCLK_3072KHZ (0x0C << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 3.072MHz */ + #define AIC_I2SDIV_BITCLK_2836KHZ (0x0D << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 2.836MHz */ + #define AIC_I2SDIV_BITCLK_1418KHZ (0x1A << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.418MHz */ + #define AIC_I2SDIV_BITCLK_1024KHZ (0x24 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.024MHz */ + #define AIC_I2SDIV_BITCLK_7089KHZ (0x34 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 708.92KHz */ + #define AIC_I2SDIV_BITCLK_512KHZ (0x48 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 512.00KHz */ + + +/************************************************************************* + * ICDC (Internal CODEC) + *************************************************************************/ +#define ICDC_CR (ICDC_BASE + 0x0400) /* ICDC Control Register */ +#define ICDC_APWAIT (ICDC_BASE + 0x0404) /* Anti-Pop WAIT Stage Timing Control Register */ +#define ICDC_APPRE (ICDC_BASE + 0x0408) /* Anti-Pop HPEN-PRE Stage Timing Control Register */ +#define ICDC_APHPEN (ICDC_BASE + 0x040C) /* Anti-Pop HPEN Stage Timing Control Register */ +#define ICDC_APSR (ICDC_BASE + 0x0410) /* Anti-Pop Status Register */ +#define ICDC_CDCCR1 (ICDC_BASE + 0x0080) +#define ICDC_CDCCR2 (ICDC_BASE + 0x0084) + +#define REG_ICDC_CR REG32(ICDC_CR) +#define REG_ICDC_APWAIT REG32(ICDC_APWAIT) +#define REG_ICDC_APPRE REG32(ICDC_APPRE) +#define REG_ICDC_APHPEN REG32(ICDC_APHPEN) +#define REG_ICDC_APSR REG32(ICDC_APSR) +#define REG_ICDC_CDCCR1 REG32(ICDC_CDCCR1) +#define REG_ICDC_CDCCR2 REG32(ICDC_CDCCR2) + +/* ICDC Control Register */ +#define ICDC_CR_LINVOL_BIT 24 /* LINE Input Volume Gain: GAIN=LINVOL*1.5-34.5 */ +#define ICDC_CR_LINVOL_MASK (0x1f << ICDC_CR_LINVOL_BIT) +#define ICDC_CR_ASRATE_BIT 20 /* Audio Sample Rate */ +#define ICDC_CR_ASRATE_MASK (0x0f << ICDC_CR_ASRATE_BIT) + #define ICDC_CR_ASRATE_8000 (0x0 << ICDC_CR_ASRATE_BIT) + #define ICDC_CR_ASRATE_11025 (0x1 << ICDC_CR_ASRATE_BIT) + #define ICDC_CR_ASRATE_12000 (0x2 << ICDC_CR_ASRATE_BIT) + #define ICDC_CR_ASRATE_16000 (0x3 << ICDC_CR_ASRATE_BIT) + #define ICDC_CR_ASRATE_22050 (0x4 << ICDC_CR_ASRATE_BIT) + #define ICDC_CR_ASRATE_24000 (0x5 << ICDC_CR_ASRATE_BIT) + #define ICDC_CR_ASRATE_32000 (0x6 << ICDC_CR_ASRATE_BIT) + #define ICDC_CR_ASRATE_44100 (0x7 << ICDC_CR_ASRATE_BIT) + #define ICDC_CR_ASRATE_48000 (0x8 << ICDC_CR_ASRATE_BIT) +#define ICDC_CR_MICBG_BIT 18 /* MIC Boost Gain */ +#define ICDC_CR_MICBG_MASK (0x3 << ICDC_CR_MICBG_BIT) + #define ICDC_CR_MICBG_0DB (0x0 << ICDC_CR_MICBG_BIT) + #define ICDC_CR_MICBG_6DB (0x1 << ICDC_CR_MICBG_BIT) + #define ICDC_CR_MICBG_12DB (0x2 << ICDC_CR_MICBG_BIT) + #define ICDC_CR_MICBG_20DB (0x3 << ICDC_CR_MICBG_BIT) +#define ICDC_CR_HPVOL_BIT 16 /* Headphone Volume Gain */ +#define ICDC_CR_HPVOL_MASK (0x3 << ICDC_CR_HPVOL_BIT) + #define ICDC_CR_HPVOL_0DB (0x0 << ICDC_CR_HPVOL_BIT) + #define ICDC_CR_HPVOL_2DB (0x1 << ICDC_CR_HPVOL_BIT) + #define ICDC_CR_HPVOL_4DB (0x2 << ICDC_CR_HPVOL_BIT) + #define ICDC_CR_HPVOL_6DB (0x3 << ICDC_CR_HPVOL_BIT) +#define ICDC_CR_ELINEIN (1 << 13) /* Enable LINE Input */ +#define ICDC_CR_EMIC (1 << 12) /* Enable MIC Input */ +#define ICDC_CR_SW1ON (1 << 11) /* Switch 1 in CODEC is on */ +#define ICDC_CR_EADC (1 << 10) /* Enable ADC */ +#define ICDC_CR_SW2ON (1 << 9) /* Switch 2 in CODEC is on */ +#define ICDC_CR_EDAC (1 << 8) /* Enable DAC */ +#define ICDC_CR_HPMUTE (1 << 5) /* Headphone Mute */ +#define ICDC_CR_HPTON (1 << 4) /* Headphone Amplifier Trun On */ +#define ICDC_CR_HPTOFF (1 << 3) /* Headphone Amplifier Trun Off */ +#define ICDC_CR_TAAP (1 << 2) /* Turn Around of the Anti-Pop Procedure */ +#define ICDC_CR_EAP (1 << 1) /* Enable Anti-Pop Procedure */ +#define ICDC_CR_SUSPD (1 << 0) /* CODEC Suspend */ + +/* Anti-Pop WAIT Stage Timing Control Register */ +#define ICDC_APWAIT_WAITSN_BIT 0 +#define ICDC_APWAIT_WAITSN_MASK (0x7ff << ICDC_APWAIT_WAITSN_BIT) + +/* Anti-Pop HPEN-PRE Stage Timing Control Register */ +#define ICDC_APPRE_PRESN_BIT 0 +#define ICDC_APPRE_PRESN_MASK (0x1ff << ICDC_APPRE_PRESN_BIT) + +/* Anti-Pop HPEN Stage Timing Control Register */ +#define ICDC_APHPEN_HPENSN_BIT 0 +#define ICDC_APHPEN_HPENSN_MASK (0x3fff << ICDC_APHPEN_HPENSN_BIT) + +/* Anti-Pop Status Register */ +#define ICDC_SR_HPST_BIT 14 /* Headphone Amplifier State */ +#define ICDC_SR_HPST_MASK (0x7 << ICDC_SR_HPST_BIT) +#define ICDC_SR_HPST_HP_OFF (0x0 << ICDC_SR_HPST_BIT) /* HP amplifier is off */ +#define ICDC_SR_HPST_TON_WAIT (0x1 << ICDC_SR_HPST_BIT) /* wait state in turn-on */ + #define ICDC_SR_HPST_TON_PRE (0x2 << ICDC_SR_HPST_BIT) /* pre-enable state in turn-on */ +#define ICDC_SR_HPST_TON_HPEN (0x3 << ICDC_SR_HPST_BIT) /* HP enable state in turn-on */ + #define ICDC_SR_HPST_TOFF_HPEN (0x4 << ICDC_SR_HPST_BIT) /* HP enable state in turn-off */ + #define ICDC_SR_HPST_TOFF_PRE (0x5 << ICDC_SR_HPST_BIT) /* pre-enable state in turn-off */ + #define ICDC_SR_HPST_TOFF_WAIT (0x6 << ICDC_SR_HPST_BIT) /* wait state in turn-off */ + #define ICDC_SR_HPST_HP_ON (0x7 << ICDC_SR_HPST_BIT) /* HP amplifier is on */ +#define ICDC_SR_SNCNT_BIT 0 /* Sample Number Counter */ +#define ICDC_SR_SNCNT_MASK (0x3fff << ICDC_SR_SNCNT_BIT) + +#define ICDC_CDCCR1_ELININ (1 << 29) +#define ICDC_CDCCR1_EMIC (1 << 28) +#define ICDC_CDCCR1_SW1ON (1 << 27) +#define ICDC_CDCCR1_EADC (1 << 26) +#define ICDC_CDCCR1_SW2ON (1 << 25) +#define ICDC_CDCCR1_EDAC (1 << 24) +#define ICDC_CDCCR1_PDVR (1 << 20) +#define ICDC_CDCCR1_PDVRA (1 << 19) +#define ICDC_CDCCR1_VRPLD (1 << 18) +#define ICDC_CDCCR1_VRCGL (1 << 17) +#define ICDC_CDCCR1_VRCGH (1 << 16) +#define ICDC_CDCCR1_HPMUTE (1 << 14) +#define ICDC_CDCCR1_HPOV0 (1 << 13) +#define ICDC_CDCCR1_HPCG (1 << 12) +#define ICDC_CDCCR1_HPPLDM (1 << 11) +#define ICDC_CDCCR1_HPPLDR (1 << 10) +#define ICDC_CDCCR1_PDHPM (1 << 9) +#define ICDC_CDCCR1_PDHP (1 << 8) +#define ICDC_CDCCR1_SUSPD (1 << 1) +#define ICDC_CDCCR1_RST (1 << 0) + +#define ICDC_CDCCR2_AINVOL(n) ((n & 0x1F) << 16) +#define ICDC_CDCCR2_SMPR(n) ((n & 0xF) << 8) +#define ICDC_CDCCR2_MICBG(n) ((n & 0x3) << 4) +#define ICDC_CDCCR2_HPVOL(n) ((n & 0x3) << 0) + +#define ICDC_CDCCR2_SMPR_8 (0) +#define ICDC_CDCCR2_SMPR_11 (1) +#define ICDC_CDCCR2_SMPR_12 (2) +#define ICDC_CDCCR2_SMPR_16 (3) +#define ICDC_CDCCR2_SMPR_22 (4) +#define ICDC_CDCCR2_SMPR_24 (5) +#define ICDC_CDCCR2_SMPR_32 (6) +#define ICDC_CDCCR2_SMPR_44 (7) +#define ICDC_CDCCR2_SMPR_48 (8) + +#define ICDC_CDCCR2_HPVOL_0 (0) +#define ICDC_CDCCR2_HPVOL_2 (1) +#define ICDC_CDCCR2_HPVOL_4 (2) +#define ICDC_CDCCR2_HPVOL_6 (3) + + +/************************************************************************* + * I2C + *************************************************************************/ +#define I2C_DR (I2C_BASE + 0x000) +#define I2C_CR (I2C_BASE + 0x004) +#define I2C_SR (I2C_BASE + 0x008) +#define I2C_GR (I2C_BASE + 0x00C) + +#define REG_I2C_DR REG8(I2C_DR) +#define REG_I2C_CR REG8(I2C_CR) +#define REG_I2C_SR REG8(I2C_SR) +#define REG_I2C_GR REG16(I2C_GR) + +/* I2C Control Register (I2C_CR) */ + +#define I2C_CR_IEN (1 << 4) +#define I2C_CR_STA (1 << 3) +#define I2C_CR_STO (1 << 2) +#define I2C_CR_AC (1 << 1) +#define I2C_CR_I2CE (1 << 0) + +/* I2C Status Register (I2C_SR) */ + +#define I2C_SR_STX (1 << 4) +#define I2C_SR_BUSY (1 << 3) +#define I2C_SR_TEND (1 << 2) +#define I2C_SR_DRF (1 << 1) +#define I2C_SR_ACKF (1 << 0) + + +/************************************************************************* + * SSI + *************************************************************************/ +#define SSI_DR (SSI_BASE + 0x000) +#define SSI_CR0 (SSI_BASE + 0x004) +#define SSI_CR1 (SSI_BASE + 0x008) +#define SSI_SR (SSI_BASE + 0x00C) +#define SSI_ITR (SSI_BASE + 0x010) +#define SSI_ICR (SSI_BASE + 0x014) +#define SSI_GR (SSI_BASE + 0x018) + +#define REG_SSI_DR REG32(SSI_DR) +#define REG_SSI_CR0 REG16(SSI_CR0) +#define REG_SSI_CR1 REG32(SSI_CR1) +#define REG_SSI_SR REG32(SSI_SR) +#define REG_SSI_ITR REG16(SSI_ITR) +#define REG_SSI_ICR REG8(SSI_ICR) +#define REG_SSI_GR REG16(SSI_GR) + +/* SSI Data Register (SSI_DR) */ + +#define SSI_DR_GPC_BIT 0 +#define SSI_DR_GPC_MASK (0x1ff << SSI_DR_GPC_BIT) + +/* SSI Control Register 0 (SSI_CR0) */ + +#define SSI_CR0_SSIE (1 << 15) +#define SSI_CR0_TIE (1 << 14) +#define SSI_CR0_RIE (1 << 13) +#define SSI_CR0_TEIE (1 << 12) +#define SSI_CR0_REIE (1 << 11) +#define SSI_CR0_LOOP (1 << 10) +#define SSI_CR0_RFINE (1 << 9) +#define SSI_CR0_RFINC (1 << 8) +#define SSI_CR0_FSEL (1 << 6) +#define SSI_CR0_TFLUSH (1 << 2) +#define SSI_CR0_RFLUSH (1 << 1) +#define SSI_CR0_DISREV (1 << 0) + +/* SSI Control Register 1 (SSI_CR1) */ + +#define SSI_CR1_FRMHL_BIT 30 +#define SSI_CR1_FRMHL_MASK (0x3 << SSI_CR1_FRMHL_BIT) + #define SSI_CR1_FRMHL_CELOW_CE2LOW (0 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is low valid */ + #define SSI_CR1_FRMHL_CEHIGH_CE2LOW (1 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is low valid */ + #define SSI_CR1_FRMHL_CELOW_CE2HIGH (2 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is high valid */ + #define SSI_CR1_FRMHL_CEHIGH_CE2HIGH (3 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is high valid */ +#define SSI_CR1_TFVCK_BIT 28 +#define SSI_CR1_TFVCK_MASK (0x3 << SSI_CR1_TFVCK_BIT) + #define SSI_CR1_TFVCK_0 (0 << SSI_CR1_TFVCK_BIT) + #define SSI_CR1_TFVCK_1 (1 << SSI_CR1_TFVCK_BIT) + #define SSI_CR1_TFVCK_2 (2 << SSI_CR1_TFVCK_BIT) + #define SSI_CR1_TFVCK_3 (3 << SSI_CR1_TFVCK_BIT) +#define SSI_CR1_TCKFI_BIT 26 +#define SSI_CR1_TCKFI_MASK (0x3 << SSI_CR1_TCKFI_BIT) + #define SSI_CR1_TCKFI_0 (0 << SSI_CR1_TCKFI_BIT) + #define SSI_CR1_TCKFI_1 (1 << SSI_CR1_TCKFI_BIT) + #define SSI_CR1_TCKFI_2 (2 << SSI_CR1_TCKFI_BIT) + #define SSI_CR1_TCKFI_3 (3 << SSI_CR1_TCKFI_BIT) +#define SSI_CR1_LFST (1 << 25) +#define SSI_CR1_ITFRM (1 << 24) +#define SSI_CR1_UNFIN (1 << 23) +#define SSI_CR1_MULTS (1 << 22) +#define SSI_CR1_FMAT_BIT 20 +#define SSI_CR1_FMAT_MASK (0x3 << SSI_CR1_FMAT_BIT) + #define SSI_CR1_FMAT_SPI (0 << SSI_CR1_FMAT_BIT) /* Motorola¡¯s SPI format */ + #define SSI_CR1_FMAT_SSP (1 << SSI_CR1_FMAT_BIT) /* TI's SSP format */ + #define SSI_CR1_FMAT_MW1 (2 << SSI_CR1_FMAT_BIT) /* National Microwire 1 format */ + #define SSI_CR1_FMAT_MW2 (3 << SSI_CR1_FMAT_BIT) /* National Microwire 2 format */ +#define SSI_CR1_TTRG_BIT 16 +#define SSI_CR1_TTRG_MASK (0xf << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_1 (0 << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_8 (1 << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_16 (2 << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_24 (3 << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_32 (4 << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_40 (5 << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_48 (6 << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_56 (7 << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_64 (8 << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_72 (9 << SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_80 (10<< SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_88 (11<< SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_96 (12<< SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_104 (13<< SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_112 (14<< SSI_CR1_TTRG_BIT) + #define SSI_CR1_TTRG_120 (15<< SSI_CR1_TTRG_BIT) +#define SSI_CR1_MCOM_BIT 12 +#define SSI_CR1_MCOM_MASK (0xf << SSI_CR1_MCOM_BIT) + #define SSI_CR1_MCOM_1BIT (0x0 << SSI_CR1_MCOM_BIT) /* 1-bit command selected */ + #define SSI_CR1_MCOM_2BIT (0x1 << SSI_CR1_MCOM_BIT) /* 2-bit command selected */ + #define SSI_CR1_MCOM_3BIT (0x2 << SSI_CR1_MCOM_BIT) /* 3-bit command selected */ + #define SSI_CR1_MCOM_4BIT (0x3 << SSI_CR1_MCOM_BIT) /* 4-bit command selected */ + #define SSI_CR1_MCOM_5BIT (0x4 << SSI_CR1_MCOM_BIT) /* 5-bit command selected */ + #define SSI_CR1_MCOM_6BIT (0x5 << SSI_CR1_MCOM_BIT) /* 6-bit command selected */ + #define SSI_CR1_MCOM_7BIT (0x6 << SSI_CR1_MCOM_BIT) /* 7-bit command selected */ + #define SSI_CR1_MCOM_8BIT (0x7 << SSI_CR1_MCOM_BIT) /* 8-bit command selected */ + #define SSI_CR1_MCOM_9BIT (0x8 << SSI_CR1_MCOM_BIT) /* 9-bit command selected */ + #define SSI_CR1_MCOM_10BIT (0x9 << SSI_CR1_MCOM_BIT) /* 10-bit command selected */ + #define SSI_CR1_MCOM_11BIT (0xA << SSI_CR1_MCOM_BIT) /* 11-bit command selected */ + #define SSI_CR1_MCOM_12BIT (0xB << SSI_CR1_MCOM_BIT) /* 12-bit command selected */ + #define SSI_CR1_MCOM_13BIT (0xC << SSI_CR1_MCOM_BIT) /* 13-bit command selected */ + #define SSI_CR1_MCOM_14BIT (0xD << SSI_CR1_MCOM_BIT) /* 14-bit command selected */ + #define SSI_CR1_MCOM_15BIT (0xE << SSI_CR1_MCOM_BIT) /* 15-bit command selected */ + #define SSI_CR1_MCOM_16BIT (0xF << SSI_CR1_MCOM_BIT) /* 16-bit command selected */ +#define SSI_CR1_RTRG_BIT 8 +#define SSI_CR1_RTRG_MASK (0xf << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_1 (0 << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_8 (1 << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_16 (2 << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_24 (3 << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_32 (4 << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_40 (5 << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_48 (6 << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_56 (7 << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_64 (8 << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_72 (9 << SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_80 (10<< SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_88 (11<< SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_96 (12<< SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_104 (13<< SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_112 (14<< SSI_CR1_RTRG_BIT) + #define SSI_CR1_RTRG_120 (15<< SSI_CR1_RTRG_BIT) +#define SSI_CR1_FLEN_BIT 4 +#define SSI_CR1_FLEN_MASK (0xf << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_2BIT (0x0 << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_3BIT (0x1 << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_4BIT (0x2 << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_5BIT (0x3 << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_6BIT (0x4 << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_7BIT (0x5 << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_8BIT (0x6 << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_9BIT (0x7 << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_10BIT (0x8 << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_11BIT (0x9 << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_12BIT (0xA << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_13BIT (0xB << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_14BIT (0xC << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_15BIT (0xD << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_16BIT (0xE << SSI_CR1_FLEN_BIT) + #define SSI_CR1_FLEN_17BIT (0xF << SSI_CR1_FLEN_BIT) +#define SSI_CR1_PHA (1 << 1) +#define SSI_CR1_POL (1 << 0) + +/* SSI Status Register (SSI_SR) */ + +#define SSI_SR_TFIFONUM_BIT 16 +#define SSI_SR_TFIFONUM_MASK (0xff << SSI_SR_TFIFONUM_BIT) +#define SSI_SR_RFIFONUM_BIT 8 +#define SSI_SR_RFIFONUM_MASK (0xff << SSI_SR_RFIFONUM_BIT) +#define SSI_SR_END (1 << 7) +#define SSI_SR_BUSY (1 << 6) +#define SSI_SR_TFF (1 << 5) +#define SSI_SR_RFE (1 << 4) +#define SSI_SR_TFHE (1 << 3) +#define SSI_SR_RFHF (1 << 2) +#define SSI_SR_UNDR (1 << 1) +#define SSI_SR_OVER (1 << 0) + +/* SSI Interval Time Control Register (SSI_ITR) */ + +#define SSI_ITR_CNTCLK (1 << 15) +#define SSI_ITR_IVLTM_BIT 0 +#define SSI_ITR_IVLTM_MASK (0x7fff << SSI_ITR_IVLTM_BIT) + + +/************************************************************************* + * MSC + *************************************************************************/ +#define MSC_STRPCL (MSC_BASE + 0x000) +#define MSC_STAT (MSC_BASE + 0x004) +#define MSC_CLKRT (MSC_BASE + 0x008) +#define MSC_CMDAT (MSC_BASE + 0x00C) +#define MSC_RESTO (MSC_BASE + 0x010) +#define MSC_RDTO (MSC_BASE + 0x014) +#define MSC_BLKLEN (MSC_BASE + 0x018) +#define MSC_NOB (MSC_BASE + 0x01C) +#define MSC_SNOB (MSC_BASE + 0x020) +#define MSC_IMASK (MSC_BASE + 0x024) +#define MSC_IREG (MSC_BASE + 0x028) +#define MSC_CMD (MSC_BASE + 0x02C) +#define MSC_ARG (MSC_BASE + 0x030) +#define MSC_RES (MSC_BASE + 0x034) +#define MSC_RXFIFO (MSC_BASE + 0x038) +#define MSC_TXFIFO (MSC_BASE + 0x03C) + +#define REG_MSC_STRPCL REG16(MSC_STRPCL) +#define REG_MSC_STAT REG32(MSC_STAT) +#define REG_MSC_CLKRT REG16(MSC_CLKRT) +#define REG_MSC_CMDAT REG32(MSC_CMDAT) +#define REG_MSC_RESTO REG16(MSC_RESTO) +#define REG_MSC_RDTO REG16(MSC_RDTO) +#define REG_MSC_BLKLEN REG16(MSC_BLKLEN) +#define REG_MSC_NOB REG16(MSC_NOB) +#define REG_MSC_SNOB REG16(MSC_SNOB) +#define REG_MSC_IMASK REG16(MSC_IMASK) +#define REG_MSC_IREG REG16(MSC_IREG) +#define REG_MSC_CMD REG8(MSC_CMD) +#define REG_MSC_ARG REG32(MSC_ARG) +#define REG_MSC_RES REG16(MSC_RES) +#define REG_MSC_RXFIFO REG32(MSC_RXFIFO) +#define REG_MSC_TXFIFO REG32(MSC_TXFIFO) + +/* MSC Clock and Control Register (MSC_STRPCL) */ + +#define MSC_STRPCL_EXIT_MULTIPLE (1 << 7) +#define MSC_STRPCL_EXIT_TRANSFER (1 << 6) +#define MSC_STRPCL_START_READWAIT (1 << 5) +#define MSC_STRPCL_STOP_READWAIT (1 << 4) +#define MSC_STRPCL_RESET (1 << 3) +#define MSC_STRPCL_START_OP (1 << 2) +#define MSC_STRPCL_CLOCK_CONTROL_BIT 0 +#define MSC_STRPCL_CLOCK_CONTROL_MASK (0x3 << MSC_STRPCL_CLOCK_CONTROL_BIT) + #define MSC_STRPCL_CLOCK_CONTROL_STOP (0x1 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Stop MMC/SD clock */ + #define MSC_STRPCL_CLOCK_CONTROL_START (0x2 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Start MMC/SD clock */ + +/* MSC Status Register (MSC_STAT) */ + +#define MSC_STAT_IS_RESETTING (1 << 15) +#define MSC_STAT_SDIO_INT_ACTIVE (1 << 14) +#define MSC_STAT_PRG_DONE (1 << 13) +#define MSC_STAT_DATA_TRAN_DONE (1 << 12) +#define MSC_STAT_END_CMD_RES (1 << 11) +#define MSC_STAT_DATA_FIFO_AFULL (1 << 10) +#define MSC_STAT_IS_READWAIT (1 << 9) +#define MSC_STAT_CLK_EN (1 << 8) +#define MSC_STAT_DATA_FIFO_FULL (1 << 7) +#define MSC_STAT_DATA_FIFO_EMPTY (1 << 6) +#define MSC_STAT_CRC_RES_ERR (1 << 5) +#define MSC_STAT_CRC_READ_ERROR (1 << 4) +#define MSC_STAT_CRC_WRITE_ERROR_BIT 2 +#define MSC_STAT_CRC_WRITE_ERROR_MASK (0x3 << MSC_STAT_CRC_WRITE_ERROR_BIT) + #define MSC_STAT_CRC_WRITE_ERROR_NO (0 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No error on transmission of data */ + #define MSC_STAT_CRC_WRITE_ERROR (1 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* Card observed erroneous transmission of data */ + #define MSC_STAT_CRC_WRITE_ERROR_NOSTS (2 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No CRC status is sent back */ +#define MSC_STAT_TIME_OUT_RES (1 << 1) +#define MSC_STAT_TIME_OUT_READ (1 << 0) + +/* MSC Bus Clock Control Register (MSC_CLKRT) */ + +#define MSC_CLKRT_CLK_RATE_BIT 0 +#define MSC_CLKRT_CLK_RATE_MASK (0x7 << MSC_CLKRT_CLK_RATE_BIT) + #define MSC_CLKRT_CLK_RATE_DIV_1 (0x0 << MSC_CLKRT_CLK_RATE_BIT) /* CLK_SRC */ + #define MSC_CLKRT_CLK_RATE_DIV_2 (0x1 << MSC_CLKRT_CLK_RATE_BIT) /* 1/2 of CLK_SRC */ + #define MSC_CLKRT_CLK_RATE_DIV_4 (0x2 << MSC_CLKRT_CLK_RATE_BIT) /* 1/4 of CLK_SRC */ + #define MSC_CLKRT_CLK_RATE_DIV_8 (0x3 << MSC_CLKRT_CLK_RATE_BIT) /* 1/8 of CLK_SRC */ + #define MSC_CLKRT_CLK_RATE_DIV_16 (0x4 << MSC_CLKRT_CLK_RATE_BIT) /* 1/16 of CLK_SRC */ + #define MSC_CLKRT_CLK_RATE_DIV_32 (0x5 << MSC_CLKRT_CLK_RATE_BIT) /* 1/32 of CLK_SRC */ + #define MSC_CLKRT_CLK_RATE_DIV_64 (0x6 << MSC_CLKRT_CLK_RATE_BIT) /* 1/64 of CLK_SRC */ + #define MSC_CLKRT_CLK_RATE_DIV_128 (0x7 << MSC_CLKRT_CLK_RATE_BIT) /* 1/128 of CLK_SRC */ + +/* MSC Command Sequence Control Register (MSC_CMDAT) */ + +#define MSC_CMDAT_IO_ABORT (1 << 11) +#define MSC_CMDAT_BUS_WIDTH_BIT 9 +#define MSC_CMDAT_BUS_WIDTH_MASK (0x3 << MSC_CMDAT_BUS_WIDTH_BIT) + #define MSC_CMDAT_BUS_WIDTH_1BIT (0x0 << MSC_CMDAT_BUS_WIDTH_BIT) /* 1-bit data bus */ + #define MSC_CMDAT_BUS_WIDTH_4BIT (0x2 << MSC_CMDAT_BUS_WIDTH_BIT) /* 4-bit data bus */ + #define CMDAT_BUS_WIDTH1 (0x0 << MSC_CMDAT_BUS_WIDTH_BIT) + #define CMDAT_BUS_WIDTH4 (0x2 << MSC_CMDAT_BUS_WIDTH_BIT) +#define MSC_CMDAT_DMA_EN (1 << 8) +#define MSC_CMDAT_INIT (1 << 7) +#define MSC_CMDAT_BUSY (1 << 6) +#define MSC_CMDAT_STREAM_BLOCK (1 << 5) +#define MSC_CMDAT_WRITE (1 << 4) +#define MSC_CMDAT_READ (0 << 4) +#define MSC_CMDAT_DATA_EN (1 << 3) +#define MSC_CMDAT_RESPONSE_BIT 0 +#define MSC_CMDAT_RESPONSE_MASK (0x7 << MSC_CMDAT_RESPONSE_BIT) + #define MSC_CMDAT_RESPONSE_NONE (0x0 << MSC_CMDAT_RESPONSE_BIT) /* No response */ + #define MSC_CMDAT_RESPONSE_R1 (0x1 << MSC_CMDAT_RESPONSE_BIT) /* Format R1 and R1b */ + #define MSC_CMDAT_RESPONSE_R2 (0x2 << MSC_CMDAT_RESPONSE_BIT) /* Format R2 */ + #define MSC_CMDAT_RESPONSE_R3 (0x3 << MSC_CMDAT_RESPONSE_BIT) /* Format R3 */ + #define MSC_CMDAT_RESPONSE_R4 (0x4 << MSC_CMDAT_RESPONSE_BIT) /* Format R4 */ + #define MSC_CMDAT_RESPONSE_R5 (0x5 << MSC_CMDAT_RESPONSE_BIT) /* Format R5 */ + #define MSC_CMDAT_RESPONSE_R6 (0x6 << MSC_CMDAT_RESPONSE_BIT) /* Format R6 */ + +#define CMDAT_DMA_EN (1 << 8) +#define CMDAT_INIT (1 << 7) +#define CMDAT_BUSY (1 << 6) +#define CMDAT_STREAM (1 << 5) +#define CMDAT_WRITE (1 << 4) +#define CMDAT_DATA_EN (1 << 3) + +/* MSC Interrupts Mask Register (MSC_IMASK) */ + +#define MSC_IMASK_SDIO (1 << 7) +#define MSC_IMASK_TXFIFO_WR_REQ (1 << 6) +#define MSC_IMASK_RXFIFO_RD_REQ (1 << 5) +#define MSC_IMASK_END_CMD_RES (1 << 2) +#define MSC_IMASK_PRG_DONE (1 << 1) +#define MSC_IMASK_DATA_TRAN_DONE (1 << 0) + + +/* MSC Interrupts Status Register (MSC_IREG) */ + +#define MSC_IREG_SDIO (1 << 7) +#define MSC_IREG_TXFIFO_WR_REQ (1 << 6) +#define MSC_IREG_RXFIFO_RD_REQ (1 << 5) +#define MSC_IREG_END_CMD_RES (1 << 2) +#define MSC_IREG_PRG_DONE (1 << 1) +#define MSC_IREG_DATA_TRAN_DONE (1 << 0) + + +/************************************************************************* + * EMC (External Memory Controller) + *************************************************************************/ +#define EMC_BCR (EMC_BASE + 0x0) /* BCR */ + +#define EMC_SMCR0 (EMC_BASE + 0x10) /* Static Memory Control Register 0 */ +#define EMC_SMCR1 (EMC_BASE + 0x14) /* Static Memory Control Register 1 */ +#define EMC_SMCR2 (EMC_BASE + 0x18) /* Static Memory Control Register 2 */ +#define EMC_SMCR3 (EMC_BASE + 0x1c) /* Static Memory Control Register 3 */ +#define EMC_SMCR4 (EMC_BASE + 0x20) /* Static Memory Control Register 4 */ +#define EMC_SACR0 (EMC_BASE + 0x30) /* Static Memory Bank 0 Addr Config Reg */ +#define EMC_SACR1 (EMC_BASE + 0x34) /* Static Memory Bank 1 Addr Config Reg */ +#define EMC_SACR2 (EMC_BASE + 0x38) /* Static Memory Bank 2 Addr Config Reg */ +#define EMC_SACR3 (EMC_BASE + 0x3c) /* Static Memory Bank 3 Addr Config Reg */ +#define EMC_SACR4 (EMC_BASE + 0x40) /* Static Memory Bank 4 Addr Config Reg */ + +#define EMC_NFCSR (EMC_BASE + 0x050) /* NAND Flash Control/Status Register */ +#define EMC_NFECR (EMC_BASE + 0x100) /* NAND Flash ECC Control Register */ +#define EMC_NFECC (EMC_BASE + 0x104) /* NAND Flash ECC Data Register */ +#define EMC_NFPAR0 (EMC_BASE + 0x108) /* NAND Flash RS Parity 0 Register */ +#define EMC_NFPAR1 (EMC_BASE + 0x10c) /* NAND Flash RS Parity 1 Register */ +#define EMC_NFPAR2 (EMC_BASE + 0x110) /* NAND Flash RS Parity 2 Register */ +#define EMC_NFINTS (EMC_BASE + 0x114) /* NAND Flash Interrupt Status Register */ +#define EMC_NFINTE (EMC_BASE + 0x118) /* NAND Flash Interrupt Enable Register */ +#define EMC_NFERR0 (EMC_BASE + 0x11c) /* NAND Flash RS Error Report 0 Register */ +#define EMC_NFERR1 (EMC_BASE + 0x120) /* NAND Flash RS Error Report 1 Register */ +#define EMC_NFERR2 (EMC_BASE + 0x124) /* NAND Flash RS Error Report 2 Register */ +#define EMC_NFERR3 (EMC_BASE + 0x128) /* NAND Flash RS Error Report 3 Register */ + +#define EMC_DMCR (EMC_BASE + 0x80) /* DRAM Control Register */ +#define EMC_RTCSR (EMC_BASE + 0x84) /* Refresh Time Control/Status Register */ +#define EMC_RTCNT (EMC_BASE + 0x88) /* Refresh Timer Counter */ +#define EMC_RTCOR (EMC_BASE + 0x8c) /* Refresh Time Constant Register */ +#define EMC_DMAR0 (EMC_BASE + 0x90) /* SDRAM Bank 0 Addr Config Register */ +#define EMC_SDMR0 (EMC_BASE + 0xa000) /* Mode Register of SDRAM bank 0 */ + +#define REG_EMC_BCR REG32(EMC_BCR) + +#define REG_EMC_SMCR0 REG32(EMC_SMCR0) +#define REG_EMC_SMCR1 REG32(EMC_SMCR1) +#define REG_EMC_SMCR2 REG32(EMC_SMCR2) +#define REG_EMC_SMCR3 REG32(EMC_SMCR3) +#define REG_EMC_SMCR4 REG32(EMC_SMCR4) +#define REG_EMC_SACR0 REG32(EMC_SACR0) +#define REG_EMC_SACR1 REG32(EMC_SACR1) +#define REG_EMC_SACR2 REG32(EMC_SACR2) +#define REG_EMC_SACR3 REG32(EMC_SACR3) +#define REG_EMC_SACR4 REG32(EMC_SACR4) + +#define REG_EMC_NFCSR REG32(EMC_NFCSR) +#define REG_EMC_NFECR REG32(EMC_NFECR) +#define REG_EMC_NFECC REG32(EMC_NFECC) +#define REG_EMC_NFPAR0 REG32(EMC_NFPAR0) +#define REG_EMC_NFPAR1 REG32(EMC_NFPAR1) +#define REG_EMC_NFPAR2 REG32(EMC_NFPAR2) +#define REG_EMC_NFINTS REG32(EMC_NFINTS) +#define REG_EMC_NFINTE REG32(EMC_NFINTE) +#define REG_EMC_NFERR0 REG32(EMC_NFERR0) +#define REG_EMC_NFERR1 REG32(EMC_NFERR1) +#define REG_EMC_NFERR2 REG32(EMC_NFERR2) +#define REG_EMC_NFERR3 REG32(EMC_NFERR3) + +#define REG_EMC_DMCR REG32(EMC_DMCR) +#define REG_EMC_RTCSR REG16(EMC_RTCSR) +#define REG_EMC_RTCNT REG16(EMC_RTCNT) +#define REG_EMC_RTCOR REG16(EMC_RTCOR) +#define REG_EMC_DMAR0 REG32(EMC_DMAR0) + +/* Static Memory Control Register */ +#define EMC_SMCR_STRV_BIT 24 +#define EMC_SMCR_STRV_MASK (0x0f << EMC_SMCR_STRV_BIT) +#define EMC_SMCR_TAW_BIT 20 +#define EMC_SMCR_TAW_MASK (0x0f << EMC_SMCR_TAW_BIT) +#define EMC_SMCR_TBP_BIT 16 +#define EMC_SMCR_TBP_MASK (0x0f << EMC_SMCR_TBP_BIT) +#define EMC_SMCR_TAH_BIT 12 +#define EMC_SMCR_TAH_MASK (0x07 << EMC_SMCR_TAH_BIT) +#define EMC_SMCR_TAS_BIT 8 +#define EMC_SMCR_TAS_MASK (0x07 << EMC_SMCR_TAS_BIT) +#define EMC_SMCR_BW_BIT 6 +#define EMC_SMCR_BW_MASK (0x03 << EMC_SMCR_BW_BIT) /* Bus Width? */ + #define EMC_SMCR_BW_8BIT (0 << EMC_SMCR_BW_BIT) + #define EMC_SMCR_BW_16BIT (1 << EMC_SMCR_BW_BIT) + #define EMC_SMCR_BW_32BIT (2 << EMC_SMCR_BW_BIT) +#define EMC_SMCR_BCM (1 << 3) +#define EMC_SMCR_BL_BIT 1 +#define EMC_SMCR_BL_MASK (0x03 << EMC_SMCR_BL_BIT) /* Bus Latency? */ + #define EMC_SMCR_BL_4 (0 << EMC_SMCR_BL_BIT) + #define EMC_SMCR_BL_8 (1 << EMC_SMCR_BL_BIT) + #define EMC_SMCR_BL_16 (2 << EMC_SMCR_BL_BIT) + #define EMC_SMCR_BL_32 (3 << EMC_SMCR_BL_BIT) +#define EMC_SMCR_SMT (1 << 0) + +/* Static Memory Bank Addr Config Reg */ +#define EMC_SACR_BASE_BIT 8 +#define EMC_SACR_BASE_MASK (0xff << EMC_SACR_BASE_BIT) +#define EMC_SACR_MASK_BIT 0 +#define EMC_SACR_MASK_MASK (0xff << EMC_SACR_MASK_BIT) + +/* NAND Flash Control/Status Register */ +#define EMC_NFCSR_NFCE4 (1 << 7) /* NAND Flash Enable */ +#define EMC_NFCSR_NFE4 (1 << 6) /* NAND Flash FCE# Assertion Enable */ +#define EMC_NFCSR_NFCE3 (1 << 5) +#define EMC_NFCSR_NFE3 (1 << 4) +#define EMC_NFCSR_NFCE2 (1 << 3) +#define EMC_NFCSR_NFE2 (1 << 2) +#define EMC_NFCSR_NFCE1 (1 << 1) +#define EMC_NFCSR_NFE1 (1 << 0) +#define EMC_NFCSR_NFE(n) (1 << (((n)-1)*2)) +#define EMC_NFCSR_NFCE(n) (1 << (((n)*2)-1)) + +/* NAND Flash ECC Control Register */ +#define EMC_NFECR_PRDY (1 << 4) /* Parity Ready */ +#define EMC_NFECR_RS_DECODING (0 << 3) /* RS is in decoding phase */ +#define EMC_NFECR_RS_ENCODING (1 << 3) /* RS is in encoding phase */ +#define EMC_NFECR_HAMMING (0 << 2) /* Select HAMMING Correction Algorithm */ +#define EMC_NFECR_RS (1 << 2) /* Select RS Correction Algorithm */ +#define EMC_NFECR_ERST (1 << 1) /* ECC Reset */ +#define EMC_NFECR_ECCE (1 << 0) /* ECC Enable */ + +/* NAND Flash ECC Data Register */ +#define EMC_NFECC_ECC2_BIT 16 +#define EMC_NFECC_ECC2_MASK (0xff << EMC_NFECC_ECC2_BIT) +#define EMC_NFECC_ECC1_BIT 8 +#define EMC_NFECC_ECC1_MASK (0xff << EMC_NFECC_ECC1_BIT) +#define EMC_NFECC_ECC0_BIT 0 +#define EMC_NFECC_ECC0_MASK (0xff << EMC_NFECC_ECC0_BIT) + +/* NAND Flash Interrupt Status Register */ +#define EMC_NFINTS_ERRCNT_BIT 29 /* Error Count */ +#define EMC_NFINTS_ERRCNT_MASK (0x7 << EMC_NFINTS_ERRCNT_BIT) +#define EMC_NFINTS_PADF (1 << 4) /* Padding Finished */ +#define EMC_NFINTS_DECF (1 << 3) /* Decoding Finished */ +#define EMC_NFINTS_ENCF (1 << 2) /* Encoding Finished */ +#define EMC_NFINTS_UNCOR (1 << 1) /* Uncorrectable Error Occurred */ +#define EMC_NFINTS_ERR (1 << 0) /* Error Occurred */ + +/* NAND Flash Interrupt Enable Register */ +#define EMC_NFINTE_PADFE (1 << 4) /* Padding Finished Interrupt Enable */ +#define EMC_NFINTE_DECFE (1 << 3) /* Decoding Finished Interrupt Enable */ +#define EMC_NFINTE_ENCFE (1 << 2) /* Encoding Finished Interrupt Enable */ +#define EMC_NFINTE_UNCORE (1 << 1) /* Uncorrectable Error Occurred Intr Enable */ +#define EMC_NFINTE_ERRE (1 << 0) /* Error Occurred Interrupt */ + +/* NAND Flash RS Error Report Register */ +#define EMC_NFERR_INDEX_BIT 16 /* Error Symbol Index */ +#define EMC_NFERR_INDEX_MASK (0x1ff << EMC_NFERR_INDEX_BIT) +#define EMC_NFERR_MASK_BIT 0 /* Error Symbol Value */ +#define EMC_NFERR_MASK_MASK (0x1ff << EMC_NFERR_MASK_BIT) + + +/* DRAM Control Register */ +#define EMC_DMCR_BW_BIT 31 +#define EMC_DMCR_BW (1 << EMC_DMCR_BW_BIT) +#define EMC_DMCR_CA_BIT 26 +#define EMC_DMCR_CA_MASK (0x07 << EMC_DMCR_CA_BIT) + #define EMC_DMCR_CA_8 (0 << EMC_DMCR_CA_BIT) + #define EMC_DMCR_CA_9 (1 << EMC_DMCR_CA_BIT) + #define EMC_DMCR_CA_10 (2 << EMC_DMCR_CA_BIT) + #define EMC_DMCR_CA_11 (3 << EMC_DMCR_CA_BIT) + #define EMC_DMCR_CA_12 (4 << EMC_DMCR_CA_BIT) +#define EMC_DMCR_RMODE (1 << 25) +#define EMC_DMCR_RFSH (1 << 24) +#define EMC_DMCR_MRSET (1 << 23) +#define EMC_DMCR_RA_BIT 20 +#define EMC_DMCR_RA_MASK (0x03 << EMC_DMCR_RA_BIT) + #define EMC_DMCR_RA_11 (0 << EMC_DMCR_RA_BIT) + #define EMC_DMCR_RA_12 (1 << EMC_DMCR_RA_BIT) + #define EMC_DMCR_RA_13 (2 << EMC_DMCR_RA_BIT) +#define EMC_DMCR_BA_BIT 19 +#define EMC_DMCR_BA (1 << EMC_DMCR_BA_BIT) +#define EMC_DMCR_PDM (1 << 18) +#define EMC_DMCR_EPIN (1 << 17) +#define EMC_DMCR_TRAS_BIT 13 +#define EMC_DMCR_TRAS_MASK (0x07 << EMC_DMCR_TRAS_BIT) +#define EMC_DMCR_RCD_BIT 11 +#define EMC_DMCR_RCD_MASK (0x03 << EMC_DMCR_RCD_BIT) +#define EMC_DMCR_TPC_BIT 8 +#define EMC_DMCR_TPC_MASK (0x07 << EMC_DMCR_TPC_BIT) +#define EMC_DMCR_TRWL_BIT 5 +#define EMC_DMCR_TRWL_MASK (0x03 << EMC_DMCR_TRWL_BIT) +#define EMC_DMCR_TRC_BIT 2 +#define EMC_DMCR_TRC_MASK (0x07 << EMC_DMCR_TRC_BIT) +#define EMC_DMCR_TCL_BIT 0 +#define EMC_DMCR_TCL_MASK (0x03 << EMC_DMCR_TCL_BIT) + +/* Refresh Time Control/Status Register */ +#define EMC_RTCSR_CMF (1 << 7) +#define EMC_RTCSR_CKS_BIT 0 +#define EMC_RTCSR_CKS_MASK (0x07 << EMC_RTCSR_CKS_BIT) + #define EMC_RTCSR_CKS_DISABLE (0 << EMC_RTCSR_CKS_BIT) + #define EMC_RTCSR_CKS_4 (1 << EMC_RTCSR_CKS_BIT) + #define EMC_RTCSR_CKS_16 (2 << EMC_RTCSR_CKS_BIT) + #define EMC_RTCSR_CKS_64 (3 << EMC_RTCSR_CKS_BIT) + #define EMC_RTCSR_CKS_256 (4 << EMC_RTCSR_CKS_BIT) + #define EMC_RTCSR_CKS_1024 (5 << EMC_RTCSR_CKS_BIT) + #define EMC_RTCSR_CKS_2048 (6 << EMC_RTCSR_CKS_BIT) + #define EMC_RTCSR_CKS_4096 (7 << EMC_RTCSR_CKS_BIT) + +/* SDRAM Bank Address Configuration Register */ +#define EMC_DMAR_BASE_BIT 8 +#define EMC_DMAR_BASE_MASK (0xff << EMC_DMAR_BASE_BIT) +#define EMC_DMAR_MASK_BIT 0 +#define EMC_DMAR_MASK_MASK (0xff << EMC_DMAR_MASK_BIT) + +/* Mode Register of SDRAM bank 0 */ +#define EMC_SDMR_BM (1 << 9) /* Write Burst Mode */ +#define EMC_SDMR_OM_BIT 7 /* Operating Mode */ +#define EMC_SDMR_OM_MASK (3 << EMC_SDMR_OM_BIT) + #define EMC_SDMR_OM_NORMAL (0 << EMC_SDMR_OM_BIT) +#define EMC_SDMR_CAS_BIT 4 /* CAS Latency */ +#define EMC_SDMR_CAS_MASK (7 << EMC_SDMR_CAS_BIT) + #define EMC_SDMR_CAS_1 (1 << EMC_SDMR_CAS_BIT) + #define EMC_SDMR_CAS_2 (2 << EMC_SDMR_CAS_BIT) + #define EMC_SDMR_CAS_3 (3 << EMC_SDMR_CAS_BIT) +#define EMC_SDMR_BT_BIT 3 /* Burst Type */ +#define EMC_SDMR_BT_MASK (1 << EMC_SDMR_BT_BIT) + #define EMC_SDMR_BT_SEQ (0 << EMC_SDMR_BT_BIT) /* Sequential */ + #define EMC_SDMR_BT_INT (1 << EMC_SDMR_BT_BIT) /* Interleave */ +#define EMC_SDMR_BL_BIT 0 /* Burst Length */ +#define EMC_SDMR_BL_MASK (7 << EMC_SDMR_BL_BIT) + #define EMC_SDMR_BL_1 (0 << EMC_SDMR_BL_BIT) + #define EMC_SDMR_BL_2 (1 << EMC_SDMR_BL_BIT) + #define EMC_SDMR_BL_4 (2 << EMC_SDMR_BL_BIT) + #define EMC_SDMR_BL_8 (3 << EMC_SDMR_BL_BIT) + +#define EMC_SDMR_CAS2_16BIT \ + (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2) +#define EMC_SDMR_CAS2_32BIT \ + (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4) +#define EMC_SDMR_CAS3_16BIT \ + (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2) +#define EMC_SDMR_CAS3_32BIT \ + (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4) + + +/************************************************************************* + * CIM + *************************************************************************/ +#define CIM_CFG (CIM_BASE + 0x0000) +#define CIM_CTRL (CIM_BASE + 0x0004) +#define CIM_STATE (CIM_BASE + 0x0008) +#define CIM_IID (CIM_BASE + 0x000C) +#define CIM_RXFIFO (CIM_BASE + 0x0010) +#define CIM_DA (CIM_BASE + 0x0020) +#define CIM_FA (CIM_BASE + 0x0024) +#define CIM_FID (CIM_BASE + 0x0028) +#define CIM_CMD (CIM_BASE + 0x002C) + +#define REG_CIM_CFG REG32(CIM_CFG) +#define REG_CIM_CTRL REG32(CIM_CTRL) +#define REG_CIM_STATE REG32(CIM_STATE) +#define REG_CIM_IID REG32(CIM_IID) +#define REG_CIM_RXFIFO REG32(CIM_RXFIFO) +#define REG_CIM_DA REG32(CIM_DA) +#define REG_CIM_FA REG32(CIM_FA) +#define REG_CIM_FID REG32(CIM_FID) +#define REG_CIM_CMD REG32(CIM_CMD) + +/* CIM Configuration Register (CIM_CFG) */ + +#define CIM_CFG_INV_DAT (1 << 15) +#define CIM_CFG_VSP (1 << 14) +#define CIM_CFG_HSP (1 << 13) +#define CIM_CFG_PCP (1 << 12) +#define CIM_CFG_DUMMY_ZERO (1 << 9) +#define CIM_CFG_EXT_VSYNC (1 << 8) +#define CIM_CFG_PACK_BIT 4 +#define CIM_CFG_PACK_MASK (0x7 << CIM_CFG_PACK_BIT) + #define CIM_CFG_PACK_0 (0 << CIM_CFG_PACK_BIT) + #define CIM_CFG_PACK_1 (1 << CIM_CFG_PACK_BIT) + #define CIM_CFG_PACK_2 (2 << CIM_CFG_PACK_BIT) + #define CIM_CFG_PACK_3 (3 << CIM_CFG_PACK_BIT) + #define CIM_CFG_PACK_4 (4 << CIM_CFG_PACK_BIT) + #define CIM_CFG_PACK_5 (5 << CIM_CFG_PACK_BIT) + #define CIM_CFG_PACK_6 (6 << CIM_CFG_PACK_BIT) + #define CIM_CFG_PACK_7 (7 << CIM_CFG_PACK_BIT) +#define CIM_CFG_DSM_BIT 0 +#define CIM_CFG_DSM_MASK (0x3 << CIM_CFG_DSM_BIT) + #define CIM_CFG_DSM_CPM (0 << CIM_CFG_DSM_BIT) /* CCIR656 Progressive Mode */ + #define CIM_CFG_DSM_CIM (1 << CIM_CFG_DSM_BIT) /* CCIR656 Interlace Mode */ + #define CIM_CFG_DSM_GCM (2 << CIM_CFG_DSM_BIT) /* Gated Clock Mode */ + #define CIM_CFG_DSM_NGCM (3 << CIM_CFG_DSM_BIT) /* Non-Gated Clock Mode */ + +/* CIM Control Register (CIM_CTRL) */ + +#define CIM_CTRL_MCLKDIV_BIT 24 +#define CIM_CTRL_MCLKDIV_MASK (0xff << CIM_CTRL_MCLKDIV_BIT) +#define CIM_CTRL_FRC_BIT 16 +#define CIM_CTRL_FRC_MASK (0xf << CIM_CTRL_FRC_BIT) + #define CIM_CTRL_FRC_1 (0x0 << CIM_CTRL_FRC_BIT) /* Sample every frame */ + #define CIM_CTRL_FRC_2 (0x1 << CIM_CTRL_FRC_BIT) /* Sample 1/2 frame */ + #define CIM_CTRL_FRC_3 (0x2 << CIM_CTRL_FRC_BIT) /* Sample 1/3 frame */ + #define CIM_CTRL_FRC_4 (0x3 << CIM_CTRL_FRC_BIT) /* Sample 1/4 frame */ + #define CIM_CTRL_FRC_5 (0x4 << CIM_CTRL_FRC_BIT) /* Sample 1/5 frame */ + #define CIM_CTRL_FRC_6 (0x5 << CIM_CTRL_FRC_BIT) /* Sample 1/6 frame */ + #define CIM_CTRL_FRC_7 (0x6 << CIM_CTRL_FRC_BIT) /* Sample 1/7 frame */ + #define CIM_CTRL_FRC_8 (0x7 << CIM_CTRL_FRC_BIT) /* Sample 1/8 frame */ + #define CIM_CTRL_FRC_9 (0x8 << CIM_CTRL_FRC_BIT) /* Sample 1/9 frame */ + #define CIM_CTRL_FRC_10 (0x9 << CIM_CTRL_FRC_BIT) /* Sample 1/10 frame */ + #define CIM_CTRL_FRC_11 (0xA << CIM_CTRL_FRC_BIT) /* Sample 1/11 frame */ + #define CIM_CTRL_FRC_12 (0xB << CIM_CTRL_FRC_BIT) /* Sample 1/12 frame */ + #define CIM_CTRL_FRC_13 (0xC << CIM_CTRL_FRC_BIT) /* Sample 1/13 frame */ + #define CIM_CTRL_FRC_14 (0xD << CIM_CTRL_FRC_BIT) /* Sample 1/14 frame */ + #define CIM_CTRL_FRC_15 (0xE << CIM_CTRL_FRC_BIT) /* Sample 1/15 frame */ + #define CIM_CTRL_FRC_16 (0xF << CIM_CTRL_FRC_BIT) /* Sample 1/16 frame */ +#define CIM_CTRL_VDDM (1 << 13) +#define CIM_CTRL_DMA_SOFM (1 << 12) +#define CIM_CTRL_DMA_EOFM (1 << 11) +#define CIM_CTRL_DMA_STOPM (1 << 10) +#define CIM_CTRL_RXF_TRIGM (1 << 9) +#define CIM_CTRL_RXF_OFM (1 << 8) +#define CIM_CTRL_RXF_TRIG_BIT 4 +#define CIM_CTRL_RXF_TRIG_MASK (0x7 << CIM_CTRL_RXF_TRIG_BIT) + #define CIM_CTRL_RXF_TRIG_4 (0 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 4 */ + #define CIM_CTRL_RXF_TRIG_8 (1 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 8 */ + #define CIM_CTRL_RXF_TRIG_12 (2 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 12 */ + #define CIM_CTRL_RXF_TRIG_16 (3 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 16 */ + #define CIM_CTRL_RXF_TRIG_20 (4 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 20 */ + #define CIM_CTRL_RXF_TRIG_24 (5 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 24 */ + #define CIM_CTRL_RXF_TRIG_28 (6 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 28 */ + #define CIM_CTRL_RXF_TRIG_32 (7 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 32 */ +#define CIM_CTRL_DMA_EN (1 << 2) +#define CIM_CTRL_RXF_RST (1 << 1) +#define CIM_CTRL_ENA (1 << 0) + +/* CIM State Register (CIM_STATE) */ + +#define CIM_STATE_DMA_SOF (1 << 6) +#define CIM_STATE_DMA_EOF (1 << 5) +#define CIM_STATE_DMA_STOP (1 << 4) +#define CIM_STATE_RXF_OF (1 << 3) +#define CIM_STATE_RXF_TRIG (1 << 2) +#define CIM_STATE_RXF_EMPTY (1 << 1) +#define CIM_STATE_VDD (1 << 0) + +/* CIM DMA Command Register (CIM_CMD) */ + +#define CIM_CMD_SOFINT (1 << 31) +#define CIM_CMD_EOFINT (1 << 30) +#define CIM_CMD_STOP (1 << 28) +#define CIM_CMD_LEN_BIT 0 +#define CIM_CMD_LEN_MASK (0xffffff << CIM_CMD_LEN_BIT) + + +/************************************************************************* + * SADC (Smart A/D Controller) + *************************************************************************/ + +#define SADC_ENA (SADC_BASE + 0x00) /* ADC Enable Register */ +#define SADC_CFG (SADC_BASE + 0x04) /* ADC Configure Register */ +#define SADC_CTRL (SADC_BASE + 0x08) /* ADC Control Register */ +#define SADC_STATE (SADC_BASE + 0x0C) /* ADC Status Register*/ +#define SADC_SAMETIME (SADC_BASE + 0x10) /* ADC Same Point Time Register */ +#define SADC_WAITTIME (SADC_BASE + 0x14) /* ADC Wait Time Register */ +#define SADC_TSDAT (SADC_BASE + 0x18) /* ADC Touch Screen Data Register */ +#define SADC_BATDAT (SADC_BASE + 0x1C) /* ADC PBAT Data Register */ +#define SADC_SADDAT (SADC_BASE + 0x20) /* ADC SADCIN Data Register */ + +#define REG_SADC_ENA REG8(SADC_ENA) +#define REG_SADC_CFG REG32(SADC_CFG) +#define REG_SADC_CTRL REG8(SADC_CTRL) +#define REG_SADC_STATE REG8(SADC_STATE) +#define REG_SADC_SAMETIME REG16(SADC_SAMETIME) +#define REG_SADC_WAITTIME REG16(SADC_WAITTIME) +#define REG_SADC_TSDAT REG32(SADC_TSDAT) +#define REG_SADC_BATDAT REG16(SADC_BATDAT) +#define REG_SADC_SADDAT REG16(SADC_SADDAT) + +/* ADC Enable Register */ +#define SADC_ENA_ADEN (1 << 7) /* Touch Screen Enable */ +#define SADC_ENA_TSEN (1 << 2) /* Touch Screen Enable */ +#define SADC_ENA_PBATEN (1 << 1) /* PBAT Enable */ +#define SADC_ENA_SADCINEN (1 << 0) /* SADCIN Enable */ + +/* ADC Configure Register */ +#define SADC_CFG_CLKOUT_NUM_BIT 16 +#define SADC_CFG_CLKOUT_NUM_MASK (0x7 << SADC_CFG_CLKOUT_NUM_BIT) +#define SADC_CFG_TS_DMA (1 << 15) /* Touch Screen DMA Enable */ +#define SADC_CFG_XYZ_BIT 13 /* XYZ selection */ +#define SADC_CFG_XYZ_MASK (0x3 << SADC_CFG_XYZ_BIT) + #define SADC_CFG_XY (0 << SADC_CFG_XYZ_BIT) + #define SADC_CFG_XYZ (1 << SADC_CFG_XYZ_BIT) + #define SADC_CFG_XYZ1Z2 (2 << SADC_CFG_XYZ_BIT) +#define SADC_CFG_SNUM_BIT 10 /* Sample Number */ +#define SADC_CFG_SNUM_MASK (0x7 << SADC_CFG_SNUM_BIT) + #define SADC_CFG_SNUM_1 (0x0 << SADC_CFG_SNUM_BIT) + #define SADC_CFG_SNUM_2 (0x1 << SADC_CFG_SNUM_BIT) + #define SADC_CFG_SNUM_3 (0x2 << SADC_CFG_SNUM_BIT) + #define SADC_CFG_SNUM_4 (0x3 << SADC_CFG_SNUM_BIT) + #define SADC_CFG_SNUM_5 (0x4 << SADC_CFG_SNUM_BIT) + #define SADC_CFG_SNUM_6 (0x5 << SADC_CFG_SNUM_BIT) + #define SADC_CFG_SNUM_8 (0x6 << SADC_CFG_SNUM_BIT) + #define SADC_CFG_SNUM_9 (0x7 << SADC_CFG_SNUM_BIT) +#define SADC_CFG_CLKDIV_BIT 5 /* AD Converter frequency clock divider */ +#define SADC_CFG_CLKDIV_MASK (0x1f << SADC_CFG_CLKDIV_BIT) +#define SADC_CFG_PBAT_HIGH (0 << 4) /* PBAT >= 2.5V */ +#define SADC_CFG_PBAT_LOW (1 << 4) /* PBAT < 2.5V */ +#define SADC_CFG_CMD_BIT 0 /* ADC Command */ +#define SADC_CFG_CMD_MASK (0xf << SADC_CFG_CMD_BIT) + #define SADC_CFG_CMD_X_SE (0x0 << SADC_CFG_CMD_BIT) /* X Single-End */ + #define SADC_CFG_CMD_Y_SE (0x1 << SADC_CFG_CMD_BIT) /* Y Single-End */ + #define SADC_CFG_CMD_X_DIFF (0x2 << SADC_CFG_CMD_BIT) /* X Differential */ + #define SADC_CFG_CMD_Y_DIFF (0x3 << SADC_CFG_CMD_BIT) /* Y Differential */ + #define SADC_CFG_CMD_Z1_DIFF (0x4 << SADC_CFG_CMD_BIT) /* Z1 Differential */ + #define SADC_CFG_CMD_Z2_DIFF (0x5 << SADC_CFG_CMD_BIT) /* Z2 Differential */ + #define SADC_CFG_CMD_Z3_DIFF (0x6 << SADC_CFG_CMD_BIT) /* Z3 Differential */ + #define SADC_CFG_CMD_Z4_DIFF (0x7 << SADC_CFG_CMD_BIT) /* Z4 Differential */ + #define SADC_CFG_CMD_TP_SE (0x8 << SADC_CFG_CMD_BIT) /* Touch Pressure */ + #define SADC_CFG_CMD_PBATH_SE (0x9 << SADC_CFG_CMD_BIT) /* PBAT >= 2.5V */ + #define SADC_CFG_CMD_PBATL_SE (0xa << SADC_CFG_CMD_BIT) /* PBAT < 2.5V */ + #define SADC_CFG_CMD_SADCIN_SE (0xb << SADC_CFG_CMD_BIT) /* Measure SADCIN */ + #define SADC_CFG_CMD_INT_PEN (0xc << SADC_CFG_CMD_BIT) /* INT_PEN Enable */ + +/* ADC Control Register */ +#define SADC_CTRL_PENDM (1 << 4) /* Pen Down Interrupt Mask */ +#define SADC_CTRL_PENUM (1 << 3) /* Pen Up Interrupt Mask */ +#define SADC_CTRL_TSRDYM (1 << 2) /* Touch Screen Data Ready Interrupt Mask */ +#define SADC_CTRL_PBATRDYM (1 << 1) /* PBAT Data Ready Interrupt Mask */ +#define SADC_CTRL_SRDYM (1 << 0) /* SADCIN Data Ready Interrupt Mask */ + +/* ADC Status Register */ +#define SADC_STATE_TSBUSY (1 << 7) /* TS A/D is working */ +#define SADC_STATE_PBATBUSY (1 << 6) /* PBAT A/D is working */ +#define SADC_STATE_SBUSY (1 << 5) /* SADCIN A/D is working */ +#define SADC_STATE_PEND (1 << 4) /* Pen Down Interrupt Flag */ +#define SADC_STATE_PENU (1 << 3) /* Pen Up Interrupt Flag */ +#define SADC_STATE_TSRDY (1 << 2) /* Touch Screen Data Ready Interrupt Flag */ +#define SADC_STATE_PBATRDY (1 << 1) /* PBAT Data Ready Interrupt Flag */ +#define SADC_STATE_SRDY (1 << 0) /* SADCIN Data Ready Interrupt Flag */ + +/* ADC Touch Screen Data Register */ +#define SADC_TSDAT_DATA0_BIT 0 +#define SADC_TSDAT_DATA0_MASK (0xfff << SADC_TSDAT_DATA0_BIT) +#define SADC_TSDAT_TYPE0 (1 << 15) +#define SADC_TSDAT_DATA1_BIT 16 +#define SADC_TSDAT_DATA1_MASK (0xfff << SADC_TSDAT_DATA1_BIT) +#define SADC_TSDAT_TYPE1 (1 << 31) + + +/************************************************************************* + * SLCD (Smart LCD Controller) + *************************************************************************/ + +#define SLCD_CFG (SLCD_BASE + 0xA0) /* SLCD Configure Register */ +#define SLCD_CTRL (SLCD_BASE + 0xA4) /* SLCD Control Register */ +#define SLCD_STATE (SLCD_BASE + 0xA8) /* SLCD Status Register */ +#define SLCD_DATA (SLCD_BASE + 0xAC) /* SLCD Data Register */ +#define SLCD_FIFO (SLCD_BASE + 0xB0) /* SLCD FIFO Register */ + +#define REG_SLCD_CFG REG32(SLCD_CFG) +#define REG_SLCD_CTRL REG8(SLCD_CTRL) +#define REG_SLCD_STATE REG8(SLCD_STATE) +#define REG_SLCD_DATA REG32(SLCD_DATA) +#define REG_SLCD_FIFO REG32(SLCD_FIFO) + +/* SLCD Configure Register */ +#define SLCD_CFG_BURST_BIT 14 +#define SLCD_CFG_BURST_MASK (0x3 << SLCD_CFG_BURST_BIT) + #define SLCD_CFG_BURST_4_WORD (0 << SLCD_CFG_BURST_BIT) + #define SLCD_CFG_BURST_8_WORD (1 << SLCD_CFG_BURST_BIT) +#define SLCD_CFG_DWIDTH_BIT 10 +#define SLCD_CFG_DWIDTH_MASK (0x7 << SLCD_CFG_DWIDTH_BIT) + #define SLCD_CFG_DWIDTH_18 (0 << SLCD_CFG_DWIDTH_BIT) + #define SLCD_CFG_DWIDTH_16 (1 << SLCD_CFG_DWIDTH_BIT) + #define SLCD_CFG_DWIDTH_8_x3 (2 << SLCD_CFG_DWIDTH_BIT) + #define SLCD_CFG_DWIDTH_8_x2 (3 << SLCD_CFG_DWIDTH_BIT) + #define SLCD_CFG_DWIDTH_8_x1 (4 << SLCD_CFG_DWIDTH_BIT) + #define SLCD_CFG_DWIDTH_9_x2 (7 << SLCD_CFG_DWIDTH_BIT) +#define SLCD_CFG_CWIDTH_BIT 8 +#define SLCD_CFG_CWIDTH_MASK (0x3 << SLCD_CFG_CWIDTH_BIT) + #define SLCD_CFG_CWIDTH_16BIT (0 << SLCD_CFG_CWIDTH_BIT) + #define SLCD_CFG_CWIDTH_8BIT (1 << SLCD_CFG_CWIDTH_BIT) + #define SLCD_CFG_CWIDTH_18BIT (2 << SLCD_CFG_CWIDTH_BIT) +#define SLCD_CFG_CS_ACTIVE_LOW (0 << 4) +#define SLCD_CFG_CS_ACTIVE_HIGH (1 << 4) +#define SLCD_CFG_RS_CMD_LOW (0 << 3) +#define SLCD_CFG_RS_CMD_HIGH (1 << 3) +#define SLCD_CFG_CLK_ACTIVE_FALLING (0 << 1) +#define SLCD_CFG_CLK_ACTIVE_RISING (1 << 1) +#define SLCD_CFG_TYPE_PARALLEL (0 << 0) +#define SLCD_CFG_TYPE_SERIAL (1 << 0) + +/* SLCD Control Register */ +#define SLCD_CTRL_DMA_EN (1 << 0) + +/* SLCD Status Register */ +#define SLCD_STATE_BUSY (1 << 0) + +/* SLCD Data Register */ +#define SLCD_DATA_RS_DATA (0 << 31) +#define SLCD_DATA_RS_COMMAND (1 << 31) + +/* SLCD FIFO Register */ +#define SLCD_FIFO_RS_DATA (0 << 31) +#define SLCD_FIFO_RS_COMMAND (1 << 31) + + +/************************************************************************* + * LCD (LCD Controller) + *************************************************************************/ +#define LCD_CFG (LCD_BASE + 0x00) /* LCD Configure Register */ +#define LCD_VSYNC (LCD_BASE + 0x04) /* Vertical Synchronize Register */ +#define LCD_HSYNC (LCD_BASE + 0x08) /* Horizontal Synchronize Register */ +#define LCD_VAT (LCD_BASE + 0x0c) /* Virtual Area Setting Register */ +#define LCD_DAH (LCD_BASE + 0x10) /* Display Area Horizontal Start/End Point */ +#define LCD_DAV (LCD_BASE + 0x14) /* Display Area Vertical Start/End Point */ +#define LCD_PS (LCD_BASE + 0x18) /* PS Signal Setting */ +#define LCD_CLS (LCD_BASE + 0x1c) /* CLS Signal Setting */ +#define LCD_SPL (LCD_BASE + 0x20) /* SPL Signal Setting */ +#define LCD_REV (LCD_BASE + 0x24) /* REV Signal Setting */ +#define LCD_CTRL (LCD_BASE + 0x30) /* LCD Control Register */ +#define LCD_STATE (LCD_BASE + 0x34) /* LCD Status Register */ +#define LCD_IID (LCD_BASE + 0x38) /* Interrupt ID Register */ +#define LCD_DA0 (LCD_BASE + 0x40) /* Descriptor Address Register 0 */ +#define LCD_SA0 (LCD_BASE + 0x44) /* Source Address Register 0 */ +#define LCD_FID0 (LCD_BASE + 0x48) /* Frame ID Register 0 */ +#define LCD_CMD0 (LCD_BASE + 0x4c) /* DMA Command Register 0 */ +#define LCD_DA1 (LCD_BASE + 0x50) /* Descriptor Address Register 1 */ +#define LCD_SA1 (LCD_BASE + 0x54) /* Source Address Register 1 */ +#define LCD_FID1 (LCD_BASE + 0x58) /* Frame ID Register 1 */ +#define LCD_CMD1 (LCD_BASE + 0x5c) /* DMA Command Register 1 */ + +#define REG_LCD_CFG REG32(LCD_CFG) +#define REG_LCD_VSYNC REG32(LCD_VSYNC) +#define REG_LCD_HSYNC REG32(LCD_HSYNC) +#define REG_LCD_VAT REG32(LCD_VAT) +#define REG_LCD_DAH REG32(LCD_DAH) +#define REG_LCD_DAV REG32(LCD_DAV) +#define REG_LCD_PS REG32(LCD_PS) +#define REG_LCD_CLS REG32(LCD_CLS) +#define REG_LCD_SPL REG32(LCD_SPL) +#define REG_LCD_REV REG32(LCD_REV) +#define REG_LCD_CTRL REG32(LCD_CTRL) +#define REG_LCD_STATE REG32(LCD_STATE) +#define REG_LCD_IID REG32(LCD_IID) +#define REG_LCD_DA0 REG32(LCD_DA0) +#define REG_LCD_SA0 REG32(LCD_SA0) +#define REG_LCD_FID0 REG32(LCD_FID0) +#define REG_LCD_CMD0 REG32(LCD_CMD0) +#define REG_LCD_DA1 REG32(LCD_DA1) +#define REG_LCD_SA1 REG32(LCD_SA1) +#define REG_LCD_FID1 REG32(LCD_FID1) +#define REG_LCD_CMD1 REG32(LCD_CMD1) + +/* LCD Configure Register */ +#define LCD_CFG_LCDPIN_BIT 31 /* LCD pins selection */ +#define LCD_CFG_LCDPIN_MASK (0x1 << LCD_CFG_LCDPIN_BIT) + #define LCD_CFG_LCDPIN_LCD (0x0 << LCD_CFG_LCDPIN_BIT) + #define LCD_CFG_LCDPIN_SLCD (0x1 << LCD_CFG_LCDPIN_BIT) +#define LCD_CFG_PSM (1 << 23) /* PS signal mode */ +#define LCD_CFG_CLSM (1 << 22) /* CLS signal mode */ +#define LCD_CFG_SPLM (1 << 21) /* SPL signal mode */ +#define LCD_CFG_REVM (1 << 20) /* REV signal mode */ +#define LCD_CFG_HSYNM (1 << 19) /* HSYNC signal mode */ +#define LCD_CFG_PCLKM (1 << 18) /* PCLK signal mode */ +#define LCD_CFG_INVDAT (1 << 17) /* Inverse output data */ +#define LCD_CFG_SYNDIR_IN (1 << 16) /* VSYNC&HSYNC direction */ +#define LCD_CFG_PSP (1 << 15) /* PS pin reset state */ +#define LCD_CFG_CLSP (1 << 14) /* CLS pin reset state */ +#define LCD_CFG_SPLP (1 << 13) /* SPL pin reset state */ +#define LCD_CFG_REVP (1 << 12) /* REV pin reset state */ +#define LCD_CFG_HSP (1 << 11) /* HSYNC pority:0-active high,1-active low */ +#define LCD_CFG_PCP (1 << 10) /* PCLK pority:0-rising,1-falling */ +#define LCD_CFG_DEP (1 << 9) /* DE pority:0-active high,1-active low */ +#define LCD_CFG_VSP (1 << 8) /* VSYNC pority:0-rising,1-falling */ +#define LCD_CFG_PDW_BIT 4 /* STN pins utilization */ +#define LCD_CFG_PDW_MASK (0x3 << LCD_DEV_PDW_BIT) +#define LCD_CFG_PDW_1 (0 << LCD_CFG_PDW_BIT) /* LCD_D[0] */ + #define LCD_CFG_PDW_2 (1 << LCD_CFG_PDW_BIT) /* LCD_D[0:1] */ + #define LCD_CFG_PDW_4 (2 << LCD_CFG_PDW_BIT) /* LCD_D[0:3]/LCD_D[8:11] */ + #define LCD_CFG_PDW_8 (3 << LCD_CFG_PDW_BIT) /* LCD_D[0:7]/LCD_D[8:15] */ +#define LCD_CFG_MODE_BIT 0 /* Display Device Mode Select */ +#define LCD_CFG_MODE_MASK (0x0f << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_GENERIC_TFT (0 << LCD_CFG_MODE_BIT) /* 16,18 bit TFT */ + #define LCD_CFG_MODE_SPECIAL_TFT_1 (1 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_SPECIAL_TFT_2 (2 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_SPECIAL_TFT_3 (3 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_NONINTER_CCIR656 (4 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_INTER_CCIR656 (5 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_SINGLE_CSTN (8 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_SINGLE_MSTN (9 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_DUAL_CSTN (10 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_DUAL_MSTN (11 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_SERIAL_TFT (12 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_GENERIC_18BIT_TFT (13 << LCD_CFG_MODE_BIT) + /* JZ47XX defines */ + #define LCD_CFG_MODE_SHARP_HR (1 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_CASIO_TFT (2 << LCD_CFG_MODE_BIT) + #define LCD_CFG_MODE_SAMSUNG_ALPHA (3 << LCD_CFG_MODE_BIT) + + + +/* Vertical Synchronize Register */ +#define LCD_VSYNC_VPS_BIT 16 /* VSYNC pulse start in line clock, fixed to 0 */ +#define LCD_VSYNC_VPS_MASK (0xffff << LCD_VSYNC_VPS_BIT) +#define LCD_VSYNC_VPE_BIT 0 /* VSYNC pulse end in line clock */ +#define LCD_VSYNC_VPE_MASK (0xffff << LCD_VSYNC_VPS_BIT) + +/* Horizontal Synchronize Register */ +#define LCD_HSYNC_HPS_BIT 16 /* HSYNC pulse start position in dot clock */ +#define LCD_HSYNC_HPS_MASK (0xffff << LCD_HSYNC_HPS_BIT) +#define LCD_HSYNC_HPE_BIT 0 /* HSYNC pulse end position in dot clock */ +#define LCD_HSYNC_HPE_MASK (0xffff << LCD_HSYNC_HPE_BIT) + +/* Virtual Area Setting Register */ +#define LCD_VAT_HT_BIT 16 /* Horizontal Total size in dot clock */ +#define LCD_VAT_HT_MASK (0xffff << LCD_VAT_HT_BIT) +#define LCD_VAT_VT_BIT 0 /* Vertical Total size in dot clock */ +#define LCD_VAT_VT_MASK (0xffff << LCD_VAT_VT_BIT) + +/* Display Area Horizontal Start/End Point Register */ +#define LCD_DAH_HDS_BIT 16 /* Horizontal display area start in dot clock */ +#define LCD_DAH_HDS_MASK (0xffff << LCD_DAH_HDS_BIT) +#define LCD_DAH_HDE_BIT 0 /* Horizontal display area end in dot clock */ +#define LCD_DAH_HDE_MASK (0xffff << LCD_DAH_HDE_BIT) + +/* Display Area Vertical Start/End Point Register */ +#define LCD_DAV_VDS_BIT 16 /* Vertical display area start in line clock */ +#define LCD_DAV_VDS_MASK (0xffff << LCD_DAV_VDS_BIT) +#define LCD_DAV_VDE_BIT 0 /* Vertical display area end in line clock */ +#define LCD_DAV_VDE_MASK (0xffff << LCD_DAV_VDE_BIT) + +/* PS Signal Setting */ +#define LCD_PS_PSS_BIT 16 /* PS signal start position in dot clock */ +#define LCD_PS_PSS_MASK (0xffff << LCD_PS_PSS_BIT) +#define LCD_PS_PSE_BIT 0 /* PS signal end position in dot clock */ +#define LCD_PS_PSE_MASK (0xffff << LCD_PS_PSE_BIT) + +/* CLS Signal Setting */ +#define LCD_CLS_CLSS_BIT 16 /* CLS signal start position in dot clock */ +#define LCD_CLS_CLSS_MASK (0xffff << LCD_CLS_CLSS_BIT) +#define LCD_CLS_CLSE_BIT 0 /* CLS signal end position in dot clock */ +#define LCD_CLS_CLSE_MASK (0xffff << LCD_CLS_CLSE_BIT) + +/* SPL Signal Setting */ +#define LCD_SPL_SPLS_BIT 16 /* SPL signal start position in dot clock */ +#define LCD_SPL_SPLS_MASK (0xffff << LCD_SPL_SPLS_BIT) +#define LCD_SPL_SPLE_BIT 0 /* SPL signal end position in dot clock */ +#define LCD_SPL_SPLE_MASK (0xffff << LCD_SPL_SPLE_BIT) + +/* REV Signal Setting */ +#define LCD_REV_REVS_BIT 16 /* REV signal start position in dot clock */ +#define LCD_REV_REVS_MASK (0xffff << LCD_REV_REVS_BIT) + +/* LCD Control Register */ +#define LCD_CTRL_BST_BIT 28 /* Burst Length Selection */ +#define LCD_CTRL_BST_MASK (0x03 << LCD_CTRL_BST_BIT) + #define LCD_CTRL_BST_4 (0 << LCD_CTRL_BST_BIT) /* 4-word */ + #define LCD_CTRL_BST_8 (1 << LCD_CTRL_BST_BIT) /* 8-word */ + #define LCD_CTRL_BST_16 (2 << LCD_CTRL_BST_BIT) /* 16-word */ +#define LCD_CTRL_RGB565 (0 << 27) /* RGB565 mode */ +#define LCD_CTRL_RGB555 (1 << 27) /* RGB555 mode */ +#define LCD_CTRL_OFUP (1 << 26) /* Output FIFO underrun protection enable */ +#define LCD_CTRL_FRC_BIT 24 /* STN FRC Algorithm Selection */ +#define LCD_CTRL_FRC_MASK (0x03 << LCD_CTRL_FRC_BIT) + #define LCD_CTRL_FRC_16 (0 << LCD_CTRL_FRC_BIT) /* 16 grayscale */ + #define LCD_CTRL_FRC_4 (1 << LCD_CTRL_FRC_BIT) /* 4 grayscale */ + #define LCD_CTRL_FRC_2 (2 << LCD_CTRL_FRC_BIT) /* 2 grayscale */ +#define LCD_CTRL_PDD_BIT 16 /* Load Palette Delay Counter */ +#define LCD_CTRL_PDD_MASK (0xff << LCD_CTRL_PDD_BIT) +#define LCD_CTRL_EOFM (1 << 13) /* EOF interrupt mask */ +#define LCD_CTRL_SOFM (1 << 12) /* SOF interrupt mask */ +#define LCD_CTRL_OFUM (1 << 11) /* Output FIFO underrun interrupt mask */ +#define LCD_CTRL_IFUM0 (1 << 10) /* Input FIFO 0 underrun interrupt mask */ +#define LCD_CTRL_IFUM1 (1 << 9) /* Input FIFO 1 underrun interrupt mask */ +#define LCD_CTRL_LDDM (1 << 8) /* LCD disable done interrupt mask */ +#define LCD_CTRL_QDM (1 << 7) /* LCD quick disable done interrupt mask */ +#define LCD_CTRL_BEDN (1 << 6) /* Endian selection */ +#define LCD_CTRL_PEDN (1 << 5) /* Endian in byte:0-msb first, 1-lsb first */ +#define LCD_CTRL_DIS (1 << 4) /* Disable indicate bit */ +#define LCD_CTRL_ENA (1 << 3) /* LCD enable bit */ +#define LCD_CTRL_BPP_BIT 0 /* Bits Per Pixel */ +#define LCD_CTRL_BPP_MASK (0x07 << LCD_CTRL_BPP_BIT) + #define LCD_CTRL_BPP_1 (0 << LCD_CTRL_BPP_BIT) /* 1 bpp */ + #define LCD_CTRL_BPP_2 (1 << LCD_CTRL_BPP_BIT) /* 2 bpp */ + #define LCD_CTRL_BPP_4 (2 << LCD_CTRL_BPP_BIT) /* 4 bpp */ + #define LCD_CTRL_BPP_8 (3 << LCD_CTRL_BPP_BIT) /* 8 bpp */ + #define LCD_CTRL_BPP_16 (4 << LCD_CTRL_BPP_BIT) /* 15/16 bpp */ + #define LCD_CTRL_BPP_18_24 (5 << LCD_CTRL_BPP_BIT) /* 18/24/32 bpp */ + +/* LCD Status Register */ +#define LCD_STATE_QD (1 << 7) /* Quick Disable Done */ +#define LCD_STATE_EOF (1 << 5) /* EOF Flag */ +#define LCD_STATE_SOF (1 << 4) /* SOF Flag */ +#define LCD_STATE_OFU (1 << 3) /* Output FIFO Underrun */ +#define LCD_STATE_IFU0 (1 << 2) /* Input FIFO 0 Underrun */ +#define LCD_STATE_IFU1 (1 << 1) /* Input FIFO 1 Underrun */ +#define LCD_STATE_LDD (1 << 0) /* LCD Disabled */ + +/* DMA Command Register */ +#define LCD_CMD_SOFINT (1 << 31) +#define LCD_CMD_EOFINT (1 << 30) +#define LCD_CMD_PAL (1 << 28) +#define LCD_CMD_LEN_BIT 0 +#define LCD_CMD_LEN_MASK (0xffffff << LCD_CMD_LEN_BIT) + + +/************************************************************************* + * USB Device + *************************************************************************/ +#define USB_BASE UDC_BASE + +#define USB_REG_FADDR (USB_BASE + 0x00) /* Function Address 8-bit */ +#define USB_REG_POWER (USB_BASE + 0x01) /* Power Managemetn 8-bit */ +#define USB_REG_INTRIN (USB_BASE + 0x02) /* Interrupt IN 16-bit */ +#define USB_REG_INTROUT (USB_BASE + 0x04) /* Interrupt OUT 16-bit */ +#define USB_REG_INTRINE (USB_BASE + 0x06) /* Intr IN enable 16-bit */ +#define USB_REG_INTROUTE (USB_BASE + 0x08) /* Intr OUT enable 16-bit */ +#define USB_REG_INTRUSB (USB_BASE + 0x0a) /* Interrupt USB 8-bit */ +#define USB_REG_INTRUSBE (USB_BASE + 0x0b) /* Interrupt USB Enable 8-bit */ +#define USB_REG_FRAME (USB_BASE + 0x0c) /* Frame number 16-bit */ +#define USB_REG_INDEX (USB_BASE + 0x0e) /* Index register 8-bit */ +#define USB_REG_TESTMODE (USB_BASE + 0x0f) /* USB test mode 8-bit */ + +#define USB_REG_CSR0 (USB_BASE + 0x12) /* EP0 CSR 8-bit */ +#define USB_REG_COUNT0 (USB_BASE + 0x18) /* bytes in EP0 FIFO 16-bit */ +#define USB_REG_INMAXP (USB_BASE + 0x10) /* EP1-2 IN Max Pkt Size 16-bit */ +#define USB_REG_INCSR (USB_BASE + 0x12) /* EP1-2 IN CSR LSB 8/16bit */ +#define USB_REG_INCSRH (USB_BASE + 0x13) /* EP1-2 IN CSR MSB 8-bit */ +#define USB_REG_OUTMAXP (USB_BASE + 0x14) /* EP1 OUT Max Pkt Size 16-bit */ +#define USB_REG_OUTCSR (USB_BASE + 0x16) /* EP1 OUT CSR LSB 8/16bit */ +#define USB_REG_OUTCSRH (USB_BASE + 0x17) /* EP1 OUT CSR MSB 8-bit */ +#define USB_REG_OUTCOUNT (USB_BASE + 0x18) /* bytes in EP0/1 OUT FIFO 16-bit */ + +#define USB_FIFO_EP0 (USB_BASE + 0x20) +#define USB_FIFO_EP1 (USB_BASE + 0x24) +#define USB_FIFO_EP2 (USB_BASE + 0x28) + +#define USB_REG_EPINFO (USB_BASE + 0x78) /* Endpoint information */ +#define USB_REG_RAMINFO (USB_BASE + 0x79) /* RAM information */ + +#define USB_REG_INTR (USB_BASE + 0x200) /* DMA pending interrupts 8-bit */ +#define USB_REG_CNTL1 (USB_BASE + 0x204) /* DMA channel 1 control 32-bit */ +#define USB_REG_ADDR1 (USB_BASE + 0x208) /* DMA channel 1 AHB memory addr 32-bit */ +#define USB_REG_COUNT1 (USB_BASE + 0x20c) /* DMA channel 1 byte count 32-bit */ +#define USB_REG_CNTL2 (USB_BASE + 0x214) /* DMA channel 2 control 32-bit */ +#define USB_REG_ADDR2 (USB_BASE + 0x218) /* DMA channel 2 AHB memory addr 32-bit */ +#define USB_REG_COUNT2 (USB_BASE + 0x21c) /* DMA channel 2 byte count 32-bit */ + +#define REG_USB_REG_FADDR REG8(USB_REG_FADDR) +#define REG_USB_REG_POWER REG8(USB_REG_POWER) +#define REG_USB_REG_INTRIN REG16(USB_REG_INTRIN) +#define REG_USB_REG_INTROUT REG16(USB_REG_INTROUT) +#define REG_USB_REG_INTRINE REG16(USB_REG_INTRINE) +#define REG_USB_REG_INTROUTE REG16(USB_REG_INTROUTE) +#define REG_USB_REG_INTRUSB REG8(USB_REG_INTRUSB) +#define REG_USB_REG_INTRUSBE REG8(USB_REG_INTRUSBE) +#define REG_USB_REG_FRAME REG16(USB_REG_FRAME) +#define REG_USB_REG_INDEX REG8(USB_REG_INDEX) +#define REG_USB_REG_TESTMODE REG8(USB_REG_TESTMODE) + +#define REG_USB_REG_CSR0 REG8(USB_REG_CSR0) +#define REG_USB_REG_COUNT0 REG16(USB_REG_COUNT0) +#define REG_USB_REG_INMAXP REG16(USB_REG_INMAXP) +#define REG_USB_REG_INCSR REG16(USB_REG_INCSR) +#define REG_USB_REG_INCSRH REG8(USB_REG_INCSRH) +#define REG_USB_REG_OUTMAXP REG16(USB_REG_OUTMAXP) +#define REG_USB_REG_OUTCSR REG16(USB_REG_OUTCSR) +#define REG_USB_REG_OUTCSRH REG8(USB_REG_OUTCSRH) +#define REG_USB_REG_OUTCOUNT REG16(USB_REG_OUTCOUNT) + +#define REG_USB_FIFO_EP0 REG32(USB_FIFO_EP0) +#define REG_USB_FIFO_EP1 REG32(USB_FIFO_EP1) +#define REG_USB_FIFO_EP2 REG32(USB_FIFO_EP2) + +#define REG_USB_REG_INTR REG8(USB_REG_INTR) +#define REG_USB_REG_CNTL1 REG32(USB_REG_CNTL1) +#define REG_USB_REG_ADDR1 REG32(USB_REG_ADDR1) +#define REG_USB_REG_COUNT1 REG32(USB_REG_COUNT1) +#define REG_USB_REG_CNTL2 REG32(USB_REG_CNTL2) +#define REG_USB_REG_ADDR2 REG32(USB_REG_ADDR2) +#define REG_USB_REG_COUNT2 REG32(USB_REG_COUNT2) + +#define REG_USB_REG_EPINFO REG16(USB_REG_EPINFO) +#define REG_USB_REG_RAMINFO REG8(USB_REG_RAMINFO) + + +/* Power register bit masks */ +#define USB_POWER_SUSPENDM 0x01 +#define USB_POWER_RESUME 0x04 +#define USB_POWER_HSMODE 0x10 +#define USB_POWER_HSENAB 0x20 +#define USB_POWER_SOFTCONN 0x40 + +/* Interrupt register bit masks */ +#define USB_INTR_SUSPEND 0x01 +#define USB_INTR_RESUME 0x02 +#define USB_INTR_RESET 0x04 + +#define USB_INTR_EP0 0x0001 +#define USB_INTR_INEP1 0x0002 +#define USB_INTR_INEP2 0x0004 +#define USB_INTR_OUTEP1 0x0002 +#define USB_INTR_OUTEP2 0x0004 + +#define USB_INTR_EP(n) ((n)==0 ? 1 : ((n)*2)) + +/* CSR0 bit masks */ +#define USB_CSR0_OUTPKTRDY 0x01 +#define USB_CSR0_INPKTRDY 0x02 +#define USB_CSR0_SENTSTALL 0x04 +#define USB_CSR0_DATAEND 0x08 +#define USB_CSR0_SETUPEND 0x10 +#define USB_CSR0_SENDSTALL 0x20 +#define USB_CSR0_SVDOUTPKTRDY 0x40 +#define USB_CSR0_SVDSETUPEND 0x80 + +/* Endpoint CSR register bits */ +#define USB_INCSRH_AUTOSET 0x80 +#define USB_INCSRH_ISO 0x40 +#define USB_INCSRH_MODE 0x20 +#define USB_INCSRH_DMAREQENAB 0x10 +#define USB_INCSRH_FRCDATATOG 0x08 +#define USB_INCSRH_DMAREQMODE 0x04 +#define USB_INCSR_CDT 0x40 +#define USB_INCSR_SENTSTALL 0x20 +#define USB_INCSR_SENDSTALL 0x10 +#define USB_INCSR_FF 0x08 +#define USB_INCSR_UNDERRUN 0x04 +#define USB_INCSR_FFNOTEMPT 0x02 +#define USB_INCSR_INPKTRDY 0x01 +#define USB_OUTCSRH_AUTOCLR 0x80 +#define USB_OUTCSRH_ISO 0x40 +#define USB_OUTCSRH_DMAREQENAB 0x20 +#define USB_OUTCSRH_DNYT 0x10 +#define USB_OUTCSRH_DMAREQMODE 0x08 +#define USB_OUTCSR_CDT 0x80 +#define USB_OUTCSR_SENTSTALL 0x40 +#define USB_OUTCSR_SENDSTALL 0x20 +#define USB_OUTCSR_FF 0x10 +#define USB_OUTCSR_DATAERR 0x08 +#define USB_OUTCSR_OVERRUN 0x04 +#define USB_OUTCSR_FFFULL 0x02 +#define USB_OUTCSR_OUTPKTRDY 0x01 + +/* Testmode register bits */ +#define USB_TEST_SE0NAK 0x01 +#define USB_TEST_J 0x02 +#define USB_TEST_K 0x04 +#define USB_TEST_PACKET 0x08 +#define USB_TEST_FORCE_HS 0x10 +#define USB_TEST_FORCE_FS 0x20 +#define USB_TEST_ALL ( USB_TEST_SE0NAK | USB_TEST_J \ + | USB_TEST_K | USB_TEST_PACKET \ + | USB_TEST_FORCE_HS | USB_TEST_FORCE_FS) + +/* DMA control bits */ +#define USB_CNTL_ENA 0x01 +#define USB_CNTL_DIR_IN 0x02 +#define USB_CNTL_MODE_1 0x04 +#define USB_CNTL_INTR_EN 0x08 +#define USB_CNTL_EP(n) ((n) << 4) +#define USB_CNTL_BURST_0 (0 << 9) +#define USB_CNTL_BURST_4 (1 << 9) +#define USB_CNTL_BURST_8 (2 << 9) +#define USB_CNTL_BURST_16 (3 << 9) + +/* DMA interrupt bits */ +#define USB_INTR_DMA_BULKIN 1 +#define USB_INTR_DMA_BULKOUT 2 + + +//---------------------------------------------------------------------- +// +// Module Operation Definitions +// +//---------------------------------------------------------------------- +#ifndef __ASSEMBLY__ + +/*************************************************************************** + * GPIO + ***************************************************************************/ + +//------------------------------------------------------ +// GPIO Pins Description +// +// PORT 0: +// +// PIN/BIT N FUNC0 FUNC1 +// 0 D0 - +// 1 D1 - +// 2 D2 - +// 3 D3 - +// 4 D4 - +// 5 D5 - +// 6 D6 - +// 7 D7 - +// 8 D8 - +// 9 D9 - +// 10 D10 - +// 11 D11 - +// 12 D12 - +// 13 D13 - +// 14 D14 - +// 15 D15 - +// 16 D16 - +// 17 D17 - +// 18 D18 - +// 19 D19 - +// 20 D20 - +// 21 D21 - +// 22 D22 - +// 23 D23 - +// 24 D24 - +// 25 D25 - +// 26 D26 - +// 27 D27 - +// 28 D28 - +// 29 D29 - +// 30 D30 - +// 31 D31 - +// +//------------------------------------------------------ +// PORT 1: +// +// PIN/BIT N FUNC0 FUNC1 +// 0 A0 - +// 1 A1 - +// 2 A2 - +// 3 A3 - +// 4 A4 - +// 5 A5 - +// 6 A6 - +// 7 A7 - +// 8 A8 - +// 9 A9 - +// 10 A10 - +// 11 A11 - +// 12 A12 - +// 13 A13 - +// 14 A14 - +// 15 A15/CL - +// 16 A16/AL - +// 17 LCD_CLS A21 +// 18 LCD_SPL A22 +// 19 DCS# - +// 20 RAS# - +// 21 CAS# - +// 22 RDWE#/BUFD# - +// 23 CKE - +// 24 CKO - +// 25 CS1# - +// 26 CS2# - +// 27 CS3# - +// 28 CS4# - +// 29 RD# - +// 30 WR# - +// 31 WE0# - +// +// Note: PIN15&16 are CL&AL when connecting to NAND flash. +//------------------------------------------------------ +// PORT 2: +// +// PIN/BIT N FUNC0 FUNC1 +// 0 LCD_D0 - +// 1 LCD_D1 - +// 2 LCD_D2 - +// 3 LCD_D3 - +// 4 LCD_D4 - +// 5 LCD_D5 - +// 6 LCD_D6 - +// 7 LCD_D7 - +// 8 LCD_D8 - +// 9 LCD_D9 - +// 10 LCD_D10 - +// 11 LCD_D11 - +// 12 LCD_D12 - +// 13 LCD_D13 - +// 14 LCD_D14 - +// 15 LCD_D15 - +// 16 LCD_D16 - +// 17 LCD_D17 - +// 18 LCD_PCLK - +// 19 LCD_HSYNC - +// 20 LCD_VSYNC - +// 21 LCD_DE - +// 22 LCD_PS A19 +// 23 LCD_REV A20 +// 24 WE1# - +// 25 WE2# - +// 26 WE3# - +// 27 WAIT# - +// 28 FRE# - +// 29 FWE# - +// 30(NOTE:FRB#) - - +// 31 - - +// +// NOTE(1): PIN30 is used for FRB# when connecting to NAND flash. +//------------------------------------------------------ +// PORT 3: +// +// PIN/BIT N FUNC0 FUNC1 +// 0 CIM_D0 - +// 1 CIM_D1 - +// 2 CIM_D2 - +// 3 CIM_D3 - +// 4 CIM_D4 - +// 5 CIM_D5 - +// 6 CIM_D6 - +// 7 CIM_D7 - +// 8 MSC_CMD - +// 9 MSC_CLK - +// 10 MSC_D0 - +// 11 MSC_D1 - +// 12 MSC_D2 - +// 13 MSC_D3 - +// 14 CIM_MCLK - +// 15 CIM_PCLK - +// 16 CIM_VSYNC - +// 17 CIM_HSYNC - +// 18 SSI_CLK SCLK_RSTN +// 19 SSI_CE0# BIT_CLK(AIC) +// 20 SSI_DT SDATA_OUT(AIC) +// 21 SSI_DR SDATA_IN(AIC) +// 22 SSI_CE1#&GPC SYNC(AIC) +// 23 PWM0 I2C_SDA +// 24 PWM1 I2C_SCK +// 25 PWM2 UART0_TxD +// 26 PWM3 UART0_RxD +// 27 PWM4 A17 +// 28 PWM5 A18 +// 29 - - +// 30 PWM6 UART0_CTS/UART1_RxD +// 31 PWM7 UART0_RTS/UART1_TxD +// +////////////////////////////////////////////////////////// + +/* + * p is the port number (0,1,2,3) + * o is the pin offset (0-31) inside the port + * n is the absolute number of a pin (0-127), regardless of the port + */ + +//------------------------------------------- +// Function Pins Mode + +#define __gpio_as_func0(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXFUNS(p) = (1 << o); \ + REG_GPIO_PXSELC(p) = (1 << o); \ +} while (0) + +#define __gpio_as_func1(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXFUNS(p) = (1 << o); \ + REG_GPIO_PXSELS(p) = (1 << o); \ +} while (0) + +/* + * D0 ~ D31, A0 ~ A16, DCS#, RAS#, CAS#, CKE#, + * RDWE#, CKO#, WE0#, WE1#, WE2#, WE3# + */ +#define __gpio_as_sdram_32bit() \ +do { \ + REG_GPIO_PXFUNS(0) = 0xffffffff; \ + REG_GPIO_PXSELC(0) = 0xffffffff; \ + REG_GPIO_PXPES(0) = 0xffffffff; \ + REG_GPIO_PXFUNS(1) = 0x81f9ffff; \ + REG_GPIO_PXSELC(1) = 0x81f9ffff; \ + REG_GPIO_PXPES(1) = 0x81f9ffff; \ + REG_GPIO_PXFUNS(2) = 0x07000000; \ + REG_GPIO_PXSELC(2) = 0x07000000; \ + REG_GPIO_PXPES(2) = 0x07000000; \ +} while (0) + +//#ifdef JZ4740_PAVO +#ifdef JZ4740_4740 +/* + * D0 ~ D15, A0 ~ A16, DCS#, RAS#, CAS#, CKE#, + * RDWE#, CKO#, WE0#, WE1#, WE2#, WE3# + */ +#define __gpio_as_sdram_16bit() \ +do { \ + REG_GPIO_PXFUNS(0) = 0x0000ffff; \ + REG_GPIO_PXFUNS(0) = 0x0000ffff; \ + REG_GPIO_PXPES(0) = 0x0000ffff; \ + REG_GPIO_PXFUNS(1) = 0x81f9ffff; \ + REG_GPIO_PXSELC(1) = 0x81f9ffff; \ + REG_GPIO_PXPES(1) = 0x81f9ffff; \ + REG_GPIO_PXFUNS(2) = 0x07000000; \ + REG_GPIO_PXSELC(2) = 0x07000000; \ + REG_GPIO_PXPES(2) = 0x07000000; \ +} while (0) + +#endif + +//#ifdef JZ4740_VIRGO +#ifdef JZ4740_4720 +/* + * D0 ~ D15, A0 ~ A16, DCS#, RAS#, CAS#, CKE#, + * RDWE#, CKO#, WE0#, WE1#, WE2#, WE3# + */ +#define __gpio_as_sdram_16bit() \ +do { \ + REG_GPIO_PXFUNS(0) = 0x5442bfaa; \ + REG_GPIO_PXSELC(0) = 0x5442bfaa; \ + REG_GPIO_PXPES(0) = 0x5442bfaa; \ + REG_GPIO_PXFUNS(1) = 0x81f9ffff; \ + REG_GPIO_PXSELC(1) = 0x81f9ffff; \ + REG_GPIO_PXPES(1) = 0x81f9ffff; \ + REG_GPIO_PXFUNS(2) = 0x01000000; \ + REG_GPIO_PXSELC(2) = 0x01000000; \ + REG_GPIO_PXPES(2) = 0x01000000; \ +} while (0) +#endif + + +#ifdef JZ4740_4725 +/* + * D0 ~ D15, A0 ~ A16, DCS#, RAS#, CAS#, CKE#, + * RDWE#, CKO#, WE0#, WE1#, WE2#, WE3# + */ +#define __jz4725__gpio_as_sdram_16bit() \ +do { \ + REG_GPIO_PXFUNS(0) = 0x0000ffff; \ + REG_GPIO_PXSELC(0) = 0x0000ffff; \ + REG_GPIO_PXPES(0) = 0x0000ffff; \ + REG_GPIO_PXFUNS(1) = 0x81f9ffff; \ + REG_GPIO_PXSELC(1) = 0x81f9ffff; \ + REG_GPIO_PXPES(1) = 0x81f9ffff; \ + REG_GPIO_PXFUNS(2) = 0x07000000; \ + REG_GPIO_PXSELC(2) = 0x07000000; \ + REG_GPIO_PXPES(2) = 0x07000000; \ +} while (0) +#endif +/* + * CS1#, CLE, ALE, FRE#, FWE#, FRB#, RDWE#/BUFD# + */ +#define __gpio_as_nand() \ +do { \ + REG_GPIO_PXFUNS(1) = 0x02018000; \ + REG_GPIO_PXSELC(1) = 0x02018000; \ + REG_GPIO_PXPES(1) = 0x02018000; \ + REG_GPIO_PXFUNS(2) = 0x30000000; \ + REG_GPIO_PXSELC(2) = 0x30000000; \ + REG_GPIO_PXPES(2) = 0x30000000; \ + REG_GPIO_PXFUNC(2) = 0x40000000; \ + REG_GPIO_PXSELC(2) = 0x40000000; \ + REG_GPIO_PXDIRC(2) = 0x40000000; \ + REG_GPIO_PXPES(2) = 0x40000000; \ + REG_GPIO_PXFUNS(1) = 0x00400000; \ + REG_GPIO_PXSELC(1) = 0x00400000; \ +} while (0) + +/* + * CS4#, RD#, WR#, WAIT#, A0 ~ A22, D0 ~ D7 + */ +#define __gpio_as_nor_8bit() \ +do { \ + REG_GPIO_PXFUNS(0) = 0x000000ff; \ + REG_GPIO_PXSELC(0) = 0x000000ff; \ + REG_GPIO_PXPES(0) = 0x000000ff; \ + REG_GPIO_PXFUNS(1) = 0x7041ffff; \ + REG_GPIO_PXSELC(1) = 0x7041ffff; \ + REG_GPIO_PXPES(1) = 0x7041ffff; \ + REG_GPIO_PXFUNS(1) = 0x00060000; \ + REG_GPIO_PXSELS(1) = 0x00060000; \ + REG_GPIO_PXPES(1) = 0x00060000; \ + REG_GPIO_PXFUNS(2) = 0x08000000; \ + REG_GPIO_PXSELC(2) = 0x08000000; \ + REG_GPIO_PXPES(2) = 0x08000000; \ + REG_GPIO_PXFUNS(2) = 0x00c00000; \ + REG_GPIO_PXSELS(2) = 0x00c00000; \ + REG_GPIO_PXPES(2) = 0x00c00000; \ + REG_GPIO_PXFUNS(3) = 0x18000000; \ + REG_GPIO_PXSELS(3) = 0x18000000; \ + REG_GPIO_PXPES(3) = 0x18000000; \ +} while (0) + +/* + * CS4#, RD#, WR#, WAIT#, A0 ~ A22, D0 ~ D15 + */ +#define __gpio_as_nor_16bit() \ +do { \ + REG_GPIO_PXFUNS(0) = 0x0000ffff; \ + REG_GPIO_PXSELC(0) = 0x0000ffff; \ + REG_GPIO_PXPES(0) = 0x0000ffff; \ + REG_GPIO_PXFUNS(1) = 0x7041ffff; \ + REG_GPIO_PXSELC(1) = 0x7041ffff; \ + REG_GPIO_PXPES(1) = 0x7041ffff; \ + REG_GPIO_PXFUNS(1) = 0x00060000; \ + REG_GPIO_PXSELS(1) = 0x00060000; \ + REG_GPIO_PXPES(1) = 0x00060000; \ + REG_GPIO_PXFUNS(2) = 0x08000000; \ + REG_GPIO_PXSELC(2) = 0x08000000; \ + REG_GPIO_PXPES(2) = 0x08000000; \ + REG_GPIO_PXFUNS(2) = 0x00c00000; \ + REG_GPIO_PXSELS(2) = 0x00c00000; \ + REG_GPIO_PXPES(2) = 0x00c00000; \ + REG_GPIO_PXFUNS(3) = 0x18000000; \ + REG_GPIO_PXSELS(3) = 0x18000000; \ + REG_GPIO_PXPES(3) = 0x18000000; \ +} while (0) + +/* + * UART0_TxD, UART_RxD0 + */ +#define __gpio_as_uart0() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x06000000; \ + REG_GPIO_PXSELS(3) = 0x06000000; \ + REG_GPIO_PXPES(3) = 0x06000000; \ +} while (0) + +/* + * UART1_TxD, UART1_RxD1 + */ +#define __gpio_as_uart1() \ +do { \ + REG_GPIO_PXFUNS(3) = 0xc0000000; \ + REG_GPIO_PXSELS(3) = 0xc0000000; \ + REG_GPIO_PXPES(3) = 0xc0000000; \ +} while (0) + +/* + * LCD_D0~LCD_D15, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE + */ +#define __gpio_as_lcd_16bit() \ +do { \ + REG_GPIO_PXFUNS(2) = 0x003cffff; \ + REG_GPIO_PXSELC(2) = 0x003cffff; \ + REG_GPIO_PXPES(2) = 0x003cffff; \ +} while (0) + +/* + * LCD_D0~LCD_D17, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE + */ +#define __gpio_as_lcd_18bit() \ +do { \ + REG_GPIO_PXFUNS(2) = 0x003fffff; \ + REG_GPIO_PXSELC(2) = 0x003fffff; \ + REG_GPIO_PXPES(2) = 0x003fffff; \ +} while (0) + + +/* LCD_D0~LCD_D7, SLCD_RS, SLCD_CS */ +#define __gpio_as_slcd_8bit() \ +do { \ + REG_GPIO_PXFUNS(2) = 0x001800ff; \ + REG_GPIO_PXSELC(2) = 0x001800ff; \ +} while (0) + +/* LCD_D0~LCD_D7, SLCD_RS, SLCD_CS */ +#define __gpio_as_slcd_9bit() \ +do { \ + REG_GPIO_PXFUNS(2) = 0x001801ff; \ + REG_GPIO_PXSELC(2) = 0x001801ff; \ +} while (0) + +/* LCD_D0~LCD_D15, SLCD_RS, SLCD_CS */ +#define __gpio_as_slcd_16bit() \ +do { \ + REG_GPIO_PXFUNS(2) = 0x0018ffff; \ + REG_GPIO_PXSELC(2) = 0x0018ffff; \ +} while (0) + +/* LCD_D0~LCD_D17, SLCD_RS, SLCD_CS */ +#define __gpio_as_slcd_18bit() \ +do { \ + REG_GPIO_PXFUNS(2) = 0x001bffff; \ + REG_GPIO_PXSELC(2) = 0x001bffff; \ +} while (0) + +/* + * CIM_D0~CIM_D7, CIM_MCLK, CIM_PCLK, CIM_VSYNC, CIM_HSYNC + */ +#define __gpio_as_cim() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x0003c0ff; \ + REG_GPIO_PXSELC(3) = 0x0003c0ff; \ + REG_GPIO_PXPES(3) = 0x0003c0ff; \ +} while (0) + +/* + * SDATA_OUT, SDATA_IN, BIT_CLK, SYNC, SCLK_RESET + */ +#define __gpio_as_aic() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x007c0000; \ + REG_GPIO_PXSELS(3) = 0x007c0000; \ + REG_GPIO_PXPES(3) = 0x007c0000; \ +} while (0) + +/* + * MSC_CMD, MSC_CLK, MSC_D0 ~ MSC_D3 + */ +#define __gpio_as_msc() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x00003f00; \ + REG_GPIO_PXSELC(3) = 0x00003f00; \ + REG_GPIO_PXPES(3) = 0x00003f00; \ +} while (0) + +/* + * SSI_CS0, SSI_CLK, SSI_DT, SSI_DR + */ +#define __gpio_as_ssi() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x003c0000; \ + REG_GPIO_PXSELC(3) = 0x003c0000; \ + REG_GPIO_PXPES(3) = 0x003c0000; \ +} while (0) + +/* + * I2C_SCK, I2C_SDA + */ +#define __gpio_as_i2c() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x01800000; \ + REG_GPIO_PXSELS(3) = 0x01800000; \ + REG_GPIO_PXPES(3) = 0x01800000; \ +} while (0) + +/* + * PWM0 + */ +#define __gpio_as_pwm0() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x00800000; \ + REG_GPIO_PXSELC(3) = 0x00800000; \ + REG_GPIO_PXPES(3) = 0x00800000; \ +} while (0) + +/* + * PWM1 + */ +#define __gpio_as_pwm1() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x01000000; \ + REG_GPIO_PXSELC(3) = 0x01000000; \ + REG_GPIO_PXPES(3) = 0x01000000; \ +} while (0) + +/* + * PWM2 + */ +#define __gpio_as_pwm2() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x02000000; \ + REG_GPIO_PXSELC(3) = 0x02000000; \ + REG_GPIO_PXPES(3) = 0x02000000; \ +} while (0) + +/* + * PWM3 + */ +#define __gpio_as_pwm3() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x04000000; \ + REG_GPIO_PXSELC(3) = 0x04000000; \ + REG_GPIO_PXPES(3) = 0x04000000; \ +} while (0) + +/* + * PWM4 + */ +#define __gpio_as_pwm4() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x08000000; \ + REG_GPIO_PXSELC(3) = 0x08000000; \ + REG_GPIO_PXPES(3) = 0x08000000; \ +} while (0) + +/* + * PWM5 + */ +#define __gpio_as_pwm5() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x10000000; \ + REG_GPIO_PXSELC(3) = 0x10000000; \ + REG_GPIO_PXPES(3) = 0x10000000; \ +} while (0) + +/* + * PWM6 + */ +#define __gpio_as_pwm6() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x40000000; \ + REG_GPIO_PXSELC(3) = 0x40000000; \ + REG_GPIO_PXPES(3) = 0x40000000; \ +} while (0) + +/* + * PWM7 + */ +#define __gpio_as_pwm7() \ +do { \ + REG_GPIO_PXFUNS(3) = 0x80000000; \ + REG_GPIO_PXSELC(3) = 0x80000000; \ + REG_GPIO_PXPES(3) = 0x80000000; \ +} while (0) + +/* + * n = 0 ~ 7 + */ +#define ___gpio_as_pwm(n) __gpio_as_pwm ## n() +#define __gpio_as_pwm(n) ___gpio_as_pwm(n) + +//------------------------------------------- +// GPIO or Interrupt Mode + +#define __gpio_get_port(p) (REG_GPIO_PXPIN(p)) + +#define __gpio_port_as_output(p, o) \ +do { \ + REG_GPIO_PXFUNC(p) = (1 << (o)); \ + REG_GPIO_PXSELC(p) = (1 << (o)); \ + REG_GPIO_PXDIRS(p) = (1 << (o)); \ +} while (0) + +#define __gpio_port_as_input(p, o) \ +do { \ + REG_GPIO_PXFUNC(p) = (1 << (o)); \ + REG_GPIO_PXSELC(p) = (1 << (o)); \ + REG_GPIO_PXDIRC(p) = (1 << (o)); \ +} while (0) + +#define __gpio_as_output(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + __gpio_port_as_output(p, o); \ +} while (0) + +#define __gpio_as_input(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + __gpio_port_as_input(p, o); \ +} while (0) + +#define __gpio_set_pin(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXDATS(p) = (1 << o); \ +} while (0) + +#define __gpio_clear_pin(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXDATC(p) = (1 << o); \ +} while (0) + +#define __gpio_get_pin(n) \ +({ \ + unsigned int p, o, v; \ + p = (n) / 32; \ + o = (n) % 32; \ + if (__gpio_get_port(p) & (1 << o)) \ + v = 1; \ + else \ + v = 0; \ + v; \ +}) + +#define __gpio_as_irq_high_level(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXIMS(p) = (1 << o); \ + REG_GPIO_PXTRGC(p) = (1 << o); \ + REG_GPIO_PXFUNC(p) = (1 << o); \ + REG_GPIO_PXSELS(p) = (1 << o); \ + REG_GPIO_PXDIRS(p) = (1 << o); \ + REG_GPIO_PXFLGC(p) = (1 << o); \ + REG_GPIO_PXIMC(p) = (1 << o); \ +} while (0) + +#define __gpio_as_irq_low_level(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXIMS(p) = (1 << o); \ + REG_GPIO_PXTRGC(p) = (1 << o); \ + REG_GPIO_PXFUNC(p) = (1 << o); \ + REG_GPIO_PXSELS(p) = (1 << o); \ + REG_GPIO_PXDIRC(p) = (1 << o); \ + REG_GPIO_PXFLGC(p) = (1 << o); \ + REG_GPIO_PXIMC(p) = (1 << o); \ +} while (0) + +#define __gpio_as_irq_rise_edge(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXIMS(p) = (1 << o); \ + REG_GPIO_PXTRGS(p) = (1 << o); \ + REG_GPIO_PXFUNC(p) = (1 << o); \ + REG_GPIO_PXSELS(p) = (1 << o); \ + REG_GPIO_PXDIRS(p) = (1 << o); \ + REG_GPIO_PXFLGC(p) = (1 << o); \ + REG_GPIO_PXIMC(p) = (1 << o); \ +} while (0) + +#define __gpio_as_irq_fall_edge(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXIMS(p) = (1 << o); \ + REG_GPIO_PXTRGS(p) = (1 << o); \ + REG_GPIO_PXFUNC(p) = (1 << o); \ + REG_GPIO_PXSELS(p) = (1 << o); \ + REG_GPIO_PXDIRC(p) = (1 << o); \ + REG_GPIO_PXFLGC(p) = (1 << o); \ + REG_GPIO_PXIMC(p) = (1 << o); \ +} while (0) + +#define __gpio_mask_irq(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXIMS(p) = (1 << o); \ +} while (0) + +#define __gpio_unmask_irq(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXIMC(p) = (1 << o); \ +} while (0) + +#define __gpio_ack_irq(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXFLGC(p) = (1 << o); \ +} while (0) + +#define __gpio_get_irq() \ +({ \ + unsigned int p, i, tmp, v = 0; \ + for (p = 3; p >= 0; p--) { \ + tmp = REG_GPIO_PXFLG(p); \ + for (i = 0; i < 32; i++) \ + if (tmp & (1 << i)) \ + v = (32*p + i); \ + } \ + v; \ +}) + +#define __gpio_group_irq(n) \ +({ \ + register int tmp, i; \ + tmp = REG_GPIO_PXFLG((n)); \ + for (i=31;i>=0;i--) \ + if (tmp & (1 << i)) \ + break; \ + i; \ +}) + +#define __gpio_enable_pull(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXPEC(p) = (1 << o); \ +} while (0) + +#define __gpio_disable_pull(n) \ +do { \ + unsigned int p, o; \ + p = (n) / 32; \ + o = (n) % 32; \ + REG_GPIO_PXPES(p) = (1 << o); \ +} while (0) + + +/*************************************************************************** + * CPM + ***************************************************************************/ +#define __cpm_get_pllm() \ + ((REG_CPM_CPPCR & CPM_CPPCR_PLLM_MASK) >> CPM_CPPCR_PLLM_BIT) +#define __cpm_get_plln() \ + ((REG_CPM_CPPCR & CPM_CPPCR_PLLN_MASK) >> CPM_CPPCR_PLLN_BIT) +#define __cpm_get_pllod() \ + ((REG_CPM_CPPCR & CPM_CPPCR_PLLOD_MASK) >> CPM_CPPCR_PLLOD_BIT) + +#define __cpm_get_cdiv() \ + ((REG_CPM_CPCCR & CPM_CPCCR_CDIV_MASK) >> CPM_CPCCR_CDIV_BIT) +#define __cpm_get_hdiv() \ + ((REG_CPM_CPCCR & CPM_CPCCR_HDIV_MASK) >> CPM_CPCCR_HDIV_BIT) +#define __cpm_get_pdiv() \ + ((REG_CPM_CPCCR & CPM_CPCCR_PDIV_MASK) >> CPM_CPCCR_PDIV_BIT) +#define __cpm_get_mdiv() \ + ((REG_CPM_CPCCR & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT) +#define __cpm_get_ldiv() \ + ((REG_CPM_CPCCR & CPM_CPCCR_LDIV_MASK) >> CPM_CPCCR_LDIV_BIT) +#define __cpm_get_udiv() \ + ((REG_CPM_CPCCR & CPM_CPCCR_UDIV_MASK) >> CPM_CPCCR_UDIV_BIT) +#define __cpm_get_i2sdiv() \ + ((REG_CPM_I2SCDR & CPM_I2SCDR_I2SDIV_MASK) >> CPM_I2SCDR_I2SDIV_BIT) +#define __cpm_get_pixdiv() \ + ((REG_CPM_LPCDR & CPM_LPCDR_PIXDIV_MASK) >> CPM_LPCDR_PIXDIV_BIT) +#define __cpm_get_mscdiv() \ + ((REG_CPM_MSCCDR & CPM_MSCCDR_MSCDIV_MASK) >> CPM_MSCCDR_MSCDIV_BIT) + +#define __cpm_set_cdiv(v) \ + (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_CDIV_MASK) | ((v) << (CPM_CPCCR_CDIV_BIT))) +#define __cpm_set_hdiv(v) \ + (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_HDIV_MASK) | ((v) << (CPM_CPCCR_HDIV_BIT))) +#define __cpm_set_pdiv(v) \ + (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_PDIV_MASK) | ((v) << (CPM_CPCCR_PDIV_BIT))) +#define __cpm_set_mdiv(v) \ + (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_MDIV_MASK) | ((v) << (CPM_CPCCR_MDIV_BIT))) +#define __cpm_set_ldiv(v) \ + (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_LDIV_MASK) | ((v) << (CPM_CPCCR_LDIV_BIT))) +#define __cpm_set_udiv(v) \ + (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_UDIV_MASK) | ((v) << (CPM_CPCCR_UDIV_BIT))) +#define __cpm_set_i2sdiv(v) \ + (REG_CPM_I2SCDR = (REG_CPM_I2SCDR & ~CPM_I2SCDR_I2SDIV_MASK) | ((v) << (CPM_I2SCDR_I2SDIV_BIT))) +#define __cpm_set_pixdiv(v) \ + (REG_CPM_LPCDR = (REG_CPM_LPCDR & ~CPM_LPCDR_PIXDIV_MASK) | ((v) << (CPM_LPCDR_PIXDIV_BIT))) +#define __cpm_set_mscdiv(v) \ + (REG_CPM_MSCCDR = (REG_CPM_MSCCDR & ~CPM_MSCCDR_MSCDIV_MASK) | ((v) << (CPM_MSCCDR_MSCDIV_BIT))) + +#define __cpm_select_i2sclk_exclk() (REG_CPM_CPCCR &= ~CPM_CPCCR_I2CS) +#define __cpm_select_i2sclk_pll() (REG_CPM_CPCCR |= CPM_CPCCR_I2CS) +#define __cpm_enable_cko() (REG_CPM_CPCCR |= CPM_CPCCR_CLKOEN) +#define __cpm_select_usbclk_exclk() (REG_CPM_CPCCR &= ~CPM_CPCCR_UCS) +#define __cpm_select_usbclk_pll() (REG_CPM_CPCCR |= CPM_CPCCR_UCS) +#define __cpm_enable_pll_change() (REG_CPM_CPCCR |= CPM_CPCCR_CE) +#define __cpm_pllout_direct() (REG_CPM_CPCCR |= CPM_CPCCR_PCS) +#define __cpm_pllout_div2() (REG_CPM_CPCCR &= ~CPM_CPCCR_PCS) + +#define __cpm_pll_is_on() (REG_CPM_CPPCR & CPM_CPPCR_PLLS) +#define __cpm_pll_bypass() (REG_CPM_CPPCR |= CPM_CPPCR_PLLBP) +#define __cpm_pll_enable() (REG_CPM_CPPCR |= CPM_CPPCR_PLLEN) + +#define __cpm_get_cclk_doze_duty() \ + ((REG_CPM_LCR & CPM_LCR_DOZE_DUTY_MASK) >> CPM_LCR_DOZE_DUTY_BIT) +#define __cpm_set_cclk_doze_duty(v) \ + (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_DOZE_DUTY_MASK) | ((v) << (CPM_LCR_DOZE_DUTY_BIT))) + +#define __cpm_doze_mode() (REG_CPM_LCR |= CPM_LCR_DOZE_ON) +#define __cpm_idle_mode() \ + (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_IDLE) +#define __cpm_sleep_mode() \ + (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_SLEEP) + +#define __cpm_stop_all() (REG_CPM_CLKGR = 0xffff) +#define __cpm_stop_uart1() (REG_CPM_CLKGR |= CPM_CLKGR_UART1) +#define __cpm_stop_uhc() (REG_CPM_CLKGR |= CPM_CLKGR_UHC) +#define __cpm_stop_ipu() (REG_CPM_CLKGR |= CPM_CLKGR_IPU) +#define __cpm_stop_dmac() (REG_CPM_CLKGR |= CPM_CLKGR_DMAC) +#define __cpm_stop_udc() (REG_CPM_CLKGR |= CPM_CLKGR_UDC) +#define __cpm_stop_lcd() (REG_CPM_CLKGR |= CPM_CLKGR_LCD) +#define __cpm_stop_cim() (REG_CPM_CLKGR |= CPM_CLKGR_CIM) +#define __cpm_stop_sadc() (REG_CPM_CLKGR |= CPM_CLKGR_SADC) +#define __cpm_stop_msc() (REG_CPM_CLKGR |= CPM_CLKGR_MSC) +#define __cpm_stop_aic1() (REG_CPM_CLKGR |= CPM_CLKGR_AIC1) +#define __cpm_stop_aic2() (REG_CPM_CLKGR |= CPM_CLKGR_AIC2) +#define __cpm_stop_ssi() (REG_CPM_CLKGR |= CPM_CLKGR_SSI) +#define __cpm_stop_i2c() (REG_CPM_CLKGR |= CPM_CLKGR_I2C) +#define __cpm_stop_rtc() (REG_CPM_CLKGR |= CPM_CLKGR_RTC) +#define __cpm_stop_tcu() (REG_CPM_CLKGR |= CPM_CLKGR_TCU) +#define __cpm_stop_uart0() (REG_CPM_CLKGR |= CPM_CLKGR_UART0) + +#define __cpm_start_all() (REG_CPM_CLKGR = 0x0) +#define __cpm_start_uart1() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART1) +#define __cpm_start_uhc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UHC) +#define __cpm_start_ipu() (REG_CPM_CLKGR &= ~CPM_CLKGR_IPU) +#define __cpm_start_dmac() (REG_CPM_CLKGR &= ~CPM_CLKGR_DMAC) +#define __cpm_start_udc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UDC) +#define __cpm_start_lcd() (REG_CPM_CLKGR &= ~CPM_CLKGR_LCD) +#define __cpm_start_cim() (REG_CPM_CLKGR &= ~CPM_CLKGR_CIM) +#define __cpm_start_sadc() (REG_CPM_CLKGR &= ~CPM_CLKGR_SADC) +#define __cpm_start_msc() (REG_CPM_CLKGR &= ~CPM_CLKGR_MSC) +#define __cpm_start_aic1() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC1) +#define __cpm_start_aic2() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC2) +#define __cpm_start_ssi() (REG_CPM_CLKGR &= ~CPM_CLKGR_SSI) +#define __cpm_start_i2c() (REG_CPM_CLKGR &= ~CPM_CLKGR_I2C) +#define __cpm_start_rtc() (REG_CPM_CLKGR &= ~CPM_CLKGR_RTC) +#define __cpm_start_tcu() (REG_CPM_CLKGR &= ~CPM_CLKGR_TCU) +#define __cpm_start_uart0() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART0) + +#define __cpm_get_o1st() \ + ((REG_CPM_SCR & CPM_SCR_O1ST_MASK) >> CPM_SCR_O1ST_BIT) +#define __cpm_set_o1st(v) \ + (REG_CPM_SCR = (REG_CPM_SCR & ~CPM_SCR_O1ST_MASK) | ((v) << (CPM_SCR_O1ST_BIT))) +#define __cpm_suspend_usbphy() (REG_CPM_SCR |= CPM_SCR_USBPHY_SUSPEND) +#define __cpm_suspend_usbhost() (REG_CPM_SCR |= CPM_SCR_USBHOST_SUSPEND) +#define __cpm_enable_osc_in_sleep() (REG_CPM_SCR |= CPM_SCR_OSC_ENABLE) + +#ifdef CFG_EXTAL +#define JZ_EXTAL CFG_EXTAL +#else +#define JZ_EXTAL 3686400 +#warning Default EXTCLK is used! +#endif +#define JZ_EXTAL2 32768 /* RTC clock */ + +/* PLL output frequency */ +static __inline__ unsigned int __cpm_get_pllout(void) +{ + unsigned long m, n, no, pllout; + unsigned long cppcr = REG_CPM_CPPCR; + unsigned long od[4] = {1, 2, 2, 4}; + + if ((cppcr & CPM_CPPCR_PLLEN) && !(cppcr & CPM_CPPCR_PLLBP)) + { + m = __cpm_get_pllm() + 2; + n = __cpm_get_plln() + 2; + no = od[__cpm_get_pllod()]; + pllout = ((JZ_EXTAL) / (n * no)) * m; + } + else + pllout = JZ_EXTAL; + + return pllout; +} + +/* PLL output frequency for MSC/I2S/LCD/USB */ +static __inline__ unsigned int __cpm_get_pllout2(void) +{ + if (REG_CPM_CPCCR & CPM_CPCCR_PCS) + return __cpm_get_pllout(); + else + return __cpm_get_pllout()/2; +} + +/* CPU core clock */ +static __inline__ unsigned int __cpm_get_cclk(void) +{ + int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; + + return __cpm_get_pllout() / div[__cpm_get_cdiv()]; +} + +/* AHB system bus clock */ +static __inline__ unsigned int __cpm_get_hclk(void) +{ + int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; + + return __cpm_get_pllout() / div[__cpm_get_hdiv()]; +} + +/* Memory bus clock */ +static __inline__ unsigned int __cpm_get_mclk(void) +{ + int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; + + return __cpm_get_pllout() / div[__cpm_get_mdiv()]; +} + +/* APB peripheral bus clock */ +static __inline__ unsigned int __cpm_get_pclk(void) +{ + int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; + + return __cpm_get_pllout() / div[__cpm_get_pdiv()]; +} + +/* LCDC module clock */ +static __inline__ unsigned int __cpm_get_lcdclk(void) +{ + return __cpm_get_pllout2() / (__cpm_get_ldiv() + 1); +} + +/* LCD pixel clock */ +static __inline__ unsigned int __cpm_get_pixclk(void) +{ + return __cpm_get_pllout2() / (__cpm_get_pixdiv() + 1); +} + +/* I2S clock */ +static __inline__ unsigned int __cpm_get_i2sclk(void) +{ + if (REG_CPM_CPCCR & CPM_CPCCR_I2CS) + return __cpm_get_pllout2() / (__cpm_get_i2sdiv() + 1); + else + return JZ_EXTAL; +} + +/* USB clock */ +static __inline__ unsigned int __cpm_get_usbclk(void) +{ + if (REG_CPM_CPCCR & CPM_CPCCR_UCS) + return __cpm_get_pllout2() / (__cpm_get_udiv() + 1); + else + return JZ_EXTAL; +} + +/* MSC clock */ +static __inline__ unsigned int __cpm_get_mscclk(void) +{ + return __cpm_get_pllout2() / (__cpm_get_mscdiv() + 1); +} + +/* EXTAL clock for UART,I2C,SSI,TCU,USB-PHY */ +static __inline__ unsigned int __cpm_get_extalclk(void) +{ + return JZ_EXTAL; +} + +/* RTC clock for CPM,INTC,RTC,TCU,WDT */ +static __inline__ unsigned int __cpm_get_rtcclk(void) +{ + return JZ_EXTAL2; +} + +/* + * Output 24MHz for SD and 16MHz for MMC. + */ +static __inline__ void __cpm_select_msc_clk(int sd) +{ + unsigned int pllout2 = __cpm_get_pllout2(); + unsigned int div = 0; + + if (sd) + div = pllout2 / 24000000; + else + div = pllout2 / 16000000; + + REG_CPM_MSCCDR = div - 1; +} + +/* + * Output 48MHz for SD and 16MHz for MMC. + */ +static __inline__ void __cpm_select_msc_hs_clk(int sd) +{ + unsigned int pllout2 = __cpm_get_pllout2(); + unsigned int div = 0; + + if (sd) + div = pllout2 / 48000000; + else + div = pllout2 / 16000000; + + REG_CPM_MSCCDR = div - 1; +} + +/*************************************************************************** + * TCU + ***************************************************************************/ +// where 'n' is the TCU channel +#define __tcu_select_extalclk(n) \ + (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_EXT_EN) +#define __tcu_select_rtcclk(n) \ + (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_RTC_EN) +#define __tcu_select_pclk(n) \ + (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_PCK_EN) + +#define __tcu_select_clk_div1(n) \ + (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE1) +#define __tcu_select_clk_div4(n) \ + (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE4) +#define __tcu_select_clk_div16(n) \ + (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE16) +#define __tcu_select_clk_div64(n) \ + (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE64) +#define __tcu_select_clk_div256(n) \ + (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE256) +#define __tcu_select_clk_div1024(n) \ + (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE1024) + +#define __tcu_enable_pwm_output(n) ( REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_EN ) +#define __tcu_disable_pwm_output(n) ( REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_EN ) + +#define __tcu_init_pwm_output_high(n) ( REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_INITL_HIGH ) +#define __tcu_init_pwm_output_low(n) ( REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_INITL_HIGH ) + +#define __tcu_set_pwm_output_shutdown_graceful(n) ( REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_SD ) +#define __tcu_set_pwm_output_shutdown_abrupt(n) ( REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_SD ) + +#define __tcu_start_counter(n) ( REG_TCU_TESR |= (1 << (n)) ) +#define __tcu_stop_counter(n) ( REG_TCU_TECR |= (1 << (n)) ) + +#define __tcu_half_match_flag(n) ( REG_TCU_TFR & (1 << ((n) + 16)) ) +#define __tcu_full_match_flag(n) ( REG_TCU_TFR & (1 << (n)) ) +#define __tcu_set_half_match_flag(n) ( REG_TCU_TFSR = (1 << ((n) + 16)) ) +#define __tcu_set_full_match_flag(n) ( REG_TCU_TFSR = (1 << (n)) ) +#define __tcu_clear_half_match_flag(n) ( REG_TCU_TFCR = (1 << ((n) + 16)) ) +#define __tcu_clear_full_match_flag(n) ( REG_TCU_TFCR = (1 << (n)) ) +#define __tcu_mask_half_match_irq(n) ( REG_TCU_TMSR = (1 << ((n) + 16)) ) +#define __tcu_mask_full_match_irq(n) ( REG_TCU_TMSR = (1 << (n)) ) +#define __tcu_unmask_half_match_irq(n) ( REG_TCU_TMCR = (1 << ((n) + 16)) ) +#define __tcu_unmask_full_match_irq(n) ( REG_TCU_TMCR = (1 << (n)) ) + +#define __tcu_wdt_clock_stopped() ( REG_TCU_TSR & TCU_TSSR_WDTSC ) +#define __tcu_timer_clock_stopped(n) ( REG_TCU_TSR & (1 << (n)) ) + +#define __tcu_start_wdt_clock() ( REG_TCU_TSCR = TCU_TSSR_WDTSC ) +#define __tcu_start_timer_clock(n) ( REG_TCU_TSCR = (1 << (n)) ) + +#define __tcu_stop_wdt_clock() ( REG_TCU_TSSR = TCU_TSSR_WDTSC ) +#define __tcu_stop_timer_clock(n) ( REG_TCU_TSSR = (1 << (n)) ) + +#define __tcu_get_count(n) ( REG_TCU_TCNT((n)) ) +#define __tcu_set_count(n,v) ( REG_TCU_TCNT((n)) = (v) ) +#define __tcu_set_full_data(n,v) ( REG_TCU_TDFR((n)) = (v) ) +#define __tcu_set_half_data(n,v) ( REG_TCU_TDHR((n)) = (v) ) + + +/*************************************************************************** + * WDT + ***************************************************************************/ +#define __wdt_start() ( REG_WDT_TCER |= WDT_TCER_TCEN ) +#define __wdt_stop() ( REG_WDT_TCER &= ~WDT_TCER_TCEN ) +#define __wdt_set_count(v) ( REG_WDT_TCNT = (v) ) +#define __wdt_set_data(v) ( REG_WDT_TDR = (v) ) + +#define __wdt_select_extalclk() \ + (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_EXT_EN) +#define __wdt_select_rtcclk() \ + (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_RTC_EN) +#define __wdt_select_pclk() \ + (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_PCK_EN) + +#define __wdt_select_clk_div1() \ + (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE1) +#define __wdt_select_clk_div4() \ + (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE4) +#define __wdt_select_clk_div16() \ + (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE16) +#define __wdt_select_clk_div64() \ + (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE64) +#define __wdt_select_clk_div256() \ + (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE256) +#define __wdt_select_clk_div1024() \ + (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE1024) + + +/*************************************************************************** + * UART + ***************************************************************************/ + +#define __uart_enable() ( REG8(UART0_FCR) |= UARTFCR_UUE | UARTFCR_FE ) +#define __uart_disable() ( REG8(UART0_FCR) = ~UARTFCR_UUE ) + +#define __uart_enable_transmit_irq() ( REG8(UART0_IER) |= UARTIER_TIE ) +#define __uart_disable_transmit_irq() ( REG8(UART0_IER) &= ~UARTIER_TIE ) + +#define __uart_enable_receive_irq() \ + ( REG8(UART0_IER) |= UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE ) +#define __uart_disable_receive_irq() \ + ( REG8(UART0_IER) &= ~(UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE) ) + +#define __uart_enable_loopback() ( REG8(UART0_MCR) |= UARTMCR_LOOP ) +#define __uart_disable_loopback() ( REG8(UART0_MCR) &= ~UARTMCR_LOOP ) + +#define __uart_set_8n1() ( REG8(UART0_LCR) = UARTLCR_WLEN_8 ) + +#define __uart_set_baud(devclk, baud) \ + do { \ + REG8(UART0_LCR) |= UARTLCR_DLAB; \ + REG8(UART0_DLLR) = (devclk / 16 / baud) & 0xff; \ + REG8(UART0_DLHR) = ((devclk / 16 / baud) >> 8) & 0xff; \ + REG8(UART0_LCR) &= ~UARTLCR_DLAB; \ + } while (0) + +#define __uart_parity_error() ( (REG8(UART0_LSR) & UARTLSR_PER) != 0 ) +#define __uart_clear_errors() \ + ( REG8(UART0_LSR) &= ~(UARTLSR_ORER | UARTLSR_BRK | UARTLSR_FER | UARTLSR_PER | UARTLSR_RFER) ) + +#define __uart_transmit_fifo_empty() ( (REG8(UART0_LSR) & UARTLSR_TDRQ) != 0 ) +#define __uart_transmit_end() ( (REG8(UART0_LSR) & UARTLSR_TEMT) != 0 ) +#define __uart_transmit_char(ch) ( REG8(UART0_TDR) = (ch) ) +#define __uart_receive_fifo_full() ( (REG8(UART0_LSR) & UARTLSR_DR) != 0 ) +#define __uart_receive_ready() ( (REG8(UART0_LSR) & UARTLSR_DR) != 0 ) +#define __uart_receive_char() REG8(UART0_RDR) +#define __uart_disable_irda() ( REG8(UART0_SIRCR) &= ~(SIRCR_TSIRE | SIRCR_RSIRE) ) +#define __uart_enable_irda() \ + /* Tx high pulse as 0, Rx low pulse as 0 */ \ + ( REG8(UART0_SIRCR) = SIRCR_TSIRE | SIRCR_RSIRE | SIRCR_RXPL | SIRCR_TPWS ) + + +/*************************************************************************** + * DMAC + ***************************************************************************/ + +/* n is the DMA channel (0 - 5) */ + +#define __dmac_enable_module() \ + ( REG_DMAC_DMACR |= DMAC_DMACR_DMAE | DMAC_DMACR_PR_RR ) +#define __dmac_disable_module() \ + ( REG_DMAC_DMACR &= ~DMAC_DMACR_DMAE ) + +/* p=0,1,2,3 */ +#define __dmac_set_priority(p) \ +do { \ + REG_DMAC_DMACR &= ~DMAC_DMACR_PR_MASK; \ + REG_DMAC_DMACR |= ((p) << DMAC_DMACR_PR_BIT); \ +} while (0) + +#define __dmac_test_halt_error() ( REG_DMAC_DMACR & DMAC_DMACR_HLT ) +#define __dmac_test_addr_error() ( REG_DMAC_DMACR & DMAC_DMACR_AR ) + +#define __dmac_enable_descriptor(n) \ + ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_NDES ) +#define __dmac_disable_descriptor(n) \ + ( REG_DMAC_DCCSR((n)) |= DMAC_DCCSR_NDES ) + +#define __dmac_enable_channel(n) \ + ( REG_DMAC_DCCSR((n)) |= DMAC_DCCSR_EN ) +#define __dmac_disable_channel(n) \ + ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_EN ) +#define __dmac_channel_enabled(n) \ + ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_EN ) + +#define __dmac_channel_enable_irq(n) \ + ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_TIE ) +#define __dmac_channel_disable_irq(n) \ + ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_TIE ) + +#define __dmac_channel_transmit_halt_detected(n) \ + ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_HLT ) +#define __dmac_channel_transmit_end_detected(n) \ + ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_TT ) +#define __dmac_channel_address_error_detected(n) \ + ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_AR ) +#define __dmac_channel_count_terminated_detected(n) \ + ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_CT ) +#define __dmac_channel_descriptor_invalid_detected(n) \ + ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_INV ) + +#define __dmac_channel_clear_transmit_halt(n) \ + ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_HLT ) +#define __dmac_channel_clear_transmit_end(n) \ + ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_TT ) +#define __dmac_channel_clear_address_error(n) \ + ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_AR ) +#define __dmac_channel_clear_count_terminated(n) \ + ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_CT ) +#define __dmac_channel_clear_descriptor_invalid(n) \ + ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_INV ) + +#define __dmac_channel_set_single_mode(n) \ + ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_TM ) +#define __dmac_channel_set_block_mode(n) \ + ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_TM ) + +#define __dmac_channel_set_transfer_unit_32bit(n) \ +do { \ + REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ + REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_32BIT; \ +} while (0) + +#define __dmac_channel_set_transfer_unit_16bit(n) \ +do { \ + REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ + REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_16BIT; \ +} while (0) + +#define __dmac_channel_set_transfer_unit_8bit(n) \ +do { \ + REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ + REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_8BIT; \ +} while (0) + +#define __dmac_channel_set_transfer_unit_16byte(n) \ +do { \ + REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ + REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_16BYTE; \ +} while (0) + +#define __dmac_channel_set_transfer_unit_32byte(n) \ +do { \ + REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ + REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_32BYTE; \ +} while (0) + +/* w=8,16,32 */ +#define __dmac_channel_set_dest_port_width(n,w) \ +do { \ + REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DWDH_MASK; \ + REG_DMAC_DCMD((n)) |= DMAC_DCMD_DWDH_##w; \ +} while (0) + +/* w=8,16,32 */ +#define __dmac_channel_set_src_port_width(n,w) \ +do { \ + REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_SWDH_MASK; \ + REG_DMAC_DCMD((n)) |= DMAC_DCMD_SWDH_##w; \ +} while (0) + +/* v=0-15 */ +#define __dmac_channel_set_rdil(n,v) \ +do { \ + REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_RDIL_MASK; \ + REG_DMAC_DCMD((n)) |= ((v) << DMAC_DCMD_RDIL_BIT); \ +} while (0) + +#define __dmac_channel_dest_addr_fixed(n) \ + ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DAI ) +#define __dmac_channel_dest_addr_increment(n) \ + ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_DAI ) + +#define __dmac_channel_src_addr_fixed(n) \ + ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_SAI ) +#define __dmac_channel_src_addr_increment(n) \ + ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_SAI ) + +#define __dmac_channel_set_doorbell(n) \ + ( REG_DMAC_DMADBSR = (1 << (n)) ) + +#define __dmac_channel_irq_detected(n) ( REG_DMAC_DMAIPR & (1 << (n)) ) +#define __dmac_channel_ack_irq(n) ( REG_DMAC_DMAIPR &= ~(1 << (n)) ) + +static __inline__ int __dmac_get_irq(void) +{ + int i; + for (i = 0; i < MAX_DMA_NUM; i++) + if (__dmac_channel_irq_detected(i)) + return i; + return -1; +} + + +/*************************************************************************** + * AIC (AC'97 & I2S Controller) + ***************************************************************************/ + +#define __aic_enable() ( REG_AIC_FR |= AIC_FR_ENB ) +#define __aic_disable() ( REG_AIC_FR &= ~AIC_FR_ENB ) + +#define __aic_select_ac97() ( REG_AIC_FR &= ~AIC_FR_AUSEL ) +#define __aic_select_i2s() ( REG_AIC_FR |= AIC_FR_AUSEL ) + +#define __i2s_as_master() ( REG_AIC_FR |= AIC_FR_BCKD | AIC_FR_SYNCD ) +#define __i2s_as_slave() ( REG_AIC_FR &= ~(AIC_FR_BCKD | AIC_FR_SYNCD) ) +#define __aic_reset_status() ( REG_AIC_FR & AIC_FR_RST ) + +#define __aic_reset() \ +do { \ + REG_AIC_FR |= AIC_FR_RST; \ +} while(0) + + +#define __aic_set_transmit_trigger(n) \ +do { \ + REG_AIC_FR &= ~AIC_FR_TFTH_MASK; \ + REG_AIC_FR |= ((n) << AIC_FR_TFTH_BIT); \ +} while(0) + +#define __aic_set_receive_trigger(n) \ +do { \ + REG_AIC_FR &= ~AIC_FR_RFTH_MASK; \ + REG_AIC_FR |= ((n) << AIC_FR_RFTH_BIT); \ +} while(0) + +#define __aic_enable_record() ( REG_AIC_CR |= AIC_CR_EREC ) +#define __aic_disable_record() ( REG_AIC_CR &= ~AIC_CR_EREC ) +#define __aic_enable_replay() ( REG_AIC_CR |= AIC_CR_ERPL ) +#define __aic_disable_replay() ( REG_AIC_CR &= ~AIC_CR_ERPL ) +#define __aic_enable_loopback() ( REG_AIC_CR |= AIC_CR_ENLBF ) +#define __aic_disable_loopback() ( REG_AIC_CR &= ~AIC_CR_ENLBF ) + +#define __aic_flush_fifo() ( REG_AIC_CR |= AIC_CR_FLUSH ) +#define __aic_unflush_fifo() ( REG_AIC_CR &= ~AIC_CR_FLUSH ) + +#define __aic_enable_transmit_intr() \ + ( REG_AIC_CR |= (AIC_CR_ETFS | AIC_CR_ETUR) ) +#define __aic_disable_transmit_intr() \ + ( REG_AIC_CR &= ~(AIC_CR_ETFS | AIC_CR_ETUR) ) +#define __aic_enable_receive_intr() \ + ( REG_AIC_CR |= (AIC_CR_ERFS | AIC_CR_EROR) ) +#define __aic_disable_receive_intr() \ + ( REG_AIC_CR &= ~(AIC_CR_ERFS | AIC_CR_EROR) ) + +#define __aic_enable_transmit_dma() ( REG_AIC_CR |= AIC_CR_TDMS ) +#define __aic_disable_transmit_dma() ( REG_AIC_CR &= ~AIC_CR_TDMS ) +#define __aic_enable_receive_dma() ( REG_AIC_CR |= AIC_CR_RDMS ) +#define __aic_disable_receive_dma() ( REG_AIC_CR &= ~AIC_CR_RDMS ) + +#define __aic_enable_mono2stereo() ( REG_AIC_CR |= AIC_CR_M2S ) +#define __aic_disable_mono2stereo() ( REG_AIC_CR &= ~AIC_CR_M2S ) +#define __aic_enable_byteswap() ( REG_AIC_CR |= AIC_CR_ENDSW ) +#define __aic_disable_byteswap() ( REG_AIC_CR &= ~AIC_CR_ENDSW ) +#define __aic_enable_unsignadj() ( REG_AIC_CR |= AIC_CR_AVSTSU ) +#define __aic_disable_unsignadj() ( REG_AIC_CR &= ~AIC_CR_AVSTSU ) + +#define AC97_PCM_XS_L_FRONT AIC_ACCR1_XS_SLOT3 +#define AC97_PCM_XS_R_FRONT AIC_ACCR1_XS_SLOT4 +#define AC97_PCM_XS_CENTER AIC_ACCR1_XS_SLOT6 +#define AC97_PCM_XS_L_SURR AIC_ACCR1_XS_SLOT7 +#define AC97_PCM_XS_R_SURR AIC_ACCR1_XS_SLOT8 +#define AC97_PCM_XS_LFE AIC_ACCR1_XS_SLOT9 + +#define AC97_PCM_RS_L_FRONT AIC_ACCR1_RS_SLOT3 +#define AC97_PCM_RS_R_FRONT AIC_ACCR1_RS_SLOT4 +#define AC97_PCM_RS_CENTER AIC_ACCR1_RS_SLOT6 +#define AC97_PCM_RS_L_SURR AIC_ACCR1_RS_SLOT7 +#define AC97_PCM_RS_R_SURR AIC_ACCR1_RS_SLOT8 +#define AC97_PCM_RS_LFE AIC_ACCR1_RS_SLOT9 + +#define __ac97_set_xs_none() ( REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK ) +#define __ac97_set_xs_mono() \ +do { \ + REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK; \ + REG_AIC_ACCR1 |= AC97_PCM_XS_R_FRONT; \ +} while(0) +#define __ac97_set_xs_stereo() \ +do { \ + REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK; \ + REG_AIC_ACCR1 |= AC97_PCM_XS_L_FRONT | AC97_PCM_XS_R_FRONT; \ +} while(0) + +/* In fact, only stereo is support now. */ +#define __ac97_set_rs_none() ( REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK ) +#define __ac97_set_rs_mono() \ +do { \ + REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK; \ + REG_AIC_ACCR1 |= AC97_PCM_RS_R_FRONT; \ +} while(0) +#define __ac97_set_rs_stereo() \ +do { \ + REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK; \ + REG_AIC_ACCR1 |= AC97_PCM_RS_L_FRONT | AC97_PCM_RS_R_FRONT; \ +} while(0) + +#define __ac97_warm_reset_codec() \ + do { \ + REG_AIC_ACCR2 |= AIC_ACCR2_SA; \ + REG_AIC_ACCR2 |= AIC_ACCR2_SS; \ + udelay(2); \ + REG_AIC_ACCR2 &= ~AIC_ACCR2_SS; \ + REG_AIC_ACCR2 &= ~AIC_ACCR2_SA; \ + } while (0) + +#define __ac97_cold_reset_codec() \ + do { \ + REG_AIC_ACCR2 |= AIC_ACCR2_SR; \ + udelay(2); \ + REG_AIC_ACCR2 &= ~AIC_ACCR2_SR; \ + } while (0) + +/* n=8,16,18,20 */ +#define __ac97_set_iass(n) \ + ( REG_AIC_ACCR2 = (REG_AIC_ACCR2 & ~AIC_ACCR2_IASS_MASK) | AIC_ACCR2_IASS_##n##BIT ) +#define __ac97_set_oass(n) \ + ( REG_AIC_ACCR2 = (REG_AIC_ACCR2 & ~AIC_ACCR2_OASS_MASK) | AIC_ACCR2_OASS_##n##BIT ) + +#define __i2s_select_i2s() ( REG_AIC_I2SCR &= ~AIC_I2SCR_AMSL ) +#define __i2s_select_msbjustified() ( REG_AIC_I2SCR |= AIC_I2SCR_AMSL ) + +/* n=8,16,18,20,24 */ +/*#define __i2s_set_sample_size(n) \ + ( REG_AIC_I2SCR |= (REG_AIC_I2SCR & ~AIC_I2SCR_WL_MASK) | AIC_I2SCR_WL_##n##BIT )*/ + +#define __i2s_set_oss_sample_size(n) \ + ( REG_AIC_CR = (REG_AIC_CR & ~AIC_CR_OSS_MASK) | AIC_CR_OSS_##n##BIT ) +#define __i2s_set_iss_sample_size(n) \ + ( REG_AIC_CR = (REG_AIC_CR & ~AIC_CR_ISS_MASK) | AIC_CR_ISS_##n##BIT ) + +#define __i2s_stop_bitclk() ( REG_AIC_I2SCR |= AIC_I2SCR_STPBK ) +#define __i2s_start_bitclk() ( REG_AIC_I2SCR &= ~AIC_I2SCR_STPBK ) + +#define __aic_transmit_request() ( REG_AIC_SR & AIC_SR_TFS ) +#define __aic_receive_request() ( REG_AIC_SR & AIC_SR_RFS ) +#define __aic_transmit_underrun() ( REG_AIC_SR & AIC_SR_TUR ) +#define __aic_receive_overrun() ( REG_AIC_SR & AIC_SR_ROR ) + +#define __aic_clear_errors() ( REG_AIC_SR &= ~(AIC_SR_TUR | AIC_SR_ROR) ) + +#define __aic_get_transmit_resident() \ + ( (REG_AIC_SR & AIC_SR_TFL_MASK) >> AIC_SR_TFL_BIT ) +#define __aic_get_receive_count() \ + ( (REG_AIC_SR & AIC_SR_RFL_MASK) >> AIC_SR_RFL_BIT ) + +#define __ac97_command_transmitted() ( REG_AIC_ACSR & AIC_ACSR_CADT ) +#define __ac97_status_received() ( REG_AIC_ACSR & AIC_ACSR_SADR ) +#define __ac97_status_receive_timeout() ( REG_AIC_ACSR & AIC_ACSR_RSTO ) +#define __ac97_codec_is_low_power_mode() ( REG_AIC_ACSR & AIC_ACSR_CLPM ) +#define __ac97_codec_is_ready() ( REG_AIC_ACSR & AIC_ACSR_CRDY ) +#define __ac97_slot_error_detected() ( REG_AIC_ACSR & AIC_ACSR_SLTERR ) +#define __ac97_clear_slot_error() ( REG_AIC_ACSR &= ~AIC_ACSR_SLTERR ) + +#define __i2s_is_busy() ( REG_AIC_I2SSR & AIC_I2SSR_BSY ) + +#define CODEC_READ_CMD (1 << 19) +#define CODEC_WRITE_CMD (0 << 19) +#define CODEC_REG_INDEX_BIT 12 +#define CODEC_REG_INDEX_MASK (0x7f << CODEC_REG_INDEX_BIT) /* 18:12 */ +#define CODEC_REG_DATA_BIT 4 +#define CODEC_REG_DATA_MASK (0x0ffff << 4) /* 19:4 */ + +#define __ac97_out_rcmd_addr(reg) \ +do { \ + REG_AIC_ACCAR = CODEC_READ_CMD | ((reg) << CODEC_REG_INDEX_BIT); \ +} while (0) + +#define __ac97_out_wcmd_addr(reg) \ +do { \ + REG_AIC_ACCAR = CODEC_WRITE_CMD | ((reg) << CODEC_REG_INDEX_BIT); \ +} while (0) + +#define __ac97_out_data(value) \ +do { \ + REG_AIC_ACCDR = ((value) << CODEC_REG_DATA_BIT); \ +} while (0) + +#define __ac97_in_data() \ + ( (REG_AIC_ACSDR & CODEC_REG_DATA_MASK) >> CODEC_REG_DATA_BIT ) + +#define __ac97_in_status_addr() \ + ( (REG_AIC_ACSAR & CODEC_REG_INDEX_MASK) >> CODEC_REG_INDEX_BIT ) + +#define __i2s_set_sample_rate(i2sclk, sync) \ + ( REG_AIC_I2SDIV = ((i2sclk) / (4*64)) / (sync) ) + +#define __aic_write_tfifo(v) ( REG_AIC_DR = (v) ) +#define __aic_read_rfifo() ( REG_AIC_DR ) + +#define __aic_internal_codec() ( REG_AIC_FR |= AIC_FR_ICDC ) +#define __aic_external_codec() ( REG_AIC_FR &= ~AIC_FR_ICDC ) + +#define AIC_FR_LSMP (1 << 6) +#define __aic_play_lastsample() ( REG_AIC_FR |= AIC_FR_LSMP ) +// +// Define next ops for AC97 compatible +// + +#define AC97_ACSR AIC_ACSR + +#define __ac97_enable() __aic_enable(); __aic_select_ac97() +#define __ac97_disable() __aic_disable() +#define __ac97_reset() __aic_reset() + +#define __ac97_set_transmit_trigger(n) __aic_set_transmit_trigger(n) +#define __ac97_set_receive_trigger(n) __aic_set_receive_trigger(n) + +#define __ac97_enable_record() __aic_enable_record() +#define __ac97_disable_record() __aic_disable_record() +#define __ac97_enable_replay() __aic_enable_replay() +#define __ac97_disable_replay() __aic_disable_replay() +#define __ac97_enable_loopback() __aic_enable_loopback() +#define __ac97_disable_loopback() __aic_disable_loopback() + +#define __ac97_enable_transmit_dma() __aic_enable_transmit_dma() +#define __ac97_disable_transmit_dma() __aic_disable_transmit_dma() +#define __ac97_enable_receive_dma() __aic_enable_receive_dma() +#define __ac97_disable_receive_dma() __aic_disable_receive_dma() + +#define __ac97_transmit_request() __aic_transmit_request() +#define __ac97_receive_request() __aic_receive_request() +#define __ac97_transmit_underrun() __aic_transmit_underrun() +#define __ac97_receive_overrun() __aic_receive_overrun() + +#define __ac97_clear_errors() __aic_clear_errors() + +#define __ac97_get_transmit_resident() __aic_get_transmit_resident() +#define __ac97_get_receive_count() __aic_get_receive_count() + +#define __ac97_enable_transmit_intr() __aic_enable_transmit_intr() +#define __ac97_disable_transmit_intr() __aic_disable_transmit_intr() +#define __ac97_enable_receive_intr() __aic_enable_receive_intr() +#define __ac97_disable_receive_intr() __aic_disable_receive_intr() + +#define __ac97_write_tfifo(v) __aic_write_tfifo(v) +#define __ac97_read_rfifo() __aic_read_rfifo() + +// +// Define next ops for I2S compatible +// + +#define I2S_ACSR AIC_I2SSR + +#define __i2s_enable() __aic_enable(); __aic_select_i2s() +#define __i2s_disable() __aic_disable() +#define __i2s_reset() __aic_reset() + +#define __i2s_set_transmit_trigger(n) __aic_set_transmit_trigger(n) +#define __i2s_set_receive_trigger(n) __aic_set_receive_trigger(n) + +#define __i2s_enable_record() __aic_enable_record() +#define __i2s_disable_record() __aic_disable_record() +#define __i2s_enable_replay() __aic_enable_replay() +#define __i2s_disable_replay() __aic_disable_replay() +#define __i2s_enable_loopback() __aic_enable_loopback() +#define __i2s_disable_loopback() __aic_disable_loopback() + +#define __i2s_enable_transmit_dma() __aic_enable_transmit_dma() +#define __i2s_disable_transmit_dma() __aic_disable_transmit_dma() +#define __i2s_enable_receive_dma() __aic_enable_receive_dma() +#define __i2s_disable_receive_dma() __aic_disable_receive_dma() + +#define __i2s_transmit_request() __aic_transmit_request() +#define __i2s_receive_request() __aic_receive_request() +#define __i2s_transmit_underrun() __aic_transmit_underrun() +#define __i2s_receive_overrun() __aic_receive_overrun() + +#define __i2s_clear_errors() __aic_clear_errors() + +#define __i2s_get_transmit_resident() __aic_get_transmit_resident() +#define __i2s_get_receive_count() __aic_get_receive_count() + +#define __i2s_enable_transmit_intr() __aic_enable_transmit_intr() +#define __i2s_disable_transmit_intr() __aic_disable_transmit_intr() +#define __i2s_enable_receive_intr() __aic_enable_receive_intr() +#define __i2s_disable_receive_intr() __aic_disable_receive_intr() + +#define __i2s_write_tfifo(v) __aic_write_tfifo(v) +#define __i2s_read_rfifo() __aic_read_rfifo() + +#define __i2s_reset_codec() \ + do { \ + } while (0) + + +/*************************************************************************** + * ICDC + ***************************************************************************/ +#define __i2s_internal_codec() __aic_internal_codec() +#define __i2s_external_codec() __aic_external_codec() + +/*************************************************************************** + * INTC + ***************************************************************************/ +#define __intc_unmask_irq(n) ( REG_INTC_IMCR = (1 << (n)) ) +#define __intc_mask_irq(n) ( REG_INTC_IMSR = (1 << (n)) ) +#define __intc_ack_irq(n) ( REG_INTC_IPR = (1 << (n)) ) + + +/*************************************************************************** + * I2C + ***************************************************************************/ + +#define __i2c_enable() ( REG_I2C_CR |= I2C_CR_I2CE ) +#define __i2c_disable() ( REG_I2C_CR &= ~I2C_CR_I2CE ) + +#define __i2c_send_start() ( REG_I2C_CR |= I2C_CR_STA ) +#define __i2c_send_stop() ( REG_I2C_CR |= I2C_CR_STO ) +#define __i2c_send_ack() ( REG_I2C_CR &= ~I2C_CR_AC ) +#define __i2c_send_nack() ( REG_I2C_CR |= I2C_CR_AC ) + +#define __i2c_set_drf() ( REG_I2C_SR |= I2C_SR_DRF ) +#define __i2c_clear_drf() ( REG_I2C_SR &= ~I2C_SR_DRF ) +#define __i2c_check_drf() ( REG_I2C_SR & I2C_SR_DRF ) + +#define __i2c_received_ack() ( !(REG_I2C_SR & I2C_SR_ACKF) ) +#define __i2c_is_busy() ( REG_I2C_SR & I2C_SR_BUSY ) +#define __i2c_transmit_ended() ( REG_I2C_SR & I2C_SR_TEND ) + +#define __i2c_set_clk(dev_clk, i2c_clk) \ + ( REG_I2C_GR = (dev_clk) / (16*(i2c_clk)) - 1 ) + +#define __i2c_read() ( REG_I2C_DR ) +#define __i2c_write(val) ( REG_I2C_DR = (val) ) + + +/*************************************************************************** + * MSC + ***************************************************************************/ + +#define __msc_start_op() \ + ( REG_MSC_STRPCL = MSC_STRPCL_START_OP | MSC_STRPCL_CLOCK_CONTROL_START ) + +#define __msc_set_resto(to) ( REG_MSC_RESTO = to ) +#define __msc_set_rdto(to) ( REG_MSC_RDTO = to ) +#define __msc_set_cmd(cmd) ( REG_MSC_CMD = cmd ) +#define __msc_set_arg(arg) ( REG_MSC_ARG = arg ) +#define __msc_set_nob(nob) ( REG_MSC_NOB = nob ) +#define __msc_get_nob() ( REG_MSC_NOB ) +#define __msc_set_blklen(len) ( REG_MSC_BLKLEN = len ) +#define __msc_set_cmdat(cmdat) ( REG_MSC_CMDAT = cmdat ) +#define __msc_set_cmdat_ioabort() ( REG_MSC_CMDAT |= MSC_CMDAT_IO_ABORT ) +#define __msc_clear_cmdat_ioabort() ( REG_MSC_CMDAT &= ~MSC_CMDAT_IO_ABORT ) + +#define __msc_set_cmdat_bus_width1() \ +do { \ + REG_MSC_CMDAT &= ~MSC_CMDAT_BUS_WIDTH_MASK; \ + REG_MSC_CMDAT |= MSC_CMDAT_BUS_WIDTH_1BIT; \ +} while(0) + +#define __msc_set_cmdat_bus_width4() \ +do { \ + REG_MSC_CMDAT &= ~MSC_CMDAT_BUS_WIDTH_MASK; \ + REG_MSC_CMDAT |= MSC_CMDAT_BUS_WIDTH_4BIT; \ +} while(0) + +#define __msc_set_cmdat_dma_en() ( REG_MSC_CMDAT |= MSC_CMDAT_DMA_EN ) +#define __msc_set_cmdat_init() ( REG_MSC_CMDAT |= MSC_CMDAT_INIT ) +#define __msc_set_cmdat_busy() ( REG_MSC_CMDAT |= MSC_CMDAT_BUSY ) +#define __msc_set_cmdat_stream() ( REG_MSC_CMDAT |= MSC_CMDAT_STREAM_BLOCK ) +#define __msc_set_cmdat_block() ( REG_MSC_CMDAT &= ~MSC_CMDAT_STREAM_BLOCK ) +#define __msc_set_cmdat_read() ( REG_MSC_CMDAT &= ~MSC_CMDAT_WRITE_READ ) +#define __msc_set_cmdat_write() ( REG_MSC_CMDAT |= MSC_CMDAT_WRITE_READ ) +#define __msc_set_cmdat_data_en() ( REG_MSC_CMDAT |= MSC_CMDAT_DATA_EN ) + +/* r is MSC_CMDAT_RESPONSE_FORMAT_Rx or MSC_CMDAT_RESPONSE_FORMAT_NONE */ +#define __msc_set_cmdat_res_format(r) \ +do { \ + REG_MSC_CMDAT &= ~MSC_CMDAT_RESPONSE_FORMAT_MASK; \ + REG_MSC_CMDAT |= (r); \ +} while(0) + +#define __msc_clear_cmdat() \ + REG_MSC_CMDAT &= ~( MSC_CMDAT_IO_ABORT | MSC_CMDAT_DMA_EN | MSC_CMDAT_INIT| \ + MSC_CMDAT_BUSY | MSC_CMDAT_STREAM_BLOCK | MSC_CMDAT_WRITE_READ | \ + MSC_CMDAT_DATA_EN | MSC_CMDAT_RESPONSE_FORMAT_MASK ) + +#define __msc_get_imask() ( REG_MSC_IMASK ) +#define __msc_mask_all_intrs() ( REG_MSC_IMASK = 0xff ) +#define __msc_unmask_all_intrs() ( REG_MSC_IMASK = 0x00 ) +#define __msc_mask_rd() ( REG_MSC_IMASK |= MSC_IMASK_RXFIFO_RD_REQ ) +#define __msc_unmask_rd() ( REG_MSC_IMASK &= ~MSC_IMASK_RXFIFO_RD_REQ ) +#define __msc_mask_wr() ( REG_MSC_IMASK |= MSC_IMASK_TXFIFO_WR_REQ ) +#define __msc_unmask_wr() ( REG_MSC_IMASK &= ~MSC_IMASK_TXFIFO_WR_REQ ) +#define __msc_mask_endcmdres() ( REG_MSC_IMASK |= MSC_IMASK_END_CMD_RES ) +#define __msc_unmask_endcmdres() ( REG_MSC_IMASK &= ~MSC_IMASK_END_CMD_RES ) +#define __msc_mask_datatrandone() ( REG_MSC_IMASK |= MSC_IMASK_DATA_TRAN_DONE ) +#define __msc_unmask_datatrandone() ( REG_MSC_IMASK &= ~MSC_IMASK_DATA_TRAN_DONE ) +#define __msc_mask_prgdone() ( REG_MSC_IMASK |= MSC_IMASK_PRG_DONE ) +#define __msc_unmask_prgdone() ( REG_MSC_IMASK &= ~MSC_IMASK_PRG_DONE ) + +/* n=0,1,2,3,4,5,6,7 */ +#define __msc_set_clkrt(n) \ +do { \ + REG_MSC_CLKRT = n; \ +} while(0) + +#define __msc_get_ireg() ( REG_MSC_IREG ) +#define __msc_ireg_rd() ( REG_MSC_IREG & MSC_IREG_RXFIFO_RD_REQ ) +#define __msc_ireg_wr() ( REG_MSC_IREG & MSC_IREG_TXFIFO_WR_REQ ) +#define __msc_ireg_end_cmd_res() ( REG_MSC_IREG & MSC_IREG_END_CMD_RES ) +#define __msc_ireg_data_tran_done() ( REG_MSC_IREG & MSC_IREG_DATA_TRAN_DONE ) +#define __msc_ireg_prg_done() ( REG_MSC_IREG & MSC_IREG_PRG_DONE ) +#define __msc_ireg_clear_end_cmd_res() ( REG_MSC_IREG = MSC_IREG_END_CMD_RES ) +#define __msc_ireg_clear_data_tran_done() ( REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE ) +#define __msc_ireg_clear_prg_done() ( REG_MSC_IREG = MSC_IREG_PRG_DONE ) + +#define __msc_get_stat() ( REG_MSC_STAT ) +#define __msc_stat_not_end_cmd_res() ( (REG_MSC_STAT & MSC_STAT_END_CMD_RES) == 0) +#define __msc_stat_crc_err() \ + ( REG_MSC_STAT & (MSC_STAT_CRC_RES_ERR | MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR_YES) ) +#define __msc_stat_res_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_RES_ERR ) +#define __msc_stat_rd_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_READ_ERROR ) +#define __msc_stat_wr_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_WRITE_ERROR_YES ) +#define __msc_stat_resto_err() ( REG_MSC_STAT & MSC_STAT_TIME_OUT_RES ) +#define __msc_stat_rdto_err() ( REG_MSC_STAT & MSC_STAT_TIME_OUT_READ ) + +#define __msc_rd_resfifo() ( REG_MSC_RES ) +#define __msc_rd_rxfifo() ( REG_MSC_RXFIFO ) +#define __msc_wr_txfifo(v) ( REG_MSC_TXFIFO = v ) + +#define __msc_reset() \ +do { \ + REG_MSC_STRPCL = MSC_STRPCL_RESET; \ + while (REG_MSC_STAT & MSC_STAT_IS_RESETTING); \ +} while (0) + +#define __msc_start_clk() \ +do { \ + REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_START; \ +} while (0) + +#define __msc_stop_clk() \ +do { \ + REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_STOP; \ +} while (0) + +#define MMC_CLK 19169200 +#define SD_CLK 24576000 + +/* msc_clk should little than pclk and little than clk retrieve from card */ +#define __msc_calc_clk_divisor(type,dev_clk,msc_clk,lv) \ +do { \ + unsigned int rate, pclk, i; \ + pclk = dev_clk; \ + rate = type?SD_CLK:MMC_CLK; \ + if (msc_clk && msc_clk < pclk) \ + pclk = msc_clk; \ + i = 0; \ + while (pclk < rate) \ + { \ + i ++; \ + rate >>= 1; \ + } \ + lv = i; \ +} while(0) + +/* divide rate to little than or equal to 400kHz */ +#define __msc_calc_slow_clk_divisor(type, lv) \ +do { \ + unsigned int rate, i; \ + rate = (type?SD_CLK:MMC_CLK)/1000/400; \ + i = 0; \ + while (rate > 0) \ + { \ + rate >>= 1; \ + i ++; \ + } \ + lv = i; \ +} while(0) + + +/*************************************************************************** + * SSI + ***************************************************************************/ + +#define __ssi_enable() ( REG_SSI_CR0 |= SSI_CR0_SSIE ) +#define __ssi_disable() ( REG_SSI_CR0 &= ~SSI_CR0_SSIE ) +#define __ssi_select_ce() ( REG_SSI_CR0 &= ~SSI_CR0_FSEL ) + +#define __ssi_normal_mode() ( REG_SSI_ITR &= ~SSI_ITR_IVLTM_MASK ) + +#define __ssi_select_ce2() \ +do { \ + REG_SSI_CR0 |= SSI_CR0_FSEL; \ + REG_SSI_CR1 &= ~SSI_CR1_MULTS; \ +} while (0) + +#define __ssi_select_gpc() \ +do { \ + REG_SSI_CR0 &= ~SSI_CR0_FSEL; \ + REG_SSI_CR1 |= SSI_CR1_MULTS; \ +} while (0) + +#define __ssi_enable_tx_intr() \ + ( REG_SSI_CR0 |= SSI_CR0_TIE | SSI_CR0_TEIE ) + +#define __ssi_disable_tx_intr() \ + ( REG_SSI_CR0 &= ~(SSI_CR0_TIE | SSI_CR0_TEIE) ) + +#define __ssi_enable_rx_intr() \ + ( REG_SSI_CR0 |= SSI_CR0_RIE | SSI_CR0_REIE ) + +#define __ssi_disable_rx_intr() \ + ( REG_SSI_CR0 &= ~(SSI_CR0_RIE | SSI_CR0_REIE) ) + +#define __ssi_enable_loopback() ( REG_SSI_CR0 |= SSI_CR0_LOOP ) +#define __ssi_disable_loopback() ( REG_SSI_CR0 &= ~SSI_CR0_LOOP ) + +#define __ssi_enable_receive() ( REG_SSI_CR0 &= ~SSI_CR0_DISREV ) +#define __ssi_disable_receive() ( REG_SSI_CR0 |= SSI_CR0_DISREV ) + +#define __ssi_finish_receive() \ + ( REG_SSI_CR0 |= (SSI_CR0_RFINE | SSI_CR0_RFINC) ) + +#define __ssi_disable_recvfinish() \ + ( REG_SSI_CR0 &= ~(SSI_CR0_RFINE | SSI_CR0_RFINC) ) + +#define __ssi_flush_txfifo() ( REG_SSI_CR0 |= SSI_CR0_TFLUSH ) +#define __ssi_flush_rxfifo() ( REG_SSI_CR0 |= SSI_CR0_RFLUSH ) + +#define __ssi_flush_fifo() \ + ( REG_SSI_CR0 |= SSI_CR0_TFLUSH | SSI_CR0_RFLUSH ) + +#define __ssi_finish_transmit() ( REG_SSI_CR1 &= ~SSI_CR1_UNFIN ) + +#define __ssi_spi_format() \ +do { \ + REG_SSI_CR1 &= ~SSI_CR1_FMAT_MASK; \ + REG_SSI_CR1 |= SSI_CR1_FMAT_SPI; \ + REG_SSI_CR1 &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK);\ + REG_SSI_CR1 |= (SSI_CR1_TFVCK_1 | SSI_CR1_TCKFI_1); \ +} while (0) + +/* TI's SSP format, must clear SSI_CR1.UNFIN */ +#define __ssi_ssp_format() \ +do { \ + REG_SSI_CR1 &= ~(SSI_CR1_FMAT_MASK | SSI_CR1_UNFIN); \ + REG_SSI_CR1 |= SSI_CR1_FMAT_SSP; \ +} while (0) + +/* National's Microwire format, must clear SSI_CR0.RFINE, and set max delay */ +#define __ssi_microwire_format() \ +do { \ + REG_SSI_CR1 &= ~SSI_CR1_FMAT_MASK; \ + REG_SSI_CR1 |= SSI_CR1_FMAT_MW1; \ + REG_SSI_CR1 &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK);\ + REG_SSI_CR1 |= (SSI_CR1_TFVCK_3 | SSI_CR1_TCKFI_3); \ + REG_SSI_CR0 &= ~SSI_CR0_RFINE; \ +} while (0) + +/* CE# level (FRMHL), CE# in interval time (ITFRM), + clock phase and polarity (PHA POL), + interval time (SSIITR), interval characters/frame (SSIICR) */ + + /* frmhl,endian,mcom,flen,pha,pol MASK */ +#define SSICR1_MISC_MASK \ + ( SSI_CR1_FRMHL_MASK | SSI_CR1_LFST | SSI_CR1_MCOM_MASK \ + | SSI_CR1_FLEN_MASK | SSI_CR1_PHA | SSI_CR1_POL ) \ + +#define __ssi_spi_set_misc(frmhl,endian,flen,mcom,pha,pol) \ +do { \ + REG_SSI_CR1 &= ~SSICR1_MISC_MASK; \ + REG_SSI_CR1 |= ((frmhl) << 30) | ((endian) << 25) | \ + (((mcom) - 1) << 12) | (((flen) - 2) << 4) | \ + ((pha) << 1) | (pol); \ +} while(0) + +/* Transfer with MSB or LSB first */ +#define __ssi_set_msb() ( REG_SSI_CR1 &= ~SSI_CR1_LFST ) +#define __ssi_set_lsb() ( REG_SSI_CR1 |= SSI_CR1_LFST ) + +#define __ssi_set_frame_length(n) \ + REG_SSI_CR1 = (REG_SSI_CR1 & ~SSI_CR1_FLEN_MASK) | (((n) - 2) << 4) + +/* n = 1 - 16 */ +#define __ssi_set_microwire_command_length(n) \ + ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_MCOM_MASK) | SSI_CR1_MCOM_##n##BIT) ) + +/* Set the clock phase for SPI */ +#define __ssi_set_spi_clock_phase(n) \ + ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_PHA) | (n&0x1)) ) + +/* Set the clock polarity for SPI */ +#define __ssi_set_spi_clock_polarity(n) \ + ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_POL) | (n&0x1)) ) + +/* n = ix8 */ +#define __ssi_set_tx_trigger(n) \ +do { \ + REG_SSI_CR1 &= ~SSI_CR1_TTRG_MASK; \ + REG_SSI_CR1 |= SSI_CR1_TTRG_##n; \ +} while (0) + +/* n = ix8 */ +#define __ssi_set_rx_trigger(n) \ +do { \ + REG_SSI_CR1 &= ~SSI_CR1_RTRG_MASK; \ + REG_SSI_CR1 |= SSI_CR1_RTRG_##n; \ +} while (0) + +#define __ssi_get_txfifo_count() \ + ( (REG_SSI_SR & SSI_SR_TFIFONUM_MASK) >> SSI_SR_TFIFONUM_BIT ) + +#define __ssi_get_rxfifo_count() \ + ( (REG_SSI_SR & SSI_SR_RFIFONUM_MASK) >> SSI_SR_RFIFONUM_BIT ) + +#define __ssi_clear_errors() \ + ( REG_SSI_SR &= ~(SSI_SR_UNDR | SSI_SR_OVER) ) + +#define __ssi_transfer_end() ( REG_SSI_SR & SSI_SR_END ) +#define __ssi_is_busy() ( REG_SSI_SR & SSI_SR_BUSY ) + +#define __ssi_txfifo_full() ( REG_SSI_SR & SSI_SR_TFF ) +#define __ssi_rxfifo_empty() ( REG_SSI_SR & SSI_SR_RFE ) +#define __ssi_rxfifo_noempty() ( REG_SSI_SR & SSI_SR_RFHF ) + +#define __ssi_set_clk(dev_clk, ssi_clk) \ + ( REG_SSI_GR = (dev_clk) / (2*(ssi_clk)) - 1 ) + +#define __ssi_receive_data() REG_SSI_DR +#define __ssi_transmit_data(v) ( REG_SSI_DR = (v) ) + + +/*************************************************************************** + * CIM + ***************************************************************************/ + +#define __cim_enable() ( REG_CIM_CTRL |= CIM_CTRL_ENA ) +#define __cim_disable() ( REG_CIM_CTRL &= ~CIM_CTRL_ENA ) + +#define __cim_input_data_inverse() ( REG_CIM_CFG |= CIM_CFG_INV_DAT ) +#define __cim_input_data_normal() ( REG_CIM_CFG &= ~CIM_CFG_INV_DAT ) + +#define __cim_vsync_active_low() ( REG_CIM_CFG |= CIM_CFG_VSP ) +#define __cim_vsync_active_high() ( REG_CIM_CFG &= ~CIM_CFG_VSP ) + +#define __cim_hsync_active_low() ( REG_CIM_CFG |= CIM_CFG_HSP ) +#define __cim_hsync_active_high() ( REG_CIM_CFG &= ~CIM_CFG_HSP ) + +#define __cim_sample_data_at_pclk_falling_edge() \ + ( REG_CIM_CFG |= CIM_CFG_PCP ) +#define __cim_sample_data_at_pclk_rising_edge() \ + ( REG_CIM_CFG &= ~CIM_CFG_PCP ) + +#define __cim_enable_dummy_zero() ( REG_CIM_CFG |= CIM_CFG_DUMMY_ZERO ) +#define __cim_disable_dummy_zero() ( REG_CIM_CFG &= ~CIM_CFG_DUMMY_ZERO ) + +#define __cim_select_external_vsync() ( REG_CIM_CFG |= CIM_CFG_EXT_VSYNC ) +#define __cim_select_internal_vsync() ( REG_CIM_CFG &= ~CIM_CFG_EXT_VSYNC ) + +/* n=0-7 */ +#define __cim_set_data_packing_mode(n) \ +do { \ + REG_CIM_CFG &= ~CIM_CFG_PACK_MASK; \ + REG_CIM_CFG |= (CIM_CFG_PACK_##n); \ +} while (0) + +#define __cim_enable_ccir656_progressive_mode() \ +do { \ + REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ + REG_CIM_CFG |= CIM_CFG_DSM_CPM; \ +} while (0) + +#define __cim_enable_ccir656_interlace_mode() \ +do { \ + REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ + REG_CIM_CFG |= CIM_CFG_DSM_CIM; \ +} while (0) + +#define __cim_enable_gated_clock_mode() \ +do { \ + REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ + REG_CIM_CFG |= CIM_CFG_DSM_GCM; \ +} while (0) + +#define __cim_enable_nongated_clock_mode() \ +do { \ + REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ + REG_CIM_CFG |= CIM_CFG_DSM_NGCM; \ +} while (0) + +/* sclk:system bus clock + * mclk: CIM master clock + */ +#define __cim_set_master_clk(sclk, mclk) \ +do { \ + REG_CIM_CTRL &= ~CIM_CTRL_MCLKDIV_MASK; \ + REG_CIM_CTRL |= (((sclk)/(mclk) - 1) << CIM_CTRL_MCLKDIV_BIT); \ +} while (0) + +#define __cim_enable_sof_intr() \ + ( REG_CIM_CTRL |= CIM_CTRL_DMA_SOFM ) +#define __cim_disable_sof_intr() \ + ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_SOFM ) + +#define __cim_enable_eof_intr() \ + ( REG_CIM_CTRL |= CIM_CTRL_DMA_EOFM ) +#define __cim_disable_eof_intr() \ + ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_EOFM ) + +#define __cim_enable_stop_intr() \ + ( REG_CIM_CTRL |= CIM_CTRL_DMA_STOPM ) +#define __cim_disable_stop_intr() \ + ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_STOPM ) + +#define __cim_enable_trig_intr() \ + ( REG_CIM_CTRL |= CIM_CTRL_RXF_TRIGM ) +#define __cim_disable_trig_intr() \ + ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_TRIGM ) + +#define __cim_enable_rxfifo_overflow_intr() \ + ( REG_CIM_CTRL |= CIM_CTRL_RXF_OFM ) +#define __cim_disable_rxfifo_overflow_intr() \ + ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_OFM ) + +/* n=1-16 */ +#define __cim_set_frame_rate(n) \ +do { \ + REG_CIM_CTRL &= ~CIM_CTRL_FRC_MASK; \ + REG_CIM_CTRL |= CIM_CTRL_FRC_##n; \ +} while (0) + +#define __cim_enable_dma() ( REG_CIM_CTRL |= CIM_CTRL_DMA_EN ) +#define __cim_disable_dma() ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_EN ) + +#define __cim_reset_rxfifo() ( REG_CIM_CTRL |= CIM_CTRL_RXF_RST ) +#define __cim_unreset_rxfifo() ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_RST ) + +/* n=4,8,12,16,20,24,28,32 */ +#define __cim_set_rxfifo_trigger(n) \ +do { \ + REG_CIM_CTRL &= ~CIM_CTRL_RXF_TRIG_MASK; \ + REG_CIM_CTRL |= CIM_CTRL_RXF_TRIG_##n; \ +} while (0) + +#define __cim_clear_state() ( REG_CIM_STATE = 0 ) + +#define __cim_disable_done() ( REG_CIM_STATE & CIM_STATE_VDD ) +#define __cim_rxfifo_empty() ( REG_CIM_STATE & CIM_STATE_RXF_EMPTY ) +#define __cim_rxfifo_reach_trigger() ( REG_CIM_STATE & CIM_STATE_RXF_TRIG ) +#define __cim_rxfifo_overflow() ( REG_CIM_STATE & CIM_STATE_RXF_OF ) +#define __cim_clear_rxfifo_overflow() ( REG_CIM_STATE &= ~CIM_STATE_RXF_OF ) +#define __cim_dma_stop() ( REG_CIM_STATE & CIM_STATE_DMA_STOP ) +#define __cim_dma_eof() ( REG_CIM_STATE & CIM_STATE_DMA_EOF ) +#define __cim_dma_sof() ( REG_CIM_STATE & CIM_STATE_DMA_SOF ) + +#define __cim_get_iid() ( REG_CIM_IID ) +#define __cim_get_image_data() ( REG_CIM_RXFIFO ) +#define __cim_get_dam_cmd() ( REG_CIM_CMD ) + +#define __cim_set_da(a) ( REG_CIM_DA = (a) ) + +/*************************************************************************** + * LCD + ***************************************************************************/ +#define __lcd_as_smart_lcd() ( REG_LCD_CFG |= (1<> LCD_VSYNC_VPS_BIT ) + +#define __lcd_vsync_get_vpe() \ + ( (REG_LCD_VSYNC & LCD_VSYNC_VPE_MASK) >> LCD_VSYNC_VPE_BIT ) +#define __lcd_vsync_set_vpe(n) \ +do { \ + REG_LCD_VSYNC &= ~LCD_VSYNC_VPE_MASK; \ + REG_LCD_VSYNC |= (n) << LCD_VSYNC_VPE_BIT; \ +} while (0) + +#define __lcd_hsync_get_hps() \ + ( (REG_LCD_HSYNC & LCD_HSYNC_HPS_MASK) >> LCD_HSYNC_HPS_BIT ) +#define __lcd_hsync_set_hps(n) \ +do { \ + REG_LCD_HSYNC &= ~LCD_HSYNC_HPS_MASK; \ + REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPS_BIT; \ +} while (0) + +#define __lcd_hsync_get_hpe() \ + ( (REG_LCD_HSYNC & LCD_HSYNC_HPE_MASK) >> LCD_VSYNC_HPE_BIT ) +#define __lcd_hsync_set_hpe(n) \ +do { \ + REG_LCD_HSYNC &= ~LCD_HSYNC_HPE_MASK; \ + REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPE_BIT; \ +} while (0) + +#define __lcd_vat_get_ht() \ + ( (REG_LCD_VAT & LCD_VAT_HT_MASK) >> LCD_VAT_HT_BIT ) +#define __lcd_vat_set_ht(n) \ +do { \ + REG_LCD_VAT &= ~LCD_VAT_HT_MASK; \ + REG_LCD_VAT |= (n) << LCD_VAT_HT_BIT; \ +} while (0) + +#define __lcd_vat_get_vt() \ + ( (REG_LCD_VAT & LCD_VAT_VT_MASK) >> LCD_VAT_VT_BIT ) +#define __lcd_vat_set_vt(n) \ +do { \ + REG_LCD_VAT &= ~LCD_VAT_VT_MASK; \ + REG_LCD_VAT |= (n) << LCD_VAT_VT_BIT; \ +} while (0) + +#define __lcd_dah_get_hds() \ + ( (REG_LCD_DAH & LCD_DAH_HDS_MASK) >> LCD_DAH_HDS_BIT ) +#define __lcd_dah_set_hds(n) \ +do { \ + REG_LCD_DAH &= ~LCD_DAH_HDS_MASK; \ + REG_LCD_DAH |= (n) << LCD_DAH_HDS_BIT; \ +} while (0) + +#define __lcd_dah_get_hde() \ + ( (REG_LCD_DAH & LCD_DAH_HDE_MASK) >> LCD_DAH_HDE_BIT ) +#define __lcd_dah_set_hde(n) \ +do { \ + REG_LCD_DAH &= ~LCD_DAH_HDE_MASK; \ + REG_LCD_DAH |= (n) << LCD_DAH_HDE_BIT; \ +} while (0) + +#define __lcd_dav_get_vds() \ + ( (REG_LCD_DAV & LCD_DAV_VDS_MASK) >> LCD_DAV_VDS_BIT ) +#define __lcd_dav_set_vds(n) \ +do { \ + REG_LCD_DAV &= ~LCD_DAV_VDS_MASK; \ + REG_LCD_DAV |= (n) << LCD_DAV_VDS_BIT; \ +} while (0) + +#define __lcd_dav_get_vde() \ + ( (REG_LCD_DAV & LCD_DAV_VDE_MASK) >> LCD_DAV_VDE_BIT ) +#define __lcd_dav_set_vde(n) \ +do { \ + REG_LCD_DAV &= ~LCD_DAV_VDE_MASK; \ + REG_LCD_DAV |= (n) << LCD_DAV_VDE_BIT; \ +} while (0) + +#define __lcd_cmd0_set_sofint() ( REG_LCD_CMD0 |= LCD_CMD_SOFINT ) +#define __lcd_cmd0_clr_sofint() ( REG_LCD_CMD0 &= ~LCD_CMD_SOFINT ) +#define __lcd_cmd1_set_sofint() ( REG_LCD_CMD1 |= LCD_CMD_SOFINT ) +#define __lcd_cmd1_clr_sofint() ( REG_LCD_CMD1 &= ~LCD_CMD_SOFINT ) + +#define __lcd_cmd0_set_eofint() ( REG_LCD_CMD0 |= LCD_CMD_EOFINT ) +#define __lcd_cmd0_clr_eofint() ( REG_LCD_CMD0 &= ~LCD_CMD_EOFINT ) +#define __lcd_cmd1_set_eofint() ( REG_LCD_CMD1 |= LCD_CMD_EOFINT ) +#define __lcd_cmd1_clr_eofint() ( REG_LCD_CMD1 &= ~LCD_CMD_EOFINT ) + +#define __lcd_cmd0_set_pal() ( REG_LCD_CMD0 |= LCD_CMD_PAL ) +#define __lcd_cmd0_clr_pal() ( REG_LCD_CMD0 &= ~LCD_CMD_PAL ) + +#define __lcd_cmd0_get_len() \ + ( (REG_LCD_CMD0 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT ) +#define __lcd_cmd1_get_len() \ + ( (REG_LCD_CMD1 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT ) + +/*************************************************************************** + * RTC ops + ***************************************************************************/ + +#define __rtc_write_ready() ( REG_RTC_RCR & RTC_RCR_WRDY ) +#define __rtc_enabled() \ +do{ \ + while(!__rtc_write_ready()); \ + REG_RTC_RCR |= RTC_RCR_RTCE ; \ +}while(0) \ + +#define __rtc_disabled() \ +do{ \ + while(!__rtc_write_ready()); \ + REG_RTC_RCR &= ~RTC_RCR_RTCE; \ +}while(0) +#define __rtc_enable_alarm() \ +do{ \ + while(!__rtc_write_ready()); \ + REG_RTC_RCR |= RTC_RCR_AE; \ +}while(0) + +#define __rtc_disable_alarm() \ +do{ \ + while(!__rtc_write_ready()); \ + REG_RTC_RCR &= ~RTC_RCR_AE; \ +}while(0) + +#define __rtc_enable_alarm_irq() \ +do{ \ + while(!__rtc_write_ready()); \ + REG_RTC_RCR |= RTC_RCR_AIE; \ +}while(0) + +#define __rtc_disable_alarm_irq() \ +do{ \ + while(!__rtc_write_ready()); \ + REG_RTC_RCR &= ~RTC_RCR_AIE; \ +}while(0) +#define __rtc_enable_Hz_irq() \ +do{ \ + while(!__rtc_write_ready()); \ + REG_RTC_RCR |= RTC_RCR_HZIE; \ +}while(0) + +#define __rtc_disable_Hz_irq() \ +do{ \ + while(!__rtc_write_ready()); \ + REG_RTC_RCR &= ~RTC_RCR_HZIE; \ +}while(0) +#define __rtc_get_1Hz_flag() \ +do{ \ + while(!__rtc_write_ready()); \ + ((REG_RTC_RCR >> RTC_RCR_HZ) & 0x1); \ +}while(0) +#define __rtc_clear_1Hz_flag() \ +do{ \ + while(!__rtc_write_ready()); \ + REG_RTC_RCR &= ~RTC_RCR_HZ; \ +}while(0) +#define __rtc_get_alarm_flag() \ +do{ \ + while(!__rtc_write_ready()); \ + ((REG_RTC_RCR >> RTC_RCR_AF) & 0x1); \ +while(0) + +///( (REG_RTC_RCR >> RTC_RCR_AF_BIT) & 0x1 ) + +#define __rtc_clear_alarm_flag() \ +do{ \ + while(!__rtc_write_ready()); \ + REG_RTC_RCR &= ~RTC_RCR_AF; \ +}while(0) +//do +#define __rtc_get_second() \ +({ \ + while(!__rtc_write_ready());\ + REG_RTC_RSR; \ +}) +//while(0) + +#define __rtc_set_second(v) \ +do{ \ + while(!__rtc_write_ready()); \ + REG_RTC_RSR = v; \ + while(!__rtc_write_ready());\ +}while(0) + +#define __rtc_get_alarm_second() \ +do{ \ + while(!__rtc_write_ready()); \ + REG_RTC_RSAR; \ +}while(0) + + +#define __rtc_set_alarm_second(v) \ +do{ \ + while(!__rtc_write_ready()); \ + REG_RTC_RSAR = v; \ +}while(0) + +#define __rtc_RGR_is_locked() \ +({ \ + while(!__rtc_write_ready()); \ + REG_RTC_RGR >> RTC_RGR_LOCK; \ +}) +#define __rtc_lock_RGR() \ +do{ \ + while(!__rtc_write_ready()); \ + REG_RTC_RGR |= RTC_RGR_LOCK; \ +}while(0) + +#define __rtc_unlock_RGR() \ +do{ \ + while(!__rtc_write_ready()); \ + REG_RTC_RGR &= ~RTC_RGR_LOCK; \ +}while(0) + +#define __rtc_get_adjc_val() \ +do{ \ + while(!__rtc_write_ready()); \ + ( (REG_RTC_RGR & RTC_RGR_ADJC_MASK) >> RTC_RGR_ADJC_BIT ); \ +}while(0) +#define __rtc_set_adjc_val(v) \ +do{ \ + while(!__rtc_write_ready()); \ + REG_RTC_RGR = (REG_RTC_RGR & (~RTC_RGR_ADJC_MASK)) |(v << RTC_RGR_ADJC_BIT); \ +}while(0) + +#define __rtc_get_nc1Hz_val() \ + ( (REG_RTC_RGR & RTC_RGR_NC1HZ_MASK) >> RTC_RGR_NC1HZ_BIT ) + +#define __rtc_set_nc1Hz_val(v) \ +do{ \ + while(!__rtc_write_ready()); \ + REG_RTC_RGR = (REG_RTC_RGR & (~RTC_RGR_NC1HZ_MASK)) | (v << RTC_RGR_NC1HZ_BIT);\ +}while(0) +#define __rtc_power_down() \ +do{ \ + while(!__rtc_write_ready()); \ + REG_RTC_HCR |= RTC_HCR_PD; \ +}while(0) + +#define __rtc_get_hwfcr_val() \ +do{ \ + while(!__rtc_write_ready()); \ + REG_RTC_HWFCR & RTC_HWFCR_MASK; \ +}while(0) +#define __rtc_set_hwfcr_val(v) \ +do{ \ + while(!__rtc_write_ready()); \ + REG_RTC_HWFCR = (v) & RTC_HWFCR_MASK; \ +}while(0) + +#define __rtc_get_hrcr_val() \ +do{ \ + while(!__rtc_write_ready()); \ + ( REG_RTC_HRCR & RTC_HRCR_MASK ); \ +}while(0) +#define __rtc_set_hrcr_val(v) \ +do{ \ + while(!__rtc_write_ready()); \ + ( REG_RTC_HRCR = (v) & RTC_HRCR_MASK ); \ +}while(0) + +#define __rtc_enable_alarm_wakeup() \ +do{ \ + while(!__rtc_write_ready()); \ + ( REG_RTC_HWCR |= RTC_HWCR_EALM ); \ +}while(0) + +#define __rtc_disable_alarm_wakeup() \ +do{ \ + while(!__rtc_write_ready()); \ + ( REG_RTC_HWCR &= ~RTC_HWCR_EALM ); \ +}while(0) + +#define __rtc_status_hib_reset_occur() \ +({ \ + (REG_RTC_HWRSR & RTC_HWRSR_HR); \ +}) +#define __rtc_status_ppr_reset_occur() \ +do{ \ + while(!__rtc_write_ready()); \ + ( (REG_RTC_HWRSR & RTC_HWRSR_PPR) & 0x1 ); \ +}while(0) +#define __rtc_status_wakeup_pin_waken_up() \ +do{ \ + while(!__rtc_write_ready()); \ + ( (REG_RTC_HWRSR >> RTC_HWRSR_PIN) & 0x1 ); \ +}while(0) +#define __rtc_status_alarm_waken_up() \ +do{ \ + while(!__rtc_write_ready()); \ + ( (REG_RTC_HWRSR >> RTC_HWRSR_ALM) & 0x1 ); \ +}while(0) +#define __rtc_clear_hib_stat_all() \ +do{ \ + while(!__rtc_write_ready()); \ + ( REG_RTC_HWRSR = 0 ); \ +}while(0) + +#define __rtc_get_scratch_pattern() \ +({ while(!__rtc_write_ready()); \ + (REG_RTC_HSPR);}) +#define __rtc_set_scratch_pattern(n) \ +do{ \ + while(!__rtc_write_ready()); \ + (REG_RTC_HSPR = n ); \ +}while(0) + + +#endif /* !__ASSEMBLY__ */ + + +#ifndef _IPU_H_ +#define _IPU_H_ + +// IPU_REG_BASE +#define IPU_P_BASE 0x13080000 +#define IPU_V_BASE 0xB3080000 +#define IPU__SIZE 0x00001000 + +struct ipu_module +{ + unsigned int reg_ctrl; // 0x0 + unsigned int reg_status; // 0x4 + unsigned int reg_d_fmt; // 0x8 + unsigned int reg_y_addr; // 0xc + unsigned int reg_u_addr; // 0x10 + unsigned int reg_v_addr; // 0x14 + unsigned int reg_in_fm_gs; // 0x18 + unsigned int reg_y_stride; // 0x1c + unsigned int reg_uv_stride; // 0x20 + unsigned int reg_out_addr; // 0x24 + unsigned int reg_out_gs; // 0x28 + unsigned int reg_out_stride; // 0x2c + unsigned int rsz_coef_index; // 0x30 + unsigned int reg_csc_c0_coef; // 0x34 + unsigned int reg_csc_c1_coef; // 0x38 + unsigned int reg_csc_c2_coef; // 0x3c + unsigned int reg_csc_c3_coef; // 0x40 + unsigned int reg_csc_c4_coef; // 0x44 + unsigned int hrsz_coef_lut[20]; // 0x48 + unsigned int vrsz_coef_lut[20]; // 0x98 +}; + +typedef struct +{ + unsigned int coef; + unsigned short int in_n; + unsigned short int out_n; +} rsz_lut; + +struct Ration2m +{ + float ratio; + int n, m; +}; + + +// Register offset +#define REG_CTRL 0x0 +#define REG_STATUS 0x4 +#define REG_D_FMT 0x8 +#define REG_Y_ADDR 0xc +#define REG_U_ADDR 0x10 +#define REG_V_ADDR 0x14 +#define REG_IN_FM_GS 0x18 +#define REG_Y_STRIDE 0x1c +#define REG_UV_STRIDE 0x20 +#define REG_OUT_ADDR 0x24 +#define REG_OUT_GS 0x28 +#define REG_OUT_STRIDE 0x2c +#define REG_RSZ_COEF_INDEX 0x30 +#define REG_CSC_C0_COEF 0x34 +#define REG_CSC_C1_COEF 0x38 +#define REG_CSC_C2_COEF 0x3c +#define REG_CSC_C3_COEF 0x40 +#define REG_CSC_C4_COEF 0x44 +#define HRSZ_LUT_BASE 0x48 +#define VRSZ_LUT_BASE 0x98 + +// REG_CTRL field define +#define IPU_EN (1 << 0) +#define RSZ_EN (1 << 1) +#define FM_IRQ_EN (1 << 2) +#define IPU_RESET (1 << 3) +#define H_UP_SCALE (1 << 8) +#define V_UP_SCALE (1 << 9) +#define H_SCALE_SHIFT (8) +#define V_SCALE_SHIFT (9) + +// REG_STATUS field define +#define OUT_END (1 << 0) + +// REG_D_FMT field define +#define INFMT_YUV420 (0 << 0) +#define INFMT_YUV422 (1 << 0) +#define INFMT_YUV444 (2 << 0) +#define INFMT_YUV411 (3 << 0) +#define INFMT_YCbCr420 (4 << 0) +#define INFMT_YCbCr422 (5 << 0) +#define INFMT_YCbCr444 (6 << 0) +#define INFMT_YCbCr411 (7 << 0) +#define INFMT_MASK (7) + +#define OUTFMT_RGB555 (0 << 16) +#define OUTFMT_RGB565 (1 << 16) +#define OUTFMT_RGB888 (2 << 16) +#define OUTFMT_MASK (3 << 16) + +// REG_IN_FM_GS field define +#define IN_FM_W(val) ((val) << 16) +#define IN_FM_H(val) ((val) << 0) + +// REG_IN_FM_GS field define +#define OUT_FM_W(val) ((val) << 16) +#define OUT_FM_H(val) ((val) << 0) + +// REG_UV_STRIDE field define +#define U_STRIDE(val) ((val) << 16) +#define V_STRIDE(val) ((val) << 0) + +#define VE_IDX_SFT 0 +#define HE_IDX_SFT 16 + +// RSZ_LUT_FIELD +#define OUT_N_SFT 0 +#define OUT_N_MSK 0x1 +#define IN_N_SFT 1 +#define IN_N_MSK 0x1 +#define W_COEF_SFT 2 +#define W_COEF_MSK 0xFF + +// function about REG_CTRL +#define IPU_STOP_IPU() \ + REG32(IPU_V_BASE + REG_CTRL) &= ~IPU_EN; + +#define IPU_RUN_IPU() \ + REG32(IPU_V_BASE + REG_CTRL) |= IPU_EN; + +#define IPU_RESET_IPU() \ + REG32(IPU_V_BASE + REG_CTRL) |= IPU_RESET; + +#define IPU_DISABLE_IRQ() \ + REG32(IPU_V_BASE + REG_CTRL) &= ~FM_IRQ_EN; + +#define IPU_ENABLE_IRQ() \ + REG32(IPU_V_BASE + REG_CTRL) |= FM_IRQ_EN; + +#define IPU_DISABLE_RSIZE() \ + REG32(IPU_V_BASE + REG_CTRL) &= ~RSZ_EN; + +#define IPU_ENABLE_RSIZE() \ + REG32(IPU_V_BASE + REG_CTRL) |= RSZ_EN; + +#define IPU_IS_ENABLED() \ + (REG32(IPU_V_BASE + REG_CTRL) & IPU_EN) + +// function about REG_STATUS +#define IPU_CLEAR_END_FLAG() \ + REG32(IPU_V_BASE + REG_STATUS) &= ~OUT_END; + +#define IPU_POLLING_END_FLAG() \ + (REG32(IPU_V_BASE + REG_STATUS) & OUT_END) + +#define IPU_SET_INFMT(fmt) \ + REG32(IPU_V_BASE + REG_D_FMT) = (REG32(IPU_V_BASE + REG_D_FMT) & ~INFMT_MASK) | (fmt); + +#define IPU_SET_OUTFMT(fmt) \ + REG32(IPU_V_BASE + REG_D_FMT) = (REG32(IPU_V_BASE + REG_D_FMT) & ~OUTFMT_MASK) | (fmt); + +#define IPU_SET_IN_FM(w, h) \ + REG32(IPU_V_BASE + REG_IN_FM_GS) = IN_FM_W(w) | IN_FM_H(h); + +#define IPU_SET_Y_STRIDE(stride) \ + REG32(IPU_V_BASE + REG_Y_STRIDE) = (stride); + +#define IPU_SET_UV_STRIDE(u, v) \ + REG32(IPU_V_BASE + REG_UV_STRIDE) = U_STRIDE(u) | V_STRIDE(v); + +#define IPU_SET_Y_ADDR(addr) \ + REG32(IPU_V_BASE + REG_Y_ADDR) = (addr); + +#define IPU_SET_U_ADDR(addr) \ + REG32(IPU_V_BASE + REG_U_ADDR) = (addr); + +#define IPU_SET_V_ADDR(addr) \ + REG32(IPU_V_BASE + REG_V_ADDR) = (addr); + +#define IPU_SET_OUT_ADDR(addr) \ + REG32(IPU_V_BASE + REG_OUT_ADDR) = (addr); + +#define IPU_SET_OUT_FM(w, h) \ + REG32(IPU_V_BASE + REG_OUT_GS) = OUT_FM_W(w) | OUT_FM_H(h); + +#define IPU_SET_OUT_STRIDE(stride) \ + REG32(IPU_V_BASE + REG_OUT_STRIDE) = (stride); + +#define IPU_SET_CSC_C0_COEF(coef) \ + REG32(IPU_V_BASE + REG_CSC_C0_COEF) = (coef); + +#define IPU_SET_CSC_C1_COEF(coef) \ + REG32(IPU_V_BASE + REG_CSC_C1_COEF) = (coef); + +#define IPU_SET_CSC_C2_COEF(coef) \ + REG32(IPU_V_BASE + REG_CSC_C2_COEF) = (coef); + +#define IPU_SET_CSC_C3_COEF(coef) \ + REG32(IPU_V_BASE + REG_CSC_C3_COEF) = (coef); + +#define IPU_SET_CSC_C4_COEF(coef) \ + REG32(IPU_V_BASE + REG_CSC_C4_COEF) = (coef); + +/* YCbCr */ +/* parameter + R = 1.164 * (Y - 16) + 1.596 * (cr - 128) {C0, C1} + G = 1.164 * (Y - 16) - 0.392 * (cb -128) - 0.813 * (cr - 128) {C0, C2, C3} + B = 1.164 * (Y - 16) + 2.017 * (cb - 128) {C0, C4} +*/ +#define YCBCR_CSC_C0 0x4A8 /* 1.164 * 1024 */ +#define YCBCR_CSC_C1 0x662 /* 1.596 * 1024 */ +#define YCBCR_CSC_C2 0x191 /* 0.392 * 1024 */ +#define YCBCR_CSC_C3 0x341 /* 0.813 * 1024 */ +#define YCBCR_CSC_C4 0x811 /* 2.017 * 1024 */ + + +/* YUV */ +/* parameter + R = 1 * (Y – 0) + 1.4026 * (V - 128) {C0, C1} + G = 1 * (Y – 0) – 0.3444 * (U - 128) – 0.7144 * (V - 128) {C0, C2, C3} + B = 1 * (Y – 0) + 1.7730 * (U - 128) {C0, C4} +*/ +#define YUV_CSC_C0 0x400 +#define YUV_CSC_C1 0x59C +#define YUV_CSC_C2 0x161 +#define YUV_CSC_C3 0x2DC +#define YUV_CSC_C4 0x718 + +#endif /* _IPU_H_ */ + +/* Rockbox USB defines */ +#define USB_NUM_ENDPOINTS 3 +#define USB_DEVBSS_ATTR IBSS_ATTR + +#endif /* __JZ4740_H__ */ diff --git a/src/link.cpp b/src/link.cpp new file mode 100644 index 0000000..fcebd37 --- /dev/null +++ b/src/link.cpp @@ -0,0 +1,124 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include "link.h" +#include "menu.h" +#include "selector.h" + +using namespace std; +using namespace fastdelegate; + +Link::Link(GMenu2X *gmenu2x) : Button(gmenu2x, true) { + this->gmenu2x = gmenu2x; + action = MakeDelegate(this, &Link::run); + edited = false; + iconPath = gmenu2x->sc.getSkinFilePath("icons/generic.png"); + iconX = 0; + padding = 0; +} + +void Link::run() {} + +void Link::paint() { + gmenu2x->sc[getIconPath()]->blit(gmenu2x->s, iconX, rect.y+padding, 32,32); + gmenu2x->s->write( gmenu2x->font, getTitle(), iconX+16, rect.y+gmenu2x->skinConfInt["linkHeight"]-padding, SFontHAlignCenter, SFontVAlignBottom ); +} + +bool Link::paintHover() { + if (gmenu2x->useSelectionPng) + gmenu2x->sc["imgs/selection.png"]->blit(gmenu2x->s,rect,SFontHAlignCenter,SFontVAlignMiddle); + else + gmenu2x->s->box(rect.x, rect.y, rect.w, rect.h, gmenu2x->skinConfColors["selectionBg"]); + return true; +} + +string Link::getTitle() { + return title; +} + +void Link::setTitle(string title) { + this->title = title; + edited = true; +} + +string Link::getDescription() { + return description; +} + +void Link::setDescription(string description) { + this->description = description; + edited = true; +} + +string Link::getIcon() { + return icon; +} + +void Link::setIcon(string icon) { + string skinpath = gmenu2x->getExePath()+"skins/"+gmenu2x->confStr["skin"]; + if (icon.substr(0,skinpath.length()) == skinpath) { + string tempIcon = icon.substr(skinpath.length(), icon.length()); + string::size_type pos = tempIcon.find("/"); + if (pos != string::npos) + icon = "skin:"+tempIcon.substr(pos+1,icon.length()); + } + + iconPath = strreplace(icon,"skin:",skinpath+"/"); + if (iconPath.empty() || !fileExists(iconPath)) { + iconPath = strreplace(icon,"skin:",gmenu2x->getExePath()+"skins/Default/"); + if (!fileExists(iconPath)) searchIcon(); + } + + this->icon = icon; + edited = true; +} + +string Link::searchIcon() { + iconPath = gmenu2x->sc.getSkinFilePath("icons/generic.png"); + return iconPath; +} + +string Link::getIconPath() { + if (iconPath.empty()) searchIcon(); + return iconPath; +} + +void Link::setIconPath(string icon) { + if (fileExists(icon)) + iconPath = icon; + else + iconPath = gmenu2x->sc.getSkinFilePath("icons/generic.png"); +} + +void Link::setSize(int w, int h) { + Button::setSize(w,h); + recalcCoordinates(); +} + +void Link::setPosition(int x, int y) { + Button::setPosition(x,y); + recalcCoordinates(); +} + +void Link::recalcCoordinates() { + iconX = rect.x+(rect.w-32)/2; + padding = (gmenu2x->skinConfInt["linkHeight"] - 32 - gmenu2x->font->getLineHeight()) / 3; +} diff --git a/src/link.h b/src/link.h new file mode 100644 index 0000000..5c0494f --- /dev/null +++ b/src/link.h @@ -0,0 +1,70 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef LINK_H +#define LINK_H + +#include +#include + +#include "button.h" + +using std::string; + +class GMenu2X; + +/** +Base class that represents a link on screen. + + @author Massimiliano Torromeo +*/ +class Link : public Button { +private: + uint iconX, padding; + +protected: + bool edited; + string title, description, icon, iconPath; + + void recalcCoordinates(); + +public: + Link(GMenu2X *gmenu2x); + virtual ~Link() {}; + + virtual void paint(); + virtual bool paintHover(); + + void setSize(int w, int h); + void setPosition(int x, int y); + + string getTitle(); + void setTitle(string title); + string getDescription(); + void setDescription(string description); + string getIcon(); + void setIcon(string icon); + virtual string searchIcon(); + string getIconPath(); + void setIconPath(string icon); + + virtual void run(); +}; + +#endif diff --git a/src/linkaction.cpp b/src/linkaction.cpp new file mode 100644 index 0000000..e9f8b4e --- /dev/null +++ b/src/linkaction.cpp @@ -0,0 +1,34 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include "linkaction.h" + +using namespace std; + +LinkAction::LinkAction(GMenu2X *gmenu2x, LinkRunAction act) + : Link(gmenu2x) { + this->gmenu2x = gmenu2x; + this->action = act; +} + +void LinkAction::run() { + this->action(); +} diff --git a/src/linkaction.h b/src/linkaction.h new file mode 100644 index 0000000..6c39fc2 --- /dev/null +++ b/src/linkaction.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef LINKACTION_H +#define LINKACTION_H + +#include +#include + +#include "FastDelegate.h" +#include "link.h" + +using std::string; +using fastdelegate::FastDelegate0; + +typedef FastDelegate0<> LinkRunAction; + +class GMenu2X; + +/** +Executes an action when launched. + + @author Massimiliano Torromeo +*/ +class LinkAction : public Link { +private: + LinkRunAction action; +public: + LinkAction(GMenu2X *gmenu2x, LinkRunAction act); + virtual ~LinkAction() {}; + virtual void run(); +}; + +#endif diff --git a/src/linkapp.cpp b/src/linkapp.cpp new file mode 100644 index 0000000..88d27e1 --- /dev/null +++ b/src/linkapp.cpp @@ -0,0 +1,574 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include + +#include +#include +#include "linkapp.h" +#include "menu.h" +#include "selector.h" +#include "textmanualdialog.h" + +using namespace std; + +LinkApp::LinkApp(GMenu2X *gmenu2x, const char* linkfile) + : Link(gmenu2x) { + this->gmenu2x = gmenu2x; + manual = ""; + file = linkfile; + wrapper = false; + dontleave = false; + setClock(336); + setVolume(-1); + //G + //setGamma(0); + setBacklight(100); + selectordir = ""; + selectorfilter = ""; + icon = iconPath = ""; + selectorbrowser = false; + useRamTimings = false; + + string line; + ifstream infile (linkfile, ios_base::in); + while (getline(infile, line, '\n')) { + line = trim(line); + if (line=="") continue; + if (line[0]=='#') continue; + + string::size_type position = line.find("="); + string name = trim(line.substr(0,position)); + string value = trim(line.substr(position+1)); + if (name == "title") { + title = value; + } else if (name == "description") { + description = value; + } else if (name == "icon") { + setIcon(value); + } else if (name == "exec") { + exec = value; + } else if (name == "params") { + params = value; + } else if (name == "workdir") { + workdir = value; + } else if (name == "manual") { + manual = value; + } else if (name == "wrapper") { + if (value=="true") wrapper = true; + } else if (name == "dontleave") { + if (value=="true") dontleave = true; + } else if (name == "clock") { + setClock( atoi(value.c_str()) ); + //G + } else if (name == "gamma") { + setGamma( atoi(value.c_str()) ); + } else if (name == "backlight") { + setBacklight( atoi(value.c_str()) ); + } else if (name == "volume") { + setVolume( atoi(value.c_str()) ); + } else if (name == "selectordir") { + setSelectorDir( value ); + } else if (name == "selectorbrowser") { + if (value=="true") selectorbrowser = true; + } else if (name == "useramtimings") { + if (value=="true") useRamTimings = true; + } else if (name == "selectorfilter") { + setSelectorFilter( value ); + } else if (name == "selectorscreens") { + setSelectorScreens( value ); + } else if (name == "selectoraliases") { + setAliasFile( value ); + } else { + cout << "Unrecognized option: " << name << endl; + break; + } + } + infile.close(); + + if (iconPath.empty()) searchIcon(); + + edited = false; +} + +string LinkApp::searchIcon() { + string execicon = exec; + string::size_type pos = exec.rfind("."); + if (pos != string::npos) execicon = exec.substr(0,pos); + execicon += ".png"; + string exectitle = execicon; + pos = execicon.rfind("/"); + if (pos != string::npos) + string exectitle = execicon.substr(pos+1,execicon.length()); + + if (!gmenu2x->sc.getSkinFilePath("icons/"+exectitle).empty()) + iconPath = gmenu2x->sc.getSkinFilePath("icons/"+exectitle); + else if (fileExists(execicon)) + iconPath = execicon; + else + iconPath = gmenu2x->sc.getSkinFilePath("icons/generic.png"); + + return iconPath; +} + +int LinkApp::clock() { + return iclock; +} + +string LinkApp::clockStr(int maxClock) { + if (iclock>maxClock) setClock(maxClock); + return sclock; +} + +void LinkApp::setClock(int mhz) { + iclock = constrain(mhz,200,430); + stringstream ss; + sclock = ""; + ss << iclock << "Mhz"; + ss >> sclock; + + edited = true; +} + +int LinkApp::volume() { + return ivolume; +} + +string LinkApp::volumeStr() { + return svolume; +} + +void LinkApp::setVolume(int vol) { + ivolume = constrain(vol,-1,100); + stringstream ss; + svolume = ""; + if (ivolume<0) + ss << gmenu2x->confInt["globalVolume"]; + else + ss << ivolume; + ss >> svolume; + + edited = true; +} + +int LinkApp::backlight() +{ + return ibacklight; +} + +string LinkApp::backlightStr() +{ + return sbacklight; +} + +void LinkApp::setBacklight(int val) +{ + ibacklight = constrain(val,5,100); + stringstream ss; + sbacklight = ""; + ss << ibacklight; + ss >> sbacklight; + + edited = true; +} +//G +int LinkApp::gamma() { + return igamma; +} + +string LinkApp::gammaStr() { + return sgamma; +} + +void LinkApp::setGamma(int gamma) { + igamma = constrain(gamma,0,100); + stringstream ss; + sgamma = ""; + ss << igamma; + ss >> sgamma; + + edited = true; +} +// /G + +bool LinkApp::targetExists() { +#ifndef TARGET_GP2X + return true; //For displaying elements during testing on pc +#endif + + string target = exec; + if (!exec.empty() && exec[0]!='/' && !workdir.empty()) + target = workdir + "/" + exec; + + return fileExists(target); +} + +bool LinkApp::save() { + if (!edited) return false; + + ofstream f(file.c_str()); + if (f.is_open()) { + if (title!="" ) f << "title=" << title << endl; + if (description!="" ) f << "description=" << description << endl; + if (icon!="" ) f << "icon=" << icon << endl; + if (exec!="" ) f << "exec=" << exec << endl; + if (params!="" ) f << "params=" << params << endl; + if (workdir!="" ) f << "workdir=" << workdir << endl; + if (manual!="" ) f << "manual=" << manual << endl; + if (iclock!=0 ) f << "clock=" << iclock << endl; + if (useRamTimings ) f << "useramtimings=true" << endl; + if (ivolume>0 ) f << "volume=" << ivolume << endl; + //G + if (igamma!=0 ) f << "gamma=" << igamma << endl; + if (ibacklight!=0 ) f << "backlight=" << ibacklight << endl; + if (selectordir!="" ) f << "selectordir=" << selectordir << endl; + if (selectorbrowser ) f << "selectorbrowser=true" << endl; + if (selectorfilter!="" ) f << "selectorfilter=" << selectorfilter << endl; + if (selectorscreens!="") f << "selectorscreens=" << selectorscreens << endl; + if (aliasfile!="" ) f << "selectoraliases=" << aliasfile << endl; + if (wrapper ) f << "wrapper=true" << endl; + if (dontleave ) f << "dontleave=true" << endl; + f.close(); + sync(); + return true; + } else + cout << "\033[0;34mGMENU2X:\033[0;31m Error while opening the file '" << file << "' for write\033[0m" << endl; + return false; +} + +void LinkApp::drawRun() { + //Darkened background + gmenu2x->s->box(0, 0, gmenu2x->resX, gmenu2x->resY, 0,0,0,150); + + string text = gmenu2x->tr.translate("Launching $1",getTitle().c_str(),NULL); + int textW = gmenu2x->font->getTextWidth(text); + int boxW = 62+textW; + int halfBoxW = boxW/2; + + //outer box + gmenu2x->s->box(gmenu2x->halfX-2-halfBoxW, gmenu2x->halfY-23, halfBoxW*2+5, 47, gmenu2x->skinConfColors["messageBoxBg"]); + //inner rectangle + gmenu2x->s->rectangle(gmenu2x->halfX-halfBoxW, gmenu2x->halfY-21, boxW, 42, gmenu2x->skinConfColors["messageBoxBorder"]); + + int x = gmenu2x->halfX+10-halfBoxW; + /*if (getIcon()!="") + gmenu2x->sc[getIcon()]->blit(gmenu2x->s,x,104); + else + gmenu2x->sc["icons/generic.png"]->blit(gmenu2x->s,x,104);*/ + gmenu2x->sc[getIconPath()]->blit(gmenu2x->s,x,gmenu2x->halfY-16); + gmenu2x->s->write( gmenu2x->font, text, x+42, gmenu2x->halfY+1, SFontHAlignLeft, SFontVAlignMiddle ); + gmenu2x->s->flip(); +} + +void LinkApp::run() { + if (selectordir!="") + selector(); + else + launch(); +} + +void LinkApp::showManual() { + if (manual=="" || !fileExists(manual)) return; + + // Png manuals + string ext8 = manual.substr(manual.size()-8,8); + if (ext8==".man.png" || ext8==".man.bmp" || ext8==".man.jpg" || manual.substr(manual.size()-9,9)==".man.jpeg") { + //Raise the clock to speed-up the loading of the manual + gmenu2x->setClock(336); + + Surface pngman(manual); + Surface bg(gmenu2x->confStr["wallpaper"],false); + stringstream ss; + string pageStatus; + + bool close = false, repaint = true; + int page=0, pagecount=pngman.raw->w/320; + + ss << pagecount; + string spagecount; + ss >> spagecount; + + //Lower the clock + gmenu2x->setClock(gmenu2x->confInt["menuClock"]); + + while (!close) { + if (repaint) { + bg.blit(gmenu2x->s, 0, 0); + pngman.blit(gmenu2x->s, -page*320, 0); + + gmenu2x->drawBottomBar(); + gmenu2x->drawButton(gmenu2x->s, "x", gmenu2x->tr["Exit"], + gmenu2x->drawButton(gmenu2x->s, "right", gmenu2x->tr["Change page"], + gmenu2x->drawButton(gmenu2x->s, "left", "", 5)-10)); + + ss.clear(); + ss << page+1; + ss >> pageStatus; + pageStatus = gmenu2x->tr["Page"]+": "+pageStatus+"/"+spagecount; + gmenu2x->s->write(gmenu2x->font, pageStatus, 310, 230, SFontHAlignRight, SFontVAlignMiddle); + + gmenu2x->s->flip(); + repaint = false; + } + + gmenu2x->input.update(); + if ( gmenu2x->input[ACTION_Y] || gmenu2x->input[ACTION_X] || gmenu2x->input[ACTION_START] ) close = true; + if ( gmenu2x->input[ACTION_LEFT] && page>0 ) { page--; repaint=true; } + if ( gmenu2x->input[ACTION_RIGHT] && page txtman; + + string line; + ifstream infile(manual.c_str(), ios_base::in); + if (infile.is_open()) { + gmenu2x->setClock(336); + while (getline(infile, line, '\n')) txtman.push_back(line); + infile.close(); + + TextManualDialog tmd(gmenu2x, getTitle(), getIconPath(), &txtman); + gmenu2x->setClock(gmenu2x->confInt["menuClock"]); + tmd.exec(); + } + + return; + } + + //Readmes + vector readme; + + string line; + ifstream infile(manual.c_str(), ios_base::in); + if (infile.is_open()) { + gmenu2x->setClock(336); + while (getline(infile, line, '\n')) readme.push_back(line); + infile.close(); + + TextDialog td(gmenu2x, getTitle(), "ReadMe", getIconPath(), &readme); + gmenu2x->setClock(gmenu2x->confInt["menuClock"]); + td.exec(); + } +} + +void LinkApp::selector(int startSelection, string selectorDir) { + //Run selector interface + Selector sel(gmenu2x, this, selectorDir); + int selection = sel.exec(startSelection); + if (selection!=-1) { + gmenu2x->writeTmp(selection,sel.dir); + launch(sel.file, sel.dir); + } +} + +void LinkApp::launch(string selectedFile, string selectedDir) { + drawRun(); + save(); +#ifndef TARGET_GP2X + //delay for testing + SDL_Delay(1000); +#endif + + //Set correct working directory + string wd = workdir; + if (wd=="") { + string::size_type pos = exec.rfind("/"); + if (pos!=string::npos) + wd = exec.substr(0,pos); + } + if (!wd.empty()) { + if (wd[0]!='/') wd = gmenu2x->getExePath() + wd; + chdir(wd.c_str()); + } + + //selectedFile + if (selectedFile!="") { + string selectedFileExtension; + string::size_type i = selectedFile.rfind("."); + if (i != string::npos) { + selectedFileExtension = selectedFile.substr(i,selectedFile.length()); + selectedFile = selectedFile.substr(0,i); + } + + if (selectedDir=="") + selectedDir = getSelectorDir(); + if (params=="") { + params = cmdclean(selectedDir+selectedFile+selectedFileExtension); + } else { + string origParams = params; + params = strreplace(params,"[selFullPath]",cmdclean(selectedDir+selectedFile+selectedFileExtension)); + params = strreplace(params,"[selPath]",cmdclean(selectedDir)); + params = strreplace(params,"[selFile]",cmdclean(selectedFile)); + params = strreplace(params,"[selExt]",cmdclean(selectedFileExtension)); + if (params == origParams) params += " " + cmdclean(selectedDir+selectedFile+selectedFileExtension); + } + } + + if (useRamTimings) + gmenu2x->applyRamTimings(); + if (volume()>=0) + gmenu2x->setVolume(volume()); + +#ifdef DEBUG + cout << "\033[0;34mGMENU2X:\033[0m Executing '" << title << "' (" << exec << " " << params << ")" << endl; +#endif + + //check if we have to quit + string command = cmdclean(exec); + + // Check to see if permissions are desirable + struct stat fstat; + if( stat( command.c_str(), &fstat ) == 0 ) { + struct stat newstat = fstat; + if( S_IRUSR != ( fstat.st_mode & S_IRUSR ) ) + newstat.st_mode |= S_IRUSR; + if( S_IXUSR != ( fstat.st_mode & S_IXUSR ) ) + newstat.st_mode |= S_IXUSR; + if( fstat.st_mode != newstat.st_mode ) + chmod( command.c_str(), newstat.st_mode ); + } // else, well.. we are no worse off :) + + if (params!="") command += " " + params; + if (gmenu2x->confInt["outputLogs"]) command += " &> " + cmdclean(gmenu2x->getExePath()) + "/log.txt"; + if (wrapper) command += "; sync & cd "+cmdclean(gmenu2x->getExePath())+"; exec ./gmenu2x"; + if (dontleave) { + system(command.c_str()); + } else { + if (gmenu2x->confInt["saveSelection"] && (gmenu2x->confInt["section"]!=gmenu2x->menu->selSectionIndex() || gmenu2x->confInt["link"]!=gmenu2x->menu->selLinkIndex())) + gmenu2x->writeConfig(); + if (gmenu2x->fwType == "open2x" && gmenu2x->savedVolumeMode != gmenu2x->volumeMode) + gmenu2x->writeConfigOpen2x(); + if (selectedFile=="") + gmenu2x->writeTmp(); + gmenu2x->quit(); + if (clock()!=gmenu2x->confInt["menuClock"]) + gmenu2x->setClock(clock()); + //if (gamma()!=0 && gamma()!=gmenu2x->confInt["gamma"]) + // gmenu2x->setGamma(gamma()); + if((backlight() != 0) && (backlight() != gmenu2x->confInt["backlight"])) + gmenu2x->setBacklight(backlight()); + + execlp("/bin/sh","/bin/sh","-c",command.c_str(),NULL); + //if execution continues then something went wrong and as we already called SDL_Quit we cannot continue + //try relaunching gmenu2x + chdir(gmenu2x->getExePath().c_str()); + execlp("./gmenu2x", "./gmenu2x", NULL); + } + + + chdir(gmenu2x->getExePath().c_str()); +} + +string LinkApp::getExec() { + return exec; +} + +void LinkApp::setExec(string exec) { + this->exec = exec; + edited = true; +} + +string LinkApp::getParams() { + return params; +} + +void LinkApp::setParams(string params) { + this->params = params; + edited = true; +} + +string LinkApp::getWorkdir() { + return workdir; +} + +void LinkApp::setWorkdir(string workdir) { + this->workdir = workdir; + edited = true; +} + +string LinkApp::getManual() { + return manual; +} + +void LinkApp::setManual(string manual) { + this->manual = manual; + edited = true; +} + +string LinkApp::getSelectorDir() { + return selectordir; +} + +void LinkApp::setSelectorDir(string selectordir) { + if (selectordir!="" && selectordir[selectordir.length()-1]!='/') selectordir += "/"; + this->selectordir = selectordir; + edited = true; +} + +bool LinkApp::getSelectorBrowser() { + return selectorbrowser; +} + +void LinkApp::setSelectorBrowser(bool value) { + selectorbrowser = value; + edited = true; +} + +bool LinkApp::getUseRamTimings() { + return useRamTimings; +} + +void LinkApp::setUseRamTimings(bool value) { + useRamTimings = value; + edited = true; +} + +string LinkApp::getSelectorFilter() { + return selectorfilter; +} + +void LinkApp::setSelectorFilter(string selectorfilter) { + this->selectorfilter = selectorfilter; + edited = true; +} + +string LinkApp::getSelectorScreens() { + return selectorscreens; +} + +void LinkApp::setSelectorScreens(string selectorscreens) { + this->selectorscreens = selectorscreens; + edited = true; +} + +string LinkApp::getAliasFile() { + return aliasfile; +} + +void LinkApp::setAliasFile(string aliasfile) { + if (fileExists(aliasfile)) { + this->aliasfile = aliasfile; + edited = true; + } +} diff --git a/src/linkapp.h b/src/linkapp.h new file mode 100644 index 0000000..37a0b1d --- /dev/null +++ b/src/linkapp.h @@ -0,0 +1,109 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef LINKAPP_H +#define LINKAPP_H + +#include +#include + +#include "link.h" + +using std::string; + +class GMenu2X; + +/** +Parses links files. + + @author Massimiliano Torromeo +*/ +class LinkApp : public Link { +private: + string sclock, svolume; + int iclock, ivolume; + //G + string sgamma; + string sbacklight; + //G + int igamma; + int ibacklight; + string exec, params, workdir, manual, selectordir, selectorfilter, selectorscreens; + bool selectorbrowser, useRamTimings; + void drawRun(); + + string aliasfile; + +public: + LinkApp(GMenu2X *gmenu2x, const char* linkfile); + virtual string searchIcon(); + + string getExec(); + void setExec(string exec); + string getParams(); + void setParams(string params); + string getWorkdir(); + void setWorkdir(string workdir); + string getManual(); + void setManual(string manual); + string getSelectorDir(); + void setSelectorDir(string selectordir); + bool getSelectorBrowser(); + void setSelectorBrowser(bool value); + bool getUseRamTimings(); + void setUseRamTimings(bool value); + string getSelectorScreens(); + void setSelectorScreens(string selectorscreens); + string getSelectorFilter(); + void setSelectorFilter(string selectorfilter); + string getAliasFile(); + void setAliasFile(string aliasfile); + + string file; + + int clock(); + string clockStr(int maxClock); + void setClock(int mhz); + + int volume(); + string volumeStr(); + void setVolume(int vol); + +//G + int gamma(); + string gammaStr(); + void setGamma(int gamma); + + int backlight(); + string backlightStr(); + void setBacklight(int val); +// /G + + bool wrapper; + bool dontleave; + + bool save(); + void run(); + void showManual(); + void selector(int startSelection=0, string selectorDir=""); + void launch(string selectedFile="", string selectedDir=""); + bool targetExists(); +}; + +#endif diff --git a/src/listview.cpp b/src/listview.cpp new file mode 100644 index 0000000..a295ca9 --- /dev/null +++ b/src/listview.cpp @@ -0,0 +1,78 @@ +#include "listview.h" + +ListView::ListView(GMenu2X *gmenu2x) { + this->gmenu2x = gmenu2x; + firstDisplayItem = selectedItem = 0; + itemsPerPage = 11; +} + +ListView::~ ListView() {} + +ListViewItem * ListView::add(ListViewItem *item) { + items.push_back(item); + return item; +} + +ListViewItem * ListView::add(string text) { + ListViewItem *item = new ListViewItem(this,text); + return add(item); +} + +void ListView::del(ListViewItem * item) { + vector::iterator p = find(items.begin(), items.end(), item); + if (p != items.end()) + items.erase(p); +} + +void ListView::del(int itemIndex) { + items.erase(items.begin()+itemIndex); +} + +void ListView::clear() { + items.clear(); +} + +ListViewItem * ListView::operator [](int index) { + return items[index]; +} + +void ListView::setPosition(int x, int y) { + rect.x = x; + rect.y = y; +} + +void ListView::setSize(int w, int h) { + rect.w = w; + rect.h = h; +} + +void ListView::paint() { + gmenu2x->s->setClipRect(rect); + + //Selection + int iY = selectedItem-firstDisplayItem; + iY = rect.y+(iY*16); + if (selectedItem<(int)items.size()) + gmenu2x->s->box(1, iY, 309, 14, gmenu2x->skinConfColors["selectionBg"]); + + //Items + iY = rect.y; + for (int i=firstDisplayItem; i<(int)items.size() && isetPosition(4,iY); + items[i]->paint(); + iY += items[i]->getHeight(); + } + + gmenu2x->drawScrollBar(itemsPerPage, items.size(), firstDisplayItem, 42,175); + + gmenu2x->s->clearClipRect(); +} + +void ListView::handleInput() { + for (int i=firstDisplayItem; i<(int)items.size() && ihandleTS(); +} + +int ListView::getWidth() { + return rect.w; +} diff --git a/src/listview.h b/src/listview.h new file mode 100644 index 0000000..e8dd6e1 --- /dev/null +++ b/src/listview.h @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef LISTVIEW_H_ +#define LISTVIEW_H_ + +#include "gmenu2x.h" +#include "listviewitem.h" + +using std::vector; + +class ListView { +private: + int firstDisplayItem, selectedItem; + int itemsPerPage; + +protected: + vector items; + SDL_Rect rect; + +public: + ListView(GMenu2X *gmenu2x); + virtual ~ListView(); + + GMenu2X *gmenu2x; + + ListViewItem *add(ListViewItem *item); + ListViewItem *add(string text); + void del(ListViewItem *item); + void del(int itemIndex); + void clear(); + + void setPosition(int x, int y); + void setSize(int w, int h); + int getWidth(); + + virtual void paint(); + virtual void handleInput(); + + ListViewItem *operator[](int); +}; + +#endif diff --git a/src/listviewitem.cpp b/src/listviewitem.cpp new file mode 100644 index 0000000..59ed829 --- /dev/null +++ b/src/listviewitem.cpp @@ -0,0 +1,30 @@ +#include "listview.h" +#include "listviewitem.h" + +ListViewItem::ListViewItem(ListView * parent, string text) { + this->parent = parent; + rect.h = 16; + rect.w = parent->getWidth(); +} + +ListViewItem::~ ListViewItem() {} + +void ListViewItem::setPosition(int x, int y) { + rect.x = x; + rect.y = y; +} + +void ListViewItem::paint() { + parent->gmenu2x->s->write(parent->gmenu2x->font, text, rect.x, rect.y, SFontHAlignLeft, SFontVAlignMiddle); +} + +int ListViewItem::getHeight() { + return rect.h; +} + +void ListViewItem::handleTS() { + if (parent->gmenu2x->ts.inRect(rect)) + onClick(); +} + +void ListViewItem::onClick() {} diff --git a/src/listviewitem.h b/src/listviewitem.h new file mode 100644 index 0000000..7c03e08 --- /dev/null +++ b/src/listviewitem.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef LISTVIEWITEM_H_ +#define LISTVIEWITEM_H_ + +#include + +using std::string; + +class ListView; + +class ListViewItem { +protected: + ListView *parent; + SDL_Rect rect; + +public: + ListViewItem(ListView *parent, string text); + virtual ~ListViewItem(); + + string text; + + void setPosition(int x, int y); + int getHeight(); + + virtual void paint(); + virtual void handleTS(); + virtual void onClick(); +}; + +#endif diff --git a/src/lr.xcf b/src/lr.xcf new file mode 100644 index 0000000..cd5c249 Binary files /dev/null and b/src/lr.xcf differ diff --git a/src/menu.cpp b/src/menu.cpp new file mode 100644 index 0000000..158219c --- /dev/null +++ b/src/menu.cpp @@ -0,0 +1,457 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "gmenu2x.h" +#include "linkapp.h" +#include "menu.h" +#include "filelister.h" +#include "utilities.h" +#include "pxml.h" + +using namespace std; + +Menu::Menu(GMenu2X *gmenu2x) { + this->gmenu2x = gmenu2x; + iFirstDispSection = 0; + + DIR *dirp; + struct stat st; + struct dirent *dptr; + string filepath; + + if ((dirp = opendir("sections")) == NULL) return; + + while ((dptr = readdir(dirp))) { + if (dptr->d_name[0]=='.') continue; + filepath = (string)"sections/"+dptr->d_name; + int statRet = stat(filepath.c_str(), &st); + if (!S_ISDIR(st.st_mode)) continue; + if (statRet != -1) { + sections.push_back((string)dptr->d_name); + linklist ll; + links.push_back(ll); + } + } + + closedir(dirp); + sort(sections.begin(),sections.end(),case_less()); + setSectionIndex(0); + readLinks(); +} + +Menu::~Menu() { + freeLinks(); +} + +uint Menu::firstDispRow() { + return iFirstDispRow; +} + +void Menu::loadIcons() { + //reload section icons + for (uint i=0; isc.getSkinFilePath(sectionIcon).empty()) + gmenu2x->sc.add("skin:"+sectionIcon); + + //check link's icons + string linkIcon; + for (uint x=0; xsize(); x++) { + linkIcon = sectionLinks(i)->at(x)->getIcon(); + LinkApp *linkapp = dynamic_cast(sectionLinks(i)->at(x)); + + if (linkIcon.substr(0,5)=="skin:") { + linkIcon = gmenu2x->sc.getSkinFilePath(linkIcon.substr(5,linkIcon.length())); + if (linkapp != NULL && !fileExists(linkIcon)) + linkapp->searchIcon(); + else + sectionLinks(i)->at(x)->setIconPath(linkIcon); + + } else if (!fileExists(linkIcon)) { + if (linkapp != NULL) linkapp->searchIcon(); + } + } + } +} + +/*==================================== + SECTION MANAGEMENT + ====================================*/ +void Menu::freeLinks() { + for (vector::iterator section = links.begin(); sectionbegin(); linkend(); link++) + free(*link); +} + +linklist *Menu::sectionLinks(int i) { + if (i<0 || i>(int)links.size()) + i = selSectionIndex(); + + if (i<0 || i>(int)links.size()) + return NULL; + + return &links[i]; +} + +void Menu::decSectionIndex() { + setSectionIndex(iSection-1); +} + +void Menu::incSectionIndex() { + setSectionIndex(iSection+1); +} + +uint Menu::firstDispSection() { + return iFirstDispSection; +} + +int Menu::selSectionIndex() { + return iSection; +} + +string Menu::selSection() { + return sections[iSection]; +} + +void Menu::setSectionIndex(int i) { + if (i<0) + i=sections.size()-1; + else if (i>=(int)sections.size()) + i=0; + iSection = i; + + if (i>(int)iFirstDispSection+4) + iFirstDispSection = i-4; + else if (i<(int)iFirstDispSection) + iFirstDispSection = i; + + iLink = 0; + iFirstDispRow = 0; +} + +string Menu::sectionPath(int section) { + if (section<0 || section>(int)sections.size()) section = iSection; + return "sections/"+sections[section]+"/"; +} + +/*==================================== + LINKS MANAGEMENT + ====================================*/ +bool Menu::addActionLink(uint section, string title, LinkRunAction action, string description, string icon) { + if (section>=sections.size()) return false; + + LinkAction *linkact = new LinkAction(gmenu2x,action); + linkact->setSize(gmenu2x->skinConfInt["linkWidth"],gmenu2x->skinConfInt["linkHeight"]); + linkact->setTitle(title); + linkact->setDescription(description); + if (gmenu2x->sc.exists(icon) || (icon.substr(0,5)=="skin:" && !gmenu2x->sc.getSkinFilePath(icon.substr(5,icon.length())).empty()) || fileExists(icon)) + linkact->setIcon(icon); + + sectionLinks(section)->push_back(linkact); + return true; +} + +bool Menu::addLink(string path, string file, string section) { + if (section=="") + section = selSection(); + else if (find(sections.begin(),sections.end(),section)==sections.end()) { + //section directory doesn't exists + if (!addSection(section)) + return false; + } + if (path[path.length()-1]!='/') path += "/"; + + //if the extension is not equal to gpu or dge then enable the wrapepr by default + bool wrapper = false, pxml = false; + + //strip the extension from the filename + string title = file; + string::size_type pos = title.rfind("."); + if (pos!=string::npos && pos>0) { + string ext = title.substr(pos, title.length()); + transform(ext.begin(), ext.end(), ext.begin(), (int(*)(int)) tolower); + if (ext == ".gpu" || ext == ".dge") wrapper = false; + else if (ext == ".pxml") pxml = true; + title = title.substr(0, pos); + } + + string linkpath = "sections/"+section+"/"+title; + int x=2; + while (fileExists(linkpath)) { + stringstream ss; + linkpath = ""; + ss << x; + ss >> linkpath; + linkpath = "sections/"+section+"/"+title+linkpath; + x++; + } +#ifdef DEBUG + cout << "\033[0;34mGMENU2X:\033[0m Adding link: " << linkpath << endl; +#endif + + //search for a manual + pos = file.rfind("."); + string exename = path+file.substr(0,pos); + string manual = ""; + if (fileExists(exename+".man.png")) { + manual = exename+".man.png"; + } else if (fileExists(exename+".man.jpg")) { + manual = exename+".man.jpg"; + } else if (fileExists(exename+".man.jpeg")) { + manual = exename+".man.jpeg"; + } else if (fileExists(exename+".man.bmp")) { + manual = exename+".man.bmp"; + } else if (fileExists(exename+".man.txt")) { + manual = exename+".man.txt"; + } else { + //scan directory for a file like *readme* + FileLister fl(path, false); + fl.setFilter(".txt"); + fl.browse(); + bool found = false; + for (uint x=0; xfont->getTextWidth(shorttitle)>gmenu2x->skinConfInt["linkWidth"]) { + while (gmenu2x->font->getTextWidth(shorttitle+"..")>gmenu2x->skinConfInt["linkWidth"]) + shorttitle = shorttitle.substr(0,shorttitle.length()-1); + shorttitle += ".."; + } + + ofstream f(linkpath.c_str()); + if (f.is_open()) { + f << "title=" << shorttitle << endl; + f << "exec=" << exec << endl; + if (!description.empty()) f << "description=" << description << endl; + if (!icon.empty()) f << "icon=" << icon << endl; + if (!manual.empty()) f << "manual=" << manual << endl; + if (wrapper) f << "wrapper=true" << endl; + f.close(); + sync(); + int isection = find(sections.begin(),sections.end(),section) - sections.begin(); + if (isection>=0 && isection<(int)sections.size()) { +#ifdef DEBUG + cout << "\033[0;34mGMENU2X:\033[0m Section: " << sections[isection] << "(" << isection << ")" << endl; +#endif + LinkApp* link = new LinkApp(gmenu2x, linkpath.c_str()); + link->setSize(gmenu2x->skinConfInt["linkWidth"],gmenu2x->skinConfInt["linkHeight"]); + links[isection].push_back( link ); + } + } else { +#ifdef DEBUG + cout << "\033[0;34mGMENU2X:\033[0;31m Error while opening the file '" << linkpath << "' for write\033[0m" << endl; +#endif + return false; + } + + return true; +} + +bool Menu::addSection(string sectionName) { + string sectiondir = "sections/"+sectionName; + if (mkdir(sectiondir.c_str(),0777)==0) { + sections.push_back(sectionName); + linklist ll; + links.push_back(ll); + return true; + } + return false; +} + +void Menu::deleteSelectedLink() { +#ifdef DEBUG + cout << "\033[0;34mGMENU2X:\033[0m Deleting link " << selLink()->getTitle() << endl; +#endif + if (selLinkApp()!=NULL) + unlink(selLinkApp()->file.c_str()); + gmenu2x->sc.del(selLink()->getIconPath()); + sectionLinks()->erase( sectionLinks()->begin() + selLinkIndex() ); + setLinkIndex(selLinkIndex()); +} + +void Menu::deleteSelectedSection() { +#ifdef DEBUG + cout << "\033[0;34mGMENU2X:\033[0m Deleting section " << selSection() << endl; +#endif + gmenu2x->sc.del("sections/"+selSection()+".png"); + links.erase( links.begin()+selSectionIndex() ); + sections.erase( sections.begin()+selSectionIndex() ); + setSectionIndex(0); //reload sections +} + +bool Menu::linkChangeSection(uint linkIndex, uint oldSectionIndex, uint newSectionIndex) { + if (oldSectionIndexsize()) { + sectionLinks(newSectionIndex)->push_back( sectionLinks(oldSectionIndex)->at(linkIndex) ); + sectionLinks(oldSectionIndex)->erase( sectionLinks(oldSectionIndex)->begin()+linkIndex ); + //Select the same link in the new position + setSectionIndex(newSectionIndex); + setLinkIndex(sectionLinks(newSectionIndex)->size()-1); + return true; + } + return false; +} + +void Menu::linkLeft() { + if (iLink%gmenu2x->linkColumns == 0) + setLinkIndex( sectionLinks()->size()>iLink+gmenu2x->linkColumns-1 ? iLink+gmenu2x->linkColumns-1 : sectionLinks()->size()-1 ); + else + setLinkIndex(iLink-1); +} + +void Menu::linkRight() { + if (iLink%gmenu2x->linkColumns == (gmenu2x->linkColumns-1) || iLink == (int)sectionLinks()->size()-1) + setLinkIndex(iLink-iLink%gmenu2x->linkColumns); + else + setLinkIndex(iLink+1); +} + +void Menu::linkUp() { + int l = iLink-gmenu2x->linkColumns; + if (l<0) { + uint rows = (uint)ceil(sectionLinks()->size()/(double)gmenu2x->linkColumns); + l = (rows*gmenu2x->linkColumns)+l; + if (l >= (int)sectionLinks()->size()) + l -= gmenu2x->linkColumns; + } + setLinkIndex(l); +} + +void Menu::linkDown() { + uint l = iLink+gmenu2x->linkColumns; + if (l >= sectionLinks()->size()) { + uint rows = (uint)ceil(sectionLinks()->size()/(double)gmenu2x->linkColumns); + uint curCol = (uint)ceil((iLink+1)/(double)gmenu2x->linkColumns); + if (rows > curCol) + l = sectionLinks()->size()-1; + else + l %= gmenu2x->linkColumns; + } + setLinkIndex(l); +} + +int Menu::selLinkIndex() { + return iLink; +} + +Link *Menu::selLink() { + if (sectionLinks()->size()==0) return NULL; + return sectionLinks()->at(iLink); +} + +LinkApp *Menu::selLinkApp() { + return dynamic_cast(selLink()); +} + +void Menu::setLinkIndex(int i) { + if (i<0) + i=sectionLinks()->size()-1; + else if (i>=(int)sectionLinks()->size()) + i=0; + + if (i>=(int)(iFirstDispRow*gmenu2x->linkColumns+gmenu2x->linkColumns*gmenu2x->linkRows)) + iFirstDispRow = i/gmenu2x->linkColumns-gmenu2x->linkRows+1; + else if (i<(int)(iFirstDispRow*gmenu2x->linkColumns)) + iFirstDispRow = i/gmenu2x->linkColumns; + + iLink = i; +} + +void Menu::readLinks() { + vector linkfiles; + + iLink = 0; + iFirstDispRow = 0; + + DIR *dirp; + struct stat st; + struct dirent *dptr; + string filepath; + + for (uint i=0; id_name[0]=='.') continue; + filepath = sectionPath(i)+dptr->d_name; + int statRet = stat(filepath.c_str(), &st); + if (S_ISDIR(st.st_mode)) continue; + if (statRet != -1) { + linkfiles.push_back(filepath); + } + } + + sort(linkfiles.begin(), linkfiles.end(),case_less()); + for (uint x=0; xsetSize(gmenu2x->skinConfInt["linkWidth"],gmenu2x->skinConfInt["linkHeight"]); + if (link->targetExists()) + links[i].push_back( link ); + else + free(link); + } + + closedir(dirp); + } +} diff --git a/src/menu.h b/src/menu.h new file mode 100644 index 0000000..a832b41 --- /dev/null +++ b/src/menu.h @@ -0,0 +1,85 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef MENU_H +#define MENU_H + +#include +#include +#include "linkaction.h" + +using std::string; +using std::vector; + +class LinkApp; +class GMenu2X; + +typedef vector linklist; + +/** +Handles the menu structure + + @author Massimiliano Torromeo +*/ +class Menu { +private: + GMenu2X *gmenu2x; + int iSection, iLink; + uint iFirstDispSection, iFirstDispRow; + void readLinks(); + void freeLinks(); + +public: + Menu(GMenu2X *gmenu2x); + ~Menu(); + + vector sections; + vector links; + linklist *sectionLinks(int i = -1); + + int selSectionIndex(); + string selSection(); + void decSectionIndex(); + void incSectionIndex(); + void setSectionIndex(int i); + uint firstDispSection(); + uint firstDispRow(); + + bool addActionLink(uint section, string title, LinkRunAction action, string description="", string icon=""); + bool addLink(string path, string file, string section=""); + bool addSection(string sectionName); + void deleteSelectedLink(); + void deleteSelectedSection(); + + void loadIcons(); + bool linkChangeSection(uint linkIndex, uint oldSectionIndex, uint newSectionIndex); + + int selLinkIndex(); + Link *selLink(); + LinkApp *selLinkApp(); + void linkLeft(); + void linkRight(); + void linkUp(); + void linkDown(); + void setLinkIndex(int i); + + string sectionPath(int section = -1); +}; + +#endif diff --git a/src/menusetting.cpp b/src/menusetting.cpp new file mode 100644 index 0000000..4f5fc97 --- /dev/null +++ b/src/menusetting.cpp @@ -0,0 +1,36 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "menusetting.h" + +MenuSetting::MenuSetting(GMenu2X *gmenu2x, string name, string description) { + this->gmenu2x = gmenu2x; + this->name = name; + this->description = description; +} + +void MenuSetting::draw(int y) { + gmenu2x->s->write( gmenu2x->font, name, 5, y+gmenu2x->font->getHalfHeight(), SFontHAlignLeft, SFontVAlignMiddle ); +} + +void MenuSetting::handleTS() {} +void MenuSetting::manageInput() {} +void MenuSetting::adjustInput() {} +void MenuSetting::drawSelected(int) {} +bool MenuSetting::edited() { return true; } diff --git a/src/menusetting.h b/src/menusetting.h new file mode 100644 index 0000000..6f83341 --- /dev/null +++ b/src/menusetting.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef MENUSETTING_H +#define MENUSETTING_H + +#ifdef TARGET_GP2X +#include "inputmanager.h" +#endif + +#include "gmenu2x.h" + +using std::string; + +/** +Base class for different kind of option + + @author Massimiliano Torromeo +*/ +class MenuSetting { +private: + GMenu2X *gmenu2x; + +public: + MenuSetting(GMenu2X *gmenu2x, string name, string description); + virtual ~MenuSetting() {}; + + virtual void draw(int y); + virtual void handleTS(); + virtual void manageInput(); + virtual void adjustInput(); + virtual void drawSelected(int y); + virtual bool edited(); + + string name, description; +}; + +#endif diff --git a/src/menusettingbool.cpp b/src/menusettingbool.cpp new file mode 100644 index 0000000..4a4e54a --- /dev/null +++ b/src/menusettingbool.cpp @@ -0,0 +1,95 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "menusettingbool.h" +#include "utilities.h" +#include + +using namespace std; +using namespace fastdelegate; + +MenuSettingBool::MenuSettingBool(GMenu2X *gmenu2x, string name, string description, int *value) + : MenuSetting(gmenu2x,name,description) { + this->gmenu2x = gmenu2x; + _ivalue = value; + _value = NULL; + originalValue = *value != 0; + setValue(this->value()); + + btnToggle = new IconButton(gmenu2x, "skin:imgs/buttons/b.png", gmenu2x->tr["Switch"]); + btnToggle->setAction(MakeDelegate(this, &MenuSettingBool::toggle)); +} + +MenuSettingBool::MenuSettingBool(GMenu2X *gmenu2x, string name, string description, bool *value) + : MenuSetting(gmenu2x,name,description) { + this->gmenu2x = gmenu2x; + _value = value; + _ivalue = NULL; + originalValue = *value; + setValue(this->value()); + + btnToggle = new IconButton(gmenu2x, "skin:imgs/buttons/b.png", gmenu2x->tr["Switch"]); + btnToggle->setAction(MakeDelegate(this, &MenuSettingBool::toggle)); +} + +void MenuSettingBool::draw(int y) { + MenuSetting::draw(y); + gmenu2x->s->write( gmenu2x->font, strvalue, 155, y+gmenu2x->font->getHalfHeight(), SFontHAlignLeft, SFontVAlignMiddle ); +} + +void MenuSettingBool::handleTS() { + btnToggle->handleTS(); +} + +void MenuSettingBool::manageInput() { + if ( gmenu2x->input[ACTION_B] ) toggle(); +} + +void MenuSettingBool::toggle() { + setValue(!value()); +} + +void MenuSettingBool::setValue(int value) { + setValue(value != 0); +} + +void MenuSettingBool::setValue(bool value) { + if (_value == NULL) + *_ivalue = value; + else + *_value = value; + strvalue = value ? "ON" : "OFF"; +} + +bool MenuSettingBool::value() { + if (_value == NULL) + return *_ivalue != 0; + else + return *_value; +} + +void MenuSettingBool::adjustInput() {} + +void MenuSettingBool::drawSelected(int) { + gmenu2x->drawButton(btnToggle); +} + +bool MenuSettingBool::edited() { + return originalValue != value(); +} diff --git a/src/menusettingbool.h b/src/menusettingbool.h new file mode 100644 index 0000000..9373a7d --- /dev/null +++ b/src/menusettingbool.h @@ -0,0 +1,57 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef MENUSETTINGBOOL_H +#define MENUSETTINGBOOL_H + +#include "iconbutton.h" +#include "menusetting.h" + +using std::string; +class GMenu2X; + +class MenuSettingBool : public MenuSetting { +private: + bool originalValue; + bool *_value; + int *_ivalue; + string strvalue; + GMenu2X *gmenu2x; + IconButton *btnToggle; + + void toggle(); + +public: + MenuSettingBool(GMenu2X *gmenu2x, string name, string description, bool *value); + MenuSettingBool(GMenu2X *gmenu2x, string name, string description, int *value); + virtual ~MenuSettingBool() {}; + + virtual void draw(int y); + virtual void handleTS(); + virtual void manageInput(); + virtual void adjustInput(); + virtual void drawSelected(int y); + virtual bool edited(); + + void setValue(int value); + void setValue(bool value); + bool value(); +}; + +#endif diff --git a/src/menusettingdir.cpp b/src/menusettingdir.cpp new file mode 100644 index 0000000..a98dc18 --- /dev/null +++ b/src/menusettingdir.cpp @@ -0,0 +1,81 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "menusettingdir.h" +#include "dirdialog.h" +#include "utilities.h" + +using namespace std; +using namespace fastdelegate; + +MenuSettingDir::MenuSettingDir(GMenu2X *gmenu2x, string name, string description, string *value) + : MenuSetting(gmenu2x,name,description) { + this->gmenu2x = gmenu2x; + _value = value; + originalValue = *value; + + btnClear = new IconButton(gmenu2x, "skin:imgs/buttons/x.png", gmenu2x->tr["Clear"]); + btnClear->setAction(MakeDelegate(this, &MenuSettingDir::clear)); + + btnSelect = new IconButton(gmenu2x, "skin:imgs/buttons/b.png", gmenu2x->tr["Select a directory"]); + btnSelect->setAction(MakeDelegate(this, &MenuSettingDir::select)); +} + +void MenuSettingDir::draw(int y) { + MenuSetting::draw(y); + gmenu2x->s->write( gmenu2x->font, value(), 155, y+gmenu2x->font->getHalfHeight(), SFontHAlignLeft, SFontVAlignMiddle ); +} + +void MenuSettingDir::handleTS() { + btnSelect->handleTS(); + btnClear->handleTS(); +} + +void MenuSettingDir::manageInput() { + if ( gmenu2x->input[ACTION_X] ) setValue(""); + if ( gmenu2x->input[ACTION_B] ) select(); +} + +void MenuSettingDir::clear() { + setValue(""); +} + +void MenuSettingDir::select() { + DirDialog dd(gmenu2x, description, value()); + if (dd.exec()) setValue( dd.path ); +} + +void MenuSettingDir::setValue(string value) { + *_value = value; +} + +string MenuSettingDir::value() { + return *_value; +} + +void MenuSettingDir::adjustInput() {} + +void MenuSettingDir::drawSelected(int) { + gmenu2x->drawButton(btnClear, + gmenu2x->drawButton(btnSelect)); +} + +bool MenuSettingDir::edited() { + return originalValue != value(); +} diff --git a/src/menusettingdir.h b/src/menusettingdir.h new file mode 100644 index 0000000..e5c4c3a --- /dev/null +++ b/src/menusettingdir.h @@ -0,0 +1,53 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef MENUSETTINGDIR_H +#define MENUSETTINGDIR_H + +#include "gmenu2x.h" +#include "menusetting.h" + +using std::string; + +class MenuSettingDir : public MenuSetting { +private: + string originalValue; + string *_value; + GMenu2X *gmenu2x; + IconButton *btnClear, *btnSelect; + + void select(); + void clear(); + +public: + MenuSettingDir(GMenu2X *gmenu2x, string name, string description, string *value); + virtual ~MenuSettingDir() {}; + + virtual void draw(int y); + virtual void handleTS(); + virtual void manageInput(); + virtual void adjustInput(); + virtual void drawSelected(int y); + virtual bool edited(); + + void setValue(string value); + string value(); +}; + +#endif diff --git a/src/menusettingfile.cpp b/src/menusettingfile.cpp new file mode 100644 index 0000000..5317226 --- /dev/null +++ b/src/menusettingfile.cpp @@ -0,0 +1,82 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "menusettingfile.h" +#include "filedialog.h" +#include "utilities.h" + +using namespace std; +using namespace fastdelegate; + +MenuSettingFile::MenuSettingFile(GMenu2X *gmenu2x, string name, string description, string *value, string filter) + : MenuSetting(gmenu2x,name,description) { + this->gmenu2x = gmenu2x; + this->filter = filter; + _value = value; + originalValue = *value; + + btnClear = new IconButton(gmenu2x, "skin:imgs/buttons/x.png", gmenu2x->tr["Clear"]); + btnClear->setAction(MakeDelegate(this, &MenuSettingFile::clear)); + + btnSelect = new IconButton(gmenu2x, "skin:imgs/buttons/b.png", gmenu2x->tr["Select a file"]); + btnSelect->setAction(MakeDelegate(this, &MenuSettingFile::select)); +} + +void MenuSettingFile::draw(int y) { + MenuSetting::draw(y); + gmenu2x->s->write( gmenu2x->font, value(), 155, y+gmenu2x->font->getHalfHeight(), SFontHAlignLeft, SFontVAlignMiddle ); +} + +void MenuSettingFile::handleTS() { + btnSelect->handleTS(); + btnClear->handleTS(); +} + +void MenuSettingFile::manageInput() { + if ( gmenu2x->input[ACTION_X] ) setValue(""); + if ( gmenu2x->input[ACTION_B] ) select(); +} + +void MenuSettingFile::clear() { + setValue(""); +} + +void MenuSettingFile::select() { + FileDialog fd(gmenu2x, description, filter, value()); + if (fd.exec()) setValue( fd.path()+"/"+fd.file ); +} + +void MenuSettingFile::setValue(string value) { + *_value = value; +} + +string MenuSettingFile::value() { + return *_value; +} + +void MenuSettingFile::adjustInput() {} + +void MenuSettingFile::drawSelected(int) { + gmenu2x->drawButton(btnClear, + gmenu2x->drawButton(btnSelect)); +} + +bool MenuSettingFile::edited() { + return originalValue != value(); +} diff --git a/src/menusettingfile.h b/src/menusettingfile.h new file mode 100644 index 0000000..811a101 --- /dev/null +++ b/src/menusettingfile.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef MENUSETTINGFILE_H +#define MENUSETTINGFILE_H + +#include "gmenu2x.h" +#include "menusetting.h" + +using std::string; + +class MenuSettingFile : public MenuSetting { +protected: + string originalValue; + string *_value; + string filter; + GMenu2X *gmenu2x; + IconButton *btnClear, *btnSelect; + + void select(); + void clear(); + +public: + MenuSettingFile(GMenu2X *gmenu2x, string name, string description, string *value, string filter=""); + virtual ~MenuSettingFile() {}; + + virtual void draw(int y); + virtual void handleTS(); + virtual void manageInput(); + virtual void adjustInput(); + virtual void drawSelected(int y); + virtual bool edited(); + + virtual void setValue(string value); + string value(); +}; + +#endif diff --git a/src/menusettingimage.cpp b/src/menusettingimage.cpp new file mode 100644 index 0000000..6726e76 --- /dev/null +++ b/src/menusettingimage.cpp @@ -0,0 +1,56 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "menusettingimage.h" +#include "imagedialog.h" +#include "utilities.h" + +using namespace std; + +MenuSettingImage::MenuSettingImage(GMenu2X *gmenu2x, string name, string description, string *value, string filter) + : MenuSettingFile(gmenu2x,name,description,value,filter) { + this->gmenu2x = gmenu2x; + this->filter = filter; + _value = value; + originalValue = *value; +} + +void MenuSettingImage::manageInput() { + if ( gmenu2x->input[ACTION_X] ) setValue(""); + if ( gmenu2x->input[ACTION_B] ) { + ImageDialog id(gmenu2x, description, filter, value()); + if (id.exec()) setValue( id.path()+"/"+id.file ); + } +} + +void MenuSettingImage::setValue(string value) { + string skinpath = gmenu2x->getExePath()+"skins/"+gmenu2x->confStr["skin"]; + bool inSkinDir = value.substr(0,skinpath.length()) == skinpath; + if (!inSkinDir && gmenu2x->confStr["skin"] != "Default") { + skinpath = gmenu2x->getExePath()+"skins/Default"; + inSkinDir = value.substr(0,skinpath.length()) == skinpath; + } + if (inSkinDir) { + string tempIcon = value.substr(skinpath.length(), value.length()); + string::size_type pos = tempIcon.find("/"); + if (pos != string::npos) + value = "skin:"+tempIcon.substr(pos+1,value.length()); + } + *_value = value; +} diff --git a/src/menusettingimage.h b/src/menusettingimage.h new file mode 100644 index 0000000..11ed068 --- /dev/null +++ b/src/menusettingimage.h @@ -0,0 +1,37 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef MENUSETTINGIMAGE_H +#define MENUSETTINGIMAGE_H + +#include "gmenu2x.h" +#include "menusettingfile.h" + +using std::string; + +class MenuSettingImage : public MenuSettingFile { +public: + MenuSettingImage(GMenu2X *gmenu2x, string name, string description, string *value, string filter=""); + virtual ~MenuSettingImage() {}; + + virtual void manageInput(); + virtual void setValue(string value); +}; + +#endif diff --git a/src/menusettingint.cpp b/src/menusettingint.cpp new file mode 100644 index 0000000..b72112d --- /dev/null +++ b/src/menusettingint.cpp @@ -0,0 +1,106 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "menusettingint.h" +#include "utilities.h" +#include + +using namespace std; +using namespace fastdelegate; + +MenuSettingInt::MenuSettingInt(GMenu2X *gmenu2x, string name, string description, int *value, int min, int max) + : MenuSetting(gmenu2x,name,description) { + this->gmenu2x = gmenu2x; + _value = value; + originalValue = *value; + this->min = min; + this->max = max; + setValue(this->value()); + + //Delegates + ButtonAction actionInc = MakeDelegate(this, &MenuSettingInt::inc); + ButtonAction actionDec = MakeDelegate(this, &MenuSettingInt::dec); + + btnInc = new IconButton(gmenu2x, "skin:imgs/buttons/y.png", gmenu2x->tr["Increase value"]); + btnInc->setAction(actionInc); + + btnDec = new IconButton(gmenu2x, "skin:imgs/buttons/x.png", gmenu2x->tr["Decrease value"]); + btnDec->setAction(actionDec); + + btnInc2 = new IconButton(gmenu2x, "skin:imgs/buttons/right.png"); + btnInc2->setAction(actionInc); + + btnDec2 = new IconButton(gmenu2x, "skin:imgs/buttons/left.png"); + btnDec2->setAction(actionDec); +} + +void MenuSettingInt::draw(int y) { + MenuSetting::draw(y); + gmenu2x->s->write( gmenu2x->font, strvalue, 155, y+gmenu2x->font->getHalfHeight(), SFontHAlignLeft, SFontVAlignMiddle ); +} + +void MenuSettingInt::handleTS() { + btnInc->handleTS(); + btnDec->handleTS(); + btnInc2->handleTS(); + btnDec2->handleTS(); +} + +void MenuSettingInt::manageInput() { + if ( gmenu2x->input[ACTION_LEFT ] || gmenu2x->input[ACTION_X] ) dec(); + if ( gmenu2x->input[ACTION_RIGHT] || gmenu2x->input[ACTION_Y] ) inc(); +} + +void MenuSettingInt::inc() { + setValue(value()+1); +} + +void MenuSettingInt::dec() { + setValue(value()-1); +} + +void MenuSettingInt::setValue(int value) { + *_value = constrain(value,min,max); + stringstream ss; + ss << *_value; + strvalue = ""; + ss >> strvalue; +} + +int MenuSettingInt::value() { + return *_value; +} + +void MenuSettingInt::adjustInput() { +#ifdef TARGET_GP2X + gmenu2x->input.setInterval(30, ACTION_LEFT ); + gmenu2x->input.setInterval(30, ACTION_RIGHT); +#endif +} + +void MenuSettingInt::drawSelected(int) { + gmenu2x->drawButton(btnInc, + gmenu2x->drawButton(btnInc2, + gmenu2x->drawButton(btnDec, + gmenu2x->drawButton(btnDec2)-10))-10); +} + +bool MenuSettingInt::edited() { + return originalValue != value(); +} diff --git a/src/menusettingint.h b/src/menusettingint.h new file mode 100644 index 0000000..57158ff --- /dev/null +++ b/src/menusettingint.h @@ -0,0 +1,57 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef MENUSETTINGINT_H +#define MENUSETTINGINT_H + +#include "iconbutton.h" +#include "menusetting.h" +#include "FastDelegate.h" + +using std::string; +class GMenu2X; + +class MenuSettingInt : public MenuSetting { +private: + int originalValue; + int *_value; + string strvalue; + IconButton *btnInc, *btnDec, *btnInc2, *btnDec2; + GMenu2X *gmenu2x; + + void inc(); + void dec(); + +public: + MenuSettingInt(GMenu2X *gmenu2x, string name, string description, int *value, int min, int max); + virtual ~MenuSettingInt() {}; + + virtual void draw(int y); + virtual void handleTS(); + virtual void manageInput(); + virtual void adjustInput(); + virtual void drawSelected(int y); + virtual bool edited(); + + int min, max; + virtual void setValue(int value); + int value(); +}; + +#endif diff --git a/src/menusettingmultistring.cpp b/src/menusettingmultistring.cpp new file mode 100644 index 0000000..220c886 --- /dev/null +++ b/src/menusettingmultistring.cpp @@ -0,0 +1,80 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "menusettingmultistring.h" +#include "utilities.h" + +using namespace std; +using namespace fastdelegate; + +MenuSettingMultiString::MenuSettingMultiString(GMenu2X *gmenu2x, string name, string description, string *value, vector *choices) + : MenuSetting(gmenu2x,name,description) { + this->gmenu2x = gmenu2x; + this->choices = choices; + this->value = value; + originalValue = *value; + setSel( find(choices->begin(),choices->end(),*value)-choices->begin() ); + + btnDec = new IconButton(gmenu2x, "skin:imgs/buttons/left.png"); + btnDec->setAction(MakeDelegate(this, &MenuSettingMultiString::decSel)); + + btnInc = new IconButton(gmenu2x, "skin:imgs/buttons/right.png", gmenu2x->tr["Change value"]); + btnInc->setAction(MakeDelegate(this, &MenuSettingMultiString::incSel)); +} + +void MenuSettingMultiString::draw(int y) { + MenuSetting::draw(y); + gmenu2x->s->write( gmenu2x->font, *value, 155, y+gmenu2x->font->getHalfHeight(), SFontHAlignLeft, SFontVAlignMiddle ); +} + +void MenuSettingMultiString::handleTS() { + btnDec->handleTS(); + btnInc->handleTS(); +} + +void MenuSettingMultiString::manageInput() { + if ( gmenu2x->input[ACTION_LEFT ] ) decSel(); + if ( gmenu2x->input[ACTION_RIGHT] ) incSel(); +} + +void MenuSettingMultiString::incSel() { + setSel(selected+1); +} + +void MenuSettingMultiString::decSel() { + setSel(selected-1); +} + +void MenuSettingMultiString::setSel(int sel) { + if (sel<0) sel = choices->size()-1; + else if (sel>=(int)choices->size()) sel = 0; + selected = sel; + *value = (*choices)[sel]; +} + +void MenuSettingMultiString::adjustInput() {} + +void MenuSettingMultiString::drawSelected(int) { + gmenu2x->drawButton(btnInc, + gmenu2x->drawButton(btnDec)-6); +} + +bool MenuSettingMultiString::edited() { + return originalValue != *value; +} diff --git a/src/menusettingmultistring.h b/src/menusettingmultistring.h new file mode 100644 index 0000000..e90df47 --- /dev/null +++ b/src/menusettingmultistring.h @@ -0,0 +1,53 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef MENUSETTINGMULTISTRING_H +#define MENUSETTINGMULTISTRING_H + +#include "gmenu2x.h" +#include "menusetting.h" + +using std::string; + +class MenuSettingMultiString : public MenuSetting { +private: + uint selected; + string *value; + string originalValue; + vector *choices; + GMenu2X *gmenu2x; + IconButton *btnDec, *btnInc; + + void incSel(); + void decSel(); + void setSel(int); + +public: + MenuSettingMultiString(GMenu2X *gmenu2x, string name, string description, string *value, vector *choices); + virtual ~MenuSettingMultiString() {}; + + virtual void draw(int y); + virtual void handleTS(); + virtual void manageInput(); + virtual void adjustInput(); + virtual void drawSelected(int y); + virtual bool edited(); +}; + +#endif diff --git a/src/menusettingrgba.cpp b/src/menusettingrgba.cpp new file mode 100644 index 0000000..98fc459 --- /dev/null +++ b/src/menusettingrgba.cpp @@ -0,0 +1,168 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "menusettingrgba.h" +#include + +using namespace std; +using namespace fastdelegate; + +MenuSettingRGBA::MenuSettingRGBA(GMenu2X *gmenu2x, string name, string description, RGBAColor *value) + : MenuSetting(gmenu2x,name,description) { + selPart = 0; + this->gmenu2x = gmenu2x; + _value = value; + originalValue = *value; + this->setR(this->value().r); + this->setG(this->value().g); + this->setB(this->value().b); + this->setA(this->value().a); + + btnDec = new IconButton(gmenu2x, "skin:imgs/buttons/x.png", gmenu2x->tr["Decrease"]); + btnDec->setAction(MakeDelegate(this, &MenuSettingRGBA::dec)); + + btnInc = new IconButton(gmenu2x, "skin:imgs/buttons/y.png", gmenu2x->tr["Increase"]); + btnInc->setAction(MakeDelegate(this, &MenuSettingRGBA::inc)); + + btnLeftComponent = new IconButton(gmenu2x, "skin:imgs/buttons/left.png"); + btnLeftComponent->setAction(MakeDelegate(this, &MenuSettingRGBA::leftComponent)); + + btnRightComponent = new IconButton(gmenu2x, "skin:imgs/buttons/right.png", gmenu2x->tr["Change color component"]); + btnRightComponent->setAction(MakeDelegate(this, &MenuSettingRGBA::rightComponent)); +} + +void MenuSettingRGBA::draw(int y) { + this->y = y; + MenuSetting::draw(y); + gmenu2x->s->rectangle( 153, y+1, 11, 11, 0,0,0,255 ); + gmenu2x->s->box( 154, y+2, 9, 9, value() ); + gmenu2x->s->write( gmenu2x->font, "R: "+strR, 169, y+gmenu2x->font->getHalfHeight(), SFontHAlignLeft, SFontVAlignMiddle ); + gmenu2x->s->write( gmenu2x->font, "G: "+strG, 205, y+gmenu2x->font->getHalfHeight(), SFontHAlignLeft, SFontVAlignMiddle ); + gmenu2x->s->write( gmenu2x->font, "B: "+strB, 241, y+gmenu2x->font->getHalfHeight(), SFontHAlignLeft, SFontVAlignMiddle ); + gmenu2x->s->write( gmenu2x->font, "A: "+strA, 277, y+gmenu2x->font->getHalfHeight(), SFontHAlignLeft, SFontVAlignMiddle ); +} + +void MenuSettingRGBA::handleTS() { + if (gmenu2x->ts.pressed()) + for (int i=0; i<4; i++) + if (i!=selPart && gmenu2x->ts.inRect(166+i*36,y,36,14)) { + selPart = i; + i = 4; + } + + btnDec->handleTS(); + btnInc->handleTS(); + btnLeftComponent->handleTS(); + btnRightComponent->handleTS(); +} + +void MenuSettingRGBA::manageInput() { + if ( gmenu2x->input[ACTION_Y ]) inc(); + if ( gmenu2x->input[ACTION_X ]) dec(); + if ( gmenu2x->input[ACTION_LEFT ]) leftComponent(); + if ( gmenu2x->input[ACTION_RIGHT]) rightComponent(); +} + +void MenuSettingRGBA::dec() { + setSelPart( constrain(getSelPart()-1,0,255) ); +} + +void MenuSettingRGBA::inc() { + setSelPart( constrain(getSelPart()+1,0,255) ); +} + +void MenuSettingRGBA::leftComponent() { + selPart = constrain(selPart-1,0,3); +} + +void MenuSettingRGBA::rightComponent() { + selPart = constrain(selPart+1,0,3); +} + +void MenuSettingRGBA::setR(unsigned short r) { + _value->r = r; + stringstream ss; + ss << r; + ss >> strR; +} + +void MenuSettingRGBA::setG(unsigned short g) { + _value->g = g; + stringstream ss; + ss << g; + ss >> strG; +} + +void MenuSettingRGBA::setB(unsigned short b) { + _value->b = b; + stringstream ss; + ss << b; + ss >> strB; +} + +void MenuSettingRGBA::setA(unsigned short a) { + _value->a = a; + stringstream ss; + ss << a; + ss >> strA; +} + +void MenuSettingRGBA::setSelPart(unsigned short value) { + switch (selPart) { + default: case 0: setR(value); break; + case 1: setG(value); break; + case 2: setB(value); break; + case 3: setA(value); break; + } +} + +RGBAColor MenuSettingRGBA::value() { + return *_value; +} + +unsigned short MenuSettingRGBA::getSelPart() { + switch (selPart) { + default: case 0: return value().r; + case 1: return value().g; + case 2: return value().b; + case 3: return value().a; + } +} + +void MenuSettingRGBA::adjustInput() { +#ifdef TARGET_GP2X + gmenu2x->input.setInterval(30, ACTION_Y ); + gmenu2x->input.setInterval(30, ACTION_X ); + gmenu2x->input.setInterval(30, ACTION_L ); +#endif +} + +void MenuSettingRGBA::drawSelected(int y) { + int x = 166+selPart*36; + gmenu2x->s->box( x, y, 36, 14, gmenu2x->skinConfColors["selectionBg"] ); + + gmenu2x->drawButton(btnDec, + gmenu2x->drawButton(btnInc, + gmenu2x->drawButton(btnRightComponent, + gmenu2x->drawButton(btnLeftComponent)-6))); +} + +bool MenuSettingRGBA::edited() { + return originalValue.r != value().r || originalValue.g != value().g || originalValue.b != value().b || originalValue.a != value().a; +} diff --git a/src/menusettingrgba.h b/src/menusettingrgba.h new file mode 100644 index 0000000..f5b0d0a --- /dev/null +++ b/src/menusettingrgba.h @@ -0,0 +1,64 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef MENUSETTINGRGBA_H +#define MENUSETTINGRGBA_H + +#include "gmenu2x.h" +#include "menusetting.h" +#include "utilities.h" + +using std::string; + +class MenuSettingRGBA : public MenuSetting { +private: + unsigned short selPart; + int y; + string strR, strG, strB, strA; + RGBAColor originalValue; + RGBAColor *_value; + GMenu2X *gmenu2x; + IconButton *btnDec, *btnInc, *btnLeftComponent, *btnRightComponent; + + void dec(); + void inc(); + void leftComponent(); + void rightComponent(); + +public: + MenuSettingRGBA(GMenu2X *gmenu2x, string name, string description, RGBAColor *value); + virtual ~MenuSettingRGBA() {}; + + virtual void draw(int y); + virtual void handleTS(); + virtual void manageInput(); + virtual void adjustInput(); + virtual void drawSelected(int y); + virtual bool edited(); + + void setSelPart(unsigned short value); + void setR(unsigned short r); + void setG(unsigned short g); + void setB(unsigned short b); + void setA(unsigned short a); + unsigned short getSelPart(); + RGBAColor value(); +}; + +#endif diff --git a/src/menusettingstring.cpp b/src/menusettingstring.cpp new file mode 100644 index 0000000..3886370 --- /dev/null +++ b/src/menusettingstring.cpp @@ -0,0 +1,82 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "menusettingstring.h" +#include "inputdialog.h" +#include "utilities.h" + +using namespace std; +using namespace fastdelegate; + +MenuSettingString::MenuSettingString(GMenu2X *gmenu2x, string name, string description, string *value, string diagTitle, string diagIcon) + : MenuSetting(gmenu2x,name,description) { + this->gmenu2x = gmenu2x; + _value = value; + originalValue = *value; + this->diagTitle = diagTitle; + this->diagIcon = diagIcon; + + btnClear = new IconButton(gmenu2x, "skin:imgs/buttons/x.png", gmenu2x->tr["Clear"]); + btnClear->setAction(MakeDelegate(this, &MenuSettingString::clear)); + + btnEdit = new IconButton(gmenu2x, "skin:imgs/buttons/b.png", gmenu2x->tr["Edit"]); + btnEdit->setAction(MakeDelegate(this, &MenuSettingString::edit)); +} + +void MenuSettingString::draw(int y) { + MenuSetting::draw(y); + gmenu2x->s->write( gmenu2x->font, value(), 155, y+gmenu2x->font->getHalfHeight(), SFontHAlignLeft, SFontVAlignMiddle ); +} + +void MenuSettingString::handleTS() { + btnEdit->handleTS(); +} + +void MenuSettingString::manageInput() { + if ( gmenu2x->input[ACTION_X] ) clear(); + if ( gmenu2x->input[ACTION_B] ) edit(); +} + +void MenuSettingString::setValue(string value) { + *_value = value; +} + +string MenuSettingString::value() { + return *_value; +} + +void MenuSettingString::adjustInput() {} + +void MenuSettingString::clear() { + setValue(""); +} + +void MenuSettingString::edit() { + InputDialog id(gmenu2x,description,value(), diagTitle,diagIcon); + if (id.exec()) setValue(id.input); +} + +void MenuSettingString::drawSelected(int) { + gmenu2x->drawButton(btnClear, + gmenu2x->drawButton(btnEdit)); +} + +bool MenuSettingString::edited() { + return originalValue != value(); +} diff --git a/src/menusettingstring.h b/src/menusettingstring.h new file mode 100644 index 0000000..4b45395 --- /dev/null +++ b/src/menusettingstring.h @@ -0,0 +1,53 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef MENUSETTINGSTRING_H +#define MENUSETTINGSTRING_H + +#include "gmenu2x.h" +#include "menusetting.h" + +using std::string; + +class MenuSettingString : public MenuSetting { +private: + string originalValue, diagTitle, diagIcon; + string *_value; + GMenu2X *gmenu2x; + IconButton *btnClear, *btnEdit; + + void edit(); + void clear(); + +public: + MenuSettingString(GMenu2X *gmenu2x, string name, string description, string *value, string diagTitle="", string diagIcon=""); + virtual ~MenuSettingString() {}; + + virtual void draw(int y); + virtual void handleTS(); + virtual void manageInput(); + virtual void adjustInput(); + virtual void drawSelected(int y); + virtual bool edited(); + + void setValue(string value); + string value(); +}; + +#endif diff --git a/src/messagebox.cpp b/src/messagebox.cpp new file mode 100644 index 0000000..43c9f8a --- /dev/null +++ b/src/messagebox.cpp @@ -0,0 +1,120 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include + +#include "messagebox.h" + +using namespace std; + +MessageBox::MessageBox(GMenu2X *gmenu2x, string text, string icon) { + this->gmenu2x = gmenu2x; + this->text = text; + this->icon = icon; + + buttons.resize(19); + buttonLabels.resize(19); + buttonPositions.resize(19); + for (uint x=0; xfont->getHeight(); + } + + //Default enabled button + buttons[ACTION_B] = "OK"; + + //Default labels + buttonLabels[ACTION_UP] = "up"; + buttonLabels[ACTION_DOWN] = "down"; + buttonLabels[ACTION_LEFT] = "left"; + buttonLabels[ACTION_RIGHT] = "right"; + buttonLabels[ACTION_A] = "a"; + buttonLabels[ACTION_B] = "b"; + buttonLabels[ACTION_X] = "x"; + buttonLabels[ACTION_Y] = "y"; + buttonLabels[ACTION_L] = "l"; + buttonLabels[ACTION_R] = "r"; + buttonLabels[ACTION_START] = "start"; + buttonLabels[ACTION_SELECT] = "select"; + buttonLabels[ACTION_VOLUP] = "vol+"; + buttonLabels[ACTION_VOLDOWN] = "vol-"; +} + +int MessageBox::exec() { + int result = -1; + + Surface bg(gmenu2x->s); + //Darken background + bg.box(0, 0, gmenu2x->resX, gmenu2x->resY, 0,0,0,200); + + SDL_Rect box; + box.h = gmenu2x->font->getHeight()*3 +4; + box.w = gmenu2x->font->getTextWidth(text) + 24 + (gmenu2x->sc[icon] != NULL ? 37 : 0); + box.x = gmenu2x->halfX - box.w/2 -2; + box.y = gmenu2x->halfY - box.h/2 -2; + + //outer box + bg.box(box, gmenu2x->skinConfColors["messageBoxBg"]); + //draw inner rectangle + bg.rectangle(box.x+2, box.y+2, box.w-4, box.h-gmenu2x->font->getHeight(), gmenu2x->skinConfColors["messageBoxBorder"]); + //icon+text + if (gmenu2x->sc[icon] != NULL) + gmenu2x->sc[icon]->blitCenter( &bg, box.x+25, box.y+gmenu2x->font->getHeight()+3 ); + bg.write( gmenu2x->font, text, box.x+(gmenu2x->sc[icon] != NULL ? 47 : 10), box.y+gmenu2x->font->getHeight()+3, SFontHAlignLeft, SFontVAlignMiddle ); + + int btnX = gmenu2x->halfX+box.w/2-6; + for (uint i=0; idrawButtonRight(&bg, buttonLabels[i], buttons[i], btnX, buttonPositions[i].y); + + buttonPositions[i].x = btnX; + buttonPositions[i].w = buttonPositions[i].x-btnX-6; + } + } + + bg.blit(gmenu2x->s,0,0); + gmenu2x->s->flip(); + + while (result<0) { + //touchscreen + if (gmenu2x->f200) { + if (gmenu2x->ts.poll()) { + for (uint i=0; its.inRect(buttonPositions[i])) { + result = i; + i = buttons.size(); + } + } + } + + gmenu2x->input.update(); + for (uint i=0; iinput[i]) result = i; + + usleep(LOOP_DELAY); + } + + return result; +} diff --git a/src/messagebox.h b/src/messagebox.h new file mode 100644 index 0000000..3bfe17d --- /dev/null +++ b/src/messagebox.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef MESSAGEBOX_H_ +#define MESSAGEBOX_H_ + +#define MB_BTN_B 0 +#define MB_BTN_X 1 +#define MB_BTN_START 2 +#define MB_BTN_SELECT 3 + +#include +#include "gmenu2x.h" + +using std::string; +using std::vector; + +class MessageBox { +private: + string text, icon; + GMenu2X *gmenu2x; + +public: + MessageBox(GMenu2X *gmenu2x, string text, string icon=""); + vector buttons; + vector buttonLabels; + vector buttonPositions; + int exec(); +}; + +#endif /*MESSAGEBOX_H_*/ diff --git a/src/pxml.cpp b/src/pxml.cpp new file mode 100644 index 0000000..f495892 --- /dev/null +++ b/src/pxml.cpp @@ -0,0 +1,127 @@ +#include "pxml.h" +#include "tinyxml/tinyxml.h" +#include + +using namespace std; + +PXml::PXml(string file) { + valid = false; + error = title = description = authorName = authorWebsite = category = exec = icon = ""; + version = osVersion = (SoftwareVersion){0,0,0,0}; + + TiXmlDocument doc(file.c_str()); + if (doc.LoadFile()) { + TiXmlHandle hDoc(&doc); + TiXmlElement* pElem; + + pElem = hDoc.FirstChildElement().Element(); + TiXmlHandle hPXML(pElem); + if (pElem) pElem = hPXML.FirstChildElement( "title" ).Element(); + if (pElem) { + title = pElem->GetText(); + pElem = hPXML.FirstChildElement( "description" ).Element(); + } + if (pElem) { + description = pElem->GetText(); + pElem = hPXML.FirstChildElement( "author" ).Element(); + } + if (pElem) { + authorName = pElem->Attribute("name"); + authorWebsite = pElem->Attribute("website"); + + pElem = hPXML.FirstChildElement( "version" ).Element(); + } + if (pElem) { + pElem->QueryIntAttribute("major", &version.major); + pElem->QueryIntAttribute("minor", &version.minor); + pElem->QueryIntAttribute("release", &version.release); + pElem->QueryIntAttribute("build", &version.build); + + pElem = hPXML.FirstChildElement( "exec" ).Element(); + } + if (pElem) { + exec = pElem->GetText(); + + pElem = hPXML.FirstChildElement( "category" ).Element(); + } + if (pElem) { + category = pElem->GetText(); + + valid = true; + + //All required fields have been found, parsing optional fields + pElem = hPXML.FirstChildElement("icon").Element(); + if (pElem) icon = pElem->GetText(); + + pElem = hPXML.FirstChildElement( "osversion" ).Element(); + if (pElem) { + pElem->QueryIntAttribute("major", &osVersion.major); + pElem->QueryIntAttribute("minor", &osVersion.minor); + pElem->QueryIntAttribute("release", &osVersion.release); + pElem->QueryIntAttribute("build", &osVersion.build); + } + } + } else { + error = doc.ErrorDesc(); + } +} + +bool PXml::isValid() { + return valid; +} + +string PXml::getTitle() { + return title; +} + +string PXml::getDescription() { + return description; +} + +string PXml::getAuthorName() { + return authorName; +} + +string PXml::getAuthorWebsite() { + return authorWebsite; +} + +string PXml::getCategory() { + return category; +} + +string PXml::getExec() { + return exec; +} + +string PXml::getIcon() { + return icon; +} + +SoftwareVersion PXml::getVersion() { + return version; +} + +string PXml::getVersionString() { + string versionString = ""; + stringstream ss; + ss << version.major << "." << version.minor << "." << version.release << "." << version.build; + ss >> versionString; + return versionString; +} + +SoftwareVersion PXml::getOsVersion() { + return osVersion; +} + +string PXml::getOsVersionString() { + string versionString = ""; + stringstream ss; + ss << osVersion.major << "." << osVersion.minor << "." << osVersion.release << "." << osVersion.build; + ss >> versionString; + return versionString; +} + +string PXml::getError() { + return error; +} diff --git a/src/pxml.h b/src/pxml.h new file mode 100644 index 0000000..451bcb3 --- /dev/null +++ b/src/pxml.h @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef PXML_H_ +#define PXML_H_ + +#include + +using std::string; + +struct SoftwareVersion { + int major, minor, release, build; +}; + +class PXml { +private: + bool valid; + string title, description, error, authorName, authorWebsite, category, exec, icon; + SoftwareVersion version, osVersion; + +public: + PXml(string file); + + bool isValid(); + + string getTitle(); + string getDescription(); + string getAuthorName(); + string getAuthorWebsite(); + string getCategory(); + string getExec(); + string getIcon(); + + SoftwareVersion getVersion(); + string getVersionString(); + SoftwareVersion getOsVersion(); + string getOsVersionString(); + + string getError(); +}; + +#endif /*PXML_H_*/ diff --git a/src/selector.cpp b/src/selector.cpp new file mode 100644 index 0000000..0bc8d17 --- /dev/null +++ b/src/selector.cpp @@ -0,0 +1,244 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include + +//for browsing the filesystem +#include +#include +#include + +#include "menu.h" +#include "linkapp.h" +#include "selector.h" +#include "filelister.h" + +using namespace std; + +Selector::Selector(GMenu2X *gmenu2x, LinkApp *link, string selectorDir) { + this->gmenu2x = gmenu2x; + this->link = link; + loadAliases(); + selRow = 0; + if (selectorDir=="") + dir = link->getSelectorDir(); + else + dir = selectorDir; + if (dir[dir.length()-1]!='/') dir += "/"; +} + +int Selector::exec(int startSelection) { + bool close = false, result = true; + vector screens, titles; + + FileLister fl(dir, link->getSelectorBrowser()); + fl.setFilter(link->getSelectorFilter()); + fl.browse(); + + Surface bg(gmenu2x->bg); + gmenu2x->drawTitleIcon(link->getIconPath(),true,&bg); + gmenu2x->writeTitle(link->getTitle(),&bg); + gmenu2x->writeSubTitle(link->getDescription(),&bg); + + if (link->getSelectorBrowser()) { + gmenu2x->drawButton(&bg, "start", gmenu2x->tr["Exit"], + gmenu2x->drawButton(&bg, "b", gmenu2x->tr["Select a file"], + gmenu2x->drawButton(&bg, "x", gmenu2x->tr["Up one folder"], 5))); + } else { + gmenu2x->drawButton(&bg, "x", gmenu2x->tr["Exit"], + gmenu2x->drawButton(&bg, "b", gmenu2x->tr["Select a file"], 5)); + } + + Uint32 selTick = SDL_GetTicks(), curTick; + uint i, firstElement = 0, iY; + + prepare(&fl,&screens,&titles); + uint selected = constrain(startSelection,0,fl.size()-1); + + //Add the folder icon manually to be sure to load it with alpha support since we are going to disable it for screenshots + if (gmenu2x->sc.skinRes("imgs/folder.png")==NULL) + gmenu2x->sc.addSkinRes("imgs/folder.png"); + gmenu2x->sc.defaultAlpha = false; + while (!close) { + bg.blit(gmenu2x->s,0,0); + + if (selected>=firstElement+SELECTOR_ELEMENTS) firstElement=selected-SELECTOR_ELEMENTS+1; + if (selecteds->box(1, iY, 309, 14, gmenu2x->skinConfColors["selectionBg"]); + + //Screenshot + if (selected-fl.dirCount()200) + gmenu2x->sc[screens[selected-fl.dirCount()]]->blitRight(gmenu2x->s, 311, 42, 160, 160, min((curTick-selTick-200)/3,255)); + } + + //Files & Dirs + gmenu2x->s->setClipRect(0,41,311,179); + for (i=firstElement; isc["imgs/folder.png"]->blit(gmenu2x->s, 4, 42+(iY*16)); + gmenu2x->s->write(gmenu2x->font, fl[i], 21, 49+(iY*16), SFontHAlignLeft, SFontVAlignMiddle); + } else + gmenu2x->s->write(gmenu2x->font, titles[i-fl.dirCount()], 4, 49+(iY*16), SFontHAlignLeft, SFontVAlignMiddle); + } + gmenu2x->s->clearClipRect(); + + gmenu2x->drawScrollBar(SELECTOR_ELEMENTS,fl.size(),firstElement,42,175); + gmenu2x->s->flip(); + + + gmenu2x->input.update(); + if ( gmenu2x->input[ACTION_START] ) { close = true; result = false; } + if ( gmenu2x->input[ACTION_UP] ) { + if (selected==0) { + selected = fl.size()-1; + } else { + selected -= 1; + } + selTick = SDL_GetTicks(); + } + if ( gmenu2x->input[ACTION_L] ) { + if ((int)(selected-SELECTOR_ELEMENTS+1)<0) { + selected = 0; + } else { + selected -= SELECTOR_ELEMENTS-1; + } + selTick = SDL_GetTicks(); + } + if ( gmenu2x->input[ACTION_DOWN] ) { + if (selected+1>=fl.size()) { + selected = 0; + } else { + selected += 1; + } + selTick = SDL_GetTicks(); + } + if ( gmenu2x->input[ACTION_R] ) { + if (selected+SELECTOR_ELEMENTS-1>=fl.size()) { + selected = fl.size()-1; + } else { + selected += SELECTOR_ELEMENTS-1; + } + selTick = SDL_GetTicks(); + } + if ( gmenu2x->input[ACTION_X] ) { + if (link->getSelectorBrowser()) { + string::size_type p = dir.rfind("/", dir.size()-2); + if (p==string::npos || dir.substr(0,4)!="/card" || p<4) { + close = true; + result = false; + } else { + dir = dir.substr(0,p+1); + cout << dir << endl; + selected = 0; + firstElement = 0; + prepare(&fl,&screens,&titles); + } + } else { + close = true; + result = false; + } + } + if ( gmenu2x->input[ACTION_B] ) { + if (fl.isFile(selected)) { + file = fl[selected]; + close = true; + } else { + dir = dir+fl[selected]+"/"; + selected = 0; + firstElement = 0; + prepare(&fl,&screens,&titles); + } + } + } + gmenu2x->sc.defaultAlpha = true; + freeScreenshots(&screens); + + return result ? (int)selected : -1; +} + +void Selector::prepare(FileLister *fl, vector *screens, vector *titles) { + fl->setPath(dir); + freeScreenshots(screens); + screens->resize(fl->files.size()); + titles->resize(fl->files.size()); + + string screendir = link->getSelectorScreens(); + if (screendir != "" && screendir[screendir.length()-1]!='/') screendir += "/"; + + string noext; + string::size_type pos; + for (uint i=0; ifiles.size(); i++) { + noext = fl->files[i]; + pos = noext.rfind("."); + if (pos!=string::npos && pos>0) + noext = noext.substr(0, pos); + titles->at(i) = getAlias(noext); + if (titles->at(i)=="") + titles->at(i) = noext; +#ifdef DEBUG + cout << "\033[0;34mGMENU2X:\033[0m Searching for screen " << screendir << noext << ".png" << endl; +#endif + if (fileExists(screendir+noext+".png")) + screens->at(i) = screendir+noext+".png"; + else if (fileExists(screendir+noext+".jpg")) + screens->at(i) = screendir+noext+".jpg"; + else + screens->at(i) = ""; + } +} + +void Selector::freeScreenshots(vector *screens) { + for (uint i=0; isize(); i++) { + if (screens->at(i) != "") + gmenu2x->sc.del(screens->at(i)); + } +} + +void Selector::loadAliases() { + aliases.clear(); + if (fileExists(link->getAliasFile())) { + string line; + ifstream infile (link->getAliasFile().c_str(), ios_base::in); + while (getline(infile, line, '\n')) { + string::size_type position = line.find("="); + string name = trim(line.substr(0,position)); + string value = trim(line.substr(position+1)); + aliases[name] = value; + } + infile.close(); + } +} + +string Selector::getAlias(string key) { + hash_map::iterator i = aliases.find(key); + if (i == aliases.end()) + return ""; + else + return i->second; +} diff --git a/src/selector.h b/src/selector.h new file mode 100644 index 0000000..c9a5fa4 --- /dev/null +++ b/src/selector.h @@ -0,0 +1,55 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef SELECTOR_H_ +#define SELECTOR_H_ + +#include +#include "gmenu2x.h" +#include "utilities.h" + +#define SELECTOR_ELEMENTS 11 + +class LinkApp; +class FileLister; + +using std::string; +using std::vector; + +class Selector { +private: + int selRow; + GMenu2X *gmenu2x; + LinkApp *link; + + hash_map aliases; + void loadAliases(); + string getAlias(string key); + void prepare(FileLister *fl, vector *screens, vector *titles); + void freeScreenshots(vector *screens); + +public: + string file, dir; + Selector(GMenu2X *gmenu2x, LinkApp *link, string selectorDir=""); + + int exec(int startSelection=0); +}; + +#endif /*SELECTOR_H_*/ diff --git a/src/selectordetector.cpp b/src/selectordetector.cpp new file mode 100644 index 0000000..9ce639d --- /dev/null +++ b/src/selectordetector.cpp @@ -0,0 +1,47 @@ +#include +#include + +#include "selectordetector.h" +#include "utilities.h" + +using namespace std; + +SelectorDetector::SelectorDetector() { + //ctor + useSelectorBackground = false; +} + +SelectorDetector::SelectorDetector(string config) { + useSelectorBackground = false; + readSelectorConfig(config); +} + +SelectorDetector::~SelectorDetector() { + //dtor +} + +bool SelectorDetector::readSelectorConfig(string config) { + if (fileExists(config)) { + ifstream inf(config.c_str(), ios_base::in); + if (inf.is_open()) { + string line; + while (getline(inf, line, '\n')) { + string::size_type pos = line.find("="); + string name = trim(line.substr(0,pos)); + string value = trim(line.substr(pos+1,line.length())); + + if (name=="cmdLine") application = value; + else if (name=="baseDir") filePath = value; + else if (name=="fileFilter"){ + if(filters.empty()) + filters = value; + else + filters += ("," + value); + } + } + inf.close(); + return true; + } + } + return false; +} diff --git a/src/selectordetector.h b/src/selectordetector.h new file mode 100644 index 0000000..7c279c5 --- /dev/null +++ b/src/selectordetector.h @@ -0,0 +1,58 @@ +#ifndef SELECTORDETECTOR_H +#define SELECTORDETECTOR_H + +/* This class is for handling applications that use Kounch's Selector, to correctly import their settings to GMenu + * It provides interfaces to examine the dge file to detect Selector and from there, parse the config files. + */ + + + /* +#Selector configuration file +#Version 1.0 + +#selector-language english (and it doesn't work, crap) +langCode=EN // ignore +layoutCode=0 // ignore + +selectRectangle=2 // ignore + +#Full path to skin files +skinPath=./ // use possibly + +#command line +cmdLine=./race // USE + +#path to base directory for file explorer +baseDir=/boot/local/gmenu2x/roms/ngpc/ // USE + +#File filters // USE +fileFilter=ngp +fileFilter=ngc +fileFilter=npc + */ +#include + +using std::string; +class SelectorDetector +{ + public: + SelectorDetector(); + SelectorDetector(string config); + ~SelectorDetector(); + + bool readSelectorConfig(string config); + + string getApplication(){return application;} + string getFilePath(){return filePath;} + string getFilters(){return filters;} + + private: + bool useSelectorBackground; + string application; + string filePath; + string filters; + //bool isSelectorGPE(string gpe); + //string getSelectorConfig(string gpe); // Looks in the GPE for the location of the selectorconfig +}; + +#endif // SELECTORDETECTOR_H diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp new file mode 100644 index 0000000..51d0df6 --- /dev/null +++ b/src/settingsdialog.cpp @@ -0,0 +1,140 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include + +#include "settingsdialog.h" + +using namespace std; + +SettingsDialog::SettingsDialog(GMenu2X *gmenu2x, string text, string icon) { + this->gmenu2x = gmenu2x; + this->text = text; + + if (icon!="" && gmenu2x->sc[icon] != NULL) + this->icon = icon; + else + this->icon = "icons/generic.png"; +} + +SettingsDialog::~SettingsDialog() { + for (uint i=0; iconfStr["wallpaper"],false); + Surface bg(gmenu2x->bg); + + bool close = false, ts_pressed = false; + uint i, sel = 0, iY, firstElement = 0, action; + voices[sel]->adjustInput(); + + SDL_Rect clipRect = {0, gmenu2x->skinConfInt["topBarHeight"]+1, gmenu2x->resX-9, gmenu2x->resY-gmenu2x->skinConfInt["topBarHeight"]-25}; + SDL_Rect touchRect = {2, gmenu2x->skinConfInt["topBarHeight"]+4, gmenu2x->resX-12, clipRect.h}; + uint rowHeight = gmenu2x->font->getHeight()+1; // gp2x=15+1 / pandora=19+1 + uint numRows = (gmenu2x->resY-gmenu2x->skinConfInt["topBarHeight"]-20)/rowHeight; + + while (!close) { + action = SD_NO_ACTION; + if (gmenu2x->f200) gmenu2x->ts.poll(); + + bg.blit(gmenu2x->s,0,0); + + gmenu2x->drawTopBar(gmenu2x->s); + //link icon + gmenu2x->drawTitleIcon(icon); + gmenu2x->writeTitle(text); + gmenu2x->drawBottomBar(gmenu2x->s); + + if (sel>firstElement+numRows-1) firstElement=sel-numRows+1; + if (selskinConfInt["topBarHeight"]+2+(iY*rowHeight); + gmenu2x->s->setClipRect(clipRect); + if (sels->box(1, iY, 148, rowHeight-2, gmenu2x->skinConfColors["selectionBg"]); + gmenu2x->s->clearClipRect(); + + //selected option + voices[sel]->drawSelected(iY); + + gmenu2x->s->setClipRect(clipRect); + if (ts_pressed && !gmenu2x->ts.pressed()) ts_pressed = false; + if (gmenu2x->f200 && gmenu2x->ts.pressed() && !gmenu2x->ts.inRect(touchRect)) ts_pressed = false; + for (i=firstElement; idraw(iY*rowHeight+gmenu2x->skinConfInt["topBarHeight"]+2); + if (gmenu2x->f200 && gmenu2x->ts.pressed() && gmenu2x->ts.inRect(touchRect.x, touchRect.y+(iY*rowHeight), touchRect.w, rowHeight)) { + ts_pressed = true; + sel = i; + } + } + gmenu2x->s->clearClipRect(); + + gmenu2x->drawScrollBar(numRows,voices.size(),firstElement,clipRect.y+1,clipRect.h); + + //description + gmenu2x->writeSubTitle(voices[sel]->description); + + gmenu2x->s->flip(); + voices[sel]->handleTS(); + + gmenu2x->input.update(); + if ( gmenu2x->input[ACTION_START] ) action = SD_ACTION_CLOSE; + if ( gmenu2x->input[ACTION_UP ] ) action = SD_ACTION_UP; + if ( gmenu2x->input[ACTION_DOWN ] ) action = SD_ACTION_DOWN; + voices[sel]->manageInput(); + + switch (action) { + case SD_ACTION_CLOSE: close = true; break; + case SD_ACTION_UP: { + if (sel==0) + sel = voices.size()-1; + else + sel -= 1; + gmenu2x->setInputSpeed(); + voices[sel]->adjustInput(); + } break; + case SD_ACTION_DOWN: { + sel += 1; + if (sel>=voices.size()) sel = 0; + gmenu2x->setInputSpeed(); + voices[sel]->adjustInput(); + } break; + } + } + + gmenu2x->setInputSpeed(); + return true; +} + +void SettingsDialog::addSetting(MenuSetting* set) { + voices.push_back(set); +} + +bool SettingsDialog::edited() { + for (uint i=0; iedited()) return true; + return false; +} diff --git a/src/settingsdialog.h b/src/settingsdialog.h new file mode 100644 index 0000000..0123efa --- /dev/null +++ b/src/settingsdialog.h @@ -0,0 +1,51 @@ +/*************************************************************************** + * Copyright (C) 2006 by Massimiliano Torromeo * + * massimiliano.torromeo@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef SETTINGSDIALOG_H_ +#define SETTINGSDIALOG_H_ + +#define SD_NO_ACTION 0 +#define SD_ACTION_CLOSE 1 +#define SD_ACTION_UP 2 +#define SD_ACTION_DOWN 3 + +#include +#include "gmenu2x.h" +#include "menusetting.h" + +using std::string; +using std::vector; + +class SettingsDialog { +private: + vector voices; + string text, icon; + GMenu2X *gmenu2x; + +public: + SettingsDialog(GMenu2X *gmenu2x, string text, string icon="skin:sections/settings.png"); + ~SettingsDialog(); + + bool edited(); + bool exec(); + void addSetting(MenuSetting* set); +}; + +#endif /*INPUTDIALOG_H_*/ diff --git a/src/sfontplus.cpp b/src/sfontplus.cpp new file mode 100644 index 0000000..4959a2f --- /dev/null +++ b/src/sfontplus.cpp @@ -0,0 +1,196 @@ +#include "sfontplus.h" + +#include +#include +#include + +using namespace std; + +Uint32 SFontPlus::getPixel(Sint32 x, Sint32 y) { + assert(x>=0); + assert(xw); + + Uint32 Bpp = surface->format->BytesPerPixel; + + // Get the pixel + switch(Bpp) { + case 1: + return *((Uint8 *)surface->pixels + y * surface->pitch + x); + break; + case 2: + return *((Uint16 *)surface->pixels + y * surface->pitch/2 + x); + break; + case 3: { // Format/endian independent + Uint8 *bits = ((Uint8 *)surface->pixels)+y*surface->pitch+x*Bpp; + Uint8 r, g, b; + r = *((bits)+surface->format->Rshift/8); + g = *((bits)+surface->format->Gshift/8); + b = *((bits)+surface->format->Bshift/8); + return SDL_MapRGB(surface->format, r, g, b); + } + break; + case 4: + return *((Uint32 *)surface->pixels + y * surface->pitch/4 + x); + break; + } + + return 0; +} + +SFontPlus::SFontPlus() { + surface = NULL; +} + +SFontPlus::SFontPlus(SDL_Surface* font) { + surface = NULL; + initFont(font); +} + +SFontPlus::SFontPlus(string font) { + surface = NULL; + initFont(font); +} + +SFontPlus::~SFontPlus() { + freeFont(); +} + +bool SFontPlus::utf8Code(unsigned char c) { + return (c>=194 && c<=198) || c==208 || c==209; + //return c>=194; +} + +void SFontPlus::initFont(string font, string characters) { + SDL_Surface *buf = IMG_Load(font.c_str()); + if (buf!=NULL) { + initFont( SDL_DisplayFormatAlpha(buf), characters ); + SDL_FreeSurface(buf); + } +} + +void SFontPlus::initFont(SDL_Surface *font, string characters) { + freeFont(); + this->characters = characters; + if (font==NULL) return; + + surface = font; + Uint32 pink = SDL_MapRGB(surface->format, 255,0,255); + +#ifdef _DEBUG + bool utf8 = false; + for (uint x=0; x128; + if (utf8) printf("%d\n", (unsigned char)characters[x]); + } +#endif + + uint c = 0; + + SDL_LockSurface(surface); + for (uint x=0; x<(uint)surface->w && cw && getPixel(x,0) == pink) x++; + charpos.push_back(x); + + //utf8 characters + if (c>0 && utf8Code(characters[c-1])) { + charpos.push_back(startx); + charpos.push_back(x); + c++; + } + + c++; + } + } + SDL_UnlockSurface(surface); + Uint32 colKey = getPixel(0,surface->h-1); + SDL_SetColorKey(surface, SDL_SRCCOLORKEY, colKey); + + string::size_type pos = characters.find("0")*2; + SDL_Rect srcrect = {charpos[pos], 1, charpos[pos+2] - charpos[pos], surface->h-1}; + uint y = srcrect.h+1; + bool nonKeyFound = false; + while (y-->0 && !nonKeyFound) { + uint x = srcrect.w+1; + while (x-->0 && !nonKeyFound) + nonKeyFound = getPixel(x+srcrect.x,y+srcrect.y) != colKey; + } + lineHeight = y+1; +} + +void SFontPlus::freeFont() { + if (surface!=NULL) { + SDL_FreeSurface(surface); + surface = NULL; + } +} + +void SFontPlus::write(SDL_Surface *s, string text, int x, int y) { + if (text.empty()) return; + + string::size_type pos; + SDL_Rect srcrect, dstrect; + + // these values won't change in the loop + srcrect.y = 1; + dstrect.y = y; + srcrect.h = dstrect.h = surface->h-1; + + for(uint i=0; iw; i++) { + //Utf8 characters + if (utf8Code(text[i]) && i+1h - 1; +} + +uint SFontPlus::getLineHeight() { + return lineHeight; +} diff --git a/src/sfontplus.h b/src/sfontplus.h new file mode 100644 index 0000000..9c9d7fb --- /dev/null +++ b/src/sfontplus.h @@ -0,0 +1,43 @@ +#ifndef SFONTPLUS_H +#define SFONTPLUS_H + +#include +#include +#include + +#define SFONTPLUS_CHARSET "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~¡¿ÀÃÈÉÌÃÒÓÙÚÃÄËÃÖÜŸÂÊÎÔÛÅÃÕÑÆÇČĎĚĽĹŇÔŘŔŠŤŮŽàáèéìíòóùúýäëïöüÿâêîôûåãõñæçÄÄěľĺňôřŕšťžůðßÃÞþÐБВГДЕÐЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрÑтуфхцчшщъыьÑÑŽÑØøąćęłńśżźĄĆĘÅŃŚŻŹ" +#ifdef _WIN32 + typedef unsigned int uint; +#endif +using std::vector; +using std::string; + +class SFontPlus { +private: + Uint32 getPixel(Sint32 x, Sint32 y); + + SDL_Surface *surface; + vector charpos; + string characters; + uint height, lineHeight; + +public: + SFontPlus(); + SFontPlus(SDL_Surface *font); + SFontPlus(string font); + ~SFontPlus(); + + bool utf8Code(unsigned char c); + + void initFont(SDL_Surface *font, string characters = SFONTPLUS_CHARSET); + void initFont(string font, string characters = SFONTPLUS_CHARSET); + void freeFont(); + + void write(SDL_Surface *s, string text, int x, int y); + + uint getTextWidth(string text); + uint getHeight(); + uint getLineHeight(); +}; + +#endif /* SFONTPLUS_H */ diff --git a/src/sparsehash-1.6/AUTHORS b/src/sparsehash-1.6/AUTHORS new file mode 100644 index 0000000..ee92be8 --- /dev/null +++ b/src/sparsehash-1.6/AUTHORS @@ -0,0 +1,2 @@ +opensource@google.com + diff --git a/src/sparsehash-1.6/COPYING b/src/sparsehash-1.6/COPYING new file mode 100644 index 0000000..e4956cf --- /dev/null +++ b/src/sparsehash-1.6/COPYING @@ -0,0 +1,28 @@ +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. diff --git a/src/sparsehash-1.6/ChangeLog b/src/sparsehash-1.6/ChangeLog new file mode 100644 index 0000000..789eb16 --- /dev/null +++ b/src/sparsehash-1.6/ChangeLog @@ -0,0 +1,182 @@ +Fri Jan 8 14:47:55 2010 Google Inc. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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. + diff --git a/src/sparsehash-1.6/INSTALL b/src/sparsehash-1.6/INSTALL new file mode 100644 index 0000000..23e5f25 --- /dev/null +++ b/src/sparsehash-1.6/INSTALL @@ -0,0 +1,236 @@ +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. + diff --git a/src/sparsehash-1.6/Makefile.am b/src/sparsehash-1.6/Makefile.am new file mode 100644 index 0000000..783baa6 --- /dev/null +++ b/src/sparsehash-1.6/Makefile.am @@ -0,0 +1,157 @@ +## 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 +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 diff --git a/src/sparsehash-1.6/NEWS b/src/sparsehash-1.6/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/src/sparsehash-1.6/README b/src/sparsehash-1.6/README new file mode 100644 index 0000000..11df6ed --- /dev/null +++ b/src/sparsehash-1.6/README @@ -0,0 +1,149 @@ +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 // or sparse_hash_set, dense_hash_map, ... + google::sparse_hash_set 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) diff --git a/src/sparsehash-1.6/TODO b/src/sparsehash-1.6/TODO new file mode 100644 index 0000000..e9b0263 --- /dev/null +++ b/src/sparsehash-1.6/TODO @@ -0,0 +1,28 @@ +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 diff --git a/src/sparsehash-1.6/aclocal.m4 b/src/sparsehash-1.6/aclocal.m4 new file mode 100644 index 0000000..2bdc7db --- /dev/null +++ b/src/sparsehash-1.6/aclocal.m4 @@ -0,0 +1,868 @@ +# 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 /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]) diff --git a/src/sparsehash-1.6/configure.ac b/src/sparsehash-1.6/configure.ac new file mode 100644 index 0000000..dea367c --- /dev/null +++ b/src/sparsehash-1.6/configure.ac @@ -0,0 +1,74 @@ +## 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 diff --git a/src/sparsehash-1.6/doc/dense_hash_map.html b/src/sparsehash-1.6/doc/dense_hash_map.html new file mode 100644 index 0000000..eaef87e --- /dev/null +++ b/src/sparsehash-1.6/doc/dense_hash_map.html @@ -0,0 +1,1591 @@ + + + + + +dense_hash_map<Key, Data, HashFcn, EqualKey, Alloc> + + + + +

[Note: this document is formatted similarly to the SGI STL +implementation documentation pages, and refers to concepts and classes +defined there. However, neither this document nor the code it +describes is associated with SGI, nor is it necessary to have SGI's +STL implementation installed in order to use this class.]

+ + +

dense_hash_map<Key, Data, HashFcn, EqualKey, Alloc>

+ +

dense_hash_map is a Hashed +Associative Container that associates objects of type Key +with objects of type Data. dense_hash_map is a Pair +Associative Container, meaning that its value type is pair<const Key, Data>. It is also a +Unique +Associative Container, meaning that no two elements have keys that +compare equal using EqualKey.

+ +

Looking up an element in a dense_hash_map by its key is +efficient, so dense_hash_map is useful for "dictionaries" +where the order of elements is irrelevant. If it is important for the +elements to be in a particular order, however, then map is more appropriate.

+ +

dense_hash_map is distinguished from other hash-map +implementations by its speed and by the ability to save +and restore contents to disk. On the other hand, this hash-map +implementation can use significantly more space than other hash-map +implementations, and it also has requirements -- for instance, for a +distinguished "empty key" -- that may not be easy for all +applications to satisfy.

+ +

This class is appropriate for applications that need speedy access +to relatively small "dictionaries" stored in memory, or for +applications that need these dictionaries to be persistent. [implementation note])

+ + +

Example

+ +(Note: this example uses SGI semantics for hash<> +-- the kind used by gcc and most Unix compiler suites -- and not +Dinkumware semantics -- the kind used by Microsoft Visual Studio. If +you are using MSVC, this example will not compile as-is: you'll need +to change hash to hash_compare, and you +won't use eqstr at all. See the MSVC documentation for +hash_map and hash_compare, for more +details.) + +
+#include <iostream>
+#include <google/dense_hash_map>
+
+using google::dense_hash_map;      // namespace where class lives by default
+using std::cout;
+using std::endl;
+using ext::hash;  // or __gnu_cxx::hash, or maybe tr1::hash, depending on your OS
+
+struct eqstr
+{
+  bool operator()(const char* s1, const char* s2) const
+  {
+    return (s1 == s2) || (s1 && s2 && strcmp(s1, s2) == 0);
+  }
+};
+
+int main()
+{
+  dense_hash_map<const char*, int, hash<const char*>, eqstr> months;
+  
+  months.set_empty_key(NULL);
+  months["january"] = 31;
+  months["february"] = 28;
+  months["march"] = 31;
+  months["april"] = 30;
+  months["may"] = 31;
+  months["june"] = 30;
+  months["july"] = 31;
+  months["august"] = 31;
+  months["september"] = 30;
+  months["october"] = 31;
+  months["november"] = 30;
+  months["december"] = 31;
+  
+  cout << "september -> " << months["september"] << endl;
+  cout << "april     -> " << months["april"] << endl;
+  cout << "june      -> " << months["june"] << endl;
+  cout << "november  -> " << months["november"] << endl;
+}
+
+ + +

Definition

+ +Defined in the header dense_hash_map. +This class is not part of the C++ standard, though it is mostly +compatible with the tr1 class unordered_map. + + +

Template parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescriptionDefault
+ Key + + The hash_map's key type. This is also defined as + dense_hash_map::key_type. + +   +
+ Data + + The hash_map's data type. This is also defined as + dense_hash_map::data_type. [7] + +   +
+ HashFcn + + The hash function used by the + hash_map. This is also defined as dense_hash_map::hasher. +
Note: Hashtable performance depends heavliy on the choice of + hash function. See the performance + page for more information. +
+ hash<Key> +
+ EqualKey + + The hash_map key equality function: a binary predicate that determines + whether two keys are equal. This is also defined as + dense_hash_map::key_equal. + + equal_to<Key> +
+ Alloc + + Ignored; this is included only for API-compatibility + with SGI's (and tr1's) STL implementation. + +
+ + +

Model of

+ +Unique Hashed Associative Container, +Pair Associative Container + + +

Type requirements

+ +
    +
  • +Key is Assignable. +
  • +EqualKey is a Binary Predicate whose argument type is Key. +
  • +EqualKey is an equivalence relation. +
  • +Alloc is an Allocator. +
+ + +

Public base classes

+ +None. + + +

Members

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberWhere definedDescription
+ key_type + + Associative + Container + + The dense_hash_map's key type, Key. +
+ data_type + + Pair + Associative Container + + The type of object associated with the keys. +
+ value_type + + Pair + Associative Container + + The type of object, pair<const key_type, data_type>, + stored in the hash_map. +
+ hasher + + Hashed + Associative Container + + The dense_hash_map's hash + function. +
+ key_equal + + Hashed + Associative Container + + Function + object that compares keys for equality. +
+ allocator_type + + Unordered Associative Container (tr1) + + The type of the Allocator given as a template parameter. +
+ pointer + + Container + + Pointer to T. +
+ reference + + Container + + Reference to T +
+ const_reference + + Container + + Const reference to T +
+ size_type + + Container + + An unsigned integral type. +
+ difference_type + + Container + + A signed integral type. +
+ iterator + + Container + + Iterator used to iterate through a dense_hash_map. [1] +
+ const_iterator + + Container + + Const iterator used to iterate through a dense_hash_map. +
+ local_iterator + + Unordered Associative Container (tr1) + + Iterator used to iterate through a subset of + dense_hash_map. [1] +
+ const_local_iterator + + Unordered Associative Container (tr1) + + Const iterator used to iterate through a subset of + dense_hash_map. +
+ iterator begin() + + Container + + Returns an iterator pointing to the beginning of the + dense_hash_map. +
+ iterator end() + + Container + + Returns an iterator pointing to the end of the + dense_hash_map. +
+ const_iterator begin() const + + Container + + Returns an const_iterator pointing to the beginning of the + dense_hash_map. +
+ const_iterator end() const + + Container + + Returns an const_iterator pointing to the end of the + dense_hash_map. +
+ local_iterator begin(size_type i) + + Unordered Associative Container (tr1) + + Returns a local_iterator pointing to the beginning of bucket + i in the dense_hash_map. +
+ local_iterator end(size_type i) + + Unordered Associative Container (tr1) + + Returns a local_iterator pointing to the end of bucket + i in the dense_hash_map. For + dense_hash_map, each bucket contains either 0 or 1 item. +
+ const_local_iterator begin(size_type i) const + + Unordered Associative Container (tr1) + + Returns a const_local_iterator pointing to the beginning of bucket + i in the dense_hash_map. +
+ const_local_iterator end(size_type i) const + + Unordered Associative Container (tr1) + + Returns a const_local_iterator pointing to the end of bucket + i in the dense_hash_map. For + dense_hash_map, each bucket contains either 0 or 1 item. +
+ size_type size() const + + Container + + Returns the size of the dense_hash_map. +
+ size_type max_size() const + + Container + + Returns the largest possible size of the dense_hash_map. +
+ bool empty() const + + Container + + true if the dense_hash_map's size is 0. +
+ size_type bucket_count() const + + Hashed + Associative Container + + Returns the number of buckets used by the dense_hash_map. +
+ size_type max_bucket_count() const + + Hashed + Associative Container + + Returns the largest possible number of buckets used by the dense_hash_map. +
+ size_type bucket_size(size_type i) const + + Unordered Associative Container (tr1) + + Returns the number of elements in bucket i. For + dense_hash_map, this will be either 0 or 1. +
+ size_type bucket(const key_type& key) const + + Unordered Associative Container (tr1) + + If the key exists in the map, returns the index of the bucket + containing the given key, otherwise, return the bucket the key + would be inserted into. + This value may be passed to begin(size_type) and + end(size_type). +
+ float load_factor() const + + Unordered Associative Container (tr1) + + The number of elements in the dense_hash_map divided by + the number of buckets. +
+ float max_load_factor() const + + Unordered Associative Container (tr1) + + The maximum load factor before increasing the number of buckets in + the dense_hash_map. +
+ void max_load_factor(float new_grow) + + Unordered Associative Container (tr1) + + Sets the maximum load factor before increasing the number of + buckets in the dense_hash_map. +
+ float min_load_factor() const + + dense_hash_map + + The minimum load factor before decreasing the number of buckets in + the dense_hash_map. +
+ void min_load_factor(float new_grow) + + dense_hash_map + + Sets the minimum load factor before decreasing the number of + buckets in the dense_hash_map. +
+ void set_resizing_parameters(float shrink, float grow) + + dense_hash_map + + DEPRECATED. See below. +
+ void resize(size_type n) + + Hashed + Associative Container + + Increases the bucket count to hold at least n items. + [4] [5] +
+ void rehash(size_type n) + + Unordered Associative Container (tr1) + + Increases the bucket count to hold at least n items. + This is identical to resize. + [4] [5] +
+ hasher hash_funct() const + + Hashed + Associative Container + + Returns the hasher object used by the dense_hash_map. +
+ hasher hash_function() const + + Unordered Associative Container (tr1) + + Returns the hasher object used by the dense_hash_map. + This is idential to hash_funct. +
+ key_equal key_eq() const + + Hashed + Associative Container + + Returns the key_equal object used by the + dense_hash_map. +
+ dense_hash_map() + + Container + + Creates an empty dense_hash_map. +
+ dense_hash_map(size_type n) + + Hashed + Associative Container + + Creates an empty dense_hash_map that's optimized for holding + up to n items. + [5] +
+ dense_hash_map(size_type n, const hasher& h) + + Hashed + Associative Container + + Creates an empty dense_hash_map that's optimized for up + to n items, using h as the hash function. +
+ dense_hash_map(size_type n, const hasher& h, const + key_equal& k) + + Hashed + Associative Container + + Creates an empty dense_hash_map that's optimized for up + to n items, using h as the hash function and + k as the key equal function. +
+
template <class InputIterator>
+dense_hash_map(InputIterator f, InputIterator l) 
+[2] +
+ Unique + Hashed Associative Container + + Creates a dense_hash_map with a copy of a range. +
+
template <class InputIterator>
+dense_hash_map(InputIterator f, InputIterator l, size_type n) 
+[2] +
+ Unique + Hashed Associative Container + + Creates a hash_map with a copy of a range that's optimized to + hold up to n items. +
+
template <class InputIterator>
+dense_hash_map(InputIterator f, InputIterator l, size_type n, const
+hasher& h) 
[2] +
+ Unique + Hashed Associative Container + + Creates a hash_map with a copy of a range that's optimized to hold + up to n items, using h as the hash function. +
+
template <class InputIterator>
+dense_hash_map(InputIterator f, InputIterator l, size_type n, const
+hasher& h, const key_equal& k) 
[2] +
+ Unique + Hashed Associative Container + + Creates a hash_map with a copy of a range that's optimized for + holding up to n items, using h as the hash + function and k as the key equal function. +
+ dense_hash_map(const hash_map&) + + Container + + The copy constructor. +
+ dense_hash_map& operator=(const hash_map&) + + Container + + The assignment operator +
+ void swap(hash_map&) + + Container + + Swaps the contents of two hash_maps. +
+
pair<iterator, bool> insert(const value_type& x)
+
+
+ Unique + Associative Container + + Inserts x into the dense_hash_map. +
+
template <class InputIterator>
+void insert(InputIterator f, InputIterator l) 
[2] +
+ Unique + Associative Container + + Inserts a range into the dense_hash_map. +
+ void set_empty_key(const key_type& key) [6] + + dense_hash_map + + See below. +
+ void set_deleted_key(const key_type& key) [6] + + dense_hash_map + + See below. +
+ void clear_deleted_key() [6] + + dense_hash_map + + See below. +
+ void erase(iterator pos) + + Associative + Container + + Erases the element pointed to by pos. + [6] +
+ size_type erase(const key_type& k) + + Associative + Container + + Erases the element whose key is k. + [6] +
+ void erase(iterator first, iterator last) + + Associative + Container + + Erases all elements in a range. + [6] +
+ void clear() + + Associative + Container + + Erases all of the elements. +
+ void clear_no_resize() + + dense_hash_map + + See below. +
+ const_iterator find(const key_type& k) const + + Associative + Container + + Finds an element whose key is k. +
+ iterator find(const key_type& k) + + Associative + Container + + Finds an element whose key is k. +
+ size_type count(const key_type& k) const + + Unique + Associative Container + + Counts the number of elements whose key is k. +
+
pair<const_iterator, const_iterator> equal_range(const
+key_type& k) const 
+
+ Associative + Container + + Finds a range containing all elements whose key is k. +
+
pair<iterator, iterator> equal_range(const
+key_type& k) 
+
+ Associative + Container + + Finds a range containing all elements whose key is k. +
+
data_type& operator[](const key_type& k) [3] 
+
+ dense_hash_map + + See below. +
+ bool write_metadata(FILE *fp) + + dense_hash_map + + See below. +
+ bool read_metadata(FILE *fp) + + dense_hash_map + + See below. +
+ bool write_nopointer_data(FILE *fp) + + dense_hash_map + + See below. +
+ bool read_nopointer_data(FILE *fp) + + dense_hash_map + + See below. +
+
bool operator==(const hash_map&, const hash_map&)
+
+
+ Hashed + Associative Container + + Tests two hash_maps for equality. This is a global function, not a + member function. +
+ + +

New members

+ +These members are not defined in the Unique +Hashed Associative Container, Pair +Associative Container, or tr1's +Unordered Associative +Container requirements, but are specific to +dense_hash_map. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberDescription
+ void set_empty_key(const key_type& key) + + Sets the distinguished "empty" key to key. This must be + called immediately after construct time, before calls to another + other dense_hash_map operation. [6] +
+ void set_deleted_key(const key_type& key) + + Sets the distinguished "deleted" key to key. This must be + called before any calls to erase(). [6] +
+ void clear_deleted_key() + + Clears the distinguished "deleted" key. After this is called, + calls to erase() are not valid on this object. + [6] +
+ void clear_no_resize() + + Clears the hashtable like clear() does, but does not + recover the memory used for hashtable buckets. (The memory + used by the items in the hashtable is still recovered.) + This can save time for applications that want to reuse a + dense_hash_map many times, each time with a similar number + of objects. +
+
+data_type& 
+operator[](const key_type& k) [3]
+
+
+ Returns a reference to the object that is associated with + a particular key. If the dense_hash_map does not already + contain such an object, operator[] inserts the default + object data_type(). [3] +
+ void set_resizing_parameters(float shrink, float grow) + + This function is DEPRECATED. It is equivalent to calling + min_load_factor(shrink); max_load_factor(grow). +
+ bool write_metadata(FILE *fp) + + Write hashtable metadata to fp. See below. +
+ bool read_metadata(FILE *fp) + + Read hashtable metadata from fp. See below. +
+ bool write_nopointer_data(FILE *fp) + + Write hashtable contents to fp. This is valid only if the + hashtable key and value are "plain" data. See below. +
+ bool read_nopointer_data(FILE *fp) + + Read hashtable contents to fp. This is valid only if the + hashtable key and value are "plain" data. See below. +
+ + +

Notes

+ +

[1] + +dense_hash_map::iterator is not a mutable iterator, because +dense_hash_map::value_type is not Assignable. +That is, if i is of type dense_hash_map::iterator +and p is of type dense_hash_map::value_type, then +*i = p is not a valid expression. However, +dense_hash_map::iterator isn't a constant iterator either, +because it can be used to modify the object that it points to. Using +the same notation as above, (*i).second = p is a valid +expression.

+ +

[2] + +This member function relies on member template functions, which +may not be supported by all compilers. If your compiler supports +member templates, you can call this function with any type of input +iterator. If your compiler does not yet support member templates, +though, then the arguments must either be of type const +value_type* or of type dense_hash_map::const_iterator.

+ +

[3] + +Since operator[] might insert a new element into the +dense_hash_map, it can't possibly be a const member +function. Note that the definition of operator[] is +extremely simple: m[k] is equivalent to +(*((m.insert(value_type(k, data_type()))).first)).second. +Strictly speaking, this member function is unnecessary: it exists only +for convenience.

+ +

[4] + +In order to preserve iterators, erasing hashtable elements does not +cause a hashtable to resize. This means that after a string of +erase() calls, the hashtable will use more space than is +required. At a cost of invalidating all current iterators, you can +call resize() to manually compact the hashtable. The +hashtable promotes too-small resize() arguments to the +smallest legal value, so to compact a hashtable, it's sufficient to +call resize(0).

+ +

[5] + +Unlike some other hashtable implementations, the optional n in +the calls to the constructor, resize, and rehash +indicates not the desired number of buckets that +should be allocated, but instead the expected number of items to be +inserted. The class then sizes the hash-map appropriately for the +number of items specified. It's not an error to actually insert more +or fewer items into the hashtable, but the implementation is most +efficient -- does the fewest hashtable resizes -- if the number of +inserted items is n or slightly less.

+ +

[6] + +dense_hash_map requires you call +set_empty_key() immediately after constructing the hash-map, +and before calling any other dense_hash_map method. (This is +the largest difference between the dense_hash_map API and +other hash-map APIs. See implementation.html +for why this is necessary.) +The argument to set_empty_key() should be a key-value that +is never used for legitimate hash-map entries. If you have no such +key value, you will be unable to use dense_hash_map. It is +an error to call insert() with an item whose key is the +"empty key."

+ +dense_hash_map also requires you call +set_deleted_key() before calling erase(). +The argument to set_deleted_key() should be a key-value that +is never used for legitimate hash-map entries. It must be different +from the key-value used for set_empty_key(). It is an error to call +erase() without first calling set_deleted_key(), and +it is also an error to call insert() with an item whose key +is the "deleted key."

+ +

There is no need to call set_deleted_key if you do not +wish to call erase() on the hash-map.

+ +

It is acceptable to change the deleted-key at any time by calling +set_deleted_key() with a new argument. You can also call +clear_deleted_key(), at which point all keys become valid for +insertion but no hashtable entries can be deleted until +set_deleted_key() is called again.

+ +

[7] + +dense_hash_map requires that data_type has a +zero-argument default constructor. This is because +dense_hash_map uses the special value pair(empty_key, +data_type()) to denote empty buckets, and thus needs to be able +to create data_type using a zero-argument constructor.

+ +

If your data_type does not have a zero-argument default +constructor, there are several workarounds:

+
    +
  • Store a pointer to data_type in the map, instead of + data_type directly. This may yield faster code as + well, since hashtable-resizes will just have to move pointers + around, rather than copying the entire data_type. +
  • Add a zero-argument default constructor to data_type. +
  • Subclass data_type and add a zero-argument default + constructor to the subclass. +
+ + +

Input/Output

+ +
+

IMPORTANT IMPLEMENTATION NOTE: In the current version of +this code, the input/output routines for dense_hash_map have +not yet been implemented. This section explains the API, but +note that all calls to these routines will fail (return +false). It is a TODO to remedy this situation.

+
+ +

It is possible to save and restore dense_hash_map objects +to disk. Storage takes place in two steps. The first writes the +hashtable metadata. The second writes the actual data.

+ +

To write a hashtable to disk, first call write_metadata() +on an open file pointer. This saves the hashtable information in a +byte-order-independent format.

+ +

After the metadata has been written to disk, you must write the +actual data stored in the hash-map to disk. If both the key and data +are "simple" enough, you can do this by calling +write_nopointer_data(). "Simple" data is data that can be +safely copied to disk via fwrite(). Native C data types fall +into this category, as do structs of native C data types. Pointers +and STL objects do not.

+ +

Note that write_nopointer_data() does not do any endian +conversion. Thus, it is only appropriate when you intend to read the +data on the same endian architecture as you write the data.

+ +

If you cannot use write_nopointer_data() for any reason, +you can write the data yourself by iterating over the +dense_hash_map with a const_iterator and writing +the key and data in any manner you wish.

+ +

To read the hashtable information from disk, first you must create +a dense_hash_map object. Then open a file pointer to point +to the saved hashtable, and call read_metadata(). If you +saved the data via write_nopointer_data(), you can follow the +read_metadata() call with a call to +read_nopointer_data(). This is all that is needed.

+ +

If you saved the data through a custom write routine, you must call +a custom read routine to read in the data. To do this, iterate over +the dense_hash_map with an iterator; this operation +is sensical because the metadata has already been set up. For each +iterator item, you can read the key and value from disk, and set it +appropriately. You will need to do a const_cast on the +iterator, since it->first is always const. You +will also need to use placement-new if the key or value is a C++ +object. The code might look like this:

+
+   for (dense_hash_map<int*, ComplicatedClass>::iterator it = ht.begin();
+        it != ht.end(); ++it) {
+       // The key is stored in the dense_hash_map as a pointer
+       const_cast<int*>(it->first) = new int;
+       fread(const_cast<int*>(it->first), sizeof(int), 1, fp);
+       // The value is a complicated C++ class that takes an int to construct
+       int ctor_arg;
+       fread(&ctor_arg, sizeof(int), 1, fp);
+       new (&it->second) ComplicatedClass(ctor_arg);  // "placement new"
+   }
+
+ + +

Validity of Iterators

+ +

erase() is guaranteed not to invalidate any iterators -- +except for any iterators pointing to the item being erased, of course. +insert() invalidates all iterators, as does +resize().

+ +

This is implemented by making erase() not resize the +hashtable. If you desire maximum space efficiency, you can call +resize(0) after a string of erase() calls, to force +the hashtable to resize to the smallest possible size.

+ +

In addition to invalidating iterators, insert() +and resize() invalidate all pointers into the hashtable. If +you want to store a pointer to an object held in a dense_hash_map, +either do so after finishing hashtable inserts, or store the object on +the heap and a pointer to it in the dense_hash_map.

+ + +

See also

+ +

The following are SGI STL, and some Google STL, concepts and +classes related to dense_hash_map.

+ +hash_map, +Associative Container, +Hashed Associative Container, +Pair Associative Container, +Unique Hashed Associative Container, +set, +map +multiset, +multimap, +hash_set, +hash_multiset, +hash_multimap, +sparse_hash_map, +sparse_hash_set, +dense_hash_set + + + diff --git a/src/sparsehash-1.6/doc/dense_hash_set.html b/src/sparsehash-1.6/doc/dense_hash_set.html new file mode 100644 index 0000000..2a5ff2e --- /dev/null +++ b/src/sparsehash-1.6/doc/dense_hash_set.html @@ -0,0 +1,1445 @@ + + + + + +dense_hash_set<Key, HashFcn, EqualKey, Alloc> + + + + +

[Note: this document is formatted similarly to the SGI STL +implementation documentation pages, and refers to concepts and classes +defined there. However, neither this document nor the code it +describes is associated with SGI, nor is it necessary to have SGI's +STL implementation installed in order to use this class.]

+ + +

dense_hash_set<Key, HashFcn, EqualKey, Alloc>

+ +

dense_hash_set is a Hashed +Associative Container that stores objects of type Key. +dense_hash_set is a Simple +Associative Container, meaning that its value type, as well as its +key type, is key. It is also a +Unique +Associative Container, meaning that no two elements have keys that +compare equal using EqualKey.

+ +

Looking up an element in a dense_hash_set by its key is +efficient, so dense_hash_set is useful for "dictionaries" +where the order of elements is irrelevant. If it is important for the +elements to be in a particular order, however, then map is more appropriate.

+ +

dense_hash_set is distinguished from other hash-set +implementations by its speed and by the ability to save +and restore contents to disk. On the other hand, this hash-set +implementation can use significantly more space than other hash-set +implementations, and it also has requirements -- for instance, for a +distinguished "empty key" -- that may not be easy for all +applications to satisfy.

+ +

This class is appropriate for applications that need speedy access +to relatively small "dictionaries" stored in memory, or for +applications that need these dictionaries to be persistent. [implementation note])

+ + +

Example

+ +(Note: this example uses SGI semantics for hash<> +-- the kind used by gcc and most Unix compiler suites -- and not +Dinkumware semantics -- the kind used by Microsoft Visual Studio. If +you are using MSVC, this example will not compile as-is: you'll need +to change hash to hash_compare, and you +won't use eqstr at all. See the MSVC documentation for +hash_map and hash_compare, for more +details.) + +
+#include <iostream>
+#include <google/dense_hash_set>
+
+using google::dense_hash_set;      // namespace where class lives by default
+using std::cout;
+using std::endl;
+using ext::hash;  // or __gnu_cxx::hash, or maybe tr1::hash, depending on your OS
+
+struct eqstr
+{
+  bool operator()(const char* s1, const char* s2) const
+  {
+    return (s1 == s2) || (s1 && s2 && strcmp(s1, s2) == 0);
+  }
+};
+
+void lookup(const hash_set<const char*, hash<const char*>, eqstr>& Set,
+            const char* word)
+{
+  dense_hash_set<const char*, hash<const char*>, eqstr>::const_iterator it
+    = Set.find(word);
+  cout << word << ": "
+       << (it != Set.end() ? "present" : "not present")
+       << endl;
+}
+
+int main()
+{
+  dense_hash_set<const char*, hash<const char*>, eqstr> Set;
+  Set.set_empty_key(NULL);
+  Set.insert("kiwi");
+  Set.insert("plum");
+  Set.insert("apple");
+  Set.insert("mango");
+  Set.insert("apricot");
+  Set.insert("banana");
+
+  lookup(Set, "mango");
+  lookup(Set, "apple");
+  lookup(Set, "durian");
+}
+
+ + +

Definition

+ +Defined in the header dense_hash_set. +This class is not part of the C++ standard, though it is mostly +compatible with the tr1 class unordered_set. + + +

Template parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescriptionDefault
+ Key + + The hash_set's key and value type. This is also defined as + dense_hash_set::key_type and + dense_hash_set::value_type. + +   +
+ HashFcn + + The hash function used by the + hash_set. This is also defined as dense_hash_set::hasher. +
Note: Hashtable performance depends heavliy on the choice of + hash function. See the performance + page for more information. +
+ hash<Key> +
+ EqualKey + + The hash_set key equality function: a binary predicate that determines + whether two keys are equal. This is also defined as + dense_hash_set::key_equal. + + equal_to<Key> +
+ Alloc + + Ignored; this is included only for API-compatibility + with SGI's (and tr1's) STL implementation. + +
+ + +

Model of

+ +Unique Hashed Associative Container, +Simple Associative Container + + +

Type requirements

+ +
    +
  • +Key is Assignable. +
  • +EqualKey is a Binary Predicate whose argument type is Key. +
  • +EqualKey is an equivalence relation. +
  • +Alloc is an Allocator. +
+ + +

Public base classes

+ +None. + + +

Members

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberWhere definedDescription
+ value_type + + Container + + The type of object, T, stored in the hash_set. +
+ key_type + + Associative + Container + + The key type associated with value_type. +
+ hasher + + Hashed + Associative Container + + The dense_hash_set's hash + function. +
+ key_equal + + Hashed + Associative Container + + Function + object that compares keys for equality. +
+ allocator_type + + Unordered Associative Container (tr1) + + The type of the Allocator given as a template parameter. +
+ pointer + + Container + + Pointer to T. +
+ reference + + Container + + Reference to T +
+ const_reference + + Container + + Const reference to T +
+ size_type + + Container + + An unsigned integral type. +
+ difference_type + + Container + + A signed integral type. +
+ iterator + + Container + + Iterator used to iterate through a dense_hash_set. +
+ const_iterator + + Container + + Const iterator used to iterate through a dense_hash_set. + (iterator and const_iterator are the same type.) +
+ local_iterator + + Unordered Associative Container (tr1) + + Iterator used to iterate through a subset of + dense_hash_set. +
+ const_local_iterator + + Unordered Associative Container (tr1) + + Const iterator used to iterate through a subset of + dense_hash_set. +
+ iterator begin() const + + Container + + Returns an iterator pointing to the beginning of the + dense_hash_set. +
+ iterator end() const + + Container + + Returns an iterator pointing to the end of the + dense_hash_set. +
+ local_iterator begin(size_type i) + + Unordered Associative Container (tr1) + + Returns a local_iterator pointing to the beginning of bucket + i in the dense_hash_set. +
+ local_iterator end(size_type i) + + Unordered Associative Container (tr1) + + Returns a local_iterator pointing to the end of bucket + i in the dense_hash_set. For + dense_hash_set, each bucket contains either 0 or 1 item. +
+ const_local_iterator begin(size_type i) const + + Unordered Associative Container (tr1) + + Returns a const_local_iterator pointing to the beginning of bucket + i in the dense_hash_set. +
+ const_local_iterator end(size_type i) const + + Unordered Associative Container (tr1) + + Returns a const_local_iterator pointing to the end of bucket + i in the dense_hash_set. For + dense_hash_set, each bucket contains either 0 or 1 item. +
+ size_type size() const + + Container + + Returns the size of the dense_hash_set. +
+ size_type max_size() const + + Container + + Returns the largest possible size of the dense_hash_set. +
+ bool empty() const + + Container + + true if the dense_hash_set's size is 0. +
+ size_type bucket_count() const + + Hashed + Associative Container + + Returns the number of buckets used by the dense_hash_set. +
+ size_type max_bucket_count() const + + Hashed + Associative Container + + Returns the largest possible number of buckets used by the dense_hash_set. +
+ size_type bucket_size(size_type i) const + + Unordered Associative Container (tr1) + + Returns the number of elements in bucket i. For + dense_hash_set, this will be either 0 or 1. +
+ size_type bucket(const key_type& key) const + + Unordered Associative Container (tr1) + + If the key exists in the map, returns the index of the bucket + containing the given key, otherwise, return the bucket the key + would be inserted into. + This value may be passed to begin(size_type) and + end(size_type). +
+ float load_factor() const + + Unordered Associative Container (tr1) + + The number of elements in the dense_hash_set divided by + the number of buckets. +
+ float max_load_factor() const + + Unordered Associative Container (tr1) + + The maximum load factor before increasing the number of buckets in + the dense_hash_set. +
+ void max_load_factor(float new_grow) + + Unordered Associative Container (tr1) + + Sets the maximum load factor before increasing the number of + buckets in the dense_hash_set. +
+ float min_load_factor() const + + dense_hash_set + + The minimum load factor before decreasing the number of buckets in + the dense_hash_set. +
+ void min_load_factor(float new_grow) + + dense_hash_set + + Sets the minimum load factor before decreasing the number of + buckets in the dense_hash_set. +
+ void set_resizing_parameters(float shrink, float grow) + + dense_hash_set + + DEPRECATED. See below. +
+ void resize(size_type n) + + Hashed + Associative Container + + Increases the bucket count to hold at least n items. + [2] [3] +
+ void rehash(size_type n) + + Unordered Associative Container (tr1) + + Increases the bucket count to hold at least n items. + This is identical to resize. + [2] [3] +
+ hasher hash_funct() const + + Hashed + Associative Container + + Returns the hasher object used by the dense_hash_set. +
+ hasher hash_function() const + + Unordered Associative Container (tr1) + + Returns the hasher object used by the dense_hash_set. + This is idential to hash_funct. +
+ key_equal key_eq() const + + Hashed + Associative Container + + Returns the key_equal object used by the + dense_hash_set. +
+ dense_hash_set() + + Container + + Creates an empty dense_hash_set. +
+ dense_hash_set(size_type n) + + Hashed + Associative Container + + Creates an empty dense_hash_set that's optimized for holding + up to n items. + [3] +
+ dense_hash_set(size_type n, const hasher& h) + + Hashed + Associative Container + + Creates an empty dense_hash_set that's optimized for up + to n items, using h as the hash function. +
+ dense_hash_set(size_type n, const hasher& h, const + key_equal& k) + + Hashed + Associative Container + + Creates an empty dense_hash_set that's optimized for up + to n items, using h as the hash function and + k as the key equal function. +
+
template <class InputIterator>
+dense_hash_set(InputIterator f, InputIterator l) 
+[2] +
+ Unique + Hashed Associative Container + + Creates a dense_hash_set with a copy of a range. +
+
template <class InputIterator>
+dense_hash_set(InputIterator f, InputIterator l, size_type n) 
+[2] +
+ Unique + Hashed Associative Container + + Creates a hash_set with a copy of a range that's optimized to + hold up to n items. +
+
template <class InputIterator>
+dense_hash_set(InputIterator f, InputIterator l, size_type n, const
+hasher& h) 
[2] +
+ Unique + Hashed Associative Container + + Creates a hash_set with a copy of a range that's optimized to hold + up to n items, using h as the hash function. +
+
template <class InputIterator>
+dense_hash_set(InputIterator f, InputIterator l, size_type n, const
+hasher& h, const key_equal& k) 
[2] +
+ Unique + Hashed Associative Container + + Creates a hash_set with a copy of a range that's optimized for + holding up to n items, using h as the hash + function and k as the key equal function. +
+ dense_hash_set(const hash_set&) + + Container + + The copy constructor. +
+ dense_hash_set& operator=(const hash_set&) + + Container + + The assignment operator +
+ void swap(hash_set&) + + Container + + Swaps the contents of two hash_sets. +
+
pair<iterator, bool> insert(const value_type& x)
+
+
+ Unique + Associative Container + + Inserts x into the dense_hash_set. +
+
template <class InputIterator>
+void insert(InputIterator f, InputIterator l) 
[2] +
+ Unique + Associative Container + + Inserts a range into the dense_hash_set. +
+ void set_empty_key(const key_type& key) [4] + + dense_hash_set + + See below. +
+ void set_deleted_key(const key_type& key) [4] + + dense_hash_set + + See below. +
+ void clear_deleted_key() [4] + + dense_hash_set + + See below. +
+ void erase(iterator pos) + + Associative + Container + + Erases the element pointed to by pos. + [4] +
+ size_type erase(const key_type& k) + + Associative + Container + + Erases the element whose key is k. + [4] +
+ void erase(iterator first, iterator last) + + Associative + Container + + Erases all elements in a range. + [4] +
+ void clear() + + Associative + Container + + Erases all of the elements. +
+ void clear_no_resize() + + dense_hash_map + + See below. +
+ iterator find(const key_type& k) const + + Associative + Container + + Finds an element whose key is k. +
+ size_type count(const key_type& k) const + + Unique + Associative Container + + Counts the number of elements whose key is k. +
+
pair<iterator, iterator> equal_range(const
+key_type& k) const
+
+ Associative + Container + + Finds a range containing all elements whose key is k. +
+ bool write_metadata(FILE *fp) + + dense_hash_set + + See below. +
+ bool read_metadata(FILE *fp) + + dense_hash_set + + See below. +
+ bool write_nopointer_data(FILE *fp) + + dense_hash_set + + See below. +
+ bool read_nopointer_data(FILE *fp) + + dense_hash_set + + See below. +
+
bool operator==(const hash_set&, const hash_set&)
+
+
+ Hashed + Associative Container + + Tests two hash_sets for equality. This is a global function, not a + member function. +
+ + +

New members

+ +These members are not defined in the Unique +Hashed Associative Container, Simple +Associative Container, or tr1's Unordered Associative +Container requirements, but are specific to +dense_hash_set. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberDescription
+ void set_empty_key(const key_type& key) + + Sets the distinguished "empty" key to key. This must be + called immediately after construct time, before calls to another + other dense_hash_set operation. [4] +
+ void set_deleted_key(const key_type& key) + + Sets the distinguished "deleted" key to key. This must be + called before any calls to erase(). [4] +
+ void clear_deleted_key() + + Clears the distinguished "deleted" key. After this is called, + calls to erase() are not valid on this object. + [4] +
+ void clear_no_resize() + + Clears the hashtable like clear() does, but does not + recover the memory used for hashtable buckets. (The memory + used by the items in the hashtable is still recovered.) + This can save time for applications that want to reuse a + dense_hash_set many times, each time with a similar number + of objects. +
+ void set_resizing_parameters(float shrink, float grow) + + This function is DEPRECATED. It is equivalent to calling + min_load_factor(shrink); max_load_factor(grow). +
+ bool write_metadata(FILE *fp) + + Write hashtable metadata to fp. See below. +
+ bool read_metadata(FILE *fp) + + Read hashtable metadata from fp. See below. +
+ bool write_nopointer_data(FILE *fp) + + Write hashtable contents to fp. This is valid only if the + hashtable key and value are "plain" data. See below. +
+ bool read_nopointer_data(FILE *fp) + + Read hashtable contents to fp. This is valid only if the + hashtable key and value are "plain" data. See below. +
+ + +

Notes

+ +

[1] + +This member function relies on member template functions, which +may not be supported by all compilers. If your compiler supports +member templates, you can call this function with any type of input +iterator. If your compiler does not yet support member templates, +though, then the arguments must either be of type const +value_type* or of type dense_hash_set::const_iterator.

+ +

[2] + +In order to preserve iterators, erasing hashtable elements does not +cause a hashtable to resize. This means that after a string of +erase() calls, the hashtable will use more space than is +required. At a cost of invalidating all current iterators, you can +call resize() to manually compact the hashtable. The +hashtable promotes too-small resize() arguments to the +smallest legal value, so to compact a hashtable, it's sufficient to +call resize(0). + +

[3] + +Unlike some other hashtable implementations, the optional n in +the calls to the constructor, resize, and rehash +indicates not the desired number of buckets that +should be allocated, but instead the expected number of items to be +inserted. The class then sizes the hash-set appropriately for the +number of items specified. It's not an error to actually insert more +or fewer items into the hashtable, but the implementation is most +efficient -- does the fewest hashtable resizes -- if the number of +inserted items is n or slightly less.

+ +

[4] + +dense_hash_set requires you call +set_empty_key() immediately after constructing the hash-set, +and before calling any other dense_hash_set method. (This is +the largest difference between the dense_hash_set API and +other hash-set APIs. See implementation.html +for why this is necessary.) +The argument to set_empty_key() should be a key-value that +is never used for legitimate hash-set entries. If you have no such +key value, you will be unable to use dense_hash_set. It is +an error to call insert() with an item whose key is the +"empty key."

+ +dense_hash_set also requires you call +set_deleted_key() before calling erase(). +The argument to set_deleted_key() should be a key-value that +is never used for legitimate hash-set entries. It must be different +from the key-value used for set_empty_key(). It is an error to call +erase() without first calling set_deleted_key(), and +it is also an error to call insert() with an item whose key +is the "deleted key."

+ +

There is no need to call set_deleted_key if you do not +wish to call erase() on the hash-set.

+ +

It is acceptable to change the deleted-key at any time by calling +set_deleted_key() with a new argument. You can also call +clear_deleted_key(), at which point all keys become valid for +insertion but no hashtable entries can be deleted until +set_deleted_key() is called again.

+ + +

Input/Output

+ +
+

IMPORTANT IMPLEMENTATION NOTE: In the current version of +this code, the input/output routines for dense_hash_set have +not yet been implemented. This section explains the API, but +note that all calls to these routines will fail (return +false). It is a TODO to remedy this situation.

+
+ +

It is possible to save and restore dense_hash_set objects +to disk. Storage takes place in two steps. The first writes the +hashtable metadata. The second writes the actual data.

+ +

To write a hashtable to disk, first call write_metadata() +on an open file pointer. This saves the hashtable information in a +byte-order-independent format.

+ +

After the metadata has been written to disk, you must write the +actual data stored in the hash-set to disk. If both the key and data +are "simple" enough, you can do this by calling +write_nopointer_data(). "Simple" data is data that can be +safely copied to disk via fwrite(). Native C data types fall +into this category, as do structs of native C data types. Pointers +and STL objects do not.

+ +

Note that write_nopointer_data() does not do any endian +conversion. Thus, it is only appropriate when you intend to read the +data on the same endian architecture as you write the data.

+ +

If you cannot use write_nopointer_data() for any reason, +you can write the data yourself by iterating over the +dense_hash_set with a const_iterator and writing +the key and data in any manner you wish.

+ +

To read the hashtable information from disk, first you must create +a dense_hash_set object. Then open a file pointer to point +to the saved hashtable, and call read_metadata(). If you +saved the data via write_nopointer_data(), you can follow the +read_metadata() call with a call to +read_nopointer_data(). This is all that is needed.

+ +

If you saved the data through a custom write routine, you must call +a custom read routine to read in the data. To do this, iterate over +the dense_hash_set with an iterator; this operation +is sensical because the metadata has already been set up. For each +iterator item, you can read the key and value from disk, and set it +appropriately. You will need to do a const_cast on the +iterator, since *it is always const. The +code might look like this:

+
+   for (dense_hash_set<int*>::iterator it = ht.begin();
+        it != ht.end(); ++it) {
+       const_cast<int*>(*it) = new int;
+       fread(const_cast<int*>(*it), sizeof(int), 1, fp);
+   }
+
+ +

Here's another example, where the item stored in the hash-set is +a C++ object with a non-trivial constructor. In this case, you must +use "placement new" to construct the object at the correct memory +location.

+
+   for (dense_hash_set<ComplicatedClass>::iterator it = ht.begin();
+        it != ht.end(); ++it) {
+       int ctor_arg;  // ComplicatedClass takes an int as its constructor arg
+       fread(&ctor_arg, sizeof(int), 1, fp);
+       new (const_cast<ComplicatedClass*>(&(*it))) ComplicatedClass(ctor_arg);
+   }
+
+ + +

Validity of Iterators

+ +

erase() is guaranteed not to invalidate any iterators -- +except for any iterators pointing to the item being erased, of course. +insert() invalidates all iterators, as does +resize().

+ +

This is implemented by making erase() not resize the +hashtable. If you desire maximum space efficiency, you can call +resize(0) after a string of erase() calls, to force +the hashtable to resize to the smallest possible size.

+ +

In addition to invalidating iterators, insert() +and resize() invalidate all pointers into the hashtable. If +you want to store a pointer to an object held in a dense_hash_set, +either do so after finishing hashtable inserts, or store the object on +the heap and a pointer to it in the dense_hash_set.

+ + + +

See also

+ +

The following are SGI STL, and some Google STL, concepts and +classes related to dense_hash_set.

+ +hash_set, +Associative Container, +Hashed Associative Container, +Simple Associative Container, +Unique Hashed Associative Container, +set, +map +multiset, +multimap, +hash_map, +hash_multiset, +hash_multimap, +sparse_hash_set, +sparse_hash_map, +dense_hash_map + + + diff --git a/src/sparsehash-1.6/doc/designstyle.css b/src/sparsehash-1.6/doc/designstyle.css new file mode 100644 index 0000000..f5d1ec2 --- /dev/null +++ b/src/sparsehash-1.6/doc/designstyle.css @@ -0,0 +1,115 @@ +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 tag for bits of code and for variables and objects. */ +code,pre,samp,var { + color: #006000; +} +/* Use the tag for file and directory paths and names. */ +file { + color: #905050; + font-family: monospace; +} +/* Use the 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; } \ No newline at end of file diff --git a/src/sparsehash-1.6/doc/implementation.html b/src/sparsehash-1.6/doc/implementation.html new file mode 100644 index 0000000..2050d54 --- /dev/null +++ b/src/sparsehash-1.6/doc/implementation.html @@ -0,0 +1,371 @@ + + + +Implementation notes: sparse_hash, dense_hash, sparsetable + + + + +

Implementation of sparse_hash_map, dense_hash_map, and +sparsetable

+ +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, The Art of Computer +Programming, Vol 3, Hashing. + + +
+

sparsetable

+ +

For specificity, consider the declaration

+ +
+   sparsetable<Foo> t(100);        // a sparse array with 100 elements
+
+ +

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().

+ +

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].

+ +

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.

+ +

find()

+ +

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.

+ +

insert()

+ +

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.

+ +

(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.)

+ +

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.

+ +

delete()

+ +

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.

+ +

iterators

+ +

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.

+ +

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:

+ +
+   printf("%d", static_cast<Foo>(*t.find(0)));
+
+ +

To avoid such problems, consider using get() and set() instead of an +iterator:

+ +
+   for (int i = 0; i < t.size(); ++i)
+      if (t.get(i) == ...)  t.set(i, ...);
+
+ +

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.

+ +

Resource use

+ +

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.

+ +

You can also look at some specific performance numbers.

+ + +
+

sparse_hash_set

+ +

For specificity, consider the declaration

+ +
+   sparse_hash_set<Foo> t;
+
+ +

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.

+ +

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.

+ +

insert()

+ +

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:

+ +

+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.) + +

+2a) Look at t.sparsetable[i % 32]. If it's unassigned, assign it to + foo. foo is now in the hashtable. + +

+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. + +

+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. + +

+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. + +

+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. +

+ +

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.

+ +

(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.)

+ +

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.

+ +

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.

+ +

find()

+ +

find() works similarly to insert. The only difference is in step +(2a): if the value is unassigned, then the lookup fails immediately.

+ +

delete()

+ +

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:

+ +
+    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
+
+ +

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.

+ +

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.

+ +

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.

+ +

When copying the hashtable, either to grow it or shrink it, the +special 'delete' values are not copied into the new table. The +copy-time rehash makes them unnecessary.

+ +

Resource use

+ +

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.

+ +

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.

+ +

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.)

+ +

You can also look at some specific performance numbers.

+ + +
+

sparse_hash_map

+ +

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>.

+ + +
+

dense_hash_set

+ +

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.

+ +

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'.

+ +

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.

+ +

Resource use

+ +

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.

+ +

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.

+ +

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.

+ +

You can also look at some specific performance numbers.

+ + +
+

dense_hash_map

+ +

dense_hash_map is identical to dense_hash_set except for what values +are stored in each table entry.

+ +
+ +Craig Silverstein
+Thu Jan 6 20:15:42 PST 2005 +
+ + + diff --git a/src/sparsehash-1.6/doc/index.html b/src/sparsehash-1.6/doc/index.html new file mode 100644 index 0000000..68a5865 --- /dev/null +++ b/src/sparsehash-1.6/doc/index.html @@ -0,0 +1,69 @@ + + + + Google Sparsehash Package + + + + + + + + +

Google Sparsehash Package

+
+ +

The Google sparsehash package consists of two hashtable +implementations: sparse, which is designed to be very space +efficient, and dense, 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.

+ +

Documentation on how to use these classes:

+ + +

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 +sparse_hash_map, but your keys are all small-ish +integers.

+ + +

There is also a doc explaining the implementation details of these +classes, for those who are curious. And finally, you can see some +performance comparisons, both between +the various classes here, but also between these implementations and +other standard hashtable implementations.

+ +
+
+Craig Silverstein
+Last modified: Thu Jan 25 17:58:02 PST 2007 +
+ + + diff --git a/src/sparsehash-1.6/doc/performance.html b/src/sparsehash-1.6/doc/performance.html new file mode 100644 index 0000000..40c1406 --- /dev/null +++ b/src/sparsehash-1.6/doc/performance.html @@ -0,0 +1,96 @@ + + + +Performance notes: sparse_hash, dense_hash, sparsetable + + + + +

Performance Numbers

+ +

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).

+ +

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.

+ +

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 gcc2. Compiled with gcc2.95.3 -g +-O2

+ +
+======
+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
+
+ + +

A Note on Hash Functions

+ +

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.

+ +

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.

+ +

There has been much research over the years into good hash +functions. Here are some hash functions of note.

+ + + + + diff --git a/src/sparsehash-1.6/doc/sparse_hash_map.html b/src/sparsehash-1.6/doc/sparse_hash_map.html new file mode 100644 index 0000000..63055c9 --- /dev/null +++ b/src/sparsehash-1.6/doc/sparse_hash_map.html @@ -0,0 +1,1527 @@ + + + + + +sparse_hash_map<Key, Data, HashFcn, EqualKey, Alloc> + + + + +

[Note: this document is formatted similarly to the SGI STL +implementation documentation pages, and refers to concepts and classes +defined there. However, neither this document nor the code it +describes is associated with SGI, nor is it necessary to have SGI's +STL implementation installed in order to use this class.]

+ + +

sparse_hash_map<Key, Data, HashFcn, EqualKey, Alloc>

+ +

sparse_hash_map is a Hashed +Associative Container that associates objects of type Key +with objects of type Data. sparse_hash_map is a Pair +Associative Container, meaning that its value type is pair<const Key, Data>. It is also a +Unique +Associative Container, meaning that no two elements have keys that +compare equal using EqualKey.

+ +

Looking up an element in a sparse_hash_map by its key is +efficient, so sparse_hash_map is useful for "dictionaries" +where the order of elements is irrelevant. If it is important for the +elements to be in a particular order, however, then map is more appropriate.

+ +

sparse_hash_map is distinguished from other hash-map +implementations by its stingy use of memory and by the ability to save +and restore contents to disk. On the other hand, this hash-map +implementation, while still efficient, is slower than other hash-map +implementations, and it also has requirements -- for instance, for a +distinguished "deleted key" -- that may not be easy for all +applications to satisfy.

+ +

This class is appropriate for applications that need to store +large "dictionaries" in memory, or for applications that need these +dictionaries to be persistent.

+ + +

Example

+ +(Note: this example uses SGI semantics for hash<> +-- the kind used by gcc and most Unix compiler suites -- and not +Dinkumware semantics -- the kind used by Microsoft Visual Studio. If +you are using MSVC, this example will not compile as-is: you'll need +to change hash to hash_compare, and you +won't use eqstr at all. See the MSVC documentation for +hash_map and hash_compare, for more +details.) + +
+#include <iostream>
+#include <google/sparse_hash_map>
+
+using google::sparse_hash_map;      // namespace where class lives by default
+using std::cout;
+using std::endl;
+using ext::hash;  // or __gnu_cxx::hash, or maybe tr1::hash, depending on your OS
+
+struct eqstr
+{
+  bool operator()(const char* s1, const char* s2) const
+  {
+    return (s1 == s2) || (s1 && s2 && strcmp(s1, s2) == 0);
+  }
+};
+
+int main()
+{
+  sparse_hash_map<const char*, int, hash<const char*>, eqstr> months;
+  
+  months["january"] = 31;
+  months["february"] = 28;
+  months["march"] = 31;
+  months["april"] = 30;
+  months["may"] = 31;
+  months["june"] = 30;
+  months["july"] = 31;
+  months["august"] = 31;
+  months["september"] = 30;
+  months["october"] = 31;
+  months["november"] = 30;
+  months["december"] = 31;
+  
+  cout << "september -> " << months["september"] << endl;
+  cout << "april     -> " << months["april"] << endl;
+  cout << "june      -> " << months["june"] << endl;
+  cout << "november  -> " << months["november"] << endl;
+}
+
+ + +

Definition

+ +Defined in the header sparse_hash_map. +This class is not part of the C++ standard, though it is mostly +compatible with the tr1 class unordered_map. + + +

Template parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescriptionDefault
+ Key + + The hash_map's key type. This is also defined as + sparse_hash_map::key_type. + +   +
+ Data + + The hash_map's data type. This is also defined as + sparse_hash_map::data_type. + +   +
+ HashFcn + + The hash function used by the + hash_map. This is also defined as sparse_hash_map::hasher. +
Note: Hashtable performance depends heavliy on the choice of + hash function. See the performance + page for more information. +
+ hash<Key> +
+ EqualKey + + The hash_map key equality function: a binary predicate that determines + whether two keys are equal. This is also defined as + sparse_hash_map::key_equal. + + equal_to<Key> +
+ Alloc + + Ignored; this is included only for API-compatibility + with SGI's (and tr1's) STL implementation. + +
+ + +

Model of

+ +Unique Hashed Associative Container, +Pair Associative Container + + +

Type requirements

+ +
    +
  • +Key is Assignable. +
  • +EqualKey is a Binary Predicate whose argument type is Key. +
  • +EqualKey is an equivalence relation. +
  • +Alloc is an Allocator. +
+ + +

Public base classes

+ +None. + + +

Members

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberWhere definedDescription
+ key_type + + Associative + Container + + The sparse_hash_map's key type, Key. +
+ data_type + + Pair + Associative Container + + The type of object associated with the keys. +
+ value_type + + Pair + Associative Container + + The type of object, pair<const key_type, data_type>, + stored in the hash_map. +
+ hasher + + Hashed + Associative Container + + The sparse_hash_map's hash + function. +
+ key_equal + + Hashed + Associative Container + + Function + object that compares keys for equality. +
+ allocator_type + + Unordered Associative Container (tr1) + + The type of the Allocator given as a template parameter. +
+ pointer + + Container + + Pointer to T. +
+ reference + + Container + + Reference to T +
+ const_reference + + Container + + Const reference to T +
+ size_type + + Container + + An unsigned integral type. +
+ difference_type + + Container + + A signed integral type. +
+ iterator + + Container + + Iterator used to iterate through a sparse_hash_map. [1] +
+ const_iterator + + Container + + Const iterator used to iterate through a sparse_hash_map. +
+ local_iterator + + Unordered Associative Container (tr1) + + Iterator used to iterate through a subset of + sparse_hash_map. [1] +
+ const_local_iterator + + Unordered Associative Container (tr1) + + Const iterator used to iterate through a subset of + sparse_hash_map. +
+ iterator begin() + + Container + + Returns an iterator pointing to the beginning of the + sparse_hash_map. +
+ iterator end() + + Container + + Returns an iterator pointing to the end of the + sparse_hash_map. +
+ const_iterator begin() const + + Container + + Returns an const_iterator pointing to the beginning of the + sparse_hash_map. +
+ const_iterator end() const + + Container + + Returns an const_iterator pointing to the end of the + sparse_hash_map. +
+ local_iterator begin(size_type i) + + Unordered Associative Container (tr1) + + Returns a local_iterator pointing to the beginning of bucket + i in the sparse_hash_map. +
+ local_iterator end(size_type i) + + Unordered Associative Container (tr1) + + Returns a local_iterator pointing to the end of bucket + i in the sparse_hash_map. For + sparse_hash_map, each bucket contains either 0 or 1 item. +
+ const_local_iterator begin(size_type i) const + + Unordered Associative Container (tr1) + + Returns a const_local_iterator pointing to the beginning of bucket + i in the sparse_hash_map. +
+ const_local_iterator end(size_type i) const + + Unordered Associative Container (tr1) + + Returns a const_local_iterator pointing to the end of bucket + i in the sparse_hash_map. For + sparse_hash_map, each bucket contains either 0 or 1 item. +
+ size_type size() const + + Container + + Returns the size of the sparse_hash_map. +
+ size_type max_size() const + + Container + + Returns the largest possible size of the sparse_hash_map. +
+ bool empty() const + + Container + + true if the sparse_hash_map's size is 0. +
+ size_type bucket_count() const + + Hashed + Associative Container + + Returns the number of buckets used by the sparse_hash_map. +
+ size_type max_bucket_count() const + + Hashed + Associative Container + + Returns the largest possible number of buckets used by the sparse_hash_map. +
+ size_type bucket_size(size_type i) const + + Unordered Associative Container (tr1) + + Returns the number of elements in bucket i. For + sparse_hash_map, this will be either 0 or 1. +
+ size_type bucket(const key_type& key) const + + Unordered Associative Container (tr1) + + If the key exists in the map, returns the index of the bucket + containing the given key, otherwise, return the bucket the key + would be inserted into. + This value may be passed to begin(size_type) and + end(size_type). +
+ float load_factor() const + + Unordered Associative Container (tr1) + + The number of elements in the sparse_hash_map divided by + the number of buckets. +
+ float max_load_factor() const + + Unordered Associative Container (tr1) + + The maximum load factor before increasing the number of buckets in + the sparse_hash_map. +
+ void max_load_factor(float new_grow) + + Unordered Associative Container (tr1) + + Sets the maximum load factor before increasing the number of + buckets in the sparse_hash_map. +
+ float min_load_factor() const + + sparse_hash_map + + The minimum load factor before decreasing the number of buckets in + the sparse_hash_map. +
+ void min_load_factor(float new_grow) + + sparse_hash_map + + Sets the minimum load factor before decreasing the number of + buckets in the sparse_hash_map. +
+ void set_resizing_parameters(float shrink, float grow) + + sparse_hash_map + + DEPRECATED. See below. +
+ void resize(size_type n) + + Hashed + Associative Container + + Increases the bucket count to hold at least n items. + [4] [5] +
+ void rehash(size_type n) + + Unordered Associative Container (tr1) + + Increases the bucket count to hold at least n items. + This is identical to resize. + [4] [5] +
+ hasher hash_funct() const + + Hashed + Associative Container + + Returns the hasher object used by the sparse_hash_map. +
+ hasher hash_function() const + + Unordered Associative Container (tr1) + + Returns the hasher object used by the sparse_hash_map. + This is idential to hash_funct. +
+ key_equal key_eq() const + + Hashed + Associative Container + + Returns the key_equal object used by the + sparse_hash_map. +
+ sparse_hash_map() + + Container + + Creates an empty sparse_hash_map. +
+ sparse_hash_map(size_type n) + + Hashed + Associative Container + + Creates an empty sparse_hash_map that's optimized for holding + up to n items. + [5] +
+ sparse_hash_map(size_type n, const hasher& h) + + Hashed + Associative Container + + Creates an empty sparse_hash_map that's optimized for up + to n items, using h as the hash function. +
+ sparse_hash_map(size_type n, const hasher& h, const + key_equal& k) + + Hashed + Associative Container + + Creates an empty sparse_hash_map that's optimized for up + to n items, using h as the hash function and + k as the key equal function. +
+
template <class InputIterator>
+sparse_hash_map(InputIterator f, InputIterator l) 
+[2] +
+ Unique + Hashed Associative Container + + Creates a sparse_hash_map with a copy of a range. +
+
template <class InputIterator>
+sparse_hash_map(InputIterator f, InputIterator l, size_type n) 
+[2] +
+ Unique + Hashed Associative Container + + Creates a hash_map with a copy of a range that's optimized to + hold up to n items. +
+
template <class InputIterator>
+sparse_hash_map(InputIterator f, InputIterator l, size_type n, const
+hasher& h) 
[2] +
+ Unique + Hashed Associative Container + + Creates a hash_map with a copy of a range that's optimized to hold + up to n items, using h as the hash function. +
+
template <class InputIterator>
+sparse_hash_map(InputIterator f, InputIterator l, size_type n, const
+hasher& h, const key_equal& k) 
[2] +
+ Unique + Hashed Associative Container + + Creates a hash_map with a copy of a range that's optimized for + holding up to n items, using h as the hash + function and k as the key equal function. +
+ sparse_hash_map(const hash_map&) + + Container + + The copy constructor. +
+ sparse_hash_map& operator=(const hash_map&) + + Container + + The assignment operator +
+ void swap(hash_map&) + + Container + + Swaps the contents of two hash_maps. +
+
pair<iterator, bool> insert(const value_type& x)
+
+
+ Unique + Associative Container + + Inserts x into the sparse_hash_map. +
+
template <class InputIterator>
+void insert(InputIterator f, InputIterator l) 
[2] +
+ Unique + Associative Container + + Inserts a range into the sparse_hash_map. +
+ void set_deleted_key(const key_type& key) [6] + + sparse_hash_map + + See below. +
+ void clear_deleted_key() [6] + + sparse_hash_map + + See below. +
+ void erase(iterator pos) + + Associative + Container + + Erases the element pointed to by pos. + [6] +
+ size_type erase(const key_type& k) + + Associative + Container + + Erases the element whose key is k. + [6] +
+ void erase(iterator first, iterator last) + + Associative + Container + + Erases all elements in a range. + [6] +
+ void clear() + + Associative + Container + + Erases all of the elements. +
+ const_iterator find(const key_type& k) const + + Associative + Container + + Finds an element whose key is k. +
+ iterator find(const key_type& k) + + Associative + Container + + Finds an element whose key is k. +
+ size_type count(const key_type& k) const + + Unique + Associative Container + + Counts the number of elements whose key is k. +
+
pair<const_iterator, const_iterator> equal_range(const
+key_type& k) const 
+
+ Associative + Container + + Finds a range containing all elements whose key is k. +
+
pair<iterator, iterator> equal_range(const
+key_type& k) 
+
+ Associative + Container + + Finds a range containing all elements whose key is k. +
+
data_type& operator[](const key_type& k) [3] 
+
+ sparse_hash_map + + See below. +
+ bool write_metadata(FILE *fp) + + sparse_hash_map + + See below. +
+ bool read_metadata(FILE *fp) + + sparse_hash_map + + See below. +
+ bool write_nopointer_data(FILE *fp) + + sparse_hash_map + + See below. +
+ bool read_nopointer_data(FILE *fp) + + sparse_hash_map + + See below. +
+
bool operator==(const hash_map&, const hash_map&)
+
+
+ Hashed + Associative Container + + Tests two hash_maps for equality. This is a global function, not a + member function. +
+ + +

New members

+ +These members are not defined in the Unique +Hashed Associative Container, Pair +Associative Container, or tr1's +Unordered Associative Container requirements, +but are specific to sparse_hash_map. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberDescription
+ void set_deleted_key(const key_type& key) + + Sets the distinguished "deleted" key to key. This must be + called before any calls to erase(). [6] +
+ void clear_deleted_key() + + Clears the distinguished "deleted" key. After this is called, + calls to erase() are not valid on this object. + [6] +
+
+data_type& 
+operator[](const key_type& k) [3]
+
+
+ Returns a reference to the object that is associated with + a particular key. If the sparse_hash_map does not already + contain such an object, operator[] inserts the default + object data_type(). [3] +
+ void set_resizing_parameters(float shrink, float grow) + + This function is DEPRECATED. It is equivalent to calling + min_load_factor(shrink); max_load_factor(grow). +
+ bool write_metadata(FILE *fp) + + Write hashtable metadata to fp. See below. +
+ bool read_metadata(FILE *fp) + + Read hashtable metadata from fp. See below. +
+ bool write_nopointer_data(FILE *fp) + + Write hashtable contents to fp. This is valid only if the + hashtable key and value are "plain" data. See below. +
+ bool read_nopointer_data(FILE *fp) + + Read hashtable contents to fp. This is valid only if the + hashtable key and value are "plain" data. See below. +
+ + +

Notes

+ +

[1] + +sparse_hash_map::iterator is not a mutable iterator, because +sparse_hash_map::value_type is not Assignable. +That is, if i is of type sparse_hash_map::iterator +and p is of type sparse_hash_map::value_type, then +*i = p is not a valid expression. However, +sparse_hash_map::iterator isn't a constant iterator either, +because it can be used to modify the object that it points to. Using +the same notation as above, (*i).second = p is a valid +expression.

+ +

[2] + +This member function relies on member template functions, which +may not be supported by all compilers. If your compiler supports +member templates, you can call this function with any type of input +iterator. If your compiler does not yet support member templates, +though, then the arguments must either be of type const +value_type* or of type sparse_hash_map::const_iterator.

+ +

[3] + +Since operator[] might insert a new element into the +sparse_hash_map, it can't possibly be a const member +function. Note that the definition of operator[] is +extremely simple: m[k] is equivalent to +(*((m.insert(value_type(k, data_type()))).first)).second. +Strictly speaking, this member function is unnecessary: it exists only +for convenience.

+ +

[4] + +In order to preserve iterators, erasing hashtable elements does not +cause a hashtable to resize. This means that after a string of +erase() calls, the hashtable will use more space than is +required. At a cost of invalidating all current iterators, you can +call resize() to manually compact the hashtable. The +hashtable promotes too-small resize() arguments to the +smallest legal value, so to compact a hashtable, it's sufficient to +call resize(0). + +

[5] + +Unlike some other hashtable implementations, the optional n in +the calls to the constructor, resize, and rehash +indicates not the desired number of buckets that +should be allocated, but instead the expected number of items to be +inserted. The class then sizes the hash-map appropriately for the +number of items specified. It's not an error to actually insert more +or fewer items into the hashtable, but the implementation is most +efficient -- does the fewest hashtable resizes -- if the number of +inserted items is n or slightly less.

+ +

[6] + +sparse_hash_map requires you call +set_deleted_key() before calling erase(). (This is +the largest difference between the sparse_hash_map API and +other hash-map APIs. See implementation.html +for why this is necessary.) +The argument to set_deleted_key() should be a key-value that +is never used for legitimate hash-map entries. It is an error to call +erase() without first calling set_deleted_key(), and +it is also an error to call insert() with an item whose key +is the "deleted key."

+ +

There is no need to call set_deleted_key if you do not +wish to call erase() on the hash-map.

+ +

It is acceptable to change the deleted-key at any time by calling +set_deleted_key() with a new argument. You can also call +clear_deleted_key(), at which point all keys become valid for +insertion but no hashtable entries can be deleted until +set_deleted_key() is called again.

+ +

Note: If you use set_deleted_key, it is also +necessary that data_type has a zero-argument default +constructor. This is because sparse_hash_map uses the +special value pair(deleted_key, data_type()) to denote +deleted buckets, and thus needs to be able to create +data_type using a zero-argument constructor.

+ +

If your data_type does not have a zero-argument default +constructor, there are several workarounds:

+
    +
  • Store a pointer to data_type in the map, instead of + data_type directly. This may yield faster code as + well, since hashtable-resizes will just have to move pointers + around, rather than copying the entire data_type. +
  • Add a zero-argument default constructor to data_type. +
  • Subclass data_type and add a zero-argument default + constructor to the subclass. +
+ +

If you do not use set_deleted_key, then there is no +requirement that data_type havea zero-argument default +constructor. + + +

Input/Output

+ +

It is possible to save and restore sparse_hash_map objects +to disk. Storage takes place in two steps. The first writes the +hashtable metadata. The second writes the actual data.

+ +

To write a hashtable to disk, first call write_metadata() +on an open file pointer. This saves the hashtable information in a +byte-order-independent format.

+ +

After the metadata has been written to disk, you must write the +actual data stored in the hash-map to disk. If both the key and data +are "simple" enough, you can do this by calling +write_nopointer_data(). "Simple" data is data that can be +safely copied to disk via fwrite(). Native C data types fall +into this category, as do structs of native C data types. Pointers +and STL objects do not.

+ +

Note that write_nopointer_data() does not do any endian +conversion. Thus, it is only appropriate when you intend to read the +data on the same endian architecture as you write the data.

+ +

If you cannot use write_nopointer_data() for any reason, +you can write the data yourself by iterating over the +sparse_hash_map with a const_iterator and writing +the key and data in any manner you wish.

+ +

To read the hashtable information from disk, first you must create +a sparse_hash_map object. Then open a file pointer to point +to the saved hashtable, and call read_metadata(). If you +saved the data via write_nopointer_data(), you can follow the +read_metadata() call with a call to +read_nopointer_data(). This is all that is needed.

+ +

If you saved the data through a custom write routine, you must call +a custom read routine to read in the data. To do this, iterate over +the sparse_hash_map with an iterator; this operation +is sensical because the metadata has already been set up. For each +iterator item, you can read the key and value from disk, and set it +appropriately. You will need to do a const_cast on the +iterator, since it->first is always const. You +will also need to use placement-new if the key or value is a C++ +object. The code might look like this:

+
+   for (sparse_hash_map<int*, ComplicatedClass>::iterator it = ht.begin();
+        it != ht.end(); ++it) {
+       // The key is stored in the sparse_hash_map as a pointer
+       const_cast<int*>(it->first) = new int;
+       fread(const_cast<int*>(it->first), sizeof(int), 1, fp);
+       // The value is a complicated C++ class that takes an int to construct
+       int ctor_arg;
+       fread(&ctor_arg, sizeof(int), 1, fp);
+       new (&it->second) ComplicatedClass(ctor_arg);  // "placement new"
+   }
+
+ + +

Validity of Iterators

+ +

erase() is guaranteed not to invalidate any iterators -- +except for any iterators pointing to the item being erased, of course. +insert() invalidates all iterators, as does +resize().

+ +

This is implemented by making erase() not resize the +hashtable. If you desire maximum space efficiency, you can call +resize(0) after a string of erase() calls, to force +the hashtable to resize to the smallest possible size.

+ +

In addition to invalidating iterators, insert() +and resize() invalidate all pointers into the hashtable. If +you want to store a pointer to an object held in a sparse_hash_map, +either do so after finishing hashtable inserts, or store the object on +the heap and a pointer to it in the sparse_hash_map.

+ + +

See also

+ +

The following are SGI STL, and some Google STL, concepts and +classes related to sparse_hash_map.

+ +hash_map, +Associative Container, +Hashed Associative Container, +Pair Associative Container, +Unique Hashed Associative Container, +set, +map +multiset, +multimap, +hash_set, +hash_multiset, +hash_multimap, +sparsetable, +sparse_hash_set, +dense_hash_set, +dense_hash_map + + + diff --git a/src/sparsehash-1.6/doc/sparse_hash_set.html b/src/sparsehash-1.6/doc/sparse_hash_set.html new file mode 100644 index 0000000..70c7721 --- /dev/null +++ b/src/sparsehash-1.6/doc/sparse_hash_set.html @@ -0,0 +1,1376 @@ + + + + + +sparse_hash_set<Key, HashFcn, EqualKey, Alloc> + + + + +

[Note: this document is formatted similarly to the SGI STL +implementation documentation pages, and refers to concepts and classes +defined there. However, neither this document nor the code it +describes is associated with SGI, nor is it necessary to have SGI's +STL implementation installed in order to use this class.]

+ + +

sparse_hash_set<Key, HashFcn, EqualKey, Alloc>

+ +

sparse_hash_set is a Hashed +Associative Container that stores objects of type Key. +sparse_hash_set is a Simple +Associative Container, meaning that its value type, as well as its +key type, is key. It is also a +Unique +Associative Container, meaning that no two elements have keys that +compare equal using EqualKey.

+ +

Looking up an element in a sparse_hash_set by its key is +efficient, so sparse_hash_set is useful for "dictionaries" +where the order of elements is irrelevant. If it is important for the +elements to be in a particular order, however, then map is more appropriate.

+ +

sparse_hash_set is distinguished from other hash-set +implementations by its stingy use of memory and by the ability to save +and restore contents to disk. On the other hand, this hash-set +implementation, while still efficient, is slower than other hash-set +implementations, and it also has requirements -- for instance, for a +distinguished "deleted key" -- that may not be easy for all +applications to satisfy.

+ +

This class is appropriate for applications that need to store +large "dictionaries" in memory, or for applications that need these +dictionaries to be persistent.

+ + +

Example

+ +(Note: this example uses SGI semantics for hash<> +-- the kind used by gcc and most Unix compiler suites -- and not +Dinkumware semantics -- the kind used by Microsoft Visual Studio. If +you are using MSVC, this example will not compile as-is: you'll need +to change hash to hash_compare, and you +won't use eqstr at all. See the MSVC documentation for +hash_map and hash_compare, for more +details.) + +
+#include <iostream>
+#include <google/sparse_hash_set>
+
+using google::sparse_hash_set;      // namespace where class lives by default
+using std::cout;
+using std::endl;
+using ext::hash;  // or __gnu_cxx::hash, or maybe tr1::hash, depending on your OS
+
+struct eqstr
+{
+  bool operator()(const char* s1, const char* s2) const
+  {
+    return (s1 == s2) || (s1 && s2 && strcmp(s1, s2) == 0);
+  }
+};
+
+void lookup(const hash_set<const char*, hash<const char*>, eqstr>& Set,
+            const char* word)
+{
+  sparse_hash_set<const char*, hash<const char*>, eqstr>::const_iterator it
+    = Set.find(word);
+  cout << word << ": "
+       << (it != Set.end() ? "present" : "not present")
+       << endl;
+}
+
+int main()
+{
+  sparse_hash_set<const char*, hash<const char*>, eqstr> Set;
+  Set.insert("kiwi");
+  Set.insert("plum");
+  Set.insert("apple");
+  Set.insert("mango");
+  Set.insert("apricot");
+  Set.insert("banana");
+
+  lookup(Set, "mango");
+  lookup(Set, "apple");
+  lookup(Set, "durian");
+}
+
+ + +

Definition

+ +Defined in the header sparse_hash_set. +This class is not part of the C++ standard, though it is mostly +compatible with the tr1 class unordered_set. + + +

Template parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescriptionDefault
+ Key + + The hash_set's key and value type. This is also defined as + sparse_hash_set::key_type and + sparse_hash_set::value_type. + +   +
+ HashFcn + + The hash function used by the + hash_set. This is also defined as sparse_hash_set::hasher. +
Note: Hashtable performance depends heavliy on the choice of + hash function. See the performance + page for more information. +
+ hash<Key> +
+ EqualKey + + The hash_set key equality function: a binary predicate that determines + whether two keys are equal. This is also defined as + sparse_hash_set::key_equal. + + equal_to<Key> +
+ Alloc + + Ignored; this is included only for API-compatibility + with SGI's (and tr1's) STL implementation. + +
+ + +

Model of

+ +Unique Hashed Associative Container, +Simple Associative Container + + +

Type requirements

+ +
    +
  • +Key is Assignable. +
  • +EqualKey is a Binary Predicate whose argument type is Key. +
  • +EqualKey is an equivalence relation. +
  • +Alloc is an Allocator. +
+ + +

Public base classes

+ +None. + + +

Members

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberWhere definedDescription
+ value_type + + Container + + The type of object, T, stored in the hash_set. +
+ key_type + + Associative + Container + + The key type associated with value_type. +
+ hasher + + Hashed + Associative Container + + The sparse_hash_set's hash + function. +
+ key_equal + + Hashed + Associative Container + + Function + object that compares keys for equality. +
+ allocator_type + + Unordered Associative Container (tr1) + + The type of the Allocator given as a template parameter. +
+ pointer + + Container + + Pointer to T. +
+ reference + + Container + + Reference to T +
+ const_reference + + Container + + Const reference to T +
+ size_type + + Container + + An unsigned integral type. +
+ difference_type + + Container + + A signed integral type. +
+ iterator + + Container + + Iterator used to iterate through a sparse_hash_set. +
+ const_iterator + + Container + + Const iterator used to iterate through a sparse_hash_set. + (iterator and const_iterator are the same type.) +
+ local_iterator + + Unordered Associative Container (tr1) + + Iterator used to iterate through a subset of + sparse_hash_set. +
+ const_local_iterator + + Unordered Associative Container (tr1) + + Const iterator used to iterate through a subset of + sparse_hash_set. +
+ iterator begin() const + + Container + + Returns an iterator pointing to the beginning of the + sparse_hash_set. +
+ iterator end() const + + Container + + Returns an iterator pointing to the end of the + sparse_hash_set. +
+ local_iterator begin(size_type i) + + Unordered Associative Container (tr1) + + Returns a local_iterator pointing to the beginning of bucket + i in the sparse_hash_set. +
+ local_iterator end(size_type i) + + Unordered Associative Container (tr1) + + Returns a local_iterator pointing to the end of bucket + i in the sparse_hash_set. For + sparse_hash_set, each bucket contains either 0 or 1 item. +
+ const_local_iterator begin(size_type i) const + + Unordered Associative Container (tr1) + + Returns a const_local_iterator pointing to the beginning of bucket + i in the sparse_hash_set. +
+ const_local_iterator end(size_type i) const + + Unordered Associative Container (tr1) + + Returns a const_local_iterator pointing to the end of bucket + i in the sparse_hash_set. For + sparse_hash_set, each bucket contains either 0 or 1 item. +
+ size_type size() const + + Container + + Returns the size of the sparse_hash_set. +
+ size_type max_size() const + + Container + + Returns the largest possible size of the sparse_hash_set. +
+ bool empty() const + + Container + + true if the sparse_hash_set's size is 0. +
+ size_type bucket_count() const + + Hashed + Associative Container + + Returns the number of buckets used by the sparse_hash_set. +
+ size_type max_bucket_count() const + + Hashed + Associative Container + + Returns the largest possible number of buckets used by the sparse_hash_set. +
+ size_type bucket_size(size_type i) const + + Unordered Associative Container (tr1) + + Returns the number of elements in bucket i. For + sparse_hash_set, this will be either 0 or 1. +
+ size_type bucket(const key_type& key) const + + Unordered Associative Container (tr1) + + If the key exists in the map, returns the index of the bucket + containing the given key, otherwise, return the bucket the key + would be inserted into. + This value may be passed to begin(size_type) and + end(size_type). +
+ float load_factor() const + + Unordered Associative Container (tr1) + + The number of elements in the sparse_hash_set divided by + the number of buckets. +
+ float max_load_factor() const + + Unordered Associative Container (tr1) + + The maximum load factor before increasing the number of buckets in + the sparse_hash_set. +
+ void max_load_factor(float new_grow) + + Unordered Associative Container (tr1) + + Sets the maximum load factor before increasing the number of + buckets in the sparse_hash_set. +
+ float min_load_factor() const + + sparse_hash_set + + The minimum load factor before decreasing the number of buckets in + the sparse_hash_set. +
+ void min_load_factor(float new_grow) + + sparse_hash_set + + Sets the minimum load factor before decreasing the number of + buckets in the sparse_hash_set. +
+ void set_resizing_parameters(float shrink, float grow) + + sparse_hash_set + + DEPRECATED. See below. +
+ void resize(size_type n) + + Hashed + Associative Container + + Increases the bucket count to hold at least n items. + [2] [3] +
+ void rehash(size_type n) + + Unordered Associative Container (tr1) + + Increases the bucket count to hold at least n items. + This is identical to resize. + [2] [3] +
+ hasher hash_funct() const + + Hashed + Associative Container + + Returns the hasher object used by the sparse_hash_set. +
+ hasher hash_function() const + + Unordered Associative Container (tr1) + + Returns the hasher object used by the sparse_hash_set. + This is idential to hash_funct. +
+ key_equal key_eq() const + + Hashed + Associative Container + + Returns the key_equal object used by the + sparse_hash_set. +
+ sparse_hash_set() + + Container + + Creates an empty sparse_hash_set. +
+ sparse_hash_set(size_type n) + + Hashed + Associative Container + + Creates an empty sparse_hash_set that's optimized for holding + up to n items. + [3] +
+ sparse_hash_set(size_type n, const hasher& h) + + Hashed + Associative Container + + Creates an empty sparse_hash_set that's optimized for up + to n items, using h as the hash function. +
+ sparse_hash_set(size_type n, const hasher& h, const + key_equal& k) + + Hashed + Associative Container + + Creates an empty sparse_hash_set that's optimized for up + to n items, using h as the hash function and + k as the key equal function. +
+
template <class InputIterator>
+sparse_hash_set(InputIterator f, InputIterator l) 
+[2] +
+ Unique + Hashed Associative Container + + Creates a sparse_hash_set with a copy of a range. +
+
template <class InputIterator>
+sparse_hash_set(InputIterator f, InputIterator l, size_type n) 
+[2] +
+ Unique + Hashed Associative Container + + Creates a hash_set with a copy of a range that's optimized to + hold up to n items. +
+
template <class InputIterator>
+sparse_hash_set(InputIterator f, InputIterator l, size_type n, const
+hasher& h) 
[2] +
+ Unique + Hashed Associative Container + + Creates a hash_set with a copy of a range that's optimized to hold + up to n items, using h as the hash function. +
+
template <class InputIterator>
+sparse_hash_set(InputIterator f, InputIterator l, size_type n, const
+hasher& h, const key_equal& k) 
[2] +
+ Unique + Hashed Associative Container + + Creates a hash_set with a copy of a range that's optimized for + holding up to n items, using h as the hash + function and k as the key equal function. +
+ sparse_hash_set(const hash_set&) + + Container + + The copy constructor. +
+ sparse_hash_set& operator=(const hash_set&) + + Container + + The assignment operator +
+ void swap(hash_set&) + + Container + + Swaps the contents of two hash_sets. +
+
pair<iterator, bool> insert(const value_type& x)
+
+
+ Unique + Associative Container + + Inserts x into the sparse_hash_set. +
+
template <class InputIterator>
+void insert(InputIterator f, InputIterator l) 
[2] +
+ Unique + Associative Container + + Inserts a range into the sparse_hash_set. +
+ void set_deleted_key(const key_type& key) [4] + + sparse_hash_set + + See below. +
+ void clear_deleted_key() [4] + + sparse_hash_set + + See below. +
+ void erase(iterator pos) + + Associative + Container + + Erases the element pointed to by pos. + [4] +
+ size_type erase(const key_type& k) + + Associative + Container + + Erases the element whose key is k. + [4] +
+ void erase(iterator first, iterator last) + + Associative + Container + + Erases all elements in a range. + [4] +
+ void clear() + + Associative + Container + + Erases all of the elements. +
+ iterator find(const key_type& k) const + + Associative + Container + + Finds an element whose key is k. +
+ size_type count(const key_type& k) const + + Unique + Associative Container + + Counts the number of elements whose key is k. +
+
pair<iterator, iterator> equal_range(const
+key_type& k) const
+
+ Associative + Container + + Finds a range containing all elements whose key is k. +
+ bool write_metadata(FILE *fp) + + sparse_hash_set + + See below. +
+ bool read_metadata(FILE *fp) + + sparse_hash_set + + See below. +
+ bool write_nopointer_data(FILE *fp) + + sparse_hash_set + + See below. +
+ bool read_nopointer_data(FILE *fp) + + sparse_hash_set + + See below. +
+
bool operator==(const hash_set&, const hash_set&)
+
+
+ Hashed + Associative Container + + Tests two hash_sets for equality. This is a global function, not a + member function. +
+ + +

New members

+ +These members are not defined in the Unique +Hashed Associative Container, Simple +Associative Container, or tr1's Unordered Associative +Container requirements, but are specific to +sparse_hash_set. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberDescription
+ void set_deleted_key(const key_type& key) + + Sets the distinguished "deleted" key to key. This must be + called before any calls to erase(). [4] +
+ void clear_deleted_key() + + Clears the distinguished "deleted" key. After this is called, + calls to erase() are not valid on this object. + [4] +
+ void set_resizing_parameters(float shrink, float grow) + + This function is DEPRECATED. It is equivalent to calling + min_load_factor(shrink); max_load_factor(grow). +
+ bool write_metadata(FILE *fp) + + Write hashtable metadata to fp. See below. +
+ bool read_metadata(FILE *fp) + + Read hashtable metadata from fp. See below. +
+ bool write_nopointer_data(FILE *fp) + + Write hashtable contents to fp. This is valid only if the + hashtable key and value are "plain" data. See below. +
+ bool read_nopointer_data(FILE *fp) + + Read hashtable contents to fp. This is valid only if the + hashtable key and value are "plain" data. See below. +
+ + +

Notes

+ +

[1] + +This member function relies on member template functions, which +may not be supported by all compilers. If your compiler supports +member templates, you can call this function with any type of input +iterator. If your compiler does not yet support member templates, +though, then the arguments must either be of type const +value_type* or of type sparse_hash_set::const_iterator.

+ +

[2] + +In order to preserve iterators, erasing hashtable elements does not +cause a hashtable to resize. This means that after a string of +erase() calls, the hashtable will use more space than is +required. At a cost of invalidating all current iterators, you can +call resize() to manually compact the hashtable. The +hashtable promotes too-small resize() arguments to the +smallest legal value, so to compact a hashtable, it's sufficient to +call resize(0). + +

[3] + +Unlike some other hashtable implementations, the optional n in +the calls to the constructor, resize, and rehash +indicates not the desired number of buckets that +should be allocated, but instead the expected number of items to be +inserted. The class then sizes the hash-set appropriately for the +number of items specified. It's not an error to actually insert more +or fewer items into the hashtable, but the implementation is most +efficient -- does the fewest hashtable resizes -- if the number of +inserted items is n or slightly less.

+ +

[4] + +sparse_hash_set requires you call +set_deleted_key() before calling erase(). (This is +the largest difference between the sparse_hash_set API and +other hash-set APIs. See implementation.html +for why this is necessary.) +The argument to set_deleted_key() should be a key-value that +is never used for legitimate hash-set entries. It is an error to call +erase() without first calling set_deleted_key(), and +it is also an error to call insert() with an item whose key +is the "deleted key."

+ +

There is no need to call set_deleted_key if you do not +wish to call erase() on the hash-set.

+ +

It is acceptable to change the deleted-key at any time by calling +set_deleted_key() with a new argument. You can also call +clear_deleted_key(), at which point all keys become valid for +insertion but no hashtable entries can be deleted until +set_deleted_key() is called again.

+ + +

Input/Output

+ +

It is possible to save and restore sparse_hash_set objects +to disk. Storage takes place in two steps. The first writes the +hashtable metadata. The second writes the actual data.

+ +

To write a hashtable to disk, first call write_metadata() +on an open file pointer. This saves the hashtable information in a +byte-order-independent format.

+ +

After the metadata has been written to disk, you must write the +actual data stored in the hash-set to disk. If both the key and data +are "simple" enough, you can do this by calling +write_nopointer_data(). "Simple" data is data that can be +safely copied to disk via fwrite(). Native C data types fall +into this category, as do structs of native C data types. Pointers +and STL objects do not.

+ +

Note that write_nopointer_data() does not do any endian +conversion. Thus, it is only appropriate when you intend to read the +data on the same endian architecture as you write the data.

+ +

If you cannot use write_nopointer_data() for any reason, +you can write the data yourself by iterating over the +sparse_hash_set with a const_iterator and writing +the key and data in any manner you wish.

+ +

To read the hashtable information from disk, first you must create +a sparse_hash_set object. Then open a file pointer to point +to the saved hashtable, and call read_metadata(). If you +saved the data via write_nopointer_data(), you can follow the +read_metadata() call with a call to +read_nopointer_data(). This is all that is needed.

+ +

If you saved the data through a custom write routine, you must call +a custom read routine to read in the data. To do this, iterate over +the sparse_hash_set with an iterator; this operation +is sensical because the metadata has already been set up. For each +iterator item, you can read the key and value from disk, and set it +appropriately. You will need to do a const_cast on the +iterator, since *it is always const. The +code might look like this:

+
+   for (sparse_hash_set<int*>::iterator it = ht.begin();
+        it != ht.end(); ++it) {
+       const_cast<int*>(*it) = new int;
+       fread(const_cast<int*>(*it), sizeof(int), 1, fp);
+   }
+
+ +

Here's another example, where the item stored in the hash-set is +a C++ object with a non-trivial constructor. In this case, you must +use "placement new" to construct the object at the correct memory +location.

+
+   for (sparse_hash_set<ComplicatedClass>::iterator it = ht.begin();
+        it != ht.end(); ++it) {
+       int ctor_arg;  // ComplicatedClass takes an int as its constructor arg
+       fread(&ctor_arg, sizeof(int), 1, fp);
+       new (const_cast<ComplicatedClass*>(&(*it))) ComplicatedClass(ctor_arg);
+   }
+
+ + +

Validity of Iterators

+ +

erase() is guaranteed not to invalidate any iterators -- +except for any iterators pointing to the item being erased, of course. +insert() invalidates all iterators, as does +resize().

+ +

This is implemented by making erase() not resize the +hashtable. If you desire maximum space efficiency, you can call +resize(0) after a string of erase() calls, to force +the hashtable to resize to the smallest possible size.

+ +

In addition to invalidating iterators, insert() +and resize() invalidate all pointers into the hashtable. If +you want to store a pointer to an object held in a sparse_hash_set, +either do so after finishing hashtable inserts, or store the object on +the heap and a pointer to it in the sparse_hash_set.

+ + +

See also

+ +

The following are SGI STL, and some Google STL, concepts and +classes related to sparse_hash_set.

+ +hash_set, +Associative Container, +Hashed Associative Container, +Simple Associative Container, +Unique Hashed Associative Container, +set, +map +multiset, +multimap, +hash_map, +hash_multiset, +hash_multimap, +sparsetable, +sparse_hash_map, +dense_hash_set, +dense_hash_map + + + diff --git a/src/sparsehash-1.6/doc/sparsetable.html b/src/sparsehash-1.6/doc/sparsetable.html new file mode 100644 index 0000000..d8c8364 --- /dev/null +++ b/src/sparsehash-1.6/doc/sparsetable.html @@ -0,0 +1,1393 @@ + + + + + +sparsetable<T, GROUP_SIZE> + + + + +

[Note: this document is formatted similarly to the SGI STL +implementation documentation pages, and refers to concepts and classes +defined there. However, neither this document nor the code it +describes is associated with SGI, nor is it necessary to have SGI's +STL implementation installed in order to use this class.]

+ +

sparsetable<T, GROUP_SIZE>

+ +

A sparsetable is a Random +Access Container that supports constant time random access to +elements, and constant time insertion and removal of elements. It +implements the "array" or "table" abstract data type. The number of +elements in a sparsetable is set at constructor time, though +you can change it at any time by calling resize().

+ +

sparsetable is distinguished from other array +implementations, including the default C implementation, in its stingy +use of memory -- in particular, unused array elements require only 1 bit +of disk space to store, rather than sizeof(T) bytes -- and by +the ability to save and restore contents to disk. On the other hand, +this array implementation, while still efficient, is slower than other +array implementations.

+ + +

A sparsetable distinguishes between table elements that +have been assigned and those that are unassigned. +Assigned table elements are those that have had a value set via +set(), operator(), assignment via an iterator, and +so forth. Unassigned table elements are those that have not had a +value set in one of these ways, or that have been explicitly +unassigned via a call to erase() or clear(). Lookup +is valid on both assigned and unassigned table elements; for +unassigned elements, lookup returns the default value +T().

+
+ +

This class is appropriate for applications that need to store large +arrays in memory, or for applications that need these arrays to be +persistent.

+ + +

Example

+ +
+#include <google/sparsetable>
+
+using google::sparsetable;      // namespace where class lives by default
+
+sparsetable<int> t(100);
+t[5] = 6;
+cout << "t[5] = " << t[5];
+cout << "Default value = " << t[99];
+
+ + +

Definition

+ +Defined in the header sparsetable. This +class is not part of the C++ standard. + + +

Template parameters

+ + + + + + + + + + + + + + + + +
ParameterDescriptionDefault
+ T + + The sparsetable's value type: the type of object that is stored in + the table. + +   +
+ GROUP_SIZE + + The number of elements in each sparsetable group (see the implementation doc for more details + on this value). This almost never need be specified; the default + template parameter value works well in all situations. + +   +
+ + +

Model of

+ +Random Access Container + + +

Type requirements

+ +None, except for those imposed by the requirements of +Random +Access Container + + +

Public base classes

+ +None. + + +

Members

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberWhere definedDescription
+ value_type + + Container + + The type of object, T, stored in the table. +
+ pointer + + Container + + Pointer to T. +
+ reference + + Container + + Reference to T. +
+ const_reference + + Container + + Const reference to T. +
+ size_type + + Container + + An unsigned integral type. +
+ difference_type + + Container + + A signed integral type. +
+ iterator + + Container + + Iterator used to iterate through a sparsetable. +
+ const_iterator + + Container + + Const iterator used to iterate through a sparsetable. +
+ reverse_iterator + + Reversible + Container + + Iterator used to iterate backwards through a sparsetable. +
+ const_reverse_iterator + + Reversible + Container + + Const iterator used to iterate backwards through a + sparsetable. +
+ nonempty_iterator + + sparsetable + + Iterator used to iterate through the + assigned elements of the + sparsetable. +
+ const_nonempty_iterator + + sparsetable + + Const iterator used to iterate through the + assigned elements of the + sparsetable. +
+ reverse_nonempty_iterator + + sparsetable + + Iterator used to iterate backwards through the + assigned elements of the + sparsetable. +
+ const_reverse_nonempty_iterator + + sparsetable + + Const iterator used to iterate backwards through the + assigned elements of the + sparsetable. +
+ destructive_iterator + + sparsetable + + Iterator used to iterate through the + assigned elements of the + sparsetable, erasing elements as it iterates. + [1] +
+ iterator begin() + + Container + + Returns an iterator pointing to the beginning of the + sparsetable. +
+ iterator end() + + Container + + Returns an iterator pointing to the end of the + sparsetable. +
+ const_iterator begin() const + + Container + + Returns an const_iterator pointing to the beginning of the + sparsetable. +
+ const_iterator end() const + + Container + + Returns an const_iterator pointing to the end of the + sparsetable. +
+ reverse_iterator rbegin() + + Reversible + Container + + Returns a reverse_iterator pointing to the beginning of the + reversed sparsetable. +
+ reverse_iterator rend() + + Reversible + Container + + Returns a reverse_iterator pointing to the end of the + reversed sparsetable. +
+ const_reverse_iterator rbegin() const + + Reversible + Container + + Returns a const_reverse_iterator pointing to the beginning + of the reversed sparsetable. +
+ const_reverse_iterator rend() const + + Reversible + Container + + Returns a const_reverse_iterator pointing to the end of + the reversed sparsetable. +
+ nonempty_iterator nonempty_begin() + + sparsetable + + Returns a nonempty_iterator pointing to the first + assigned element of the + sparsetable. +
+ nonempty_iterator nonempty_end() + + sparsetable + + Returns a nonempty_iterator pointing to the end of the + sparsetable. +
+ const_nonempty_iterator nonempty_begin() const + + sparsetable + + Returns a const_nonempty_iterator pointing to the first + assigned element of the + sparsetable. +
+ const_nonempty_iterator nonempty_end() const + + sparsetable + + Returns a const_nonempty_iterator pointing to the end of + the sparsetable. +
+ reverse_nonempty_iterator nonempty_rbegin() + + sparsetable + + Returns a reverse_nonempty_iterator pointing to the first + assigned element of the reversed + sparsetable. +
+ reverse_nonempty_iterator nonempty_rend() + + sparsetable + + Returns a reverse_nonempty_iterator pointing to the end of + the reversed sparsetable. +
+ const_reverse_nonempty_iterator nonempty_rbegin() const + + sparsetable + + Returns a const_reverse_nonempty_iterator pointing to the + first assigned element of the reversed + sparsetable. +
+ const_reverse_nonempty_iterator nonempty_rend() const + + sparsetable + + Returns a const_reverse_nonempty_iterator pointing to the + end of the reversed sparsetable. +
+ destructive_iterator destructive_begin() + + sparsetable + + Returns a destructive_iterator pointing to the first + assigned element of the + sparsetable. +
+ destructive_iterator destructive_end() + + sparsetable + + Returns a destructive_iterator pointing to the end of + the sparsetable. +
+ size_type size() const + + Container + + Returns the size of the sparsetable. +
+ size_type max_size() const + + Container + + Returns the largest possible size of the sparsetable. +
+ bool empty() const + + Container + + true if the sparsetable's size is 0. +
+ size_type num_nonempty() const + + sparsetable + + Returns the number of sparsetable elements that are currently assigned. +
+ sparsetable(size_type n) + + Container + + Creates a sparsetable with n elements. +
+ sparsetable(const sparsetable&) + + Container + + The copy constructor. +
+ ~sparsetable() + + Container + + The destructor. +
+ sparsetable& operator=(const sparsetable&) + + Container + + The assignment operator +
+ void swap(sparsetable&) + + Container + + Swaps the contents of two sparsetables. +
+ reference operator[](size_type n) + + Random + Access Container + + Returns the n'th element. [2] +
+ const_reference operator[](size_type n) const + + Random + Access Container + + Returns the n'th element. +
+ bool test(size_type i) const + + sparsetable + + true if the i'th element of the sparsetable is assigned. +
+ bool test(iterator pos) const + + sparsetable + + true if the sparsetable element pointed to by pos + is assigned. +
+ bool test(const_iterator pos) const + + sparsetable + + true if the sparsetable element pointed to by pos + is assigned. +
+ const_reference get(size_type i) const + + sparsetable + + returns the i'th element of the sparsetable. +
+ reference set(size_type i, const_reference val) + + sparsetable + + Sets the i'th element of the sparsetable to value + val. +
+ void erase(size_type i) + + sparsetable + + Erases the i'th element of the sparsetable. +
+ void erase(iterator pos) + + sparsetable + + Erases the element of the sparsetable pointed to by + pos. +
+ void erase(iterator first, iterator last) + + sparsetable + + Erases the elements of the sparsetable in the range + [first, last). +
+ void clear() + + sparsetable + + Erases all of the elements. +
+ void resize(size_type n) + + sparsetable + + Changes the size of sparsetable to n. +
+ bool write_metadata(FILE *fp) + + sparsetable + + See below. +
+ bool read_metadata(FILE *fp) + + sparsetable + + See below. +
+ bool write_nopointer_data(FILE *fp) + + sparsetable + + See below. +
+ bool read_nopointer_data(FILE *fp) + + sparsetable + + See below. +
+
bool operator==(const sparsetable&, const sparsetable&)
+
+
+ Forward + Container + + Tests two sparsetables for equality. This is a global function, + not a member function. +
+
bool operator<(const sparsetable&, const sparsetable&)
+
+
+ Forward + Container + + Lexicographical comparison. This is a global function, + not a member function. +
+ + +

New members

+ +These members are not defined in the Random +Access Container requirement, but are specific to +sparsetable. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberDescription
+ nonempty_iterator + + Iterator used to iterate through the + assigned elements of the + sparsetable. +
+ const_nonempty_iterator + + Const iterator used to iterate through the + assigned elements of the + sparsetable. +
+ reverse_nonempty_iterator + + Iterator used to iterate backwards through the + assigned elements of the + sparsetable. +
+ const_reverse_nonempty_iterator + + Const iterator used to iterate backwards through the + assigned elements of the + sparsetable. +
+ destructive_iterator + + Iterator used to iterate through the + assigned elements of the + sparsetable, erasing elements as it iterates. + [1] +
+ nonempty_iterator nonempty_begin() + + Returns a nonempty_iterator pointing to the first + assigned element of the + sparsetable. +
+ nonempty_iterator nonempty_end() + + Returns a nonempty_iterator pointing to the end of the + sparsetable. +
+ const_nonempty_iterator nonempty_begin() const + + Returns a const_nonempty_iterator pointing to the first + assigned element of the + sparsetable. +
+ const_nonempty_iterator nonempty_end() const + + Returns a const_nonempty_iterator pointing to the end of + the sparsetable. +
+ reverse_nonempty_iterator nonempty_rbegin() + + Returns a reverse_nonempty_iterator pointing to the first + assigned element of the reversed + sparsetable. +
+ reverse_nonempty_iterator nonempty_rend() + + Returns a reverse_nonempty_iterator pointing to the end of + the reversed sparsetable. +
+ const_reverse_nonempty_iterator nonempty_rbegin() const + + Returns a const_reverse_nonempty_iterator pointing to the + first assigned element of the reversed + sparsetable. +
+ const_reverse_nonempty_iterator nonempty_rend() const + + Returns a const_reverse_nonempty_iterator pointing to the + end of the reversed sparsetable. +
+ destructive_iterator destructive_begin() + + Returns a destructive_iterator pointing to the first + assigned element of the + sparsetable. +
+ destructive_iterator destructive_end() + + Returns a destructive_iterator pointing to the end of + the sparsetable. +
+ size_type num_nonempty() const + + Returns the number of sparsetable elements that are currently assigned. +
+ bool test(size_type i) const + + true if the i'th element of the sparsetable is assigned. +
+ bool test(iterator pos) const + + true if the sparsetable element pointed to by pos + is assigned. +
+ bool test(const_iterator pos) const + + true if the sparsetable element pointed to by pos + is assigned. +
+ const_reference get(size_type i) const + + returns the i'th element of the sparsetable. If + the i'th element is assigned, the + assigned value is returned, otherwise, the default value + T() is returned. +
+ reference set(size_type i, const_reference val) + + Sets the i'th element of the sparsetable to value + val, and returns a reference to the i'th element + of the table. This operation causes the i'th element to + be assigned. +
+ void erase(size_type i) + + Erases the i'th element of the sparsetable. This + operation causes the i'th element to be unassigned. +
+ void erase(iterator pos) + + Erases the element of the sparsetable pointed to by + pos. This operation causes the i'th element to + be unassigned. +
+ void erase(iterator first, iterator last) + + Erases the elements of the sparsetable in the range + [first, last). This operation causes these elements to + be unassigned. +
+ void clear() + + Erases all of the elements. This causes all elements to be + unassigned. +
+ void resize(size_type n) + + Changes the size of sparsetable to n. If n is + greater than the old size, new, unassigned + elements are appended. If n is less than the old size, + all elements in position >n are deleted. +
+ bool write_metadata(FILE *fp) + + Write hashtable metadata to fp. See below. +
+ bool read_metadata(FILE *fp) + + Read hashtable metadata from fp. See below. +
+ bool write_nopointer_data(FILE *fp) + + Write hashtable contents to fp. This is valid only if the + hashtable key and value are "plain" data. See below. +
+ bool read_nopointer_data(FILE *fp) + + Read hashtable contents to fp. This is valid only if the + hashtable key and value are "plain" data. See below. +
+ + +

Notes

+ +

[1] + +sparsetable::destructive_iterator iterates through a +sparsetable like a normal iterator, but ++it may delete the +element being iterated past. Obviously, this iterator can only be +used once on a given table! One application of this iterator is to +copy data from a sparsetable to some other data structure without +using extra memory to store the data in both places during the +copy.

+ +

[2] + +Since operator[] might insert a new element into the +sparsetable, it can't possibly be a const member +function. In theory, since it might insert a new element, it should +cause the element it refers to to become assigned. However, this is undesirable when +operator[] is used to examine elements, rather than assign +them. Thus, as an implementation trick, operator[] does not +really return a reference. Instead it returns an object that +behaves almost exactly like a reference. This object, +however, delays setting the appropriate sparsetable element to assigned to when it is actually assigned to.

+ +

For a bit more detail: the object returned by operator[] +is an opaque type which defines operator=, operator +reference(), and operator&. The first operator controls +assigning to the value. The second controls examining the value. The +third controls pointing to the value.

+ +

All three operators perform exactly as an object of type +reference would perform. The only problems that arise is +when this object is accessed in situations where C++ cannot do the +conversion by default. By far the most common situation is with +variadic functions such as printf. In such situations, you +may need to manually cast the object to the right type:

+
+   printf("%d", static_cast<typename table::reference>(table[i]));
+
+ + +

Input/Output

+ +

It is possible to save and restore sparsetable objects +to disk. Storage takes place in two steps. The first writes the +table metadata. The second writes the actual data.

+ +

To write a sparsetable to disk, first call write_metadata() +on an open file pointer. This saves the sparsetable information in a +byte-order-independent format.

+ +

After the metadata has been written to disk, you must write the +actual data stored in the sparsetable to disk. If the value is +"simple" enough, you can do this by calling +write_nopointer_data(). "Simple" data is data that can be +safely copied to disk via fwrite(). Native C data types fall +into this category, as do structs of native C data types. Pointers +and STL objects do not.

+ +

Note that write_nopointer_data() does not do any endian +conversion. Thus, it is only appropriate when you intend to read the +data on the same endian architecture as you write the data.

+ +

If you cannot use write_nopointer_data() for any reason, +you can write the data yourself by iterating over the +sparsetable with a const_nonempty_iterator and +writing the key and data in any manner you wish.

+ +

To read the hashtable information from disk, first you must create +a sparsetable object. Then open a file pointer to point +to the saved sparsetable, and call read_metadata(). If you +saved the data via write_nopointer_data(), you can follow the +read_metadata() call with a call to +read_nopointer_data(). This is all that is needed.

+ +

If you saved the data through a custom write routine, you must call +a custom read routine to read in the data. To do this, iterate over +the sparsetable with a nonempty_iterator; this +operation is sensical because the metadata has already been set up. +For each iterator item, you can read the key and value from disk, and +set it appropriately. The code might look like this:

+
+   for (sparsetable<int*>::nonempty_iterator it = t.nonempty_begin();
+        it != t.nonempty_end(); ++it) {
+       *it = new int;
+       fread(*it, sizeof(int), 1, fp);
+   }
+
+ +

Here's another example, where the item stored in the sparsetable is +a C++ object with a non-trivial constructor. In this case, you must +use "placement new" to construct the object at the correct memory +location.

+
+   for (sparsetable<ComplicatedCppClass>::nonempty_iterator it = t.nonempty_begin();
+        it != t.nonempty_end(); ++it) {
+       int constructor_arg;   // ComplicatedCppClass takes an int to construct
+       fread(&constructor_arg, sizeof(int), 1, fp);
+       new (&(*it)) ComplicatedCppClass(constructor_arg);     // placement new
+   }
+
+ + +

See also

+ +

The following are SGI STL concepts and classes related to +sparsetable.

+ +Container, +Random Access Container, +sparse_hash_set, +sparse_hash_map + + + diff --git a/src/sparsehash-1.6/experimental/Makefile b/src/sparsehash-1.6/experimental/Makefile new file mode 100644 index 0000000..aa997f7 --- /dev/null +++ b/src/sparsehash-1.6/experimental/Makefile @@ -0,0 +1,9 @@ +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 diff --git a/src/sparsehash-1.6/experimental/README b/src/sparsehash-1.6/experimental/README new file mode 100644 index 0000000..150161d --- /dev/null +++ b/src/sparsehash-1.6/experimental/README @@ -0,0 +1,14 @@ +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 diff --git a/src/sparsehash-1.6/experimental/example.c b/src/sparsehash-1.6/experimental/example.c new file mode 100644 index 0000000..38a3265 --- /dev/null +++ b/src/sparsehash-1.6/experimental/example.c @@ -0,0 +1,54 @@ +#include +#include +#include +#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; +} diff --git a/src/sparsehash-1.6/experimental/libchash.c b/src/sparsehash-1.6/experimental/libchash.c new file mode 100644 index 0000000..eff9eeb --- /dev/null +++ b/src/sparsehash-1.6/experimental/libchash.c @@ -0,0 +1,1537 @@ +/* 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. + * + * See libchash.h for parameters you can modify. Make sure LOG_WORD_SIZE + * is defined correctly for your machine! (5 for 32 bit words, 6 for 64). + */ + +#include +#include +#include /* for strcmp, memcmp, etc */ +#include /* ULTRIX needs this for in.h */ +#include /* for reading/writing hashtables */ +#include +#include "libchash.h" /* all the types */ + + /* if keys are stored directly but cchKey is less than sizeof(ulong), */ + /* this cuts off the bits at the end */ +char grgKeyTruncMask[sizeof(ulong)][sizeof(ulong)]; +#define KEY_TRUNC(ht, key) \ + ( STORES_PTR(ht) || (ht)->cchKey == sizeof(ulong) \ + ? (key) : ((key) & *(ulong *)&(grgKeyTruncMask[(ht)->cchKey][0])) ) + + /* round num up to a multiple of wordsize. (LOG_WORD_SIZE-3 is in bytes) */ +#define WORD_ROUND(num) ( ((num-1) | ((1<<(LOG_WORD_SIZE-3))-1)) + 1 ) +#define NULL_TERMINATED 0 /* val of cchKey if keys are null-term strings */ + + /* Useful operations we do to keys: compare them, copy them, free them */ + +#define KEY_CMP(ht, key1, key2) ( !STORES_PTR(ht) ? (key1) - (key2) : \ + (key1) == (key2) ? 0 : \ + HashKeySize(ht) == NULL_TERMINATED ? \ + strcmp((char *)key1, (char *)key2) :\ + memcmp((void *)key1, (void *)key2, \ + HashKeySize(ht)) ) + +#define COPY_KEY(ht, keyTo, keyFrom) do \ + if ( !STORES_PTR(ht) || !(ht)->fSaveKeys ) \ + (keyTo) = (keyFrom); /* just copy pointer or info */\ + else if ( (ht)->cchKey == NULL_TERMINATED ) /* copy 0-term.ed str */\ + { \ + (keyTo) = (ulong)HTsmalloc( WORD_ROUND(strlen((char *)(keyFrom))+1) ); \ + strcpy((char *)(keyTo), (char *)(keyFrom)); \ + } \ + else \ + { \ + (keyTo) = (ulong) HTsmalloc( WORD_ROUND((ht)->cchKey) ); \ + memcpy( (char *)(keyTo), (char *)(keyFrom), (ht)->cchKey); \ + } \ + while ( 0 ) + +#define FREE_KEY(ht, key) do \ + if ( STORES_PTR(ht) && (ht)->fSaveKeys ) \ + if ( (ht)->cchKey == NULL_TERMINATED ) \ + HTfree((char *)(key), WORD_ROUND(strlen((char *)(key))+1)); \ + else \ + HTfree((char *)(key), WORD_ROUND((ht)->cchKey)); \ + while ( 0 ) + + /* the following are useful for bitmaps */ + /* Format is like this (if 1 word = 4 bits): 3210 7654 ba98 fedc ... */ +typedef ulong HTBitmapPart; /* this has to be unsigned, for >> */ +typedef HTBitmapPart HTBitmap[1<> LOG_WORD_SIZE) << (LOG_WORD_SIZE-3) ) +#define MOD2(i, logmod) ( (i) & ((1<<(logmod))-1) ) +#define DIV_NUM_ENTRIES(i) ( (i) >> LOG_WORD_SIZE ) +#define MOD_NUM_ENTRIES(i) ( MOD2(i, LOG_WORD_SIZE) ) +#define MODBIT(i) ( ((ulong)1) << MOD_NUM_ENTRIES(i) ) + +#define TEST_BITMAP(bm, i) ( (bm)[DIV_NUM_ENTRIES(i)] & MODBIT(i) ? 1 : 0 ) +#define SET_BITMAP(bm, i) (bm)[DIV_NUM_ENTRIES(i)] |= MODBIT(i) +#define CLEAR_BITMAP(bm, i) (bm)[DIV_NUM_ENTRIES(i)] &= ~MODBIT(i) + + /* the following are useful for reading and writing hashtables */ +#define READ_UL(fp, data) \ + do { \ + long _ul; \ + fread(&_ul, sizeof(_ul), 1, (fp)); \ + data = ntohl(_ul); \ + } while (0) + +#define WRITE_UL(fp, data) \ + do { \ + long _ul = htonl((long)(data)); \ + fwrite(&_ul, sizeof(_ul), 1, (fp)); \ + } while (0) + + /* Moves data from disk to memory if necessary. Note dataRead cannot be * + * NULL, because then we might as well (and do) load the data into memory */ +#define LOAD_AND_RETURN(ht, loadCommand) /* lC returns an HTItem * */ \ + if ( !(ht)->fpData ) /* data is stored in memory */ \ + return (loadCommand); \ + else /* must read data off of disk */ \ + { \ + int cchData; \ + HTItem *bck; \ + if ( (ht)->bckData.data ) free((char *)(ht)->bckData.data); \ + ht->bckData.data = (ulong)NULL; /* needed if loadCommand fails */ \ + bck = (loadCommand); \ + if ( bck == NULL ) /* loadCommand failed: key not found */ \ + return NULL; \ + else \ + (ht)->bckData = *bck; \ + fseek(ht->fpData, (ht)->bckData.data, SEEK_SET); \ + READ_UL((ht)->fpData, cchData); \ + (ht)->bckData.data = (ulong)(ht)->dataRead((ht)->fpData, cchData); \ + return &((ht)->bckData); \ + } + + +/* ======================================================================== */ +/* UTILITY ROUTINES */ +/* ---------------------- */ + +/* HTsmalloc() -- safe malloc + * allocates memory, or crashes if the allocation fails. + */ +static void *HTsmalloc(unsigned long size) +{ + void *retval; + + if ( size == 0 ) + return NULL; + retval = (void *)malloc(size); + if ( !retval ) + { + fprintf(stderr, "HTsmalloc: Unable to allocate %lu bytes of memory\n", + size); + exit(1); + } + return retval; +} + +/* HTscalloc() -- safe calloc + * allocates memory and initializes it to 0, or crashes if + * the allocation fails. + */ +static void *HTscalloc(unsigned long size) +{ + void *retval; + + retval = (void *)calloc(size, 1); + if ( !retval && size > 0 ) + { + fprintf(stderr, "HTscalloc: Unable to allocate %lu bytes of memory\n", + size); + exit(1); + } + return retval; +} + +/* HTsrealloc() -- safe calloc + * grows the amount of memory from a source, or crashes if + * the allocation fails. + */ +static void *HTsrealloc(void *ptr, unsigned long new_size, long delta) +{ + if ( ptr == NULL ) + return HTsmalloc(new_size); + ptr = realloc(ptr, new_size); + if ( !ptr && new_size > 0 ) + { + fprintf(stderr, "HTsrealloc: Unable to reallocate %lu bytes of memory\n", + new_size); + exit(1); + } + return ptr; +} + +/* HTfree() -- keep track of memory use + * frees memory using free, but updates count of how much memory + * is being used. + */ +static void HTfree(void *ptr, unsigned long size) +{ + if ( size > 0 ) /* some systems seem to not like freeing NULL */ + free(ptr); +} + +/*************************************************************************\ +| HTcopy() | +| Sometimes we interpret data as a ulong. But ulongs must be | +| aligned on some machines, so instead of casting we copy. | +\*************************************************************************/ + +unsigned long HTcopy(char *ul) +{ + unsigned long retval; + + memcpy(&retval, ul, sizeof(retval)); + return retval; +} + +/*************************************************************************\ +| HTSetupKeyTrunc() | +| If keys are stored directly but cchKey is less than | +| sizeof(ulong), this cuts off the bits at the end. | +\*************************************************************************/ + +static void HTSetupKeyTrunc(void) +{ + int i, j; + + for ( i = 0; i < sizeof(unsigned long); i++ ) + for ( j = 0; j < sizeof(unsigned long); j++ ) + grgKeyTruncMask[i][j] = j < i ? 255 : 0; /* chars have 8 bits */ +} + + +/* ======================================================================== */ +/* TABLE ROUTINES */ +/* -------------------- */ + +/* The idea is that a hashtable with (logically) t buckets is divided + * into t/M groups of M buckets each. (M is a constant set in + * LOG_BM_WORDS for efficiency.) Each group is stored sparsely. + * Thus, inserting into the table causes some array to grow, which is + * slow but still constant time. Lookup involves doing a + * logical-position-to-sparse-position lookup, which is also slow but + * constant time. The larger M is, the slower these operations are + * but the less overhead (slightly). + * + * To store the sparse array, we store a bitmap B, where B[i] = 1 iff + * bucket i is non-empty. Then to look up bucket i we really look up + * array[# of 1s before i in B]. This is constant time for fixed M. + * + * Terminology: the position of an item in the overall table (from + * 1 .. t) is called its "location." The logical position in a group + * (from 1 .. M ) is called its "position." The actual location in + * the array (from 1 .. # of non-empty buckets in the group) is + * called its "offset." + * + * The following operations are supported: + * o Allocate an array with t buckets, all empty + * o Free a array (but not whatever was stored in the buckets) + * o Tell whether or not a bucket is empty + * o Return a bucket with a given location + * o Set the value of a bucket at a given location + * o Iterate through all the buckets in the array + * o Read and write an occupancy bitmap to disk + * o Return how much memory is being allocated by the array structure + */ + +#ifndef SparseBucket /* by default, each bucket holds an HTItem */ +#define SparseBucket HTItem +#endif + +typedef struct SparseBin { + SparseBucket *binSparse; + HTBitmap bmOccupied; /* bmOccupied[i] is 1 if bucket i has an item */ + short cOccupied; /* size of binSparse; useful for iterators, eg */ +} SparseBin; + +typedef struct SparseIterator { + long posGroup; + long posOffset; + SparseBin *binSparse; /* state info, to avoid args for NextBucket() */ + ulong cBuckets; +} SparseIterator; + +#define LOG_LOW_BIN_SIZE ( LOG_BM_WORDS+LOG_WORD_SIZE ) +#define SPARSE_GROUPS(cBuckets) ( (((cBuckets)-1) >> LOG_LOW_BIN_SIZE) + 1 ) + + /* we need a small function to figure out # of items set in the bm */ +static HTOffset EntriesUpto(HTBitmapPart *bm, int i) +{ /* returns # of set bits in 0..i-1 */ + HTOffset retval = 0; + static HTOffset rgcBits[256] = /* # of bits set in one char */ + {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8}; + + if ( i == 0 ) return 0; + for ( ; i > sizeof(*bm)*8; i -= sizeof(*bm)*8, bm++ ) + { /* think of it as loop unrolling */ +#if LOG_WORD_SIZE >= 3 /* 1 byte per word, or more */ + retval += rgcBits[*bm & 255]; /* get the low byte */ +#if LOG_WORD_SIZE >= 4 /* at least 2 bytes */ + retval += rgcBits[(*bm >> 8) & 255]; +#if LOG_WORD_SIZE >= 5 /* at least 4 bytes */ + retval += rgcBits[(*bm >> 16) & 255]; + retval += rgcBits[(*bm >> 24) & 255]; +#if LOG_WORD_SIZE >= 6 /* 8 bytes! */ + retval += rgcBits[(*bm >> 32) & 255]; + retval += rgcBits[(*bm >> 40) & 255]; + retval += rgcBits[(*bm >> 48) & 255]; + retval += rgcBits[(*bm >> 56) & 255]; +#if LOG_WORD_SIZE >= 7 /* not a concern for a while... */ +#error Need to rewrite EntriesUpto to support such big words +#endif /* >8 bytes */ +#endif /* 8 bytes */ +#endif /* 4 bytes */ +#endif /* 2 bytes */ +#endif /* 1 byte */ + } + switch ( i ) { /* from 0 to 63 */ + case 0: + return retval; +#if LOG_WORD_SIZE >= 3 /* 1 byte per word, or more */ + case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: + return (retval + rgcBits[*bm & ((1 << i)-1)]); +#if LOG_WORD_SIZE >= 4 /* at least 2 bytes */ + case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: + return (retval + rgcBits[*bm & 255] + + rgcBits[(*bm >> 8) & ((1 << (i-8))-1)]); +#if LOG_WORD_SIZE >= 5 /* at least 4 bytes */ + case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 24: + return (retval + rgcBits[*bm & 255] + rgcBits[(*bm >> 8) & 255] + + rgcBits[(*bm >> 16) & ((1 << (i-16))-1)]); + case 25: case 26: case 27: case 28: case 29: case 30: case 31: case 32: + return (retval + rgcBits[*bm & 255] + rgcBits[(*bm >> 8) & 255] + + rgcBits[(*bm >> 16) & 255] + + rgcBits[(*bm >> 24) & ((1 << (i-24))-1)]); +#if LOG_WORD_SIZE >= 6 /* 8 bytes! */ + case 33: case 34: case 35: case 36: case 37: case 38: case 39: case 40: + return (retval + rgcBits[*bm & 255] + rgcBits[(*bm >> 8) & 255] + + rgcBits[(*bm >> 16) & 255] + rgcBits[(*bm >> 24) & 255] + + rgcBits[(*bm >> 32) & ((1 << (i-32))-1)]); + case 41: case 42: case 43: case 44: case 45: case 46: case 47: case 48: + return (retval + rgcBits[*bm & 255] + rgcBits[(*bm >> 8) & 255] + + rgcBits[(*bm >> 16) & 255] + rgcBits[(*bm >> 24) & 255] + + rgcBits[(*bm >> 32) & 255] + + rgcBits[(*bm >> 40) & ((1 << (i-40))-1)]); + case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: + return (retval + rgcBits[*bm & 255] + rgcBits[(*bm >> 8) & 255] + + rgcBits[(*bm >> 16) & 255] + rgcBits[(*bm >> 24) & 255] + + rgcBits[(*bm >> 32) & 255] + rgcBits[(*bm >> 40) & 255] + + rgcBits[(*bm >> 48) & ((1 << (i-48))-1)]); + case 57: case 58: case 59: case 60: case 61: case 62: case 63: case 64: + return (retval + rgcBits[*bm & 255] + rgcBits[(*bm >> 8) & 255] + + rgcBits[(*bm >> 16) & 255] + rgcBits[(*bm >> 24) & 255] + + rgcBits[(*bm >> 32) & 255] + rgcBits[(*bm >> 40) & 255] + + rgcBits[(*bm >> 48) & 255] + + rgcBits[(*bm >> 56) & ((1 << (i-56))-1)]); +#endif /* 8 bytes */ +#endif /* 4 bytes */ +#endif /* 2 bytes */ +#endif /* 1 byte */ + } + assert("" == "word size is too big in EntriesUpto()"); + return -1; +} +#define SPARSE_POS_TO_OFFSET(bm, i) ( EntriesUpto(&((bm)[0]), i) ) +#define SPARSE_BUCKET(bin, location) \ + ( (bin)[(location) >> LOG_LOW_BIN_SIZE].binSparse + \ + SPARSE_POS_TO_OFFSET((bin)[(location)>>LOG_LOW_BIN_SIZE].bmOccupied, \ + MOD2(location, LOG_LOW_BIN_SIZE)) ) + + +/*************************************************************************\ +| SparseAllocate() | +| SparseFree() | +| Allocates, sets-to-empty, and frees a sparse array. All you need | +| to tell me is how many buckets you want. I return the number of | +| buckets I actually allocated, setting the array as a parameter. | +| Note that you have to set auxilliary parameters, like cOccupied. | +\*************************************************************************/ + +static ulong SparseAllocate(SparseBin **pbinSparse, ulong cBuckets) +{ + int cGroups = SPARSE_GROUPS(cBuckets); + + *pbinSparse = (SparseBin *) HTscalloc(sizeof(**pbinSparse) * cGroups); + return cGroups << LOG_LOW_BIN_SIZE; +} + +static SparseBin *SparseFree(SparseBin *binSparse, ulong cBuckets) +{ + ulong iGroup, cGroups = SPARSE_GROUPS(cBuckets); + + for ( iGroup = 0; iGroup < cGroups; iGroup++ ) + HTfree(binSparse[iGroup].binSparse, (sizeof(*binSparse[iGroup].binSparse) + * binSparse[iGroup].cOccupied)); + HTfree(binSparse, sizeof(*binSparse) * cGroups); + return NULL; +} + +/*************************************************************************\ +| SparseIsEmpty() | +| SparseFind() | +| You give me a location (ie a number between 1 and t), and I | +| return the bucket at that location, or NULL if the bucket is | +| empty. It's OK to call Find() on an empty table. | +\*************************************************************************/ + +static int SparseIsEmpty(SparseBin *binSparse, ulong location) +{ + return !TEST_BITMAP(binSparse[location>>LOG_LOW_BIN_SIZE].bmOccupied, + MOD2(location, LOG_LOW_BIN_SIZE)); +} + +static SparseBucket *SparseFind(SparseBin *binSparse, ulong location) +{ + if ( SparseIsEmpty(binSparse, location) ) + return NULL; + return SPARSE_BUCKET(binSparse, location); +} + +/*************************************************************************\ +| SparseInsert() | +| You give me a location, and contents to put there, and I insert | +| into that location and RETURN a pointer to the location. If | +| bucket was already occupied, I write over the contents only if | +| *pfOverwrite is 1. We set *pfOverwrite to 1 if there was someone | +| there (whether or not we overwrote) and 0 else. | +\*************************************************************************/ + +static SparseBucket *SparseInsert(SparseBin *binSparse, SparseBucket *bckInsert, + ulong location, int *pfOverwrite) +{ + SparseBucket *bckPlace; + HTOffset offset; + + bckPlace = SparseFind(binSparse, location); + if ( bckPlace ) /* means we replace old contents */ + { + if ( *pfOverwrite ) + *bckPlace = *bckInsert; + *pfOverwrite = 1; + return bckPlace; + } + + binSparse += (location >> LOG_LOW_BIN_SIZE); + offset = SPARSE_POS_TO_OFFSET(binSparse->bmOccupied, + MOD2(location, LOG_LOW_BIN_SIZE)); + binSparse->binSparse = (SparseBucket *) + HTsrealloc(binSparse->binSparse, + sizeof(*binSparse->binSparse) * ++binSparse->cOccupied, + sizeof(*binSparse->binSparse)); + memmove(binSparse->binSparse + offset+1, + binSparse->binSparse + offset, + (binSparse->cOccupied-1 - offset) * sizeof(*binSparse->binSparse)); + binSparse->binSparse[offset] = *bckInsert; + SET_BITMAP(binSparse->bmOccupied, MOD2(location, LOG_LOW_BIN_SIZE)); + *pfOverwrite = 0; + return binSparse->binSparse + offset; +} + +/*************************************************************************\ +| SparseFirstBucket() | +| SparseNextBucket() | +| SparseCurrentBit() | +| Iterate through the occupied buckets of a dense hashtable. You | +| must, of course, have allocated space yourself for the iterator. | +\*************************************************************************/ + +static SparseBucket *SparseNextBucket(SparseIterator *iter) +{ + if ( iter->posOffset != -1 && /* not called from FirstBucket()? */ + (++iter->posOffset < iter->binSparse[iter->posGroup].cOccupied) ) + return iter->binSparse[iter->posGroup].binSparse + iter->posOffset; + + iter->posOffset = 0; /* start the next group */ + for ( iter->posGroup++; iter->posGroup < SPARSE_GROUPS(iter->cBuckets); + iter->posGroup++ ) + if ( iter->binSparse[iter->posGroup].cOccupied > 0 ) + return iter->binSparse[iter->posGroup].binSparse; /* + 0 */ + return NULL; /* all remaining groups were empty */ +} + +static SparseBucket *SparseFirstBucket(SparseIterator *iter, + SparseBin *binSparse, ulong cBuckets) +{ + iter->binSparse = binSparse; /* set it up for NextBucket() */ + iter->cBuckets = cBuckets; + iter->posOffset = -1; /* when we advance, we're at 0 */ + iter->posGroup = -1; + return SparseNextBucket(iter); +} + +/*************************************************************************\ +| SparseWrite() | +| SparseRead() | +| These are routines for storing a sparse hashtable onto disk. We | +| store the number of buckets and a bitmap indicating which buckets | +| are allocated (occupied). The actual contents of the buckets | +| must be stored separately. | +\*************************************************************************/ + +static void SparseWrite(FILE *fp, SparseBin *binSparse, ulong cBuckets) +{ + ulong i, j; + + WRITE_UL(fp, cBuckets); + for ( i = 0; i < SPARSE_GROUPS(cBuckets); i++ ) + for ( j = 0; j < (1<rgBuckets, cBuckets); +} + +static ulong DenseAllocate(DenseBin **pbin, ulong cBuckets) +{ + *pbin = (DenseBin *) HTsmalloc(sizeof(*pbin)); + (*pbin)->rgBuckets = (DenseBucket *) HTsmalloc(sizeof(*(*pbin)->rgBuckets) + * cBuckets); + DenseClear(*pbin, cBuckets); + return cBuckets; +} + +static DenseBin *DenseFree(DenseBin *bin, ulong cBuckets) +{ + HTfree(bin->rgBuckets, sizeof(*bin->rgBuckets) * cBuckets); + HTfree(bin, sizeof(*bin)); + return NULL; +} + +static int DenseIsEmpty(DenseBin *bin, ulong location) +{ + return DENSE_IS_EMPTY(bin->rgBuckets, location); +} + +static DenseBucket *DenseFind(DenseBin *bin, ulong location) +{ + if ( DenseIsEmpty(bin, location) ) + return NULL; + return bin->rgBuckets + location; +} + +static DenseBucket *DenseInsert(DenseBin *bin, DenseBucket *bckInsert, + ulong location, int *pfOverwrite) +{ + DenseBucket *bckPlace; + + bckPlace = DenseFind(bin, location); + if ( bckPlace ) /* means something is already there */ + { + if ( *pfOverwrite ) + *bckPlace = *bckInsert; + *pfOverwrite = 1; /* set to 1 to indicate someone was there */ + return bckPlace; + } + else + { + bin->rgBuckets[location] = *bckInsert; + *pfOverwrite = 0; + return bin->rgBuckets + location; + } +} + +static DenseBucket *DenseNextBucket(DenseIterator *iter) +{ + for ( iter->pos++; iter->pos < iter->cBuckets; iter->pos++ ) + if ( !DenseIsEmpty(iter->bin, iter->pos) ) + return iter->bin->rgBuckets + iter->pos; + return NULL; /* all remaining groups were empty */ +} + +static DenseBucket *DenseFirstBucket(DenseIterator *iter, + DenseBin *bin, ulong cBuckets) +{ + iter->bin = bin; /* set it up for NextBucket() */ + iter->cBuckets = cBuckets; + iter->pos = -1; /* thus the next bucket will be 0 */ + return DenseNextBucket(iter); +} + +static void DenseWrite(FILE *fp, DenseBin *bin, ulong cBuckets) +{ + ulong pos = 0, bit, bm; + + WRITE_UL(fp, cBuckets); + while ( pos < cBuckets ) + { + bm = 0; + for ( bit = 0; bit < 8*sizeof(ulong); bit++ ) + { + if ( !DenseIsEmpty(bin, pos) ) + SET_BITMAP(&bm, bit); /* in fks-hash.h */ + if ( ++pos == cBuckets ) + break; + } + WRITE_UL(fp, bm); + } +} + +static ulong DenseRead(FILE *fp, DenseBin **pbin) +{ + ulong pos = 0, bit, bm, cBuckets; + + READ_UL(fp, cBuckets); + cBuckets = DenseAllocate(pbin, cBuckets); + while ( pos < cBuckets ) + { + READ_UL(fp, bm); + for ( bit = 0; bit < 8*sizeof(ulong); bit++ ) + { + if ( TEST_BITMAP(&bm, bit) ) /* in fks-hash.h */ + DENSE_SET_OCCUPIED((*pbin)->rgBuckets, pos); + else + DENSE_SET_EMPTY((*pbin)->rgBuckets, pos); + if ( ++pos == cBuckets ) + break; + } + } + return cBuckets; +} + +static ulong DenseMemory(ulong cBuckets, ulong cOccupied) +{ + return cBuckets * sizeof(DenseBucket); +} + + +/* ======================================================================== */ +/* HASHING ROUTINES */ +/* ---------------------- */ + +/* Implements a simple quadratic hashing scheme. We have a single hash + * table of size t and a single hash function h(x). When inserting an + * item, first we try h(x) % t. If it's occupied, we try h(x) + + * i*(i-1)/2 % t for increasing values of i until we hit a not-occupied + * space. To make this dynamic, we double the size of the hash table as + * soon as more than half the cells are occupied. When deleting, we can + * choose to shrink the hashtable when less than a quarter of the + * cells are occupied, or we can choose never to shrink the hashtable. + * For lookup, we check h(x) + i*(i-1)/2 % t (starting with i=0) until + * we get a match or we hit an empty space. Note that as a result, + * we can't make a cell empty on deletion, or lookups may end prematurely. + * Instead we mark the cell as "deleted." We thus steal the value + * DELETED as a possible "data" value. As long as data are pointers, + * that's ok. + * The hash increment we use, i(i-1)/2, is not the standard quadratic + * hash increment, which is i^2. i(i-1)/2 covers the entire bucket space + * when the hashtable size is a power of two, as it is for us. In fact, + * the first n probes cover n distinct buckets; then it repeats. This + * guarantees insertion will always succeed. + * If you linear hashing, set JUMP in chash.h. You can also change + * various other parameters there. + */ + +/*************************************************************************\ +| Hash() | +| The hash function I use is due to Bob Jenkins (see | +| http://burtleburtle.net/bob/hash/evahash.html | +| According to http://burtleburtle.net/bob/c/lookup2.c, | +| his implementation is public domain.) | +| It takes 36 instructions, in 18 cycles if you're lucky. | +| hashing depends on the fact the hashtable size is always a | +| power of 2. cBuckets is probably ht->cBuckets. | +\*************************************************************************/ + +#if LOG_WORD_SIZE == 5 /* 32 bit words */ + +#define mix(a,b,c) \ +{ \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<<8); \ + c -= a; c -= b; c ^= (b>>13); \ + a -= b; a -= c; a ^= (c>>12); \ + b -= c; b -= a; b ^= (a<<16); \ + c -= a; c -= b; c ^= (b>>5); \ + a -= b; a -= c; a ^= (c>>3); \ + b -= c; b -= a; b ^= (a<<10); \ + c -= a; c -= b; c ^= (b>>15); \ +} +#ifdef WORD_HASH /* play with this on little-endian machines */ +#define WORD_AT(ptr) ( *(ulong *)(ptr) ) +#else +#define WORD_AT(ptr) ( (ptr)[0] + ((ulong)(ptr)[1]<<8) + \ + ((ulong)(ptr)[2]<<16) + ((ulong)(ptr)[3]<<24) ) +#endif + +#elif LOG_WORD_SIZE == 6 /* 64 bit words */ + +#define mix(a,b,c) \ +{ \ + a -= b; a -= c; a ^= (c>>43); \ + b -= c; b -= a; b ^= (a<<9); \ + c -= a; c -= b; c ^= (b>>8); \ + a -= b; a -= c; a ^= (c>>38); \ + b -= c; b -= a; b ^= (a<<23); \ + c -= a; c -= b; c ^= (b>>5); \ + a -= b; a -= c; a ^= (c>>35); \ + b -= c; b -= a; b ^= (a<<49); \ + c -= a; c -= b; c ^= (b>>11); \ + a -= b; a -= c; a ^= (c>>12); \ + b -= c; b -= a; b ^= (a<<18); \ + c -= a; c -= b; c ^= (b>>22); \ +} +#ifdef WORD_HASH /* alpha is little-endian, btw */ +#define WORD_AT(ptr) ( *(ulong *)(ptr) ) +#else +#define WORD_AT(ptr) ( (ptr)[0] + ((ulong)(ptr)[1]<<8) + \ + ((ulong)(ptr)[2]<<16) + ((ulong)(ptr)[3]<<24) + \ + ((ulong)(ptr)[4]<<32) + ((ulong)(ptr)[5]<<40) + \ + ((ulong)(ptr)[6]<<48) + ((ulong)(ptr)[7]<<56) ) +#endif + +#else /* neither 32 or 64 bit words */ +#error This hash function can only hash 32 or 64 bit words. Sorry. +#endif + +static ulong Hash(HashTable *ht, char *key, ulong cBuckets) +{ + ulong a, b, c, cchKey, cchKeyOrig; + + cchKeyOrig = ht->cchKey == NULL_TERMINATED ? strlen(key) : ht->cchKey; + a = b = c = 0x9e3779b9; /* the golden ratio; an arbitrary value */ + + for ( cchKey = cchKeyOrig; cchKey >= 3 * sizeof(ulong); + cchKey -= 3 * sizeof(ulong), key += 3 * sizeof(ulong) ) + { + a += WORD_AT(key); + b += WORD_AT(key + sizeof(ulong)); + c += WORD_AT(key + sizeof(ulong)*2); + mix(a,b,c); + } + + c += cchKeyOrig; + switch ( cchKey ) { /* deal with rest. Cases fall through */ +#if LOG_WORD_SIZE == 5 + case 11: c += (ulong)key[10]<<24; + case 10: c += (ulong)key[9]<<16; + case 9 : c += (ulong)key[8]<<8; + /* the first byte of c is reserved for the length */ + case 8 : b += WORD_AT(key+4); a+= WORD_AT(key); break; + case 7 : b += (ulong)key[6]<<16; + case 6 : b += (ulong)key[5]<<8; + case 5 : b += key[4]; + case 4 : a += WORD_AT(key); break; + case 3 : a += (ulong)key[2]<<16; + case 2 : a += (ulong)key[1]<<8; + case 1 : a += key[0]; + /* case 0 : nothing left to add */ +#elif LOG_WORD_SIZE == 6 + case 23: c += (ulong)key[22]<<56; + case 22: c += (ulong)key[21]<<48; + case 21: c += (ulong)key[20]<<40; + case 20: c += (ulong)key[19]<<32; + case 19: c += (ulong)key[18]<<24; + case 18: c += (ulong)key[17]<<16; + case 17: c += (ulong)key[16]<<8; + /* the first byte of c is reserved for the length */ + case 16: b += WORD_AT(key+8); a+= WORD_AT(key); break; + case 15: b += (ulong)key[14]<<48; + case 14: b += (ulong)key[13]<<40; + case 13: b += (ulong)key[12]<<32; + case 12: b += (ulong)key[11]<<24; + case 11: b += (ulong)key[10]<<16; + case 10: b += (ulong)key[ 9]<<8; + case 9: b += (ulong)key[ 8]; + case 8: a += WORD_AT(key); break; + case 7: a += (ulong)key[ 6]<<48; + case 6: a += (ulong)key[ 5]<<40; + case 5: a += (ulong)key[ 4]<<32; + case 4: a += (ulong)key[ 3]<<24; + case 3: a += (ulong)key[ 2]<<16; + case 2: a += (ulong)key[ 1]<<8; + case 1: a += (ulong)key[ 0]; + /* case 0: nothing left to add */ +#endif + } + mix(a,b,c); + return c & (cBuckets-1); +} + + +/*************************************************************************\ +| Rehash() | +| You give me a hashtable, a new size, and a bucket to follow, and | +| I resize the hashtable's bin to be the new size, rehashing | +| everything in it. I keep particular track of the bucket you pass | +| in, and RETURN a pointer to where the item in the bucket got to. | +| (If you pass in NULL, I return an arbitrary pointer.) | +\*************************************************************************/ + +static HTItem *Rehash(HashTable *ht, ulong cNewBuckets, HTItem *bckWatch) +{ + Table *tableNew; + ulong iBucketFirst; + HTItem *bck, *bckNew = NULL; + ulong offset; /* the i in h(x) + i*(i-1)/2 */ + int fOverwrite = 0; /* not an issue: there can be no collisions */ + + assert( ht->table ); + cNewBuckets = Table(Allocate)(&tableNew, cNewBuckets); + /* Since we RETURN the new position of bckWatch, we want * + * to make sure it doesn't get moved due to some table * + * rehashing that comes after it's inserted. Thus, we * + * have to put it in last. This makes the loop weird. */ + for ( bck = HashFirstBucket(ht); ; bck = HashNextBucket(ht) ) + { + if ( bck == NULL ) /* we're done iterating, so look at bckWatch */ + { + bck = bckWatch; + if ( bck == NULL ) /* I guess bckWatch wasn't specified */ + break; + } + else if ( bck == bckWatch ) + continue; /* ignore if we see it during the iteration */ + + offset = 0; /* a new i for a new bucket */ + for ( iBucketFirst = Hash(ht, KEY_PTR(ht, bck->key), cNewBuckets); + !Table(IsEmpty)(tableNew, iBucketFirst); + iBucketFirst = (iBucketFirst + JUMP(KEY_PTR(ht,bck->key), offset)) + & (cNewBuckets-1) ) + ; + bckNew = Table(Insert)(tableNew, bck, iBucketFirst, &fOverwrite); + if ( bck == bckWatch ) /* we're done with the last thing to do */ + break; + } + Table(Free)(ht->table, ht->cBuckets); + ht->table = tableNew; + ht->cBuckets = cNewBuckets; + ht->cDeletedItems = 0; + return bckNew; /* new position of bckWatch, which was inserted last */ +} + +/*************************************************************************\ +| Find() | +| Does the quadratic searching stuff. RETURNS NULL if we don't | +| find an object with the given key, and a pointer to the Item | +| holding the key, if we do. Also sets posLastFind. If piEmpty is | +| non-NULL, we set it to the first open bucket we pass; helpful for | +| doing a later insert if the search fails, for instance. | +\*************************************************************************/ + +static HTItem *Find(HashTable *ht, ulong key, ulong *piEmpty) +{ + ulong iBucketFirst; + HTItem *item; + ulong offset = 0; /* the i in h(x) + i*(i-1)/2 */ + int fFoundEmpty = 0; /* set when we pass over an empty bucket */ + + ht->posLastFind = NULL; /* set up for failure: a new find starts */ + if ( ht->table == NULL ) /* empty hash table: find is bound to fail */ + return NULL; + + iBucketFirst = Hash(ht, KEY_PTR(ht, key), ht->cBuckets); + while ( 1 ) /* now try all i > 0 */ + { + item = Table(Find)(ht->table, iBucketFirst); + if ( item == NULL ) /* it's not in the table */ + { + if ( piEmpty && !fFoundEmpty ) *piEmpty = iBucketFirst; + return NULL; + } + else + { + if ( IS_BCK_DELETED(item) ) /* always 0 ifdef INSERT_ONLY */ + { + if ( piEmpty && !fFoundEmpty ) + { + *piEmpty = iBucketFirst; + fFoundEmpty = 1; + } + } else + if ( !KEY_CMP(ht, key, item->key) ) /* must be occupied */ + { + ht->posLastFind = item; + return item; /* we found it! */ + } + } + iBucketFirst = ((iBucketFirst + JUMP(KEY_PTR(ht, key), offset)) + & (ht->cBuckets-1)); + } +} + +/*************************************************************************\ +| Insert() | +| If an item with the key already exists in the hashtable, RETURNS | +| a pointer to the item (replacing its data if fOverwrite is 1). | +| If not, we find the first place-to-insert (which Find() is nice | +| enough to set for us) and insert the item there, RETURNing a | +| pointer to the item. We might grow the hashtable if it's getting | +| full. Note we include buckets holding DELETED when determining | +| fullness, because they slow down searching. | +\*************************************************************************/ + +static ulong NextPow2(ulong x) /* returns next power of 2 > x, or 2^31 */ +{ + if ( ((x << 1) >> 1) != x ) /* next power of 2 overflows */ + x >>= 1; /* so we return highest power of 2 we can */ + while ( (x & (x-1)) != 0 ) /* blacks out all but the top bit */ + x &= (x-1); + return x << 1; /* makes it the *next* power of 2 */ +} + +static HTItem *Insert(HashTable *ht, ulong key, ulong data, int fOverwrite) +{ + HTItem *item, bckInsert; + ulong iEmpty; /* first empty bucket key probes */ + + if ( ht->table == NULL ) /* empty hash table: find is bound to fail */ + return NULL; + item = Find(ht, key, &iEmpty); + ht->posLastFind = NULL; /* last operation is insert, not find */ + if ( item ) + { + if ( fOverwrite ) + item->data = data; /* key already matches */ + return item; + } + + COPY_KEY(ht, bckInsert.key, key); /* make our own copy of the key */ + bckInsert.data = data; /* oh, and the data too */ + item = Table(Insert)(ht->table, &bckInsert, iEmpty, &fOverwrite); + if ( fOverwrite ) /* we overwrote a deleted bucket */ + ht->cDeletedItems--; + ht->cItems++; /* insert couldn't have overwritten */ + if ( ht->cDeltaGoalSize > 0 ) /* closer to our goal size */ + ht->cDeltaGoalSize--; + if ( ht->cItems + ht->cDeletedItems >= ht->cBuckets * OCCUPANCY_PCT + || ht->cDeltaGoalSize < 0 ) /* we must've overestimated # of deletes */ + item = Rehash(ht, + NextPow2((ulong)(((ht->cDeltaGoalSize > 0 ? + ht->cDeltaGoalSize : 0) + + ht->cItems) / OCCUPANCY_PCT)), + item); + return item; +} + +/*************************************************************************\ +| Delete() | +| Removes the item from the hashtable, and if fShrink is 1, will | +| shrink the hashtable if it's too small (ie even after halving, | +| the ht would be less than half full, though in order to avoid | +| oscillating table size, we insist that after halving the ht would | +| be less than 40% full). RETURNS 1 if the item was found, 0 else. | +| If fLastFindSet is true, then this function is basically | +| DeleteLastFind. | +\*************************************************************************/ + +static int Delete(HashTable *ht, ulong key, int fShrink, int fLastFindSet) +{ + if ( !fLastFindSet && !Find(ht, key, NULL) ) + return 0; + SET_BCK_DELETED(ht, ht->posLastFind); /* find set this, how nice */ + ht->cItems--; + ht->cDeletedItems++; + if ( ht->cDeltaGoalSize < 0 ) /* heading towards our goal of deletion */ + ht->cDeltaGoalSize++; + + if ( fShrink && ht->cItems < ht->cBuckets * OCCUPANCY_PCT*0.4 + && ht->cDeltaGoalSize >= 0 /* wait until we're done deleting */ + && (ht->cBuckets >> 1) >= MIN_HASH_SIZE ) /* shrink */ + Rehash(ht, + NextPow2((ulong)((ht->cItems+ht->cDeltaGoalSize)/OCCUPANCY_PCT)), + NULL); + ht->posLastFind = NULL; /* last operation is delete, not find */ + return 1; +} + + +/* ======================================================================== */ +/* USER-VISIBLE API */ +/* ---------------------- */ + +/*************************************************************************\ +| AllocateHashTable() | +| ClearHashTable() | +| FreeHashTable() | +| Allocate() allocates a hash table and sets up size parameters. | +| Free() frees it. Clear() deletes all the items from the hash | +| table, but frees not. | +| cchKey is < 0 if the keys you send me are meant to be pointers | +| to \0-terminated strings. Then -cchKey is the maximum key size. | +| If cchKey < one word (ulong), the keys you send me are the keys | +| themselves; else the keys you send me are pointers to the data. | +| If fSaveKeys is 1, we copy any keys given to us to insert. We | +| also free these keys when freeing the hash table. If it's 0, the | +| user is responsible for key space management. | +| AllocateHashTable() RETURNS a hash table; the others TAKE one. | +\*************************************************************************/ + +HashTable *AllocateHashTable(int cchKey, int fSaveKeys) +{ + HashTable *ht; + + ht = (HashTable *) HTsmalloc(sizeof(*ht)); /* set everything to 0 */ + ht->cBuckets = Table(Allocate)(&ht->table, MIN_HASH_SIZE); + ht->cchKey = cchKey <= 0 ? NULL_TERMINATED : cchKey; + ht->cItems = 0; + ht->cDeletedItems = 0; + ht->fSaveKeys = fSaveKeys; + ht->cDeltaGoalSize = 0; + ht->iter = HTsmalloc( sizeof(TableIterator) ); + + ht->fpData = NULL; /* set by HashLoad, maybe */ + ht->bckData.data = (ulong) NULL; /* this must be done */ + HTSetupKeyTrunc(); /* in util.c */ + return ht; +} + +void ClearHashTable(HashTable *ht) +{ + HTItem *bck; + + if ( STORES_PTR(ht) && ht->fSaveKeys ) /* need to free keys */ + for ( bck = HashFirstBucket(ht); bck; bck = HashNextBucket(ht) ) + { + FREE_KEY(ht, bck->key); + if ( ht->fSaveKeys == 2 ) /* this means key stored in one block */ + break; /* ...so only free once */ + } + Table(Free)(ht->table, ht->cBuckets); + ht->cBuckets = Table(Allocate)(&ht->table, MIN_HASH_SIZE); + + ht->cItems = 0; + ht->cDeletedItems = 0; + ht->cDeltaGoalSize = 0; + ht->posLastFind = NULL; + ht->fpData = NULL; /* no longer HashLoading */ + if ( ht->bckData.data ) free( (char *)(ht)->bckData.data); + ht->bckData.data = (ulong) NULL; +} + +void FreeHashTable(HashTable *ht) +{ + ClearHashTable(ht); + if ( ht->iter ) HTfree(ht->iter, sizeof(TableIterator)); + if ( ht->table ) Table(Free)(ht->table, ht->cBuckets); + free(ht); +} + +/*************************************************************************\ +| HashFind() | +| HashFindLast() | +| HashFind(): looks in h(x) + i(i-1)/2 % t as i goes up from 0 | +| until we either find the key or hit an empty bucket. RETURNS a | +| pointer to the item in the hit bucket, if we find it, else | +| RETURNS NULL. | +| HashFindLast() returns the item returned by the last | +| HashFind(), which may be NULL if the last HashFind() failed. | +| LOAD_AND_RETURN reads the data from off disk, if necessary. | +\*************************************************************************/ + +HTItem *HashFind(HashTable *ht, ulong key) +{ + LOAD_AND_RETURN(ht, Find(ht, KEY_TRUNC(ht, key), NULL)); +} + +HTItem *HashFindLast(HashTable *ht) +{ + LOAD_AND_RETURN(ht, ht->posLastFind); +} + +/*************************************************************************\ +| HashFindOrInsert() | +| HashFindOrInsertItem() | +| HashInsert() | +| HashInsertItem() | +| HashDelete() | +| HashDeleteLast() | +| Pretty obvious what these guys do. Some take buckets (items), | +| some take keys and data separately. All things RETURN the bucket | +| (a pointer into the hashtable) if appropriate. | +\*************************************************************************/ + +HTItem *HashFindOrInsert(HashTable *ht, ulong key, ulong dataInsert) +{ + /* This is equivalent to Insert without samekey-overwrite */ + return Insert(ht, KEY_TRUNC(ht, key), dataInsert, 0); +} + +HTItem *HashFindOrInsertItem(HashTable *ht, HTItem *pItem) +{ + return HashFindOrInsert(ht, pItem->key, pItem->data); +} + +HTItem *HashInsert(HashTable *ht, ulong key, ulong data) +{ + return Insert(ht, KEY_TRUNC(ht, key), data, SAMEKEY_OVERWRITE); +} + +HTItem *HashInsertItem(HashTable *ht, HTItem *pItem) +{ + return HashInsert(ht, pItem->key, pItem->data); +} + +int HashDelete(HashTable *ht, ulong key) +{ + return Delete(ht, KEY_TRUNC(ht, key), !FAST_DELETE, 0); +} + +int HashDeleteLast(HashTable *ht) +{ + if ( !ht->posLastFind ) /* last find failed */ + return 0; + return Delete(ht, 0, !FAST_DELETE, 1); /* no need to specify a key */ +} + +/*************************************************************************\ +| HashFirstBucket() | +| HashNextBucket() | +| Iterates through the items in the hashtable by iterating through | +| the table. Since we know about deleted buckets and loading data | +| off disk, and the table doesn't, our job is to take care of these | +| things. RETURNS a bucket, or NULL after the last bucket. | +\*************************************************************************/ + +HTItem *HashFirstBucket(HashTable *ht) +{ + HTItem *retval; + + for ( retval = Table(FirstBucket)(ht->iter, ht->table, ht->cBuckets); + retval; retval = Table(NextBucket)(ht->iter) ) + if ( !IS_BCK_DELETED(retval) ) + LOAD_AND_RETURN(ht, retval); + return NULL; +} + +HTItem *HashNextBucket(HashTable *ht) +{ + HTItem *retval; + + while ( (retval=Table(NextBucket)(ht->iter)) ) + if ( !IS_BCK_DELETED(retval) ) + LOAD_AND_RETURN(ht, retval); + return NULL; +} + +/*************************************************************************\ +| HashSetDeltaGoalSize() | +| If we're going to insert 100 items, set the delta goal size to | +| 100 and we take that into account when inserting. Likewise, if | +| we're going to delete 10 items, set it to -100 and we won't | +| rehash until all 100 have been done. It's ok to be wrong, but | +| it's efficient to be right. Returns the delta value. | +\*************************************************************************/ + +int HashSetDeltaGoalSize(HashTable *ht, int delta) +{ + ht->cDeltaGoalSize = delta; +#if FAST_DELETE == 1 || defined INSERT_ONLY + if ( ht->cDeltaGoalSize < 0 ) /* for fast delete, we never */ + ht->cDeltaGoalSize = 0; /* ...rehash after deletion */ +#endif + return ht->cDeltaGoalSize; +} + + +/*************************************************************************\ +| HashSave() | +| HashLoad() | +| HashLoadKeys() | +| Routines for saving and loading the hashtable from disk. We can | +| then use the hashtable in two ways: loading it back into memory | +| (HashLoad()) or loading only the keys into memory, in which case | +| the data for a given key is loaded off disk when the key is | +| retrieved. The data is freed when something new is retrieved in | +| its place, so this is not a "lazy-load" scheme. | +| The key is saved automatically and restored upon load, but the | +| user needs to specify a routine for reading and writing the data. | +| fSaveKeys is of course set to 1 when you read in a hashtable. | +| HashLoad RETURNS a newly allocated hashtable. | +| DATA_WRITE() takes an fp and a char * (representing the data | +| field), and must perform two separate tasks. If fp is NULL, | +| return the number of bytes written. If not, writes the data to | +| disk at the place the fp points to. | +| DATA_READ() takes an fp and the number of bytes in the data | +| field, and returns a char * which points to wherever you've | +| written the data. Thus, you must allocate memory for the data. | +| Both dataRead and dataWrite may be NULL if you just wish to | +| store the data field directly, as an integer. | +\*************************************************************************/ + +void HashSave(FILE *fp, HashTable *ht, int (*dataWrite)(FILE *, char *)) +{ + long cchData, posStart; + HTItem *bck; + + /* File format: magic number (4 bytes) + : cchKey (one word) + : cItems (one word) + : cDeletedItems (one word) + : table info (buckets and a bitmap) + : cchAllKeys (one word) + Then the keys, in a block. If cchKey is NULL_TERMINATED, the keys + are null-terminated too, otherwise this takes up cchKey*cItems bytes. + Note that keys are not written for DELETED buckets. + Then the data: + : EITHER DELETED (one word) to indicate it's a deleted bucket, + : OR number of bytes for this (non-empty) bucket's data + (one word). This is not stored if dataWrite == NULL + since the size is known to be sizeof(ul). Plus: + : the data for this bucket (variable length) + All words are in network byte order. */ + + fprintf(fp, "%s", MAGIC_KEY); + WRITE_UL(fp, ht->cchKey); /* WRITE_UL, READ_UL, etc in fks-hash.h */ + WRITE_UL(fp, ht->cItems); + WRITE_UL(fp, ht->cDeletedItems); + Table(Write)(fp, ht->table, ht->cBuckets); /* writes cBuckets too */ + + WRITE_UL(fp, 0); /* to be replaced with sizeof(key block) */ + posStart = ftell(fp); + for ( bck = HashFirstBucket(ht); bck; bck = HashNextBucket(ht) ) + fwrite(KEY_PTR(ht, bck->key), 1, + (ht->cchKey == NULL_TERMINATED ? + strlen(KEY_PTR(ht, bck->key))+1 : ht->cchKey), fp); + cchData = ftell(fp) - posStart; + fseek(fp, posStart - sizeof(unsigned long), SEEK_SET); + WRITE_UL(fp, cchData); + fseek(fp, 0, SEEK_END); /* done with our sojourn at the header */ + + /* Unlike HashFirstBucket, TableFirstBucket iters through deleted bcks */ + for ( bck = Table(FirstBucket)(ht->iter, ht->table, ht->cBuckets); + bck; bck = Table(NextBucket)(ht->iter) ) + if ( dataWrite == NULL || IS_BCK_DELETED(bck) ) + WRITE_UL(fp, bck->data); + else /* write cchData followed by the data */ + { + WRITE_UL(fp, (*dataWrite)(NULL, (char *)bck->data)); + (*dataWrite)(fp, (char *)bck->data); + } +} + +static HashTable *HashDoLoad(FILE *fp, char * (*dataRead)(FILE *, int), + HashTable *ht) +{ + ulong cchKey; + char szMagicKey[4], *rgchKeys; + HTItem *bck; + + fread(szMagicKey, 1, 4, fp); + if ( strncmp(szMagicKey, MAGIC_KEY, 4) ) + { + fprintf(stderr, "ERROR: not a hash table (magic key is %4.4s, not %s)\n", + szMagicKey, MAGIC_KEY); + exit(3); + } + Table(Free)(ht->table, ht->cBuckets); /* allocated in AllocateHashTable */ + + READ_UL(fp, ht->cchKey); + READ_UL(fp, ht->cItems); + READ_UL(fp, ht->cDeletedItems); + ht->cBuckets = Table(Read)(fp, &ht->table); /* next is the table info */ + + READ_UL(fp, cchKey); + rgchKeys = (char *) HTsmalloc( cchKey ); /* stores all the keys */ + fread(rgchKeys, 1, cchKey, fp); + /* We use the table iterator so we don't try to LOAD_AND_RETURN */ + for ( bck = Table(FirstBucket)(ht->iter, ht->table, ht->cBuckets); + bck; bck = Table(NextBucket)(ht->iter) ) + { + READ_UL(fp, bck->data); /* all we need if dataRead is NULL */ + if ( IS_BCK_DELETED(bck) ) /* always 0 if defined(INSERT_ONLY) */ + continue; /* this is why we read the data first */ + if ( dataRead != NULL ) /* if it's null, we're done */ + if ( !ht->fpData ) /* load data into memory */ + bck->data = (ulong)dataRead(fp, bck->data); + else /* store location of data on disk */ + { + fseek(fp, bck->data, SEEK_CUR); /* bck->data held size of data */ + bck->data = ftell(fp) - bck->data - sizeof(unsigned long); + } + + if ( ht->cchKey == NULL_TERMINATED ) /* now read the key */ + { + bck->key = (ulong) rgchKeys; + rgchKeys = strchr(rgchKeys, '\0') + 1; /* read past the string */ + } + else + { + if ( STORES_PTR(ht) ) /* small keys stored directly */ + bck->key = (ulong) rgchKeys; + else + memcpy(&bck->key, rgchKeys, ht->cchKey); + rgchKeys += ht->cchKey; + } + } + if ( !STORES_PTR(ht) ) /* keys are stored directly */ + HTfree(rgchKeys - cchKey, cchKey); /* we've advanced rgchK to end */ + return ht; +} + +HashTable *HashLoad(FILE *fp, char * (*dataRead)(FILE *, int)) +{ + HashTable *ht; + ht = AllocateHashTable(0, 2); /* cchKey set later, fSaveKey should be 2! */ + return HashDoLoad(fp, dataRead, ht); +} + +HashTable *HashLoadKeys(FILE *fp, char * (*dataRead)(FILE *, int)) +{ + HashTable *ht; + + if ( dataRead == NULL ) + return HashLoad(fp, NULL); /* no reason not to load the data here */ + ht = AllocateHashTable(0, 2); /* cchKey set later, fSaveKey should be 2! */ + ht->fpData = fp; /* tells HashDoLoad() to only load keys */ + ht->dataRead = dataRead; + return HashDoLoad(fp, dataRead, ht); +} + +/*************************************************************************\ +| PrintHashTable() | +| A debugging tool. Prints the entire contents of the hash table, | +| like so: : key of the contents. Returns number of bytes | +| allocated. If time is not -1, we print it as the time required | +| for the hash. If iForm is 0, we just print the stats. If it's | +| 1, we print the keys and data too, but the keys are printed as | +| ulongs. If it's 2, we print the keys correctly (as long numbers | +| or as strings). | +\*************************************************************************/ + +ulong PrintHashTable(HashTable *ht, double time, int iForm) +{ + ulong cbData = 0, cbBin = 0, cItems = 0, cOccupied = 0; + HTItem *item; + + printf("HASH TABLE.\n"); + if ( time > -1.0 ) + { + printf("----------\n"); + printf("Time: %27.2f\n", time); + } + + for ( item = Table(FirstBucket)(ht->iter, ht->table, ht->cBuckets); + item; item = Table(NextBucket)(ht->iter) ) + { + cOccupied++; /* this includes deleted buckets */ + if ( IS_BCK_DELETED(item) ) /* we don't need you for anything else */ + continue; + cItems++; /* this is for a sanity check */ + if ( STORES_PTR(ht) ) + cbData += ht->cchKey == NULL_TERMINATED ? + WORD_ROUND(strlen((char *)item->key)+1) : ht->cchKey; + else + cbBin -= sizeof(item->key), cbData += sizeof(item->key); + cbBin -= sizeof(item->data), cbData += sizeof(item->data); + if ( iForm != 0 ) /* we want the actual contents */ + { + if ( iForm == 2 && ht->cchKey == NULL_TERMINATED ) + printf("%s/%lu\n", (char *)item->key, item->data); + else if ( iForm == 2 && STORES_PTR(ht) ) + printf("%.*s/%lu\n", + (int)ht->cchKey, (char *)item->key, item->data); + else /* either key actually is a ulong, or iForm == 1 */ + printf("%lu/%lu\n", item->key, item->data); + } + } + assert( cItems == ht->cItems ); /* sanity check */ + cbBin = Table(Memory)(ht->cBuckets, cOccupied); + + printf("----------\n"); + printf("%lu buckets (%lu bytes). %lu empty. %lu hold deleted items.\n" + "%lu items (%lu bytes).\n" + "%lu bytes total. %lu bytes (%2.1f%%) of this is ht overhead.\n", + ht->cBuckets, cbBin, ht->cBuckets - cOccupied, cOccupied - ht->cItems, + ht->cItems, cbData, + cbData + cbBin, cbBin, cbBin*100.0/(cbBin+cbData)); + + return cbData + cbBin; +} diff --git a/src/sparsehash-1.6/experimental/libchash.h b/src/sparsehash-1.6/experimental/libchash.h new file mode 100644 index 0000000..0c0f70a --- /dev/null +++ b/src/sparsehash-1.6/experimental/libchash.h @@ -0,0 +1,252 @@ +/* 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 /* 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)); diff --git a/src/sparsehash-1.6/google-sparsehash.sln b/src/sparsehash-1.6/google-sparsehash.sln new file mode 100755 index 0000000..6148fb5 --- /dev/null +++ b/src/sparsehash-1.6/google-sparsehash.sln @@ -0,0 +1,47 @@ +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 diff --git a/src/sparsehash-1.6/hashtable_unittest b/src/sparsehash-1.6/hashtable_unittest new file mode 100755 index 0000000..d4ce1fc Binary files /dev/null and b/src/sparsehash-1.6/hashtable_unittest differ diff --git a/src/sparsehash-1.6/m4/acx_pthread.m4 b/src/sparsehash-1.6/m4/acx_pthread.m4 new file mode 100644 index 0000000..2cf20de --- /dev/null +++ b/src/sparsehash-1.6/m4/acx_pthread.m4 @@ -0,0 +1,363 @@ +# 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 +dnl @version 2006-05-29 +dnl @license GPLWithACException +dnl +dnl Checks for GCC shared/pthread inconsistency based on work by +dnl Marcin Owsiany + + +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_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 ], [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_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_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_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 diff --git a/src/sparsehash-1.6/m4/google_namespace.m4 b/src/sparsehash-1.6/m4/google_namespace.m4 new file mode 100644 index 0000000..7f244cc --- /dev/null +++ b/src/sparsehash-1.6/m4/google_namespace.m4 @@ -0,0 +1,42 @@ +# 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) +]) diff --git a/src/sparsehash-1.6/m4/namespaces.m4 b/src/sparsehash-1.6/m4/namespaces.m4 new file mode 100644 index 0000000..d78dbe4 --- /dev/null +++ b/src/sparsehash-1.6/m4/namespaces.m4 @@ -0,0 +1,15 @@ +# 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]) diff --git a/src/sparsehash-1.6/m4/stl_hash.m4 b/src/sparsehash-1.6/m4/stl_hash.m4 new file mode 100644 index 0000000..a31baab --- /dev/null +++ b/src/sparsehash-1.6/m4/stl_hash.m4 @@ -0,0 +1,70 @@ +# 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 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 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 or ]) + AC_DEFINE_UNQUOTED(HASH_SET_H,$ac_cv_cxx_hash_set, + [the location of or ]) + 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 +]) diff --git a/src/sparsehash-1.6/m4/stl_hash_fun.m4 b/src/sparsehash-1.6/m4/stl_hash_fun.m4 new file mode 100644 index 0000000..962b088 --- /dev/null +++ b/src/sparsehash-1.6/m4/stl_hash_fun.m4 @@ -0,0 +1,36 @@ +# 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()(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]) +]) diff --git a/src/sparsehash-1.6/m4/stl_namespace.m4 b/src/sparsehash-1.6/m4/stl_namespace.m4 new file mode 100644 index 0000000..989ad80 --- /dev/null +++ b/src/sparsehash-1.6/m4/stl_namespace.m4 @@ -0,0 +1,25 @@ +# 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 t; return 0;], + ac_cv_cxx_stl_namespace=none) + AC_TRY_COMPILE([#include ], + [std::vector 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 +]) diff --git a/src/sparsehash-1.6/missing b/src/sparsehash-1.6/missing new file mode 100755 index 0000000..894e786 --- /dev/null +++ b/src/sparsehash-1.6/missing @@ -0,0 +1,360 @@ +#! /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 , 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 ." + 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: diff --git a/src/sparsehash-1.6/mkinstalldirs b/src/sparsehash-1.6/mkinstalldirs new file mode 100755 index 0000000..259dbfc --- /dev/null +++ b/src/sparsehash-1.6/mkinstalldirs @@ -0,0 +1,158 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy + +scriptversion=2005-06-29.22 + +# Original author: Noah Friedman +# Created: 1993-05-16 +# Public domain. +# +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +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 ." + +# 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: diff --git a/src/sparsehash-1.6/packages/deb.sh b/src/sparsehash-1.6/packages/deb.sh new file mode 100755 index 0000000..31b423c --- /dev/null +++ b/src/sparsehash-1.6/packages/deb.sh @@ -0,0 +1,74 @@ +#!/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" diff --git a/src/sparsehash-1.6/packages/deb/README b/src/sparsehash-1.6/packages/deb/README new file mode 100644 index 0000000..57becfd --- /dev/null +++ b/src/sparsehash-1.6/packages/deb/README @@ -0,0 +1,7 @@ +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'. diff --git a/src/sparsehash-1.6/packages/deb/changelog b/src/sparsehash-1.6/packages/deb/changelog new file mode 100644 index 0000000..7786c37 --- /dev/null +++ b/src/sparsehash-1.6/packages/deb/changelog @@ -0,0 +1,113 @@ +sparsehash (1.6-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Fri, 08 Jan 2010 14:47:55 -0800 + +sparsehash (1.5.2-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Tue, 12 May 2009 14:16:38 -0700 + +sparsehash (1.5.1-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Fri, 08 May 2009 15:23:44 -0700 + +sparsehash (1.5-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Wed, 06 May 2009 11:28:49 -0700 + +sparsehash (1.4-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Wed, 28 Jan 2009 17:11:31 -0800 + +sparsehash (1.3-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Thu, 06 Nov 2008 15:06:09 -0800 + +sparsehash (1.2-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Thu, 18 Sep 2008 13:53:20 -0700 + +sparsehash (1.1-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. 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. Tue, 13 Nov 2007 15:15:46 -0800 + +sparsehash (0.9.1-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Fri, 12 Oct 2007 12:35:24 -0700 + +sparsehash (0.9-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Tue, 09 Oct 2007 14:15:21 -0700 + +sparsehash (0.8-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Tue, 03 Jul 2007 12:55:04 -0700 + +sparsehash (0.7-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Mon, 11 Jun 2007 11:33:41 -0700 + +sparsehash (0.6-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Tue, 20 Mar 2007 17:29:34 -0700 + +sparsehash (0.5-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Sat, 21 Oct 2006 13:47:47 -0700 + +sparsehash (0.4-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Sun, 23 Apr 2006 22:42:35 -0700 + +sparsehash (0.3-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Thu, 03 Nov 2005 20:12:31 -0800 + +sparsehash (0.2-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Mon, 02 May 2005 07:04:46 -0700 + +sparsehash (0.1-1) unstable; urgency=low + + * Initial release. + + -- Google Inc. Tue, 15 Feb 2005 07:17:02 -0800 diff --git a/src/sparsehash-1.6/packages/deb/compat b/src/sparsehash-1.6/packages/deb/compat new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/src/sparsehash-1.6/packages/deb/compat @@ -0,0 +1 @@ +4 diff --git a/src/sparsehash-1.6/packages/deb/control b/src/sparsehash-1.6/packages/deb/control new file mode 100644 index 0000000..c387952 --- /dev/null +++ b/src/sparsehash-1.6/packages/deb/control @@ -0,0 +1,17 @@ +Source: sparsehash +Section: libdevel +Priority: optional +Maintainer: Google Inc. +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. diff --git a/src/sparsehash-1.6/packages/deb/copyright b/src/sparsehash-1.6/packages/deb/copyright new file mode 100644 index 0000000..725a37d --- /dev/null +++ b/src/sparsehash-1.6/packages/deb/copyright @@ -0,0 +1,35 @@ +This package was debianized by Google Inc. 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. diff --git a/src/sparsehash-1.6/packages/deb/docs b/src/sparsehash-1.6/packages/deb/docs new file mode 100644 index 0000000..752adb4 --- /dev/null +++ b/src/sparsehash-1.6/packages/deb/docs @@ -0,0 +1,16 @@ +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 diff --git a/src/sparsehash-1.6/packages/deb/rules b/src/sparsehash-1.6/packages/deb/rules new file mode 100755 index 0000000..f520bef --- /dev/null +++ b/src/sparsehash-1.6/packages/deb/rules @@ -0,0 +1,117 @@ +#!/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 diff --git a/src/sparsehash-1.6/packages/deb/sparsehash.dirs b/src/sparsehash-1.6/packages/deb/sparsehash.dirs new file mode 100644 index 0000000..4f17144 --- /dev/null +++ b/src/sparsehash-1.6/packages/deb/sparsehash.dirs @@ -0,0 +1,2 @@ +usr/include +usr/include/google diff --git a/src/sparsehash-1.6/packages/deb/sparsehash.install b/src/sparsehash-1.6/packages/deb/sparsehash.install new file mode 100644 index 0000000..9625860 --- /dev/null +++ b/src/sparsehash-1.6/packages/deb/sparsehash.install @@ -0,0 +1,2 @@ +usr/include/google/* +debian/tmp/usr/include/google/* diff --git a/src/sparsehash-1.6/packages/rpm.sh b/src/sparsehash-1.6/packages/rpm.sh new file mode 100755 index 0000000..a655080 --- /dev/null +++ b/src/sparsehash-1.6/packages/rpm.sh @@ -0,0 +1,86 @@ +#!/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 " 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" diff --git a/src/sparsehash-1.6/packages/rpm/rpm.spec b/src/sparsehash-1.6/packages/rpm/rpm.spec new file mode 100644 index 0000000..f412efe --- /dev/null +++ b/src/sparsehash-1.6/packages/rpm/rpm.spec @@ -0,0 +1,61 @@ +%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 +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 + - 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 + - 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 diff --git a/src/sparsehash-1.6/simple_test b/src/sparsehash-1.6/simple_test new file mode 100755 index 0000000..e2b9a84 Binary files /dev/null and b/src/sparsehash-1.6/simple_test differ diff --git a/src/sparsehash-1.6/sparsetable_unittest b/src/sparsehash-1.6/sparsetable_unittest new file mode 100755 index 0000000..39eeecf Binary files /dev/null and b/src/sparsehash-1.6/sparsetable_unittest differ diff --git a/src/sparsehash-1.6/src/config.h b/src/sparsehash-1.6/src/config.h new file mode 100644 index 0000000..4183665 --- /dev/null +++ b/src/sparsehash-1.6/src/config.h @@ -0,0 +1,132 @@ +/* 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 + +/* the location of or */ +#define HASH_MAP_H + +/* the namespace of the hash<> function */ +#define HASH_NAMESPACE std::tr1 + +/* the location of or */ +#define HASH_SET_H + +/* Define to 1 if you have the 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 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 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 header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the 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 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 { diff --git a/src/sparsehash-1.6/src/config.h.in b/src/sparsehash-1.6/src/config.h.in new file mode 100644 index 0000000..bef1650 --- /dev/null +++ b/src/sparsehash-1.6/src/config.h.in @@ -0,0 +1,131 @@ +/* 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 or */ +#undef HASH_MAP_H + +/* the namespace of the hash<> function */ +#undef HASH_NAMESPACE + +/* the location of or */ +#undef HASH_SET_H + +/* Define to 1 if you have the 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 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 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 header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the 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 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_ diff --git a/src/sparsehash-1.6/src/config.h.include b/src/sparsehash-1.6/src/config.h.include new file mode 100644 index 0000000..5b0e3a2 --- /dev/null +++ b/src/sparsehash-1.6/src/config.h.include @@ -0,0 +1,23 @@ +/*** + *** 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_ diff --git a/src/sparsehash-1.6/src/google/dense_hash_map b/src/sparsehash-1.6/src/google/dense_hash_map new file mode 100644 index 0000000..888643a --- /dev/null +++ b/src/sparsehash-1.6/src/google/dense_hash_map @@ -0,0 +1,319 @@ +// 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 +#include // for FILE * in read()/write() +#include // for the default template args +#include // for equal_to +#include // for alloc<> +#include // for pair<> +#include HASH_FUN_H // defined in config.h +#include + + +_START_GOOGLE_NAMESPACE_ + +using STL_NAMESPACE::pair; + +template , // defined in sparseconfig.h + class EqualKey = STL_NAMESPACE::equal_to, + class Alloc = STL_NAMESPACE::allocator > +class dense_hash_map { + private: + // Apparently select1st is not stl-standard, so we define our own + struct SelectKey { + const Key& operator()(const pair& p) const { + return p.first; + } + }; + struct SetKey { + void operator()(pair* value, const Key& new_key) const { + *const_cast(&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, 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 + 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 equal_range(const key_type& key) { + return rep.equal_range(key); + } + pair equal_range(const key_type& key) const { + return rep.equal_range(key); + } + + // Insertion routines + pair insert(const value_type& obj) { return rep.insert(obj); } + template + 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 +inline void swap(dense_hash_map& hm1, + dense_hash_map& hm2) { + hm1.swap(hm2); +} + +_END_GOOGLE_NAMESPACE_ + +#endif /* _DENSE_HASH_MAP_H_ */ diff --git a/src/sparsehash-1.6/src/google/dense_hash_set b/src/sparsehash-1.6/src/google/dense_hash_set new file mode 100644 index 0000000..75be3e3 --- /dev/null +++ b/src/sparsehash-1.6/src/google/dense_hash_set @@ -0,0 +1,296 @@ +// 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 +#include // for FILE * in read()/write() +#include // for the default template args +#include // for equal_to +#include // for alloc<> +#include // for pair<> +#include HASH_FUN_H // defined in config.h +#include + + +_START_GOOGLE_NAMESPACE_ + +using STL_NAMESPACE::pair; + +template , // defined in sparseconfig.h + class EqualKey = STL_NAMESPACE::equal_to, + class Alloc = STL_NAMESPACE::allocator > +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 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 + 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 equal_range(const key_type& key) const { + return rep.equal_range(key); + } + + // Insertion routines + pair insert(const value_type& obj) { + pair p = rep.insert(obj); + return pair(p.first, p.second); // const to non-const + } + template + 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 +inline void swap(dense_hash_set& hs1, + dense_hash_set& hs2) { + hs1.swap(hs2); +} + +_END_GOOGLE_NAMESPACE_ + +#endif /* _DENSE_HASH_SET_H_ */ diff --git a/src/sparsehash-1.6/src/google/sparse_hash_map b/src/sparsehash-1.6/src/google/sparse_hash_map new file mode 100644 index 0000000..82ab2bd --- /dev/null +++ b/src/sparsehash-1.6/src/google/sparse_hash_map @@ -0,0 +1,301 @@ +// 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 +#include // for FILE * in read()/write() +#include // for the default template args +#include // for equal_to +#include // for alloc<> +#include // for pair<> +#include HASH_FUN_H // defined in config.h +#include + + +_START_GOOGLE_NAMESPACE_ + +using STL_NAMESPACE::pair; + +template , // defined in sparseconfig.h + class EqualKey = STL_NAMESPACE::equal_to, + class Alloc = STL_NAMESPACE::allocator > +class sparse_hash_map { + private: + // Apparently select1st is not stl-standard, so we define our own + struct SelectKey { + const Key& operator()(const pair& p) const { + return p.first; + } + }; + struct SetKey { + void operator()(pair* value, const Key& new_key) const { + *const_cast(&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, 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 + 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 equal_range(const key_type& key) { + return rep.equal_range(key); + } + pair equal_range(const key_type& key) const { + return rep.equal_range(key); + } + + // Insertion routines + pair insert(const value_type& obj) { return rep.insert(obj); } + template + 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 +inline void swap(sparse_hash_map& hm1, + sparse_hash_map& hm2) { + hm1.swap(hm2); +} + +_END_GOOGLE_NAMESPACE_ + +#endif /* _SPARSE_HASH_MAP_H_ */ diff --git a/src/sparsehash-1.6/src/google/sparse_hash_set b/src/sparsehash-1.6/src/google/sparse_hash_set new file mode 100644 index 0000000..17b4ad5 --- /dev/null +++ b/src/sparsehash-1.6/src/google/sparse_hash_set @@ -0,0 +1,282 @@ +// 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 +#include // for FILE * in read()/write() +#include // for the default template args +#include // for equal_to +#include // for alloc<> +#include // for pair<> +#include HASH_FUN_H // defined in config.h +#include + +_START_GOOGLE_NAMESPACE_ + +using STL_NAMESPACE::pair; + +template , // defined in sparseconfig.h + class EqualKey = STL_NAMESPACE::equal_to, + class Alloc = STL_NAMESPACE::allocator > +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 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 + 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 equal_range(const key_type& key) const { + return rep.equal_range(key); + } + + // Insertion routines + pair insert(const value_type& obj) { + pair p = rep.insert(obj); + return pair(p.first, p.second); // const to non-const + } + template + 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 +inline void swap(sparse_hash_set& hs1, + sparse_hash_set& hs2) { + hs1.swap(hs2); +} + +_END_GOOGLE_NAMESPACE_ + +#endif /* _SPARSE_HASH_SET_H_ */ diff --git a/src/sparsehash-1.6/src/google/sparsehash/densehashtable.h b/src/sparsehash-1.6/src/google/sparsehash/densehashtable.h new file mode 100644 index 0000000..50d9b92 --- /dev/null +++ b/src/sparsehash-1.6/src/google/sparsehash/densehashtable.h @@ -0,0 +1,1158 @@ +// 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 +// +// A dense hashtable is a particular implementation of +// a hashtable: one that is meant to minimize memory allocation. +// It does this by using an array to store all the data. We +// steal a value from the key space to indicate "empty" array +// elements (ie indices where no item lives) and another to indicate +// "deleted" elements. +// +// (Note it is possible to change the value of the delete key +// on the fly; you can even remove it, though after that point +// the hashtable is insert_only until you set it again. The empty +// value however can't be changed.) +// +// To minimize allocation and pointer overhead, we use internal +// probing, in which the hashtable is a single table, and collisions +// are resolved by trying to insert again in another bucket. The +// most cache-efficient internal probing schemes are linear probing +// (which suffers, alas, from clumping) and quadratic probing, which +// is what we implement by default. +// +// Type requirements: value_type is required to be Copy Constructible +// and Default Constructible. It is not required to be (and commonly +// isn't) Assignable. +// +// You probably shouldn't use this code directly. Use +// or instead. + +// You can change the following below: +// HT_OCCUPANCY_FLT -- how full before we double size +// HT_EMPTY_FLT -- how empty before we halve size +// HT_MIN_BUCKETS -- default smallest bucket size +// +// You can also change enlarge_resize_percent (which defaults to +// HT_OCCUPANCY_FLT), and shrink_resize_percent (which defaults to +// HT_EMPTY_FLT) with set_resizing_parameters(). +// +// How to decide what values to use? +// shrink_resize_percent's default of .4 * OCCUPANCY_FLT, is probably good. +// HT_MIN_BUCKETS is probably unnecessary since you can specify +// (indirectly) the starting number of buckets at construct-time. +// For enlarge_resize_percent, you can use this chart to try to trade-off +// expected lookup time to the space taken up. By default, this +// code uses quadratic probing, though you can change it to linear +// via _JUMP below if you really want to. +// +// From http://www.augustana.ca/~mohrj/courses/1999.fall/csc210/lecture_notes/hashing.html +// NUMBER OF PROBES / LOOKUP Successful Unsuccessful +// Quadratic collision resolution 1 - ln(1-L) - L/2 1/(1-L) - L - ln(1-L) +// Linear collision resolution [1+1/(1-L)]/2 [1+1/(1-L)2]/2 +// +// -- enlarge_resize_percent -- 0.10 0.50 0.60 0.75 0.80 0.90 0.99 +// QUADRATIC COLLISION RES. +// probes/successful lookup 1.05 1.44 1.62 2.01 2.21 2.85 5.11 +// probes/unsuccessful lookup 1.11 2.19 2.82 4.64 5.81 11.4 103.6 +// LINEAR COLLISION RES. +// probes/successful lookup 1.06 1.5 1.75 2.5 3.0 5.5 50.5 +// probes/unsuccessful lookup 1.12 2.5 3.6 8.5 13.0 50.0 5000.0 + +#ifndef _DENSEHASHTABLE_H_ +#define _DENSEHASHTABLE_H_ + +// The probing method +// Linear probing +// #define JUMP_(key, num_probes) ( 1 ) +// Quadratic-ish probing +#define JUMP_(key, num_probes) ( num_probes ) + + +#include +#include +#include +#include // for abort() +#include // For swap(), eg +#include // For length_error +#include // For cerr +#include // For uninitialized_fill, uninitialized_copy +#include // for pair<> +#include // for facts about iterator tags +#include // for true_type, integral_constant, etc. + +_START_GOOGLE_NAMESPACE_ + +using STL_NAMESPACE::pair; + +// Hashtable class, used to implement the hashed associative containers +// hash_set and hash_map. + +// Value: what is stored in the table (each bucket is a Value). +// Key: something in a 1-to-1 correspondence to a Value, that can be used +// to search for a Value in the table (find() takes a Key). +// HashFcn: Takes a Key and returns an integer, the more unique the better. +// ExtractKey: given a Value, returns the unique Key associated with it. +// SetKey: given a Value* and a Key, modifies the value such that +// ExtractKey(value) == key. We guarantee this is only called +// with key == deleted_key or key == empty_key. +// EqualKey: Given two Keys, says whether they are the same (that is, +// if they are both associated with the same Value). +// Alloc: STL allocator to use to allocate memory. Currently ignored. + +template +class dense_hashtable; + +template +struct dense_hashtable_iterator; + +template +struct dense_hashtable_const_iterator; + +// We're just an array, but we need to skip over empty and deleted elements +template +struct dense_hashtable_iterator { + public: + typedef dense_hashtable_iterator iterator; + typedef dense_hashtable_const_iterator const_iterator; + + typedef STL_NAMESPACE::forward_iterator_tag iterator_category; + typedef V value_type; + typedef ptrdiff_t difference_type; + typedef size_t size_type; + typedef V& reference; // Value + typedef V* pointer; + + // "Real" constructor and default constructor + dense_hashtable_iterator(const dense_hashtable *h, + pointer it, pointer it_end, bool advance) + : ht(h), pos(it), end(it_end) { + if (advance) advance_past_empty_and_deleted(); + } + dense_hashtable_iterator() { } + // The default destructor is fine; we don't define one + // The default operator= is fine; we don't define one + + // Happy dereferencer + reference operator*() const { return *pos; } + pointer operator->() const { return &(operator*()); } + + // Arithmetic. The only hard part is making sure that + // we're not on an empty or marked-deleted array element + void advance_past_empty_and_deleted() { + while ( pos != end && (ht->test_empty(*this) || ht->test_deleted(*this)) ) + ++pos; + } + iterator& operator++() { + assert(pos != end); ++pos; advance_past_empty_and_deleted(); return *this; + } + iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; } + + // Comparison. + bool operator==(const iterator& it) const { return pos == it.pos; } + bool operator!=(const iterator& it) const { return pos != it.pos; } + + + // The actual data + const dense_hashtable *ht; + pointer pos, end; +}; + + +// Now do it all again, but with const-ness! +template +struct dense_hashtable_const_iterator { + public: + typedef dense_hashtable_iterator iterator; + typedef dense_hashtable_const_iterator const_iterator; + + typedef STL_NAMESPACE::forward_iterator_tag iterator_category; + typedef V value_type; + typedef ptrdiff_t difference_type; + typedef size_t size_type; + typedef const V& reference; // Value + typedef const V* pointer; + + // "Real" constructor and default constructor + dense_hashtable_const_iterator( + const dense_hashtable *h, + pointer it, pointer it_end, bool advance) + : ht(h), pos(it), end(it_end) { + if (advance) advance_past_empty_and_deleted(); + } + dense_hashtable_const_iterator() { } + // This lets us convert regular iterators to const iterators + dense_hashtable_const_iterator(const iterator &it) + : ht(it.ht), pos(it.pos), end(it.end) { } + // The default destructor is fine; we don't define one + // The default operator= is fine; we don't define one + + // Happy dereferencer + reference operator*() const { return *pos; } + pointer operator->() const { return &(operator*()); } + + // Arithmetic. The only hard part is making sure that + // we're not on an empty or marked-deleted array element + void advance_past_empty_and_deleted() { + while ( pos != end && (ht->test_empty(*this) || ht->test_deleted(*this)) ) + ++pos; + } + const_iterator& operator++() { + assert(pos != end); ++pos; advance_past_empty_and_deleted(); return *this; + } + const_iterator operator++(int) { const_iterator tmp(*this); ++*this; return tmp; } + + // Comparison. + bool operator==(const const_iterator& it) const { return pos == it.pos; } + bool operator!=(const const_iterator& it) const { return pos != it.pos; } + + + // The actual data + const dense_hashtable *ht; + pointer pos, end; +}; + +template +class dense_hashtable { + public: + typedef Key key_type; + typedef Value value_type; + typedef HashFcn hasher; + typedef EqualKey key_equal; + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef dense_hashtable_iterator + iterator; + + typedef dense_hashtable_const_iterator + const_iterator; + + // These come from tr1. For us they're the same as regular iterators. + typedef iterator local_iterator; + typedef const_iterator const_local_iterator; + + // How full we let the table get before we resize, by default. + // Knuth says .8 is good -- higher causes us to probe too much, + // though it saves memory. + static const float HT_OCCUPANCY_FLT; // = 0.5; + + // How empty we let the table get before we resize lower, by default. + // (0.0 means never resize lower.) + // It should be less than OCCUPANCY_FLT / 2 or we thrash resizing + static const float HT_EMPTY_FLT; // = 0.4 * HT_OCCUPANCY_FLT + + // Minimum size we're willing to let hashtables be. + // Must be a power of two, and at least 4. + // Note, however, that for a given hashtable, the initial size is a + // function of the first constructor arg, and may be >HT_MIN_BUCKETS. + static const size_t HT_MIN_BUCKETS = 4; + + // By default, if you don't specify a hashtable size at + // construction-time, we use this size. Must be a power of two, and + // at least HT_MIN_BUCKETS. + static const size_t HT_DEFAULT_STARTING_BUCKETS = 32; + + + // ITERATOR FUNCTIONS + iterator begin() { return iterator(this, table, + table + num_buckets, true); } + iterator end() { return iterator(this, table + num_buckets, + table + num_buckets, true); } + const_iterator begin() const { return const_iterator(this, table, + table+num_buckets,true);} + const_iterator end() const { return const_iterator(this, table + num_buckets, + table+num_buckets,true);} + + // These come from tr1 unordered_map. They iterate over 'bucket' n. + // For sparsehashtable, we could consider each 'group' to be a bucket, + // I guess, but I don't really see the point. We'll just consider + // bucket n to be the n-th element of the sparsetable, if it's occupied, + // or some empty element, otherwise. + local_iterator begin(size_type i) { + return local_iterator(this, table + i, table + i+1, false); + } + local_iterator end(size_type i) { + local_iterator it = begin(i); + if (!test_empty(i) && !test_deleted(i)) + ++it; + return it; + } + const_local_iterator begin(size_type i) const { + return const_local_iterator(this, table + i, table + i+1, false); + } + const_local_iterator end(size_type i) const { + const_local_iterator it = begin(i); + if (!test_empty(i) && !test_deleted(i)) + ++it; + return it; + } + + // ACCESSOR FUNCTIONS for the things we templatize on, basically + hasher hash_funct() const { return hash; } + key_equal key_eq() const { return equals; } + + // Accessor function for statistics gathering. + int num_table_copies() const { return num_ht_copies; } + + private: + // Annoyingly, we can't copy values around, because they might have + // const components (they're probably pair). We use + // explicit destructor invocation and placement new to get around + // this. Arg. + void set_value(value_type* dst, const value_type& src) { + dst->~value_type(); + new(dst) value_type(src); + } + + void destroy_buckets(size_type first, size_type last) { + for ( ; first != last; ++first) + table[first].~value_type(); + } + + // DELETE HELPER FUNCTIONS + // This lets the user describe a key that will indicate deleted + // table entries. This key should be an "impossible" entry -- + // if you try to insert it for real, you won't be able to retrieve it! + // (NB: while you pass in an entire value, only the key part is looked + // at. This is just because I don't know how to assign just a key.) + private: + void squash_deleted() { // gets rid of any deleted entries we have + if ( num_deleted ) { // get rid of deleted before writing + dense_hashtable tmp(*this); // copying will get rid of deleted + swap(tmp); // now we are tmp + } + assert(num_deleted == 0); + } + + bool test_deleted_key(const key_type& key) const { + // The num_deleted test is crucial for read(): after read(), the ht values + // are garbage, and we don't want to think some of them are deleted. + // Invariant: !use_deleted implies num_deleted is 0. + assert(use_deleted || num_deleted == 0); + return num_deleted > 0 && equals(delkey, key); + } + + public: + void set_deleted_key(const key_type &key) { + // the empty indicator (if specified) and the deleted indicator + // must be different + assert(!use_empty || !equals(key, get_key(emptyval))); + // It's only safe to change what "deleted" means if we purge deleted guys + squash_deleted(); + use_deleted = true; + delkey = key; + } + void clear_deleted_key() { + squash_deleted(); + use_deleted = false; + } + key_type deleted_key() const { + assert(use_deleted); + return delkey; + } + + // These are public so the iterators can use them + // True if the item at position bucknum is "deleted" marker + bool test_deleted(size_type bucknum) const { + return test_deleted_key(get_key(table[bucknum])); + } + bool test_deleted(const iterator &it) const { + return test_deleted_key(get_key(*it)); + } + bool test_deleted(const const_iterator &it) const { + return test_deleted_key(get_key(*it)); + } + + // Set it so test_deleted is true. true if object didn't used to be deleted. + bool set_deleted(iterator &it) { + assert(use_deleted); // bad if set_deleted_key() wasn't called + bool retval = !test_deleted(it); + // &* converts from iterator to value-type. + set_key(&(*it), delkey); + return retval; + } + // Set it so test_deleted is false. true if object used to be deleted + bool clear_deleted(iterator &it) { + assert(use_deleted); // bad if set_deleted_key() wasn't called + // Happens automatically when we assign something else in its place. + return test_deleted(it); + } + + // We also allow to set/clear the deleted bit on a const iterator. + // We allow a const_iterator for the same reason you can delete a + // const pointer: it's convenient, and semantically you can't use + // 'it' after it's been deleted anyway, so its const-ness doesn't + // really matter. + bool set_deleted(const_iterator &it) { + assert(use_deleted); // bad if set_deleted_key() wasn't called + bool retval = !test_deleted(it); + set_key(const_cast(&(*it)), delkey); + return retval; + } + // Set it so test_deleted is false. true if object used to be deleted + bool clear_deleted(const_iterator &it) { + assert(use_deleted); // bad if set_deleted_key() wasn't called + return test_deleted(it); + } + + // EMPTY HELPER FUNCTIONS + // This lets the user describe a key that will indicate empty (unused) + // table entries. This key should be an "impossible" entry -- + // if you try to insert it for real, you won't be able to retrieve it! + // (NB: while you pass in an entire value, only the key part is looked + // at. This is just because I don't know how to assign just a key.) + public: + // These are public so the iterators can use them + // True if the item at position bucknum is "empty" marker + bool test_empty(size_type bucknum) const { + assert(use_empty); // we always need to know what's empty! + return equals(get_key(emptyval), get_key(table[bucknum])); + } + bool test_empty(const iterator &it) const { + assert(use_empty); // we always need to know what's empty! + return equals(get_key(emptyval), get_key(*it)); + } + bool test_empty(const const_iterator &it) const { + assert(use_empty); // we always need to know what's empty! + return equals(get_key(emptyval), get_key(*it)); + } + + private: + // You can either set a range empty or an individual element + void set_empty(size_type bucknum) { + assert(use_empty); + set_value(&table[bucknum], emptyval); + } + void fill_range_with_empty(value_type* table_start, value_type* table_end) { + // Like set_empty(range), but doesn't destroy previous contents + STL_NAMESPACE::uninitialized_fill(table_start, table_end, emptyval); + } + void set_empty(size_type buckstart, size_type buckend) { + assert(use_empty); + destroy_buckets(buckstart, buckend); + fill_range_with_empty(table + buckstart, table + buckend); + } + + public: + // TODO(csilvers): change all callers of this to pass in a key instead, + // and take a const key_type instead of const value_type. + void set_empty_key(const value_type &val) { + // Once you set the empty key, you can't change it + assert(!use_empty); + // The deleted indicator (if specified) and the empty indicator + // must be different. + assert(!use_deleted || !equals(get_key(val), delkey)); + use_empty = true; + set_value(&emptyval, val); + + assert(!table); // must set before first use + // num_buckets was set in constructor even though table was NULL + table = (value_type *) malloc(num_buckets * sizeof(*table)); + assert(table); + fill_range_with_empty(table, table + num_buckets); + } + // TODO(sjackman): return a key_type rather than a value_type + value_type empty_key() const { + assert(use_empty); + return emptyval; + } + + // FUNCTIONS CONCERNING SIZE + public: + size_type size() const { return num_elements - num_deleted; } + // Buckets are always a power of 2 + size_type max_size() const { return (size_type(-1) >> 1U) + 1; } + bool empty() const { return size() == 0; } + size_type bucket_count() const { return num_buckets; } + size_type max_bucket_count() const { return max_size(); } + size_type nonempty_bucket_count() const { return num_elements; } + // These are tr1 methods. Their idea of 'bucket' doesn't map well to + // what we do. We just say every bucket has 0 or 1 items in it. + size_type bucket_size(size_type i) const { + return begin(i) == end(i) ? 0 : 1; + } + + + + private: + // Because of the above, size_type(-1) is never legal; use it for errors + static const size_type ILLEGAL_BUCKET = size_type(-1); + + private: + // This is the smallest size a hashtable can be without being too crowded + // If you like, you can give a min #buckets as well as a min #elts + size_type min_size(size_type num_elts, size_type min_buckets_wanted) { + size_type sz = HT_MIN_BUCKETS; // min buckets allowed + while ( sz < min_buckets_wanted || + num_elts >= static_cast(sz * enlarge_resize_percent) ) { + if (sz * 2 < sz) + throw std::length_error("resize overflow"); // protect against overflow + sz *= 2; + } + return sz; + } + + // Used after a string of deletes + void maybe_shrink() { + assert(num_elements >= num_deleted); + assert((bucket_count() & (bucket_count()-1)) == 0); // is a power of two + assert(bucket_count() >= HT_MIN_BUCKETS); + + // If you construct a hashtable with < HT_DEFAULT_STARTING_BUCKETS, + // we'll never shrink until you get relatively big, and we'll never + // shrink below HT_DEFAULT_STARTING_BUCKETS. Otherwise, something + // like "dense_hash_set x; x.insert(4); x.erase(4);" will + // shrink us down to HT_MIN_BUCKETS buckets, which is too small. + if (shrink_threshold > 0 && + (num_elements-num_deleted) < shrink_threshold && + bucket_count() > HT_DEFAULT_STARTING_BUCKETS ) { + size_type sz = bucket_count() / 2; // find how much we should shrink + while ( sz > HT_DEFAULT_STARTING_BUCKETS && + (num_elements - num_deleted) < sz * shrink_resize_percent ) + sz /= 2; // stay a power of 2 + dense_hashtable tmp(*this, sz); // Do the actual resizing + swap(tmp); // now we are tmp + } + consider_shrink = false; // because we just considered it + } + + // We'll let you resize a hashtable -- though this makes us copy all! + // When you resize, you say, "make it big enough for this many more elements" + void resize_delta(size_type delta) { + if ( consider_shrink ) // see if lots of deletes happened + maybe_shrink(); + if ( bucket_count() > HT_MIN_BUCKETS && + (num_elements + delta) <= enlarge_threshold ) + return; // we're ok as we are + + // Sometimes, we need to resize just to get rid of all the + // "deleted" buckets that are clogging up the hashtable. So when + // deciding whether to resize, count the deleted buckets (which + // are currently taking up room). But later, when we decide what + // size to resize to, *don't* count deleted buckets, since they + // get discarded during the resize. + const size_type needed_size = min_size(num_elements + delta, 0); + if ( needed_size > bucket_count() ) { // we don't have enough buckets + size_type resize_to = min_size(num_elements - num_deleted + delta, + bucket_count()); + if (resize_to < needed_size) { + // This situation means that we have enough deleted elements, + // that once we purge them, we won't actually have needed to + // grow. But we may want to grow anyway: if we just purge one + // element, say, we'll have to grow anyway next time we + // insert. Might as well grow now, since we're already going + // through the trouble of copying (in order to purge the + // deleted elements). + if (num_elements - num_deleted + delta >= + static_cast(resize_to*2 * shrink_resize_percent)) { + // Good, we won't be below the shrink threshhold even if we double. + resize_to *= 2; + } + } + dense_hashtable tmp(*this, resize_to); + swap(tmp); // now we are tmp + } + } + + // Increase number of buckets, assuming value_type has trivial copy + // constructor and destructor. (Really, we want it to have "trivial + // move", because that's what realloc does. But there's no way to + // capture that using type_traits, so we pretend that move(x, y) is + // equivalent to "x.~T(); new(x) T(y);" which is pretty much + // correct, if a bit conservative.) + void expand_array(size_t resize_to, true_type) { + table = (value_type *) realloc(table, resize_to * sizeof(value_type)); + assert(table); + fill_range_with_empty(table + num_buckets, table + resize_to); + } + + // Increase number of buckets, without special assumptions about value_type. + // TODO(austern): make this exception safe. Handle exceptions from + // value_type's copy constructor. + void expand_array(size_t resize_to, false_type) { + value_type* new_table = + (value_type *) malloc(resize_to * sizeof(value_type)); + assert(new_table); + STL_NAMESPACE::uninitialized_copy(table, table + num_buckets, new_table); + fill_range_with_empty(new_table + num_buckets, new_table + resize_to); + destroy_buckets(0, num_buckets); + free(table); + table = new_table; + } + + // Used to actually do the rehashing when we grow/shrink a hashtable + void copy_from(const dense_hashtable &ht, size_type min_buckets_wanted) { + clear(); // clear table, set num_deleted to 0 + + // If we need to change the size of our table, do it now + const size_type resize_to = min_size(ht.size(), min_buckets_wanted); + if ( resize_to > bucket_count() ) { // we don't have enough buckets + typedef integral_constant::value && + has_trivial_destructor::value)> + realloc_ok; // we pretend mv(x,y) == "x.~T(); new(x) T(y)" + expand_array(resize_to, realloc_ok()); + num_buckets = resize_to; + reset_thresholds(); + } + + // We use a normal iterator to get non-deleted bcks from ht + // We could use insert() here, but since we know there are + // no duplicates and no deleted items, we can be more efficient + assert((bucket_count() & (bucket_count()-1)) == 0); // a power of two + for ( const_iterator it = ht.begin(); it != ht.end(); ++it ) { + size_type num_probes = 0; // how many times we've probed + size_type bucknum; + const size_type bucket_count_minus_one = bucket_count() - 1; + for (bucknum = hash(get_key(*it)) & bucket_count_minus_one; + !test_empty(bucknum); // not empty + bucknum = (bucknum + JUMP_(key, num_probes)) & bucket_count_minus_one) { + ++num_probes; + assert(num_probes < bucket_count()); // or else the hashtable is full + } + set_value(&table[bucknum], *it); // copies the value to here + num_elements++; + } + num_ht_copies++; + } + + // Required by the spec for hashed associative container + public: + // Though the docs say this should be num_buckets, I think it's much + // more useful as req_elements. As a special feature, calling with + // req_elements==0 will cause us to shrink if we can, saving space. + void resize(size_type req_elements) { // resize to this or larger + if ( consider_shrink || req_elements == 0 ) + maybe_shrink(); + if ( req_elements > num_elements ) + return resize_delta(req_elements - num_elements); + } + + // Get and change the value of shrink_resize_percent and + // enlarge_resize_percent. The description at the beginning of this + // file explains how to choose the values. Setting the shrink + // parameter to 0.0 ensures that the table never shrinks. + void get_resizing_parameters(float* shrink, float* grow) const { + *shrink = shrink_resize_percent; + *grow = enlarge_resize_percent; + } + void set_resizing_parameters(float shrink, float grow) { + assert(shrink >= 0.0); + assert(grow <= 1.0); + if (shrink > grow/2.0f) + shrink = grow / 2.0f; // otherwise we thrash hashtable size + shrink_resize_percent = shrink; + enlarge_resize_percent = grow; + reset_thresholds(); + } + + // CONSTRUCTORS -- as required by the specs, we take a size, + // but also let you specify a hashfunction, key comparator, + // and key extractor. We also define a copy constructor and =. + // DESTRUCTOR -- needs to free the table + explicit dense_hashtable(size_type expected_max_items_in_table = 0, + const HashFcn& hf = HashFcn(), + const EqualKey& eql = EqualKey(), + const ExtractKey& ext = ExtractKey(), + const SetKey& set = SetKey()) + : hash(hf), equals(eql), get_key(ext), set_key(set), num_deleted(0), + use_deleted(false), use_empty(false), + delkey(), emptyval(), enlarge_resize_percent(HT_OCCUPANCY_FLT), + shrink_resize_percent(HT_EMPTY_FLT), table(NULL), + num_buckets(expected_max_items_in_table == 0 + ? HT_DEFAULT_STARTING_BUCKETS + : min_size(expected_max_items_in_table, 0)), + num_elements(0), num_ht_copies(0) { + // table is NULL until emptyval is set. However, we set num_buckets + // here so we know how much space to allocate once emptyval is set + reset_thresholds(); + } + + // As a convenience for resize(), we allow an optional second argument + // which lets you make this new hashtable a different size than ht + dense_hashtable(const dense_hashtable& ht, + size_type min_buckets_wanted = HT_DEFAULT_STARTING_BUCKETS) + : hash(ht.hash), equals(ht.equals), + get_key(ht.get_key), set_key(ht.set_key), num_deleted(0), + use_deleted(ht.use_deleted), use_empty(ht.use_empty), + delkey(ht.delkey), emptyval(ht.emptyval), + enlarge_resize_percent(ht.enlarge_resize_percent), + shrink_resize_percent(ht.shrink_resize_percent), table(NULL), + num_buckets(0), num_elements(0), num_ht_copies(ht.num_ht_copies) { + if (!ht.use_empty) { + // If use_empty isn't set, copy_from will crash, so we do our own copying. + assert(ht.empty()); + num_buckets = min_size(ht.size(), min_buckets_wanted); + reset_thresholds(); + return; + } + reset_thresholds(); + copy_from(ht, min_buckets_wanted); // copy_from() ignores deleted entries + } + + dense_hashtable& operator= (const dense_hashtable& ht) { + if (&ht == this) return *this; // don't copy onto ourselves + if (!ht.use_empty) { + assert(ht.empty()); + dense_hashtable empty_table(ht); // empty table with ht's thresholds + this->swap(empty_table); + return *this; + } + hash = ht.hash; + equals = ht.equals; + get_key = ht.get_key; + set_key = ht.set_key; + use_deleted = ht.use_deleted; + use_empty = ht.use_empty; + delkey = ht.delkey; + set_value(&emptyval, ht.emptyval); + enlarge_resize_percent = ht.enlarge_resize_percent; + shrink_resize_percent = ht.shrink_resize_percent; + copy_from(ht, HT_MIN_BUCKETS); // calls clear and sets num_deleted to 0 too + return *this; + } + + ~dense_hashtable() { + if (table) { + destroy_buckets(0, num_buckets); + free(table); + } + } + + // Many STL algorithms use swap instead of copy constructors + void swap(dense_hashtable& ht) { + STL_NAMESPACE::swap(hash, ht.hash); + STL_NAMESPACE::swap(equals, ht.equals); + STL_NAMESPACE::swap(get_key, ht.get_key); + STL_NAMESPACE::swap(set_key, ht.set_key); + STL_NAMESPACE::swap(num_deleted, ht.num_deleted); + STL_NAMESPACE::swap(use_deleted, ht.use_deleted); + STL_NAMESPACE::swap(use_empty, ht.use_empty); + STL_NAMESPACE::swap(enlarge_resize_percent, ht.enlarge_resize_percent); + STL_NAMESPACE::swap(shrink_resize_percent, ht.shrink_resize_percent); + STL_NAMESPACE::swap(delkey, ht.delkey); + { value_type tmp; // for annoying reasons, swap() doesn't work + set_value(&tmp, emptyval); + set_value(&emptyval, ht.emptyval); + set_value(&ht.emptyval, tmp); + } + STL_NAMESPACE::swap(table, ht.table); + STL_NAMESPACE::swap(num_buckets, ht.num_buckets); + STL_NAMESPACE::swap(num_elements, ht.num_elements); + STL_NAMESPACE::swap(num_ht_copies, ht.num_ht_copies); + reset_thresholds(); + ht.reset_thresholds(); + } + + // It's always nice to be able to clear a table without deallocating it + void clear() { + const size_type new_num_buckets = min_size(0,0); + if (num_elements == 0 && + num_deleted == 0 && + new_num_buckets == num_buckets) { + // Table is already empty, and the number of buckets is already as we + // desire, so nothing to do. + return; + } + if (table) + destroy_buckets(0, num_buckets); + if (!table || (new_num_buckets != num_buckets)) { + // Recompute the resize thresholds and realloc the table only if we're + // actually changing its size. + num_buckets = new_num_buckets; // our new size + reset_thresholds(); + table = (value_type *) realloc(table, num_buckets * sizeof(*table)); + } + assert(table); + fill_range_with_empty(table, table + num_buckets); + num_elements = 0; + num_deleted = 0; + } + + // Clear the table without resizing it. + // Mimicks the stl_hashtable's behaviour when clear()-ing in that it + // does not modify the bucket count + void clear_no_resize() { + if (table) { + set_empty(0, num_buckets); + } + // don't consider to shrink before another erase() + reset_thresholds(); + num_elements = 0; + num_deleted = 0; + } + + // LOOKUP ROUTINES + private: + // Returns a pair of positions: 1st where the object is, 2nd where + // it would go if you wanted to insert it. 1st is ILLEGAL_BUCKET + // if object is not found; 2nd is ILLEGAL_BUCKET if it is. + // Note: because of deletions where-to-insert is not trivial: it's the + // first deleted bucket we see, as long as we don't find the key later + pair find_position(const key_type &key) const { + size_type num_probes = 0; // how many times we've probed + const size_type bucket_count_minus_one = bucket_count() - 1; + size_type bucknum = hash(key) & bucket_count_minus_one; + size_type insert_pos = ILLEGAL_BUCKET; // where we would insert + while ( 1 ) { // probe until something happens + if ( test_empty(bucknum) ) { // bucket is empty + if ( insert_pos == ILLEGAL_BUCKET ) // found no prior place to insert + return pair(ILLEGAL_BUCKET, bucknum); + else + return pair(ILLEGAL_BUCKET, insert_pos); + + } else if ( test_deleted(bucknum) ) {// keep searching, but mark to insert + if ( insert_pos == ILLEGAL_BUCKET ) + insert_pos = bucknum; + + } else if ( equals(key, get_key(table[bucknum])) ) { + return pair(bucknum, ILLEGAL_BUCKET); + } + ++num_probes; // we're doing another probe + bucknum = (bucknum + JUMP_(key, num_probes)) & bucket_count_minus_one; + assert(num_probes < bucket_count()); // don't probe too many times! + } + } + + public: + iterator find(const key_type& key) { + if ( size() == 0 ) return end(); + pair pos = find_position(key); + if ( pos.first == ILLEGAL_BUCKET ) // alas, not there + return end(); + else + return iterator(this, table + pos.first, table + num_buckets, false); + } + + const_iterator find(const key_type& key) const { + if ( size() == 0 ) return end(); + pair pos = find_position(key); + if ( pos.first == ILLEGAL_BUCKET ) // alas, not there + return end(); + else + return const_iterator(this, table + pos.first, table+num_buckets, false); + } + + // This is a tr1 method: the bucket a given key is in, or what bucket + // it would be put in, if it were to be inserted. Shrug. + size_type bucket(const key_type& key) const { + pair pos = find_position(key); + return pos.first == ILLEGAL_BUCKET ? pos.second : pos.first; + } + + // Counts how many elements have key key. For maps, it's either 0 or 1. + size_type count(const key_type &key) const { + pair pos = find_position(key); + return pos.first == ILLEGAL_BUCKET ? 0 : 1; + } + + // Likewise, equal_range doesn't really make sense for us. Oh well. + pair equal_range(const key_type& key) { + iterator pos = find(key); // either an iterator or end + if (pos == end()) { + return pair(pos, pos); + } else { + const iterator startpos = pos++; + return pair(startpos, pos); + } + } + pair equal_range(const key_type& key) const { + const_iterator pos = find(key); // either an iterator or end + if (pos == end()) { + return pair(pos, pos); + } else { + const const_iterator startpos = pos++; + return pair(startpos, pos); + } + } + + + // INSERTION ROUTINES + private: + // If you know *this is big enough to hold obj, use this routine + pair insert_noresize(const value_type& obj) { + // First, double-check we're not inserting delkey or emptyval + assert(!use_empty || !equals(get_key(obj), get_key(emptyval))); + assert(!use_deleted || !equals(get_key(obj), delkey)); + const pair pos = find_position(get_key(obj)); + if ( pos.first != ILLEGAL_BUCKET) { // object was already there + return pair(iterator(this, table + pos.first, + table + num_buckets, false), + false); // false: we didn't insert + } else { // pos.second says where to put it + if ( test_deleted(pos.second) ) { // just replace if it's been del. + const_iterator delpos(this, table + pos.second, // shrug: + table + num_buckets, false);// shouldn't need const + clear_deleted(delpos); + assert( num_deleted > 0); + --num_deleted; // used to be, now it isn't + } else { + ++num_elements; // replacing an empty bucket + } + set_value(&table[pos.second], obj); + return pair(iterator(this, table + pos.second, + table + num_buckets, false), + true); // true: we did insert + } + } + + public: + // This is the normal insert routine, used by the outside world + pair insert(const value_type& obj) { + resize_delta(1); // adding an object, grow if need be + return insert_noresize(obj); + } + + // When inserting a lot at a time, we specialize on the type of iterator + template + void insert(InputIterator f, InputIterator l) { + // specializes on iterator type + insert(f, l, typename STL_NAMESPACE::iterator_traits::iterator_category()); + } + + // Iterator supports operator-, resize before inserting + template + void insert(ForwardIterator f, ForwardIterator l, + STL_NAMESPACE::forward_iterator_tag) { + size_type n = STL_NAMESPACE::distance(f, l); // TODO(csilvers): standard? + resize_delta(n); + for ( ; n > 0; --n, ++f) + insert_noresize(*f); + } + + // Arbitrary iterator, can't tell how much to resize + template + void insert(InputIterator f, InputIterator l, + STL_NAMESPACE::input_iterator_tag) { + for ( ; f != l; ++f) + insert(*f); + } + + + // DELETION ROUTINES + size_type erase(const key_type& key) { + // First, double-check we're not trying to erase delkey or emptyval + assert(!use_empty || !equals(key, get_key(emptyval))); + assert(!use_deleted || !equals(key, delkey)); + const_iterator pos = find(key); // shrug: shouldn't need to be const + if ( pos != end() ) { + assert(!test_deleted(pos)); // or find() shouldn't have returned it + set_deleted(pos); + ++num_deleted; + consider_shrink = true; // will think about shrink after next insert + return 1; // because we deleted one thing + } else { + return 0; // because we deleted nothing + } + } + + // We return the iterator past the deleted item. + void erase(iterator pos) { + if ( pos == end() ) return; // sanity check + if ( set_deleted(pos) ) { // true if object has been newly deleted + ++num_deleted; + consider_shrink = true; // will think about shrink after next insert + } + } + + void erase(iterator f, iterator l) { + for ( ; f != l; ++f) { + if ( set_deleted(f) ) // should always be true + ++num_deleted; + } + consider_shrink = true; // will think about shrink after next insert + } + + // We allow you to erase a const_iterator just like we allow you to + // erase an iterator. This is in parallel to 'delete': you can delete + // a const pointer just like a non-const pointer. The logic is that + // you can't use the object after it's erased anyway, so it doesn't matter + // if it's const or not. + void erase(const_iterator pos) { + if ( pos == end() ) return; // sanity check + if ( set_deleted(pos) ) { // true if object has been newly deleted + ++num_deleted; + consider_shrink = true; // will think about shrink after next insert + } + } + void erase(const_iterator f, const_iterator l) { + for ( ; f != l; ++f) { + if ( set_deleted(f) ) // should always be true + ++num_deleted; + } + consider_shrink = true; // will think about shrink after next insert + } + + + // COMPARISON + bool operator==(const dense_hashtable& ht) const { + if (size() != ht.size()) { + return false; + } else if (this == &ht) { + return true; + } else { + // Iterate through the elements in "this" and see if the + // corresponding element is in ht + for ( const_iterator it = begin(); it != end(); ++it ) { + const_iterator it2 = ht.find(get_key(*it)); + if ((it2 == ht.end()) || (*it != *it2)) { + return false; + } + } + return true; + } + } + bool operator!=(const dense_hashtable& ht) const { + return !(*this == ht); + } + + + // I/O + // We support reading and writing hashtables to disk. Alas, since + // I don't know how to write a hasher or key_equal, you have to make + // sure everything but the table is the same. We compact before writing + // + // NOTE: These functions are currently TODO. They've not been implemented. + bool write_metadata(FILE *fp) { + squash_deleted(); // so we don't have to worry about delkey + return false; // TODO + } + + bool read_metadata(FILE *fp) { + num_deleted = 0; // since we got rid before writing + assert(use_empty); // have to set this before calling us + if (table) free(table); // we'll make our own + // TODO: read magic number + // TODO: read num_buckets + reset_thresholds(); + table = (value_type *) malloc(num_buckets * sizeof(*table)); + assert(table); + fill_range_with_empty(table, table + num_buckets); + // TODO: read num_elements + for ( size_type i = 0; i < num_elements; ++i ) { + // TODO: read bucket_num + // TODO: set with non-empty, non-deleted value + } + return false; // TODO + } + + // If your keys and values are simple enough, we can write them to + // disk for you. "simple enough" means value_type is a POD type + // that contains no pointers. However, we don't try to normalize + // endianness + bool write_nopointer_data(FILE *fp) const { + for ( const_iterator it = begin(); it != end(); ++it ) { + // TODO: skip empty/deleted values + if ( !fwrite(&*it, sizeof(*it), 1, fp) ) return false; + } + return false; + } + + // When reading, we have to override the potential const-ness of *it + bool read_nopointer_data(FILE *fp) { + for ( iterator it = begin(); it != end(); ++it ) { + // TODO: skip empty/deleted values + if ( !fread(reinterpret_cast(&(*it)), sizeof(*it), 1, fp) ) + return false; + } + return false; + } + + private: + // The actual data + hasher hash; // required by hashed_associative_container + key_equal equals; + ExtractKey get_key; + SetKey set_key; + size_type num_deleted; // how many occupied buckets are marked deleted + bool use_deleted; // false until delkey has been set + bool use_empty; // you must do this before you start + // TODO(csilvers): make a pointer, and get rid of use_deleted (benchmark!) + key_type delkey; // which key marks deleted entries + value_type emptyval; // which key marks unused entries + float enlarge_resize_percent; // how full before resize + float shrink_resize_percent; // how empty before resize + size_type shrink_threshold; // num_buckets * shrink_resize_percent + size_type enlarge_threshold; // num_buckets * enlarge_resize_percent + value_type *table; + size_type num_buckets; + size_type num_elements; + int num_ht_copies; // a statistics counter incremented every Copy + bool consider_shrink; // true if we should try to shrink before next insert + + void reset_thresholds() { + enlarge_threshold = static_cast(num_buckets + * enlarge_resize_percent); + shrink_threshold = static_cast(num_buckets + * shrink_resize_percent); + consider_shrink = false; // whatever caused us to reset already considered + } +}; + +// We need a global swap as well +template +inline void swap(dense_hashtable &x, + dense_hashtable &y) { + x.swap(y); +} + +#undef JUMP_ + +template +const typename dense_hashtable::size_type +dense_hashtable::ILLEGAL_BUCKET; + +// How full we let the table get before we resize. Knuth says .8 is +// good -- higher causes us to probe too much, though saves memory. +// However, we go with .5, getting better performance at the cost of +// more space (a trade-off densehashtable explicitly chooses to make). +// Feel free to play around with different values, though. +template +const float dense_hashtable::HT_OCCUPANCY_FLT = 0.5f; + +// How empty we let the table get before we resize lower. +// It should be less than OCCUPANCY_FLT / 2 or we thrash resizing +template +const float dense_hashtable::HT_EMPTY_FLT + = 0.4f * dense_hashtable::HT_OCCUPANCY_FLT; + +_END_GOOGLE_NAMESPACE_ + +#endif /* _DENSEHASHTABLE_H_ */ diff --git a/src/sparsehash-1.6/src/google/sparsehash/sparseconfig.h b/src/sparsehash-1.6/src/google/sparsehash/sparseconfig.h new file mode 100644 index 0000000..f397d3b --- /dev/null +++ b/src/sparsehash-1.6/src/google/sparsehash/sparseconfig.h @@ -0,0 +1,49 @@ +/* + * 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 + +/* the namespace of the hash<> function */ +#define HASH_NAMESPACE std::tr1 + +/* Define to 1 if you have the 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 header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the 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 { diff --git a/src/sparsehash-1.6/src/google/sparsehash/sparsehashtable.h b/src/sparsehash-1.6/src/google/sparsehash/sparsehashtable.h new file mode 100644 index 0000000..62c9dc8 --- /dev/null +++ b/src/sparsehash-1.6/src/google/sparsehash/sparsehashtable.h @@ -0,0 +1,1081 @@ +// 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 +// +// A sparse hashtable is a particular implementation of +// a hashtable: one that is meant to minimize memory use. +// It does this by using a *sparse table* (cf sparsetable.h), +// which uses between 1 and 2 bits to store empty buckets +// (we may need another bit for hashtables that support deletion). +// +// When empty buckets are so cheap, an appealing hashtable +// implementation is internal probing, in which the hashtable +// is a single table, and collisions are resolved by trying +// to insert again in another bucket. The most cache-efficient +// internal probing schemes are linear probing (which suffers, +// alas, from clumping) and quadratic probing, which is what +// we implement by default. +// +// Deleted buckets are a bit of a pain. We have to somehow mark +// deleted buckets (the probing must distinguish them from empty +// buckets). The most principled way is to have another bitmap, +// but that's annoying and takes up space. Instead we let the +// user specify an "impossible" key. We set deleted buckets +// to have the impossible key. +// +// Note it is possible to change the value of the delete key +// on the fly; you can even remove it, though after that point +// the hashtable is insert_only until you set it again. +// +// You probably shouldn't use this code directly. Use +// or instead. +// +// You can modify the following, below: +// HT_OCCUPANCY_FLT -- how full before we double size +// HT_EMPTY_FLT -- how empty before we halve size +// HT_MIN_BUCKETS -- smallest bucket size +// HT_DEFAULT_STARTING_BUCKETS -- default bucket size at construct-time +// +// You can also change enlarge_resize_percent (which defaults to +// HT_OCCUPANCY_FLT), and shrink_resize_percent (which defaults to +// HT_EMPTY_FLT) with set_resizing_parameters(). +// +// How to decide what values to use? +// shrink_resize_percent's default of .4 * OCCUPANCY_FLT, is probably good. +// HT_MIN_BUCKETS is probably unnecessary since you can specify +// (indirectly) the starting number of buckets at construct-time. +// For enlarge_resize_percent, you can use this chart to try to trade-off +// expected lookup time to the space taken up. By default, this +// code uses quadratic probing, though you can change it to linear +// via _JUMP below if you really want to. +// +// From http://www.augustana.ca/~mohrj/courses/1999.fall/csc210/lecture_notes/hashing.html +// NUMBER OF PROBES / LOOKUP Successful Unsuccessful +// Quadratic collision resolution 1 - ln(1-L) - L/2 1/(1-L) - L - ln(1-L) +// Linear collision resolution [1+1/(1-L)]/2 [1+1/(1-L)2]/2 +// +// -- enlarge_resize_percent -- 0.10 0.50 0.60 0.75 0.80 0.90 0.99 +// QUADRATIC COLLISION RES. +// probes/successful lookup 1.05 1.44 1.62 2.01 2.21 2.85 5.11 +// probes/unsuccessful lookup 1.11 2.19 2.82 4.64 5.81 11.4 103.6 +// LINEAR COLLISION RES. +// probes/successful lookup 1.06 1.5 1.75 2.5 3.0 5.5 50.5 +// probes/unsuccessful lookup 1.12 2.5 3.6 8.5 13.0 50.0 5000.0 +// +// The value type is required to be copy constructible and default +// constructible, but it need not be (and commonly isn't) assignable. + +#ifndef _SPARSEHASHTABLE_H_ +#define _SPARSEHASHTABLE_H_ + +#ifndef SPARSEHASH_STAT_UPDATE +#define SPARSEHASH_STAT_UPDATE(x) ((void) 0) +#endif + +// The probing method +// Linear probing +// #define JUMP_(key, num_probes) ( 1 ) +// Quadratic-ish probing +#define JUMP_(key, num_probes) ( num_probes ) + + +#include +#include +#include // For swap(), eg +#include // For length_error +#include // for facts about iterator tags +#include // for pair<> +#include // Since that's basically what we are + +_START_GOOGLE_NAMESPACE_ + +using STL_NAMESPACE::pair; + +// Hashtable class, used to implement the hashed associative containers +// hash_set and hash_map. +// +// Value: what is stored in the table (each bucket is a Value). +// Key: something in a 1-to-1 correspondence to a Value, that can be used +// to search for a Value in the table (find() takes a Key). +// HashFcn: Takes a Key and returns an integer, the more unique the better. +// ExtractKey: given a Value, returns the unique Key associated with it. +// SetKey: given a Value* and a Key, modifies the value such that +// ExtractKey(value) == key. We guarantee this is only called +// with key == deleted_key. +// EqualKey: Given two Keys, says whether they are the same (that is, +// if they are both associated with the same Value). +// Alloc: STL allocator to use to allocate memory. Currently ignored. + +template +class sparse_hashtable; + +template +struct sparse_hashtable_iterator; + +template +struct sparse_hashtable_const_iterator; + +// As far as iterating, we're basically just a sparsetable +// that skips over deleted elements. +template +struct sparse_hashtable_iterator { + public: + typedef sparse_hashtable_iterator iterator; + typedef sparse_hashtable_const_iterator const_iterator; + typedef typename sparsetable::nonempty_iterator st_iterator; + + typedef STL_NAMESPACE::forward_iterator_tag iterator_category; + typedef V value_type; + typedef ptrdiff_t difference_type; + typedef size_t size_type; + typedef V& reference; // Value + typedef V* pointer; + + // "Real" constructor and default constructor + sparse_hashtable_iterator(const sparse_hashtable *h, + st_iterator it, st_iterator it_end) + : ht(h), pos(it), end(it_end) { advance_past_deleted(); } + sparse_hashtable_iterator() { } // not ever used internally + // The default destructor is fine; we don't define one + // The default operator= is fine; we don't define one + + // Happy dereferencer + reference operator*() const { return *pos; } + pointer operator->() const { return &(operator*()); } + + // Arithmetic. The only hard part is making sure that + // we're not on a marked-deleted array element + void advance_past_deleted() { + while ( pos != end && ht->test_deleted(*this) ) + ++pos; + } + iterator& operator++() { + assert(pos != end); ++pos; advance_past_deleted(); return *this; + } + iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; } + + // Comparison. + bool operator==(const iterator& it) const { return pos == it.pos; } + bool operator!=(const iterator& it) const { return pos != it.pos; } + + + // The actual data + const sparse_hashtable *ht; + st_iterator pos, end; +}; + +// Now do it all again, but with const-ness! +template +struct sparse_hashtable_const_iterator { + public: + typedef sparse_hashtable_iterator iterator; + typedef sparse_hashtable_const_iterator const_iterator; + typedef typename sparsetable::const_nonempty_iterator st_iterator; + + typedef STL_NAMESPACE::forward_iterator_tag iterator_category; + typedef V value_type; + typedef ptrdiff_t difference_type; + typedef size_t size_type; + typedef const V& reference; // Value + typedef const V* pointer; + + // "Real" constructor and default constructor + sparse_hashtable_const_iterator(const sparse_hashtable *h, + st_iterator it, st_iterator it_end) + : ht(h), pos(it), end(it_end) { advance_past_deleted(); } + // This lets us convert regular iterators to const iterators + sparse_hashtable_const_iterator() { } // never used internally + sparse_hashtable_const_iterator(const iterator &it) + : ht(it.ht), pos(it.pos), end(it.end) { } + // The default destructor is fine; we don't define one + // The default operator= is fine; we don't define one + + // Happy dereferencer + reference operator*() const { return *pos; } + pointer operator->() const { return &(operator*()); } + + // Arithmetic. The only hard part is making sure that + // we're not on a marked-deleted array element + void advance_past_deleted() { + while ( pos != end && ht->test_deleted(*this) ) + ++pos; + } + const_iterator& operator++() { + assert(pos != end); ++pos; advance_past_deleted(); return *this; + } + const_iterator operator++(int) { const_iterator tmp(*this); ++*this; return tmp; } + + // Comparison. + bool operator==(const const_iterator& it) const { return pos == it.pos; } + bool operator!=(const const_iterator& it) const { return pos != it.pos; } + + + // The actual data + const sparse_hashtable *ht; + st_iterator pos, end; +}; + +// And once again, but this time freeing up memory as we iterate +template +struct sparse_hashtable_destructive_iterator { + public: + typedef sparse_hashtable_destructive_iterator iterator; + typedef typename sparsetable::destructive_iterator st_iterator; + + typedef STL_NAMESPACE::forward_iterator_tag iterator_category; + typedef V value_type; + typedef ptrdiff_t difference_type; + typedef size_t size_type; + typedef V& reference; // Value + typedef V* pointer; + + // "Real" constructor and default constructor + sparse_hashtable_destructive_iterator(const + sparse_hashtable *h, + st_iterator it, st_iterator it_end) + : ht(h), pos(it), end(it_end) { advance_past_deleted(); } + sparse_hashtable_destructive_iterator() { } // never used internally + // The default destructor is fine; we don't define one + // The default operator= is fine; we don't define one + + // Happy dereferencer + reference operator*() const { return *pos; } + pointer operator->() const { return &(operator*()); } + + // Arithmetic. The only hard part is making sure that + // we're not on a marked-deleted array element + void advance_past_deleted() { + while ( pos != end && ht->test_deleted(*this) ) + ++pos; + } + iterator& operator++() { + assert(pos != end); ++pos; advance_past_deleted(); return *this; + } + iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; } + + // Comparison. + bool operator==(const iterator& it) const { return pos == it.pos; } + bool operator!=(const iterator& it) const { return pos != it.pos; } + + + // The actual data + const sparse_hashtable *ht; + st_iterator pos, end; +}; + + +template +class sparse_hashtable { + public: + typedef Key key_type; + typedef Value value_type; + typedef HashFcn hasher; + typedef EqualKey key_equal; + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef sparse_hashtable_iterator + iterator; + + typedef sparse_hashtable_const_iterator + const_iterator; + + typedef sparse_hashtable_destructive_iterator + destructive_iterator; + + // These come from tr1. For us they're the same as regular iterators. + typedef iterator local_iterator; + typedef const_iterator const_local_iterator; + + // How full we let the table get before we resize, by default. + // Knuth says .8 is good -- higher causes us to probe too much, + // though it saves memory. + static const float HT_OCCUPANCY_FLT; // = 0.8f; + + // How empty we let the table get before we resize lower, by default. + // It should be less than OCCUPANCY_FLT / 2 or we thrash resizing + static const float HT_EMPTY_FLT; // = 0.4 * HT_OCCUPANCY_FLT; + + // Minimum size we're willing to let hashtables be. + // Must be a power of two, and at least 4. + // Note, however, that for a given hashtable, the minimum size is + // determined by the first constructor arg, and may be >HT_MIN_BUCKETS. + static const size_t HT_MIN_BUCKETS = 4; + + // By default, if you don't specify a hashtable size at + // construction-time, we use this size. Must be a power of two, and + // at least HT_MIN_BUCKETS. + static const size_t HT_DEFAULT_STARTING_BUCKETS = 32; + + // ITERATOR FUNCTIONS + iterator begin() { return iterator(this, table.nonempty_begin(), + table.nonempty_end()); } + iterator end() { return iterator(this, table.nonempty_end(), + table.nonempty_end()); } + const_iterator begin() const { return const_iterator(this, + table.nonempty_begin(), + table.nonempty_end()); } + const_iterator end() const { return const_iterator(this, + table.nonempty_end(), + table.nonempty_end()); } + + // These come from tr1 unordered_map. They iterate over 'bucket' n. + // For sparsehashtable, we could consider each 'group' to be a bucket, + // I guess, but I don't really see the point. We'll just consider + // bucket n to be the n-th element of the sparsetable, if it's occupied, + // or some empty element, otherwise. + local_iterator begin(size_type i) { + if (table.test(i)) + return local_iterator(this, table.get_iter(i), table.nonempty_end()); + else + return local_iterator(this, table.nonempty_end(), table.nonempty_end()); + } + local_iterator end(size_type i) { + local_iterator it = begin(i); + if (table.test(i) && !test_deleted(i)) + ++it; + return it; + } + const_local_iterator begin(size_type i) const { + if (table.test(i)) + return const_local_iterator(this, table.get_iter(i), + table.nonempty_end()); + else + return const_local_iterator(this, table.nonempty_end(), + table.nonempty_end()); + } + const_local_iterator end(size_type i) const { + const_local_iterator it = begin(i); + if (table.test(i) && !test_deleted(i)) + ++it; + return it; + } + + // This is used when resizing + destructive_iterator destructive_begin() { + return destructive_iterator(this, table.destructive_begin(), + table.destructive_end()); + } + destructive_iterator destructive_end() { + return destructive_iterator(this, table.destructive_end(), + table.destructive_end()); + } + + + // ACCESSOR FUNCTIONS for the things we templatize on, basically + hasher hash_funct() const { return hash; } + key_equal key_eq() const { return equals; } + + // Accessor function for statistics gathering. + int num_table_copies() const { return num_ht_copies; } + + private: + // We need to copy values when we set the special marker for deleted + // elements, but, annoyingly, we can't just use the copy assignment + // operator because value_type might not be assignable (it's often + // pair). We use explicit destructor invocation and + // placement new to get around this. Arg. + void set_value(value_type* dst, const value_type src) { + dst->~value_type(); // delete the old value, if any + new(dst) value_type(src); + } + + // This is used as a tag for the copy constructor, saying to destroy its + // arg We have two ways of destructively copying: with potentially growing + // the hashtable as we copy, and without. To make sure the outside world + // can't do a destructive copy, we make the typename private. + enum MoveDontCopyT {MoveDontCopy, MoveDontGrow}; + + + // DELETE HELPER FUNCTIONS + // This lets the user describe a key that will indicate deleted + // table entries. This key should be an "impossible" entry -- + // if you try to insert it for real, you won't be able to retrieve it! + // (NB: while you pass in an entire value, only the key part is looked + // at. This is just because I don't know how to assign just a key.) + private: + void squash_deleted() { // gets rid of any deleted entries we have + if ( num_deleted ) { // get rid of deleted before writing + sparse_hashtable tmp(MoveDontGrow, *this); + swap(tmp); // now we are tmp + } + assert(num_deleted == 0); + } + + public: + void set_deleted_key(const key_type &key) { + // It's only safe to change what "deleted" means if we purge deleted guys + squash_deleted(); + use_deleted = true; + delkey = key; + } + void clear_deleted_key() { + squash_deleted(); + use_deleted = false; + } + key_type deleted_key() const { + assert(use_deleted); + return delkey; + } + + // These are public so the iterators can use them + // True if the item at position bucknum is "deleted" marker + bool test_deleted(size_type bucknum) const { + // The num_deleted test is crucial for read(): after read(), the ht values + // are garbage, and we don't want to think some of them are deleted. + return (use_deleted && num_deleted > 0 && table.test(bucknum) && + equals(delkey, get_key(table.unsafe_get(bucknum)))); + } + bool test_deleted(const iterator &it) const { + return (use_deleted && num_deleted > 0 && + equals(delkey, get_key(*it))); + } + bool test_deleted(const const_iterator &it) const { + return (use_deleted && num_deleted > 0 && + equals(delkey, get_key(*it))); + } + bool test_deleted(const destructive_iterator &it) const { + return (use_deleted && num_deleted > 0 && + equals(delkey, get_key(*it))); + } + // Set it so test_deleted is true. true if object didn't used to be deleted. + bool set_deleted(iterator &it) { + assert(use_deleted); + bool retval = !test_deleted(it); + // &* converts from iterator to value-type. + set_key(&(*it), delkey); + return retval; + } + // Set it so test_deleted is false. true if object used to be deleted. + bool clear_deleted(iterator &it) { + assert(use_deleted); + // Happens automatically when we assign something else in its place. + return test_deleted(it); + } + + // We also allow to set/clear the deleted bit on a const iterator. + // We allow a const_iterator for the same reason you can delete a + // const pointer: it's convenient, and semantically you can't use + // 'it' after it's been deleted anyway, so its const-ness doesn't + // really matter. + bool set_deleted(const_iterator &it) { + assert(use_deleted); // bad if set_deleted_key() wasn't called + bool retval = !test_deleted(it); + set_key(const_cast(&(*it)), delkey); + return retval; + } + bool clear_deleted(const_iterator &it) { + assert(use_deleted); // bad if set_deleted_key() wasn't called + return test_deleted(it); + } + + + // FUNCTIONS CONCERNING SIZE + size_type size() const { return table.num_nonempty() - num_deleted; } + // Buckets are always a power of 2 + size_type max_size() const { return (size_type(-1) >> 1U) + 1; } + bool empty() const { return size() == 0; } + size_type bucket_count() const { return table.size(); } + size_type max_bucket_count() const { return max_size(); } + // These are tr1 methods. Their idea of 'bucket' doesn't map well to + // what we do. We just say every bucket has 0 or 1 items in it. + size_type bucket_size(size_type i) const { + return begin(i) == end(i) ? 0 : 1; + } + + + private: + // Because of the above, size_type(-1) is never legal; use it for errors + static const size_type ILLEGAL_BUCKET = size_type(-1); + + private: + // This is the smallest size a hashtable can be without being too crowded + // If you like, you can give a min #buckets as well as a min #elts + size_type min_size(size_type num_elts, size_type min_buckets_wanted) { + size_type sz = HT_MIN_BUCKETS; // min buckets allowed + while ( sz < min_buckets_wanted || + num_elts >= static_cast(sz * enlarge_resize_percent) ) { + if (sz * 2 < sz) + throw std::length_error("resize overflow"); // protect against overflow + sz *= 2; + } + return sz; + } + + // Used after a string of deletes + void maybe_shrink() { + assert(table.num_nonempty() >= num_deleted); + assert((bucket_count() & (bucket_count()-1)) == 0); // is a power of two + assert(bucket_count() >= HT_MIN_BUCKETS); + + // If you construct a hashtable with < HT_DEFAULT_STARTING_BUCKETS, + // we'll never shrink until you get relatively big, and we'll never + // shrink below HT_DEFAULT_STARTING_BUCKETS. Otherwise, something + // like "dense_hash_set x; x.insert(4); x.erase(4);" will + // shrink us down to HT_MIN_BUCKETS buckets, which is too small. + if (shrink_threshold > 0 && + (table.num_nonempty()-num_deleted) < shrink_threshold && + bucket_count() > HT_DEFAULT_STARTING_BUCKETS) { + size_type sz = bucket_count() / 2; // find how much we should shrink + while ( sz > HT_DEFAULT_STARTING_BUCKETS && + (table.num_nonempty() - num_deleted) <= sz * + shrink_resize_percent ) + sz /= 2; // stay a power of 2 + sparse_hashtable tmp(MoveDontCopy, *this, sz); + swap(tmp); // now we are tmp + } + consider_shrink = false; // because we just considered it + } + + // We'll let you resize a hashtable -- though this makes us copy all! + // When you resize, you say, "make it big enough for this many more elements" + void resize_delta(size_type delta) { + if ( consider_shrink ) // see if lots of deletes happened + maybe_shrink(); + if ( bucket_count() >= HT_MIN_BUCKETS && + (table.num_nonempty() + delta) <= enlarge_threshold ) + return; // we're ok as we are + + // Sometimes, we need to resize just to get rid of all the + // "deleted" buckets that are clogging up the hashtable. So when + // deciding whether to resize, count the deleted buckets (which + // are currently taking up room). But later, when we decide what + // size to resize to, *don't* count deleted buckets, since they + // get discarded during the resize. + const size_type needed_size = min_size(table.num_nonempty() + delta, 0); + if ( needed_size > bucket_count() ) { // we don't have enough buckets + size_type resize_to = min_size(table.num_nonempty() - num_deleted + delta, + bucket_count()); + if (resize_to < needed_size) { + // This situation means that we have enough deleted elements, + // that once we purge them, we won't actually have needed to + // grow. But we may want to grow anyway: if we just purge one + // element, say, we'll have to grow anyway next time we + // insert. Might as well grow now, since we're already going + // through the trouble of copying (in order to purge the + // deleted elements). + if (table.num_nonempty() - num_deleted + delta >= + static_cast(resize_to*2 * shrink_resize_percent)) { + // Good, we won't be below the shrink threshhold even if we double. + resize_to *= 2; + } + } + + sparse_hashtable tmp(MoveDontCopy, *this, resize_to); + swap(tmp); // now we are tmp + } + } + + // Used to actually do the rehashing when we grow/shrink a hashtable + void copy_from(const sparse_hashtable &ht, size_type min_buckets_wanted) { + clear(); // clear table, set num_deleted to 0 + + // If we need to change the size of our table, do it now + const size_type resize_to = min_size(ht.size(), min_buckets_wanted); + if ( resize_to > bucket_count() ) { // we don't have enough buckets + table.resize(resize_to); // sets the number of buckets + reset_thresholds(); + } + + // We use a normal iterator to get non-deleted bcks from ht + // We could use insert() here, but since we know there are + // no duplicates and no deleted items, we can be more efficient + assert( (bucket_count() & (bucket_count()-1)) == 0); // a power of two + for ( const_iterator it = ht.begin(); it != ht.end(); ++it ) { + size_type num_probes = 0; // how many times we've probed + size_type bucknum; + const size_type bucket_count_minus_one = bucket_count() - 1; + for (bucknum = hash(get_key(*it)) & bucket_count_minus_one; + table.test(bucknum); // not empty + bucknum = (bucknum + JUMP_(key, num_probes)) & bucket_count_minus_one) { + ++num_probes; + assert(num_probes < bucket_count()); // or else the hashtable is full + } + table.set(bucknum, *it); // copies the value to here + } + num_ht_copies++; + } + + // Implementation is like copy_from, but it destroys the table of the + // "from" guy by freeing sparsetable memory as we iterate. This is + // useful in resizing, since we're throwing away the "from" guy anyway. + void move_from(MoveDontCopyT mover, sparse_hashtable &ht, + size_type min_buckets_wanted) { + clear(); // clear table, set num_deleted to 0 + + // If we need to change the size of our table, do it now + size_t resize_to; + if ( mover == MoveDontGrow ) + resize_to = ht.bucket_count(); // keep same size as old ht + else // MoveDontCopy + resize_to = min_size(ht.size(), min_buckets_wanted); + if ( resize_to > bucket_count() ) { // we don't have enough buckets + table.resize(resize_to); // sets the number of buckets + reset_thresholds(); + } + + // We use a normal iterator to get non-deleted bcks from ht + // We could use insert() here, but since we know there are + // no duplicates and no deleted items, we can be more efficient + assert( (bucket_count() & (bucket_count()-1)) == 0); // a power of two + // THIS IS THE MAJOR LINE THAT DIFFERS FROM COPY_FROM(): + for ( destructive_iterator it = ht.destructive_begin(); + it != ht.destructive_end(); ++it ) { + size_type num_probes = 0; // how many times we've probed + size_type bucknum; + for ( bucknum = hash(get_key(*it)) & (bucket_count()-1); // h % buck_cnt + table.test(bucknum); // not empty + bucknum = (bucknum + JUMP_(key, num_probes)) & (bucket_count()-1) ) { + ++num_probes; + assert(num_probes < bucket_count()); // or else the hashtable is full + } + table.set(bucknum, *it); // copies the value to here + } + num_ht_copies++; + } + + + // Required by the spec for hashed associative container + public: + // Though the docs say this should be num_buckets, I think it's much + // more useful as num_elements. As a special feature, calling with + // req_elements==0 will cause us to shrink if we can, saving space. + void resize(size_type req_elements) { // resize to this or larger + if ( consider_shrink || req_elements == 0 ) + maybe_shrink(); + if ( req_elements > table.num_nonempty() ) // we only grow + resize_delta(req_elements - table.num_nonempty()); + } + + // Get and change the value of shrink_resize_percent and + // enlarge_resize_percent. The description at the beginning of this + // file explains how to choose the values. Setting the shrink + // parameter to 0.0 ensures that the table never shrinks. + void get_resizing_parameters(float* shrink, float* grow) const { + *shrink = shrink_resize_percent; + *grow = enlarge_resize_percent; + } + void set_resizing_parameters(float shrink, float grow) { + assert(shrink >= 0.0); + assert(grow <= 1.0); + if (shrink > grow/2.0f) + shrink = grow / 2.0f; // otherwise we thrash hashtable size + shrink_resize_percent = shrink; + enlarge_resize_percent = grow; + reset_thresholds(); + } + + // CONSTRUCTORS -- as required by the specs, we take a size, + // but also let you specify a hashfunction, key comparator, + // and key extractor. We also define a copy constructor and =. + // DESTRUCTOR -- the default is fine, surprisingly. + explicit sparse_hashtable(size_type expected_max_items_in_table = 0, + const HashFcn& hf = HashFcn(), + const EqualKey& eql = EqualKey(), + const SetKey& set = SetKey(), + const ExtractKey& ext = ExtractKey()) + : hash(hf), equals(eql), get_key(ext), set_key(set), num_deleted(0), + use_deleted(false), delkey(), enlarge_resize_percent(HT_OCCUPANCY_FLT), + shrink_resize_percent(HT_EMPTY_FLT), + table(expected_max_items_in_table == 0 + ? HT_DEFAULT_STARTING_BUCKETS + : min_size(expected_max_items_in_table, 0)), + num_ht_copies(0) { + reset_thresholds(); + } + + // As a convenience for resize(), we allow an optional second argument + // which lets you make this new hashtable a different size than ht. + // We also provide a mechanism of saying you want to "move" the ht argument + // into us instead of copying. + sparse_hashtable(const sparse_hashtable& ht, + size_type min_buckets_wanted = HT_DEFAULT_STARTING_BUCKETS) + : hash(ht.hash), equals(ht.equals), + get_key(ht.get_key), set_key(ht.set_key), num_deleted(0), + use_deleted(ht.use_deleted), delkey(ht.delkey), + enlarge_resize_percent(ht.enlarge_resize_percent), + shrink_resize_percent(ht.shrink_resize_percent), + table(), num_ht_copies(ht.num_ht_copies) { + reset_thresholds(); + copy_from(ht, min_buckets_wanted); // copy_from() ignores deleted entries + } + sparse_hashtable(MoveDontCopyT mover, sparse_hashtable& ht, + size_type min_buckets_wanted = HT_DEFAULT_STARTING_BUCKETS) + : hash(ht.hash), equals(ht.equals), get_key(ht.get_key), + num_deleted(0), use_deleted(ht.use_deleted), delkey(ht.delkey), + enlarge_resize_percent(ht.enlarge_resize_percent), + shrink_resize_percent(ht.shrink_resize_percent), + table(), num_ht_copies(ht.num_ht_copies) { + reset_thresholds(); + move_from(mover, ht, min_buckets_wanted); // ignores deleted entries + } + + sparse_hashtable& operator= (const sparse_hashtable& ht) { + if (&ht == this) return *this; // don't copy onto ourselves + hash = ht.hash; + equals = ht.equals; + get_key = ht.get_key; + set_key = ht.set_key; + use_deleted = ht.use_deleted; + delkey = ht.delkey; + copy_from(ht, HT_MIN_BUCKETS); // calls clear and sets num_deleted to 0 too + return *this; + } + + // Many STL algorithms use swap instead of copy constructors + void swap(sparse_hashtable& ht) { + STL_NAMESPACE::swap(hash, ht.hash); + STL_NAMESPACE::swap(equals, ht.equals); + STL_NAMESPACE::swap(get_key, ht.get_key); + STL_NAMESPACE::swap(set_key, ht.set_key); + STL_NAMESPACE::swap(num_deleted, ht.num_deleted); + STL_NAMESPACE::swap(use_deleted, ht.use_deleted); + STL_NAMESPACE::swap(enlarge_resize_percent, ht.enlarge_resize_percent); + STL_NAMESPACE::swap(shrink_resize_percent, ht.shrink_resize_percent); + STL_NAMESPACE::swap(delkey, ht.delkey); + table.swap(ht.table); + STL_NAMESPACE::swap(num_ht_copies, ht.num_ht_copies); + reset_thresholds(); + ht.reset_thresholds(); + } + + // It's always nice to be able to clear a table without deallocating it + void clear() { + if (!empty() || (num_deleted != 0)) { + table.clear(); + } + reset_thresholds(); + num_deleted = 0; + } + + + // LOOKUP ROUTINES + private: + // Returns a pair of positions: 1st where the object is, 2nd where + // it would go if you wanted to insert it. 1st is ILLEGAL_BUCKET + // if object is not found; 2nd is ILLEGAL_BUCKET if it is. + // Note: because of deletions where-to-insert is not trivial: it's the + // first deleted bucket we see, as long as we don't find the key later + pair find_position(const key_type &key) const { + size_type num_probes = 0; // how many times we've probed + const size_type bucket_count_minus_one = bucket_count() - 1; + size_type bucknum = hash(key) & bucket_count_minus_one; + size_type insert_pos = ILLEGAL_BUCKET; // where we would insert + SPARSEHASH_STAT_UPDATE(total_lookups += 1); + while ( 1 ) { // probe until something happens + if ( !table.test(bucknum) ) { // bucket is empty + SPARSEHASH_STAT_UPDATE(total_probes += num_probes); + if ( insert_pos == ILLEGAL_BUCKET ) // found no prior place to insert + return pair(ILLEGAL_BUCKET, bucknum); + else + return pair(ILLEGAL_BUCKET, insert_pos); + + } else if ( test_deleted(bucknum) ) {// keep searching, but mark to insert + if ( insert_pos == ILLEGAL_BUCKET ) + insert_pos = bucknum; + + } else if ( equals(key, get_key(table.unsafe_get(bucknum))) ) { + SPARSEHASH_STAT_UPDATE(total_probes += num_probes); + return pair(bucknum, ILLEGAL_BUCKET); + } + ++num_probes; // we're doing another probe + bucknum = (bucknum + JUMP_(key, num_probes)) & bucket_count_minus_one; + assert(num_probes < bucket_count()); // don't probe too many times! + } + } + + public: + iterator find(const key_type& key) { + if ( size() == 0 ) return end(); + pair pos = find_position(key); + if ( pos.first == ILLEGAL_BUCKET ) // alas, not there + return end(); + else + return iterator(this, table.get_iter(pos.first), table.nonempty_end()); + } + + const_iterator find(const key_type& key) const { + if ( size() == 0 ) return end(); + pair pos = find_position(key); + if ( pos.first == ILLEGAL_BUCKET ) // alas, not there + return end(); + else + return const_iterator(this, + table.get_iter(pos.first), table.nonempty_end()); + } + + // This is a tr1 method: the bucket a given key is in, or what bucket + // it would be put in, if it were to be inserted. Shrug. + size_type bucket(const key_type& key) const { + pair pos = find_position(key); + return pos.first == ILLEGAL_BUCKET ? pos.second : pos.first; + } + + // Counts how many elements have key key. For maps, it's either 0 or 1. + size_type count(const key_type &key) const { + pair pos = find_position(key); + return pos.first == ILLEGAL_BUCKET ? 0 : 1; + } + + // Likewise, equal_range doesn't really make sense for us. Oh well. + pair equal_range(const key_type& key) { + iterator pos = find(key); // either an iterator or end + if (pos == end()) { + return pair(pos, pos); + } else { + const iterator startpos = pos++; + return pair(startpos, pos); + } + } + pair equal_range(const key_type& key) const { + const_iterator pos = find(key); // either an iterator or end + if (pos == end()) { + return pair(pos, pos); + } else { + const const_iterator startpos = pos++; + return pair(startpos, pos); + } + } + + + // INSERTION ROUTINES + private: + // If you know *this is big enough to hold obj, use this routine + pair insert_noresize(const value_type& obj) { + // First, double-check we're not inserting delkey + assert(!use_deleted || !equals(get_key(obj), delkey)); + const pair pos = find_position(get_key(obj)); + if ( pos.first != ILLEGAL_BUCKET) { // object was already there + return pair(iterator(this, table.get_iter(pos.first), + table.nonempty_end()), + false); // false: we didn't insert + } else { // pos.second says where to put it + if ( test_deleted(pos.second) ) { // just replace if it's been del. + // The set() below will undelete this object. We just worry about stats + assert(num_deleted > 0); + --num_deleted; // used to be, now it isn't + } + table.set(pos.second, obj); + return pair(iterator(this, table.get_iter(pos.second), + table.nonempty_end()), + true); // true: we did insert + } + } + + public: + // This is the normal insert routine, used by the outside world + pair insert(const value_type& obj) { + resize_delta(1); // adding an object, grow if need be + return insert_noresize(obj); + } + + // When inserting a lot at a time, we specialize on the type of iterator + template + void insert(InputIterator f, InputIterator l) { + // specializes on iterator type + insert(f, l, typename STL_NAMESPACE::iterator_traits::iterator_category()); + } + + // Iterator supports operator-, resize before inserting + template + void insert(ForwardIterator f, ForwardIterator l, + STL_NAMESPACE::forward_iterator_tag) { + size_type n = STL_NAMESPACE::distance(f, l); // TODO(csilvers): standard? + resize_delta(n); + for ( ; n > 0; --n, ++f) + insert_noresize(*f); + } + + // Arbitrary iterator, can't tell how much to resize + template + void insert(InputIterator f, InputIterator l, + STL_NAMESPACE::input_iterator_tag) { + for ( ; f != l; ++f) + insert(*f); + } + + + // DELETION ROUTINES + size_type erase(const key_type& key) { + // First, double-check we're not erasing delkey. + assert(!use_deleted || !equals(key, delkey)); + const_iterator pos = find(key); // shrug: shouldn't need to be const + if ( pos != end() ) { + assert(!test_deleted(pos)); // or find() shouldn't have returned it + set_deleted(pos); + ++num_deleted; + consider_shrink = true; // will think about shrink after next insert + return 1; // because we deleted one thing + } else { + return 0; // because we deleted nothing + } + } + + // We return the iterator past the deleted item. + void erase(iterator pos) { + if ( pos == end() ) return; // sanity check + if ( set_deleted(pos) ) { // true if object has been newly deleted + ++num_deleted; + consider_shrink = true; // will think about shrink after next insert + } + } + + void erase(iterator f, iterator l) { + for ( ; f != l; ++f) { + if ( set_deleted(f) ) // should always be true + ++num_deleted; + } + consider_shrink = true; // will think about shrink after next insert + } + + // We allow you to erase a const_iterator just like we allow you to + // erase an iterator. This is in parallel to 'delete': you can delete + // a const pointer just like a non-const pointer. The logic is that + // you can't use the object after it's erased anyway, so it doesn't matter + // if it's const or not. + void erase(const_iterator pos) { + if ( pos == end() ) return; // sanity check + if ( set_deleted(pos) ) { // true if object has been newly deleted + ++num_deleted; + consider_shrink = true; // will think about shrink after next insert + } + } + void erase(const_iterator f, const_iterator l) { + for ( ; f != l; ++f) { + if ( set_deleted(f) ) // should always be true + ++num_deleted; + } + consider_shrink = true; // will think about shrink after next insert + } + + + // COMPARISON + bool operator==(const sparse_hashtable& ht) const { + // We really want to check that the hash functions are the same + // but alas there's no way to do this. We just hope. + return ( num_deleted == ht.num_deleted && table == ht.table ); + } + bool operator!=(const sparse_hashtable& ht) const { + return !(*this == ht); + } + + + // I/O + // We support reading and writing hashtables to disk. NOTE that + // this only stores the hashtable metadata, not the stuff you've + // actually put in the hashtable! Alas, since I don't know how to + // write a hasher or key_equal, you have to make sure everything + // but the table is the same. We compact before writing. + bool write_metadata(FILE *fp) { + squash_deleted(); // so we don't have to worry about delkey + return table.write_metadata(fp); + } + + bool read_metadata(FILE *fp) { + num_deleted = 0; // since we got rid before writing + bool result = table.read_metadata(fp); + reset_thresholds(); + return result; + } + + // Only meaningful if value_type is a POD. + bool write_nopointer_data(FILE *fp) { + return table.write_nopointer_data(fp); + } + + // Only meaningful if value_type is a POD. + bool read_nopointer_data(FILE *fp) { + return table.read_nopointer_data(fp); + } + + private: + // The actual data + hasher hash; // required by hashed_associative_container + key_equal equals; + ExtractKey get_key; + SetKey set_key; + size_type num_deleted; // how many occupied buckets are marked deleted + bool use_deleted; // false until delkey has been set + // TODO(csilvers): make a pointer, and get rid of use_deleted (benchmark!) + key_type delkey; // which key marks deleted entries + float enlarge_resize_percent; // how full before resize + float shrink_resize_percent; // how empty before resize + size_type shrink_threshold; // table.size() * shrink_resize_percent + size_type enlarge_threshold; // table.size() * enlarge_resize_percent + sparsetable table; // holds num_buckets and num_elements too + bool consider_shrink; // true if we should try to shrink before next insert + int num_ht_copies; // a statistics counter incremented every Copy/Move + + void reset_thresholds() { + enlarge_threshold = static_cast(table.size() + * enlarge_resize_percent); + shrink_threshold = static_cast(table.size() + * shrink_resize_percent); + consider_shrink = false; // whatever caused us to reset already considered + } +}; + +// We need a global swap as well +template +inline void swap(sparse_hashtable &x, + sparse_hashtable &y) { + x.swap(y); +} + +#undef JUMP_ + +template +const typename sparse_hashtable::size_type + sparse_hashtable::ILLEGAL_BUCKET; + +// How full we let the table get before we resize. Knuth says .8 is +// good -- higher causes us to probe too much, though saves memory +template +const float sparse_hashtable::HT_OCCUPANCY_FLT = 0.8f; + +// How empty we let the table get before we resize lower. +// It should be less than OCCUPANCY_FLT / 2 or we thrash resizing +template +const float sparse_hashtable::HT_EMPTY_FLT = 0.4f * +sparse_hashtable::HT_OCCUPANCY_FLT; + +_END_GOOGLE_NAMESPACE_ + +#endif /* _SPARSEHASHTABLE_H_ */ diff --git a/src/sparsehash-1.6/src/google/sparsetable b/src/sparsehash-1.6/src/google/sparsetable new file mode 100644 index 0000000..6dc0937 --- /dev/null +++ b/src/sparsehash-1.6/src/google/sparsetable @@ -0,0 +1,1473 @@ +// 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 +// +// 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] = , 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". +// +// Unassigned values seem to have the default value of T (see below). +// Nevertheless, there is a difference between an unassigned index and +// one explicitly assigned the value of T(). The latter is considered +// assigned. +// +// Access to an array element is constant time, as is insertion and +// deletion. Insertion and deletion may be fairly slow, however: +// because of this container's memory economy, each insert and delete +// causes a memory reallocation. +// +// See /usr/(local/)?doc/sparsehash-0.1/sparsetable.html +// for information about how to use this class. + +#ifndef _SPARSETABLE_H_ +#define _SPARSETABLE_H_ + +#include +#include // for malloc/free +#include // to read/write tables +#ifdef HAVE_STDINT_H +#include // the normal place uint16_t is defined +#endif +#ifdef HAVE_SYS_TYPES_H +#include // the normal place u_int16_t is defined +#endif +#ifdef HAVE_INTTYPES_H +#include // a third place for uint16_t or u_int16_t +#endif +#include // for bounds checking +#include // to define reverse_iterator for me +#include // equal, lexicographical_compare, swap,... +#include // uninitialized_copy +#include // a sparsetable is a vector of groups +#include // for true_type, integral_constant, etc. + +#if STDC_HEADERS +#include // for memcpy +#else +#if !HAVE_MEMCPY +#define memcpy(d, s, n) bcopy ((s), (d), (n)) +#endif +#endif + +_START_GOOGLE_NAMESPACE_ + +#ifndef HAVE_U_INT16_T +# if defined HAVE_UINT16_T + typedef uint16_t u_int16_t; // true on solaris, possibly other C99 libc's +# elif defined HAVE___UINT16 + typedef __int16 int16_t; // true on vc++7 + typedef unsigned __int16 u_int16_t; +# else + // Cannot find a 16-bit integer type. Hoping for the best with "short"... + typedef short int int16_t; + typedef unsigned short int u_int16_t; +# endif +#endif + +using STL_NAMESPACE::vector; +using STL_NAMESPACE::uninitialized_copy; + +// The smaller this is, the faster lookup is (because the group bitmap is +// smaller) and the faster insert is, because there's less to move. +// On the other hand, there are more groups. Since group::size_type is +// a short, this number should be of the form 32*x + 16 to avoid waste. +static const u_int16_t DEFAULT_SPARSEGROUP_SIZE = 48; // fits in 1.5 words + + +// A NOTE ON ASSIGNING: +// A sparse table does not actually allocate memory for entries +// that are not filled. Because of this, it becomes complicated +// to have a non-const iterator: we don't know, if the iterator points +// to a not-filled bucket, whether you plan to fill it with something +// or whether you plan to read its value (in which case you'll get +// the default bucket value). Therefore, while we can define const +// operations in a pretty 'normal' way, for non-const operations, we +// define something that returns a helper object with operator= and +// operator& that allocate a bucket lazily. We use this for table[] +// and also for regular table iterators. + +template +class table_element_adaptor { + public: + typedef typename tabletype::value_type value_type; + typedef typename tabletype::size_type size_type; + typedef typename tabletype::reference reference; + typedef typename tabletype::pointer pointer; + + table_element_adaptor(tabletype *tbl, size_type p) + : table(tbl), pos(p) { } + table_element_adaptor& operator= (const value_type &val) { + table->set(pos, val); + return *this; + } + operator value_type() { return table->get(pos); } // we look like a value + pointer operator& () { return &table->mutating_get(pos); } + + private: + tabletype* table; + size_type pos; +}; + +// Our iterator as simple as iterators can be: basically it's just +// the index into our table. Dereference, the only complicated +// thing, we punt to the table class. This just goes to show how +// much machinery STL requires to do even the most trivial tasks. +// +// By templatizing over tabletype, we have one iterator type which +// we can use for both sparsetables and sparsebins. In fact it +// works on any class that allows size() and operator[] (eg vector), +// as long as it does the standard STL typedefs too (eg value_type). + +template +class table_iterator { + public: + typedef table_iterator iterator; + + typedef STL_NAMESPACE::random_access_iterator_tag iterator_category; + typedef typename tabletype::value_type value_type; + typedef typename tabletype::difference_type difference_type; + typedef typename tabletype::size_type size_type; + typedef table_element_adaptor reference; + typedef table_element_adaptor* pointer; + + // The "real" constructor + table_iterator(tabletype *tbl, size_type p) + : table(tbl), pos(p) { } + // The default constructor, used when I define vars of type table::iterator + table_iterator() : table(NULL), pos(0) { } + // The copy constructor, for when I say table::iterator foo = tbl.begin() + // The default destructor is fine; we don't define one + // The default operator= is fine; we don't define one + + // The main thing our iterator does is dereference. If the table entry + // we point to is empty, we return the default value type. + // This is the big different function from the const iterator. + reference operator*() { + return table_element_adaptor(table, pos); + } + pointer operator->() { return &(operator*()); } + + // Helper function to assert things are ok; eg pos is still in range + void check() const { + assert(table); + assert(pos <= table->size()); + } + + // Arithmetic: we just do arithmetic on pos. We don't even need to + // do bounds checking, since STL doesn't consider that it's job. :-) + iterator& operator+=(size_type t) { pos += t; check(); return *this; } + iterator& operator-=(size_type t) { pos -= t; check(); return *this; } + iterator& operator++() { ++pos; check(); return *this; } + iterator& operator--() { --pos; check(); return *this; } + iterator operator++(int) { iterator tmp(*this); // for x++ + ++pos; check(); return tmp; } + iterator operator--(int) { iterator tmp(*this); // for x-- + --pos; check(); return tmp; } + iterator operator+(difference_type i) const { iterator tmp(*this); + tmp += i; return tmp; } + iterator operator-(difference_type i) const { iterator tmp(*this); + tmp -= i; return tmp; } + difference_type operator-(iterator it) const { // for "x = it2 - it" + assert(table == it.table); + return pos - it.pos; + } + reference operator[](difference_type n) const { + return *(*this + n); // simple though not totally efficient + } + + // Comparisons. + bool operator==(const iterator& it) const { + return table == it.table && pos == it.pos; + } + bool operator<(const iterator& it) const { + assert(table == it.table); // life is bad bad bad otherwise + return pos < it.pos; + } + bool operator!=(const iterator& it) const { return !(*this == it); } + bool operator<=(const iterator& it) const { return !(it < *this); } + bool operator>(const iterator& it) const { return it < *this; } + bool operator>=(const iterator& it) const { return !(*this < it); } + + // Here's the info we actually need to be an iterator + tabletype *table; // so we can dereference and bounds-check + size_type pos; // index into the table +}; + +// support for "3 + iterator" has to be defined outside the class, alas +template +table_iterator operator+(typename table_iterator::difference_type i, + table_iterator it) { + return it + i; // so people can say it2 = 3 + it +} + +template +class const_table_iterator { + public: + typedef table_iterator iterator; + typedef const_table_iterator const_iterator; + + typedef STL_NAMESPACE::random_access_iterator_tag iterator_category; + typedef typename tabletype::value_type value_type; + typedef typename tabletype::difference_type difference_type; + typedef typename tabletype::size_type size_type; + typedef typename tabletype::const_reference reference; // we're const-only + typedef typename tabletype::const_pointer pointer; + + // The "real" constructor + const_table_iterator(const tabletype *tbl, size_type p) + : table(tbl), pos(p) { } + // The default constructor, used when I define vars of type table::iterator + const_table_iterator() : table(NULL), pos(0) { } + // The copy constructor, for when I say table::iterator foo = tbl.begin() + // Also converts normal iterators to const iterators + const_table_iterator(const iterator &from) + : table(from.table), pos(from.pos) { } + // The default destructor is fine; we don't define one + // The default operator= is fine; we don't define one + + // The main thing our iterator does is dereference. If the table entry + // we point to is empty, we return the default value type. + reference operator*() const { return (*table)[pos]; } + pointer operator->() const { return &(operator*()); } + + // Helper function to assert things are ok; eg pos is still in range + void check() const { + assert(table); + assert(pos <= table->size()); + } + + // Arithmetic: we just do arithmetic on pos. We don't even need to + // do bounds checking, since STL doesn't consider that it's job. :-) + const_iterator& operator+=(size_type t) { pos += t; check(); return *this; } + const_iterator& operator-=(size_type t) { pos -= t; check(); return *this; } + const_iterator& operator++() { ++pos; check(); return *this; } + const_iterator& operator--() { --pos; check(); return *this; } + const_iterator operator++(int) { const_iterator tmp(*this); // for x++ + ++pos; check(); return tmp; } + const_iterator operator--(int) { const_iterator tmp(*this); // for x-- + --pos; check(); return tmp; } + const_iterator operator+(difference_type i) const { const_iterator tmp(*this); + tmp += i; return tmp; } + const_iterator operator-(difference_type i) const { const_iterator tmp(*this); + tmp -= i; return tmp; } + difference_type operator-(const_iterator it) const { // for "x = it2 - it" + assert(table == it.table); + return pos - it.pos; + } + reference operator[](difference_type n) const { + return *(*this + n); // simple though not totally efficient + } + + // Comparisons. + bool operator==(const const_iterator& it) const { + return table == it.table && pos == it.pos; + } + bool operator<(const const_iterator& it) const { + assert(table == it.table); // life is bad bad bad otherwise + return pos < it.pos; + } + bool operator!=(const const_iterator& it) const { return !(*this == it); } + bool operator<=(const const_iterator& it) const { return !(it < *this); } + bool operator>(const const_iterator& it) const { return it < *this; } + bool operator>=(const const_iterator& it) const { return !(*this < it); } + + // Here's the info we actually need to be an iterator + const tabletype *table; // so we can dereference and bounds-check + size_type pos; // index into the table +}; + +// support for "3 + iterator" has to be defined outside the class, alas +template +const_table_iterator operator+(typename + const_table_iterator::difference_type i, + const_table_iterator it) { + return it + i; // so people can say it2 = 3 + it +} + + +// --------------------------------------------------------------------------- + + +/* +// This is a 2-D iterator. You specify a begin and end over a list +// of *containers*. We iterate over each container by iterating over +// it. It's actually simple: +// VECTOR.begin() VECTOR[0].begin() --------> VECTOR[0].end() ---, +// | ________________________________________________/ +// | \_> VECTOR[1].begin() --------> VECTOR[1].end() -, +// | ___________________________________________________/ +// v \_> ...... +// VECTOR.end() +// +// It's impossible to do random access on one of these things in constant +// time, so it's just a bidirectional iterator. +// +// Unfortunately, because we need to use this for a non-empty iterator, +// we use nonempty_begin() and nonempty_end() instead of begin() and end() +// (though only going across, not down). +*/ + +#define TWOD_BEGIN_ nonempty_begin +#define TWOD_END_ nonempty_end +#define TWOD_ITER_ nonempty_iterator +#define TWOD_CONST_ITER_ const_nonempty_iterator + +template +class two_d_iterator { + public: + typedef two_d_iterator iterator; + + typedef STL_NAMESPACE::bidirectional_iterator_tag iterator_category; + // apparently some versions of VC++ have trouble with two ::'s in a typename + typedef typename containertype::value_type _tmp_vt; + typedef typename _tmp_vt::value_type value_type; + typedef typename _tmp_vt::difference_type difference_type; + typedef typename _tmp_vt::reference reference; + typedef typename _tmp_vt::pointer pointer; + + // The "real" constructor. begin and end specify how many rows we have + // (in the diagram above); we always iterate over each row completely. + two_d_iterator(typename containertype::iterator begin, + typename containertype::iterator end, + typename containertype::iterator curr) + : row_begin(begin), row_end(end), row_current(curr), col_current() { + if ( row_current != row_end ) { + col_current = row_current->TWOD_BEGIN_(); + advance_past_end(); // in case cur->begin() == cur->end() + } + } + // If you want to start at an arbitrary place, you can, I guess + two_d_iterator(typename containertype::iterator begin, + typename containertype::iterator end, + typename containertype::iterator curr, + typename containertype::value_type::TWOD_ITER_ col) + : row_begin(begin), row_end(end), row_current(curr), col_current(col) { + advance_past_end(); // in case cur->begin() == cur->end() + } + // The default constructor, used when I define vars of type table::iterator + two_d_iterator() : row_begin(), row_end(), row_current(), col_current() { } + // The default destructor is fine; we don't define one + // The default operator= is fine; we don't define one + + // Happy dereferencer + reference operator*() const { return *col_current; } + pointer operator->() const { return &(operator*()); } + + // Arithmetic: we just do arithmetic on pos. We don't even need to + // do bounds checking, since STL doesn't consider that it's job. :-) + // NOTE: this is not amortized constant time! What do we do about it? + void advance_past_end() { // used when col_current points to end() + while ( col_current == row_current->TWOD_END_() ) { // end of current row + ++row_current; // go to beginning of next + if ( row_current != row_end ) // col is irrelevant at end + col_current = row_current->TWOD_BEGIN_(); + else + break; // don't go past row_end + } + } + + iterator& operator++() { + assert(row_current != row_end); // how to ++ from there? + ++col_current; + advance_past_end(); // in case col_current is at end() + return *this; + } + iterator& operator--() { + while ( row_current == row_end || + col_current == row_current->TWOD_BEGIN_() ) { + assert(row_current != row_begin); + --row_current; + col_current = row_current->TWOD_END_(); // this is 1 too far + } + --col_current; + return *this; + } + iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; } + iterator operator--(int) { iterator tmp(*this); --*this; return tmp; } + + + // Comparisons. + bool operator==(const iterator& it) const { + return ( row_begin == it.row_begin && + row_end == it.row_end && + row_current == it.row_current && + (row_current == row_end || col_current == it.col_current) ); + } + bool operator!=(const iterator& it) const { return !(*this == it); } + + + // Here's the info we actually need to be an iterator + // These need to be public so we convert from iterator to const_iterator + typename containertype::iterator row_begin, row_end, row_current; + typename containertype::value_type::TWOD_ITER_ col_current; +}; + +// The same thing again, but this time const. :-( +template +class const_two_d_iterator { + public: + typedef const_two_d_iterator iterator; + + typedef STL_NAMESPACE::bidirectional_iterator_tag iterator_category; + // apparently some versions of VC++ have trouble with two ::'s in a typename + typedef typename containertype::value_type _tmp_vt; + typedef typename _tmp_vt::value_type value_type; + typedef typename _tmp_vt::difference_type difference_type; + typedef typename _tmp_vt::const_reference reference; + typedef typename _tmp_vt::const_pointer pointer; + + const_two_d_iterator(typename containertype::const_iterator begin, + typename containertype::const_iterator end, + typename containertype::const_iterator curr) + : row_begin(begin), row_end(end), row_current(curr), col_current() { + if ( curr != end ) { + col_current = curr->TWOD_BEGIN_(); + advance_past_end(); // in case cur->begin() == cur->end() + } + } + const_two_d_iterator(typename containertype::const_iterator begin, + typename containertype::const_iterator end, + typename containertype::const_iterator curr, + typename containertype::value_type::TWOD_CONST_ITER_ col) + : row_begin(begin), row_end(end), row_current(curr), col_current(col) { + advance_past_end(); // in case cur->begin() == cur->end() + } + const_two_d_iterator() + : row_begin(), row_end(), row_current(), col_current() { + } + // Need this explicitly so we can convert normal iterators to const iterators + const_two_d_iterator(const two_d_iterator& it) : + row_begin(it.row_begin), row_end(it.row_end), row_current(it.row_current), + col_current(it.col_current) { } + + typename containertype::const_iterator row_begin, row_end, row_current; + typename containertype::value_type::TWOD_CONST_ITER_ col_current; + + + // EVERYTHING FROM HERE DOWN IS THE SAME AS THE NON-CONST ITERATOR + reference operator*() const { return *col_current; } + pointer operator->() const { return &(operator*()); } + + void advance_past_end() { // used when col_current points to end() + while ( col_current == row_current->TWOD_END_() ) { // end of current row + ++row_current; // go to beginning of next + if ( row_current != row_end ) // col is irrelevant at end + col_current = row_current->TWOD_BEGIN_(); + else + break; // don't go past row_end + } + } + iterator& operator++() { + assert(row_current != row_end); // how to ++ from there? + ++col_current; + advance_past_end(); // in case col_current is at end() + return *this; + } + iterator& operator--() { + while ( row_current == row_end || + col_current == row_current->TWOD_BEGIN_() ) { + assert(row_current != row_begin); + --row_current; + col_current = row_current->TWOD_END_(); // this is 1 too far + } + --col_current; + return *this; + } + iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; } + iterator operator--(int) { iterator tmp(*this); --*this; return tmp; } + + bool operator==(const iterator& it) const { + return ( row_begin == it.row_begin && + row_end == it.row_end && + row_current == it.row_current && + (row_current == row_end || col_current == it.col_current) ); + } + bool operator!=(const iterator& it) const { return !(*this == it); } +}; + +// We provide yet another version, to be as frugal with memory as +// possible. This one frees each block of memory as it finishes +// iterating over it. By the end, the entire table is freed. +// For understandable reasons, you can only iterate over it once, +// which is why it's an input iterator +template +class destructive_two_d_iterator { + public: + typedef destructive_two_d_iterator iterator; + + typedef STL_NAMESPACE::input_iterator_tag iterator_category; + // apparently some versions of VC++ have trouble with two ::'s in a typename + typedef typename containertype::value_type _tmp_vt; + typedef typename _tmp_vt::value_type value_type; + typedef typename _tmp_vt::difference_type difference_type; + typedef typename _tmp_vt::reference reference; + typedef typename _tmp_vt::pointer pointer; + + destructive_two_d_iterator(typename containertype::iterator begin, + typename containertype::iterator end, + typename containertype::iterator curr) + : row_begin(begin), row_end(end), row_current(curr), col_current() { + if ( curr != end ) { + col_current = curr->TWOD_BEGIN_(); + advance_past_end(); // in case cur->begin() == cur->end() + } + } + destructive_two_d_iterator(typename containertype::iterator begin, + typename containertype::iterator end, + typename containertype::iterator curr, + typename containertype::value_type::TWOD_ITER_ col) + : row_begin(begin), row_end(end), row_current(curr), col_current(col) { + advance_past_end(); // in case cur->begin() == cur->end() + } + destructive_two_d_iterator() + : row_begin(), row_end(), row_current(), col_current() { + } + + typename containertype::iterator row_begin, row_end, row_current; + typename containertype::value_type::TWOD_ITER_ col_current; + + // This is the part that destroys + void advance_past_end() { // used when col_current points to end() + while ( col_current == row_current->TWOD_END_() ) { // end of current row + row_current->clear(); // the destructive part + // It would be nice if we could decrement sparsetable->num_buckets here + ++row_current; // go to beginning of next + if ( row_current != row_end ) // col is irrelevant at end + col_current = row_current->TWOD_BEGIN_(); + else + break; // don't go past row_end + } + } + + // EVERYTHING FROM HERE DOWN IS THE SAME AS THE REGULAR ITERATOR + reference operator*() const { return *col_current; } + pointer operator->() const { return &(operator*()); } + + iterator& operator++() { + assert(row_current != row_end); // how to ++ from there? + ++col_current; + advance_past_end(); // in case col_current is at end() + return *this; + } + iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; } + + bool operator==(const iterator& it) const { + return ( row_begin == it.row_begin && + row_end == it.row_end && + row_current == it.row_current && + (row_current == row_end || col_current == it.col_current) ); + } + bool operator!=(const iterator& it) const { return !(*this == it); } +}; + +#undef TWOD_BEGIN_ +#undef TWOD_END_ +#undef TWOD_ITER_ +#undef TWOD_CONST_ITER_ + + + + +// SPARSE-TABLE +// ------------ +// The idea is that a table with (logically) t buckets is divided +// into t/M *groups* of M buckets each. (M is a constant set in +// GROUP_SIZE for efficiency.) Each group is stored sparsely. +// Thus, inserting into the table causes some array to grow, which is +// slow but still constant time. Lookup involves doing a +// logical-position-to-sparse-position lookup, which is also slow but +// constant time. The larger M is, the slower these operations are +// but the less overhead (slightly). +// +// To store the sparse array, we store a bitmap B, where B[i] = 1 iff +// bucket i is non-empty. Then to look up bucket i we really look up +// array[# of 1s before i in B]. This is constant time for fixed M. +// +// Terminology: the position of an item in the overall table (from +// 1 .. t) is called its "location." The logical position in a group +// (from 1 .. M ) is called its "position." The actual location in +// the array (from 1 .. # of non-empty buckets in the group) is +// called its "offset." + +// The weird mod in the offset is entirely to quiet compiler warnings +// as is the cast to int after doing the "x mod 256" +#define PUT_(take_from, offset) do { \ + if (putc(static_cast(((take_from) >> ((offset) % (sizeof(take_from)*8)))\ + % 256), fp) \ + == EOF) \ + return false; \ +} while (0) + +#define GET_(add_to, offset) do { \ + if ((x=getc(fp)) == EOF) \ + return false; \ + else \ + add_to |= (static_cast(x) << ((offset) % (sizeof(add_to)*8))); \ +} while (0) + +template +class sparsegroup { + public: + // Basic types + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef table_iterator > iterator; + typedef const_table_iterator > const_iterator; + typedef table_element_adaptor > element_adaptor; + typedef value_type &reference; + typedef const value_type &const_reference; + typedef u_int16_t size_type; // max # of buckets + typedef int16_t difference_type; + typedef STL_NAMESPACE::reverse_iterator const_reverse_iterator; + typedef STL_NAMESPACE::reverse_iterator reverse_iterator; + + // These are our special iterators, that go over non-empty buckets in a + // group. These aren't const-only because you can change non-empty bcks. + typedef pointer nonempty_iterator; + typedef const_pointer const_nonempty_iterator; + typedef STL_NAMESPACE::reverse_iterator reverse_nonempty_iterator; + typedef STL_NAMESPACE::reverse_iterator const_reverse_nonempty_iterator; + + // Iterator functions + iterator begin() { return iterator(this, 0); } + const_iterator begin() const { return const_iterator(this, 0); } + iterator end() { return iterator(this, size()); } + const_iterator end() const { return const_iterator(this, size()); } + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + + // We'll have versions for our special non-empty iterator too + nonempty_iterator nonempty_begin() { return group; } + const_nonempty_iterator nonempty_begin() const { return group; } + nonempty_iterator nonempty_end() { return group + num_buckets; } + const_nonempty_iterator nonempty_end() const { return group + num_buckets; } + reverse_nonempty_iterator nonempty_rbegin() { + return reverse_nonempty_iterator(nonempty_end()); + } + const_reverse_nonempty_iterator nonempty_rbegin() const { + return const_reverse_nonempty_iterator(nonempty_end()); + } + reverse_nonempty_iterator nonempty_rend() { + return reverse_nonempty_iterator(nonempty_begin()); + } + const_reverse_nonempty_iterator nonempty_rend() const { + return const_reverse_nonempty_iterator(nonempty_begin()); + } + + + // This gives us the "default" value to return for an empty bucket. + // We just use the default constructor on T, the template type + const_reference default_value() const { + static value_type defaultval = value_type(); + return defaultval; + } + + + private: + // We need to do all this bit manipulation, of course. ick + static size_type charbit(size_type i) { return i >> 3; } + static size_type modbit(size_type i) { return 1 << (i&7); } + int bmtest(size_type i) const { return bitmap[charbit(i)] & modbit(i); } + void bmset(size_type i) { bitmap[charbit(i)] |= modbit(i); } + void bmclear(size_type i) { bitmap[charbit(i)] &= ~modbit(i); } + + void* realloc_or_die(void* ptr, size_t num_bytes) { + void* retval = realloc(ptr, num_bytes); + if (retval == NULL) { + // We really should use PRIuS here, but I don't want to have to add + // a whole new configure option, with concomitant macro namespace + // pollution, just to print this (unlikely) error message. So I cast. + fprintf(stderr, "FATAL ERROR: failed to allocate %lu bytes for ptr %p", + static_cast(num_bytes), ptr); + exit(1); + } + return retval; + } + + value_type* allocate_group(size_t n) { + return static_cast(realloc_or_die(NULL, + n * sizeof(value_type))); + } + + void free_group() { + // Valid even for empty group, because NULL+0 is defined to be NULL + value_type* end_it = group + num_buckets; + for (value_type* p = group; p != end_it; ++p) + p->~value_type(); + free(group); + group = NULL; + } + + public: // get_iter() in sparsetable needs it + // We need a small function that tells us how many set bits there are + // in positions 0..i-1 of the bitmap. It uses a big table. + // We make it static so templates don't allocate lots of these tables. + // There are lots of ways to do this calculation (called 'popcount'). + // The 8-bit table lookup is one of the fastest, though this + // implementation suffers from not doing any loop unrolling. See, eg, + // http://www.dalkescientific.com/writings/diary/archive/2008/07/03/hakmem_and_other_popcounts.html + // http://gurmeetsingh.wordpress.com/2008/08/05/fast-bit-counting-routines/ + static size_type pos_to_offset(const unsigned char *bm, size_type pos) { + // We could make these ints. The tradeoff is size (eg does it overwhelm + // the cache?) vs efficiency in referencing sub-word-sized array elements + static const char bits_in[256] = { // # of bits set in one char + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, + }; + size_type retval = 0; + + // [Note: condition pos > 8 is an optimization; convince yourself we + // give exactly the same result as if we had pos >= 8 here instead.] + for ( ; pos > 8; pos -= 8 ) // bm[0..pos/8-1] + retval += bits_in[*bm++]; // chars we want *all* bits in + return retval + bits_in[*bm & ((1 << pos)-1)]; // the char that includes pos + } + + size_type pos_to_offset(size_type pos) const { // not static but still const + return pos_to_offset(bitmap, pos); + } + + + public: + // Constructors -- default and copy -- and destructor + sparsegroup() : group(0), num_buckets(0) { memset(bitmap, 0, sizeof(bitmap)); } + sparsegroup(const sparsegroup& x) : group(0), num_buckets(x.num_buckets) { + if ( num_buckets ) { + group = allocate_group(x.num_buckets); + uninitialized_copy(x.group, x.group + x.num_buckets, group); + } + memcpy(bitmap, x.bitmap, sizeof(bitmap)); + } + ~sparsegroup() { free_group(); } + + // Operator= is just like the copy constructor, I guess + // TODO(austern): Make this exception safe. Handle exceptions in value_type's + // copy constructor. + sparsegroup &operator=(const sparsegroup& x) { + if ( &x == this ) return *this; // x = x + if ( x.num_buckets == 0 ) { + free_group(); + } else { + value_type* p = allocate_group(x.num_buckets); + uninitialized_copy(x.group, x.group + x.num_buckets, p); + free_group(); + group = p; + } + memcpy(bitmap, x.bitmap, sizeof(bitmap)); + num_buckets = x.num_buckets; + return *this; + } + + // Many STL algorithms use swap instead of copy constructors + void swap(sparsegroup& x) { + STL_NAMESPACE::swap(group, x.group); + for ( int i = 0; i < sizeof(bitmap) / sizeof(*bitmap); ++i ) + STL_NAMESPACE::swap(bitmap[i], x.bitmap[i]); // swap not defined on arrays + STL_NAMESPACE::swap(num_buckets, x.num_buckets); + } + + // It's always nice to be able to clear a table without deallocating it + void clear() { + free_group(); + memset(bitmap, 0, sizeof(bitmap)); + num_buckets = 0; + } + + // Functions that tell you about size. Alas, these aren't so useful + // because our table is always fixed size. + size_type size() const { return GROUP_SIZE; } + size_type max_size() const { return GROUP_SIZE; } + bool empty() const { return false; } + // We also may want to know how many *used* buckets there are + size_type num_nonempty() const { return num_buckets; } + + + // get()/set() are explicitly const/non-const. You can use [] if + // you want something that can be either (potentially more expensive). + const_reference get(size_type i) const { + if ( bmtest(i) ) // bucket i is occupied + return group[pos_to_offset(bitmap, i)]; + else + return default_value(); // return the default reference + } + + // TODO(csilvers): make protected + friend + // This is used by sparse_hashtable to get an element from the table + // when we know it exists. + const_reference unsafe_get(size_type i) const { + assert(bmtest(i)); + return group[pos_to_offset(bitmap, i)]; + } + + // TODO(csilvers): make protected + friend + reference mutating_get(size_type i) { // fills bucket i before getting + if ( !bmtest(i) ) + set(i, default_value()); + return group[pos_to_offset(bitmap, i)]; + } + + // Syntactic sugar. It's easy to return a const reference. To + // return a non-const reference, we need to use the assigner adaptor. + const_reference operator[](size_type i) const { + return get(i); + } + + element_adaptor operator[](size_type i) { + return element_adaptor(this, i); + } + + private: + // Create space at group[offset], assuming value_type has trivial + // copy constructor and destructor. (Really, we want it to have + // "trivial move", because that's what realloc and memmove both do. + // But there's no way to capture that using type_traits, so we + // pretend that move(x, y) is equivalent to "x.~T(); new(x) T(y);" + // which is pretty much correct, if a bit conservative.) + void set_aux(size_type offset, true_type) { + group = (value_type *) + realloc_or_die(group, sizeof(*group) * (num_buckets+1)); + // This is equivalent to memmove(), but faster on my Intel P4, + // at least with gcc4.1 -O2 / glibc 2.3.6. + for (size_type i = num_buckets; i > offset; --i) + memcpy(group + i, group + i-1, sizeof(*group)); + } + + // Create space at group[offset], without special assumptions about value_type + void set_aux(size_type offset, false_type) { + // This is valid because 0 <= offset <= num_buckets + value_type* p = allocate_group(num_buckets + 1); + uninitialized_copy(group, group + offset, p); + uninitialized_copy(group + offset, group + num_buckets, p + offset + 1); + free_group(); + group = p; + } + + public: + // This returns a reference to the inserted item (which is a copy of val). + // TODO(austern): Make this exception safe: handle exceptions from + // value_type's copy constructor. + reference set(size_type i, const_reference val) { + size_type offset = pos_to_offset(bitmap, i); // where we'll find (or insert) + if ( bmtest(i) ) { + // Delete the old value, which we're replacing with the new one + group[offset].~value_type(); + } else { + typedef integral_constant::value && + has_trivial_destructor::value)> + realloc_and_memmove_ok; // we pretend mv(x,y) == "x.~T(); new(x) T(y)" + set_aux(offset, realloc_and_memmove_ok()); + ++num_buckets; + bmset(i); + } + // This does the actual inserting. Since we made the array using + // malloc, we use "placement new" to just call the constructor. + new(&group[offset]) value_type(val); + return group[offset]; + } + + // We let you see if a bucket is non-empty without retrieving it + bool test(size_type i) const { + return bmtest(i) ? true : false; // cast an int to a bool + } + bool test(iterator pos) const { + return bmtest(pos.pos) ? true : false; + } + + private: + // Shrink the array, assuming value_type has trivial copy + // constructor and destructor. (Really, we want it to have "trivial + // move", because that's what realloc and memmove both do. But + // there's no way to capture that using type_traits, so we pretend + // that move(x, y) is equivalent to ""x.~T(); new(x) T(y);" + // which is pretty much correct, if a bit conservative.) + void erase_aux(size_type offset, true_type) { + // This isn't technically necessary, since we know we have a + // trivial destructor, but is a cheap way to get a bit more safety. + group[offset].~value_type(); + // This is equivalent to memmove(), but faster on my Intel P4, + // at lesat with gcc4.1 -O2 / glibc 2.3.6. + assert(num_buckets > 0); + for (size_type i = offset; i < num_buckets-1; ++i) + memcpy(group + i, group + i+1, sizeof(*group)); // hopefully inlined! + group = (value_type *) + realloc_or_die(group, sizeof(*group) * (num_buckets-1)); + } + + // Shrink the array, without any special assumptions about value_type. + void erase_aux(size_type offset, false_type) { + // This is valid because 0 <= offset < num_buckets. Note the inequality. + value_type* p = allocate_group(num_buckets - 1); + uninitialized_copy(group, group + offset, p); + uninitialized_copy(group + offset + 1, group + num_buckets, p + offset); + free_group(); + group = p; + } + + public: + // This takes the specified elements out of the group. This is + // "undefining", rather than "clearing". + // TODO(austern): Make this exception safe: handle exceptions from + // value_type's copy constructor. + void erase(size_type i) { + if ( bmtest(i) ) { // trivial to erase empty bucket + size_type offset = pos_to_offset(bitmap,i); // where we'll find (or insert) + if ( num_buckets == 1 ) { + free_group(); + group = NULL; + } else { + typedef integral_constant::value && + has_trivial_destructor::value)> + realloc_and_memmove_ok; // pretend mv(x,y) == "x.~T(); new(x) T(y)" + erase_aux(offset, realloc_and_memmove_ok()); + } + --num_buckets; + bmclear(i); + } + } + + void erase(iterator pos) { + erase(pos.pos); + } + + void erase(iterator start_it, iterator end_it) { + // This could be more efficient, but to do so we'd need to make + // bmclear() clear a range of indices. Doesn't seem worth it. + for ( ; start_it != end_it; ++start_it ) + erase(start_it); + } + + + // I/O + // We support reading and writing groups to disk. We don't store + // the actual array contents (which we don't know how to store), + // just the bitmap and size. Meant to be used with table I/O. + // Returns true if all was ok + bool write_metadata(FILE *fp) const { + assert(sizeof(num_buckets) == 2); // we explicitly set to u_int16_t + PUT_(num_buckets, 8); + PUT_(num_buckets, 0); + if ( !fwrite(bitmap, sizeof(bitmap), 1, fp) ) return false; + return true; + } + + // Reading destroys the old group contents! Returns true if all was ok + bool read_metadata(FILE *fp) { + clear(); + + int x; // the GET_ macro requires an 'int x' to be defined + GET_(num_buckets, 8); + GET_(num_buckets, 0); + + if ( !fread(bitmap, sizeof(bitmap), 1, fp) ) return false; + + // We'll allocate the space, but we won't fill it: it will be + // left as uninitialized raw memory. + group = allocate_group(num_buckets); + return true; + } + + // If your keys and values are simple enough, we can write them + // to disk for you. "simple enough" means POD and no pointers. + // However, we don't try to normalize endianness + bool write_nopointer_data(FILE *fp) const { + for ( const_nonempty_iterator it = nonempty_begin(); + it != nonempty_end(); ++it ) { + if ( !fwrite(&*it, sizeof(*it), 1, fp) ) return false; + } + return true; + } + + // When reading, we have to override the potential const-ness of *it. + // Again, only meaningful if value_type is a POD. + bool read_nopointer_data(FILE *fp) { + for ( nonempty_iterator it = nonempty_begin(); + it != nonempty_end(); ++it ) { + if ( !fread(reinterpret_cast(&(*it)), sizeof(*it), 1, fp) ) + return false; + } + return true; + } + + // Comparisons. Note the comparisons are pretty arbitrary: we + // compare values of the first index that isn't equal (using default + // value for empty buckets). + bool operator==(const sparsegroup& x) const { + return ( num_buckets == x.num_buckets && + memcmp(bitmap, x.bitmap, sizeof(bitmap)) == 0 && + STL_NAMESPACE::equal(begin(), end(), x.begin()) ); // from algorithm + } + bool operator<(const sparsegroup& x) const { // also from algorithm + return STL_NAMESPACE::lexicographical_compare(begin(), end(), + x.begin(), x.end()); + } + bool operator!=(const sparsegroup& x) const { return !(*this == x); } + bool operator<=(const sparsegroup& x) const { return !(x < *this); } + bool operator>(const sparsegroup& x) const { return x < *this; } + bool operator>=(const sparsegroup& x) const { return !(*this < x); } + + private: + // The actual data + value_type *group; // (small) array of T's + unsigned char bitmap[(GROUP_SIZE-1)/8 + 1]; // fancy math is so we round up + size_type num_buckets; // limits GROUP_SIZE to 64K +}; + +// We need a global swap as well +template +inline void swap(sparsegroup &x, sparsegroup &y) { + x.swap(y); +} + +// --------------------------------------------------------------------------- + + +template +class sparsetable { + public: + // Basic types + typedef T value_type; // stolen from stl_vector.h + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef table_iterator > iterator; + typedef const_table_iterator > const_iterator; + typedef table_element_adaptor > element_adaptor; + typedef value_type &reference; + typedef const value_type &const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef STL_NAMESPACE::reverse_iterator const_reverse_iterator; + typedef STL_NAMESPACE::reverse_iterator reverse_iterator; + + // These are our special iterators, that go over non-empty buckets in a + // table. These aren't const only because you can change non-empty bcks. + typedef two_d_iterator< vector< sparsegroup > > + nonempty_iterator; + typedef const_two_d_iterator< vector< sparsegroup > > + const_nonempty_iterator; + typedef STL_NAMESPACE::reverse_iterator reverse_nonempty_iterator; + typedef STL_NAMESPACE::reverse_iterator const_reverse_nonempty_iterator; + // Another special iterator: it frees memory as it iterates (used to resize) + typedef destructive_two_d_iterator< vector< sparsegroup > > + destructive_iterator; + + // Iterator functions + iterator begin() { return iterator(this, 0); } + const_iterator begin() const { return const_iterator(this, 0); } + iterator end() { return iterator(this, size()); } + const_iterator end() const { return const_iterator(this, size()); } + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + + // Versions for our special non-empty iterator + nonempty_iterator nonempty_begin() { + return nonempty_iterator(groups.begin(), groups.end(), groups.begin()); + } + const_nonempty_iterator nonempty_begin() const { + return const_nonempty_iterator(groups.begin(),groups.end(), groups.begin()); + } + nonempty_iterator nonempty_end() { + return nonempty_iterator(groups.begin(), groups.end(), groups.end()); + } + const_nonempty_iterator nonempty_end() const { + return const_nonempty_iterator(groups.begin(), groups.end(), groups.end()); + } + reverse_nonempty_iterator nonempty_rbegin() { + return reverse_nonempty_iterator(nonempty_end()); + } + const_reverse_nonempty_iterator nonempty_rbegin() const { + return const_reverse_nonempty_iterator(nonempty_end()); + } + reverse_nonempty_iterator nonempty_rend() { + return reverse_nonempty_iterator(nonempty_begin()); + } + const_reverse_nonempty_iterator nonempty_rend() const { + return const_reverse_nonempty_iterator(nonempty_begin()); + } + destructive_iterator destructive_begin() { + return destructive_iterator(groups.begin(), groups.end(), groups.begin()); + } + destructive_iterator destructive_end() { + return destructive_iterator(groups.begin(), groups.end(), groups.end()); + } + + private: + typedef typename vector< sparsegroup >::reference + GroupsReference; + typedef typename + vector< sparsegroup >::const_reference + GroupsConstReference; + typedef typename vector< sparsegroup >::iterator + GroupsIterator; + typedef typename vector< sparsegroup >::const_iterator + GroupsConstIterator; + + // How to deal with the proper group + static size_type num_groups(size_type num) { // how many to hold num buckets + return num == 0 ? 0 : ((num-1) / GROUP_SIZE) + 1; + } + + u_int16_t pos_in_group(size_type i) const { + return static_cast(i % GROUP_SIZE); + } + size_type group_num(size_type i) const { + return i / GROUP_SIZE; + } + GroupsReference which_group(size_type i) { + return groups[group_num(i)]; + } + GroupsConstReference which_group(size_type i) const { + return groups[group_num(i)]; + } + + public: + // Constructors -- default, normal (when you specify size), and copy + sparsetable(size_type sz = 0) + : groups(num_groups(sz)), table_size(sz), num_buckets(0) { } + // We'll can get away with using the default copy constructor, + // and default destructor, and hence the default operator=. Huzzah! + + // Many STL algorithms use swap instead of copy constructors + void swap(sparsetable& x) { + STL_NAMESPACE::swap(groups, x.groups); + STL_NAMESPACE::swap(table_size, x.table_size); + STL_NAMESPACE::swap(num_buckets, x.num_buckets); + } + + // It's always nice to be able to clear a table without deallocating it + void clear() { + GroupsIterator group; + for ( group = groups.begin(); group != groups.end(); ++group ) { + group->clear(); + } + num_buckets = 0; + } + + // Functions that tell you about size. + // NOTE: empty() is non-intuitive! It does not tell you the number + // of not-empty buckets (use num_nonempty() for that). Instead + // it says whether you've allocated any buckets or not. + size_type size() const { return table_size; } + size_type max_size() const { return size_type(-1); } + bool empty() const { return table_size == 0; } + // We also may want to know how many *used* buckets there are + size_type num_nonempty() const { return num_buckets; } + + // OK, we'll let you resize one of these puppies + void resize(size_type new_size) { + groups.resize(num_groups(new_size)); + if ( new_size < table_size) { // lower num_buckets, clear last group + if ( pos_in_group(new_size) > 0 ) // need to clear inside last group + groups.back().erase(groups.back().begin() + pos_in_group(new_size), + groups.back().end()); + num_buckets = 0; // refigure # of used buckets + GroupsConstIterator group; + for ( group = groups.begin(); group != groups.end(); ++group ) + num_buckets += group->num_nonempty(); + } + table_size = new_size; + } + + + // We let you see if a bucket is non-empty without retrieving it + bool test(size_type i) const { + return which_group(i).test(pos_in_group(i)); + } + bool test(iterator pos) const { + return which_group(pos.pos).test(pos_in_group(pos.pos)); + } + bool test(const_iterator pos) const { + return which_group(pos.pos).test(pos_in_group(pos.pos)); + } + + // We only return const_references because it's really hard to + // return something settable for empty buckets. Use set() instead. + const_reference get(size_type i) const { + assert(i < table_size); + return which_group(i).get(pos_in_group(i)); + } + + // TODO(csilvers): make protected + friend + // This is used by sparse_hashtable to get an element from the table + // when we know it exists (because the caller has called test(i)). + const_reference unsafe_get(size_type i) const { + assert(i < table_size); + assert(test(i)); + return which_group(i).unsafe_get(pos_in_group(i)); + } + + // TODO(csilvers): make protected + friend element_adaptor + reference mutating_get(size_type i) { // fills bucket i before getting + assert(i < table_size); + size_type old_numbuckets = which_group(i).num_nonempty(); + reference retval = which_group(i).mutating_get(pos_in_group(i)); + num_buckets += which_group(i).num_nonempty() - old_numbuckets; + return retval; + } + + // Syntactic sugar. As in sparsegroup, the non-const version is harder + const_reference operator[](size_type i) const { + return get(i); + } + + element_adaptor operator[](size_type i) { + return element_adaptor(this, i); + } + + // Needed for hashtables, gets as a nonempty_iterator. Crashes for empty bcks + const_nonempty_iterator get_iter(size_type i) const { + assert(test(i)); // how can a nonempty_iterator point to an empty bucket? + return const_nonempty_iterator( + groups.begin(), groups.end(), + groups.begin() + group_num(i), + (groups[group_num(i)].nonempty_begin() + + groups[group_num(i)].pos_to_offset(pos_in_group(i)))); + } + // For nonempty we can return a non-const version + nonempty_iterator get_iter(size_type i) { + assert(test(i)); // how can a nonempty_iterator point to an empty bucket? + return nonempty_iterator( + groups.begin(), groups.end(), + groups.begin() + group_num(i), + (groups[group_num(i)].nonempty_begin() + + groups[group_num(i)].pos_to_offset(pos_in_group(i)))); + } + + + // This returns a reference to the inserted item (which is a copy of val) + // The trick is to figure out whether we're replacing or inserting anew + reference set(size_type i, const_reference val) { + assert(i < table_size); + size_type old_numbuckets = which_group(i).num_nonempty(); + reference retval = which_group(i).set(pos_in_group(i), val); + num_buckets += which_group(i).num_nonempty() - old_numbuckets; + return retval; + } + + // This takes the specified elements out of the table. This is + // "undefining", rather than "clearing". + void erase(size_type i) { + assert(i < table_size); + size_type old_numbuckets = which_group(i).num_nonempty(); + which_group(i).erase(pos_in_group(i)); + num_buckets += which_group(i).num_nonempty() - old_numbuckets; + } + + void erase(iterator pos) { + erase(pos.pos); + } + + void erase(iterator start_it, iterator end_it) { + // This could be more efficient, but then we'd need to figure + // out if we spanned groups or not. Doesn't seem worth it. + for ( ; start_it != end_it; ++start_it ) + erase(start_it); + } + + + // We support reading and writing tables to disk. We don't store + // the actual array contents (which we don't know how to store), + // just the groups and sizes. Returns true if all went ok. + + private: + // Every time the disk format changes, this should probably change too + static const unsigned long MAGIC_NUMBER = 0x24687531; + + // Old versions of this code write all data in 32 bits. We need to + // support these files as well as having support for 64-bit systems. + // So we use the following encoding scheme: for values < 2^32-1, we + // store in 4 bytes in big-endian order. For values > 2^32, we + // store 0xFFFFFFF followed by 8 bytes in big-endian order. This + // causes us to mis-read old-version code that stores exactly + // 0xFFFFFFF, but I don't think that is likely to have happened for + // these particular values. + static bool write_32_or_64(FILE* fp, size_type value) { + if ( value < 0xFFFFFFFFULL ) { // fits in 4 bytes + PUT_(value, 24); + PUT_(value, 16); + PUT_(value, 8); + PUT_(value, 0); + } else if ( value == 0xFFFFFFFFUL ) { // special case in 32bit systems + PUT_(0xFF, 0); PUT_(0xFF, 0); PUT_(0xFF, 0); PUT_(0xFF, 0); // marker + PUT_(0, 0); PUT_(0, 0); PUT_(0, 0); PUT_(0, 0); + PUT_(0xFF, 0); PUT_(0xFF, 0); PUT_(0xFF, 0); PUT_(0xFF, 0); + } else { + PUT_(0xFF, 0); PUT_(0xFF, 0); PUT_(0xFF, 0); PUT_(0xFF, 0); // marker + PUT_(value, 56); + PUT_(value, 48); + PUT_(value, 40); + PUT_(value, 32); + PUT_(value, 24); + PUT_(value, 16); + PUT_(value, 8); + PUT_(value, 0); + } + return true; + } + + static bool read_32_or_64(FILE* fp, size_type *value) { // reads into value + size_type first4 = 0; + int x; + GET_(first4, 24); + GET_(first4, 16); + GET_(first4, 8); + GET_(first4, 0); + if ( first4 < 0xFFFFFFFFULL ) { + *value = first4; + } else { + GET_(*value, 56); + GET_(*value, 48); + GET_(*value, 40); + GET_(*value, 32); + GET_(*value, 24); + GET_(*value, 16); + GET_(*value, 8); + GET_(*value, 0); + } + return true; + } + + public: + bool write_metadata(FILE *fp) const { + if ( !write_32_or_64(fp, MAGIC_NUMBER) ) return false; + if ( !write_32_or_64(fp, table_size) ) return false; + if ( !write_32_or_64(fp, num_buckets) ) return false; + + GroupsConstIterator group; + for ( group = groups.begin(); group != groups.end(); ++group ) + if ( group->write_metadata(fp) == false ) return false; + return true; + } + + // Reading destroys the old table contents! Returns true if read ok. + bool read_metadata(FILE *fp) { + size_type magic_read = 0; + if ( !read_32_or_64(fp, &magic_read) ) return false; + if ( magic_read != MAGIC_NUMBER ) { + clear(); // just to be consistent + return false; + } + + if ( !read_32_or_64(fp, &table_size) ) return false; + if ( !read_32_or_64(fp, &num_buckets) ) return false; + + resize(table_size); // so the vector's sized ok + GroupsIterator group; + for ( group = groups.begin(); group != groups.end(); ++group ) + if ( group->read_metadata(fp) == false ) return false; + return true; + } + + // This code is identical to that for SparseGroup + // If your keys and values are simple enough, we can write them + // to disk for you. "simple enough" means no pointers. + // However, we don't try to normalize endianness + bool write_nopointer_data(FILE *fp) const { + for ( const_nonempty_iterator it = nonempty_begin(); + it != nonempty_end(); ++it ) { + if ( !fwrite(&*it, sizeof(*it), 1, fp) ) return false; + } + return true; + } + + // When reading, we have to override the potential const-ness of *it + bool read_nopointer_data(FILE *fp) { + for ( nonempty_iterator it = nonempty_begin(); + it != nonempty_end(); ++it ) { + if ( !fread(reinterpret_cast(&(*it)), sizeof(*it), 1, fp) ) + return false; + } + return true; + } + + // Comparisons. Note the comparisons are pretty arbitrary: we + // compare values of the first index that isn't equal (using default + // value for empty buckets). + bool operator==(const sparsetable& x) const { + return ( table_size == x.table_size && + num_buckets == x.num_buckets && + groups == x.groups ); + } + bool operator<(const sparsetable& x) const { // also from algobase.h + return STL_NAMESPACE::lexicographical_compare(begin(), end(), + x.begin(), x.end()); + } + bool operator!=(const sparsetable& x) const { return !(*this == x); } + bool operator<=(const sparsetable& x) const { return !(x < *this); } + bool operator>(const sparsetable& x) const { return x < *this; } + bool operator>=(const sparsetable& x) const { return !(*this < x); } + + + private: + // The actual data + vector< sparsegroup > groups; // our list of groups + size_type table_size; // how many buckets they want + size_type num_buckets; // number of non-empty buckets +}; + +// We need a global swap as well +template +inline void swap(sparsetable &x, sparsetable &y) { + x.swap(y); +} + +#undef GET_ +#undef PUT_ + +_END_GOOGLE_NAMESPACE_ + +#endif diff --git a/src/sparsehash-1.6/src/google/type_traits.h b/src/sparsehash-1.6/src/google/type_traits.h new file mode 100644 index 0000000..5f88133 --- /dev/null +++ b/src/sparsehash-1.6/src/google/type_traits.h @@ -0,0 +1,250 @@ +// 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 +#include // 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 +struct integral_constant { + static const T value = v; + typedef T value_type; + typedef integral_constant type; +}; + +template const T integral_constant::value; + +// Abbreviations: true_type and false_type are structs that represent +// boolean true and false values. +typedef integral_constant true_type; +typedef integral_constant 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 struct is_integral : false_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : 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 : true_type { }; +#endif +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +#ifdef HAVE_LONG_LONG +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +#endif + + +// is_floating_point is false except for the built-in floating-point types. +template struct is_floating_point : false_type { }; +template<> struct is_floating_point : true_type { }; +template<> struct is_floating_point : true_type { }; +template<> struct is_floating_point : true_type { }; + + +// is_pointer is false except for pointer types. +template struct is_pointer : false_type { }; +template struct is_pointer : true_type { }; + + +// is_reference is false except for reference types. +template struct is_reference : false_type {}; +template struct is_reference : 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 struct is_pod + : integral_constant::value || + is_floating_point::value || + is_pointer::value)> { }; +template struct is_pod : is_pod { }; + + +// 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 struct has_trivial_constructor : is_pod { }; +template struct has_trivial_constructor > + : integral_constant::value && + has_trivial_constructor::value)> { }; +template struct has_trivial_constructor + : has_trivial_constructor { }; +template struct has_trivial_constructor + : has_trivial_constructor { }; + +// 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 struct has_trivial_copy : is_pod { }; +template struct has_trivial_copy > + : integral_constant::value && + has_trivial_copy::value)> { }; +template struct has_trivial_copy + : has_trivial_copy { }; +template struct has_trivial_copy : has_trivial_copy { }; + +// 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 struct has_trivial_assign : is_pod { }; +template struct has_trivial_assign > + : integral_constant::value && + has_trivial_assign::value)> { }; +template struct has_trivial_assign + : has_trivial_assign { }; + +// 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 struct has_trivial_destructor : is_pod { }; +template struct has_trivial_destructor > + : integral_constant::value && + has_trivial_destructor::value)> { }; +template struct has_trivial_destructor + : has_trivial_destructor { }; +template struct has_trivial_destructor + : has_trivial_destructor { }; + +// Specified by TR1 [4.7.1] +template struct remove_const { typedef T type; }; +template struct remove_const { typedef T type; }; +template struct remove_volatile { typedef T type; }; +template struct remove_volatile { typedef T type; }; +template struct remove_cv { + typedef typename remove_const::type>::type type; +}; + + +// Specified by TR1 [4.7.2] +template struct remove_reference { typedef T type; }; +template struct remove_reference { typedef T type; }; + +// Specified by TR1 [4.7.4] Pointer modifications. +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { + 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 +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 +struct is_convertible + : integral_constant::Test( + internal::ConvertHelper::Create())) + == sizeof(small_)> { +}; +#endif + +_END_GOOGLE_NAMESPACE_ + +#endif // BASE_TYPE_TRAITS_H_ diff --git a/src/sparsehash-1.6/src/hashtable_unittest.cc b/src/sparsehash-1.6/src/hashtable_unittest.cc new file mode 100644 index 0000000..3dcbfee --- /dev/null +++ b/src/sparsehash-1.6/src/hashtable_unittest.cc @@ -0,0 +1,1531 @@ +// 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 +// This tests +// This tests +// This tests +// This tests +// This tests + +// Since {dense,sparse}hashtable 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 +#include // for stat() +#ifdef HAVE_UNISTD_H +#include // for unlink() +#endif +#include +#include // for silly random-number-seed generator +#include // for sqrt() +#include +#include +#include // for insert_iterator +#include +#include // for setprecision() +#include +#include // for std::length_error +#include HASH_FUN_H // defined in config.h +#include +#include +#include +#include +#include +#include +#include + +// Otherwise, VC++7 warns about size_t -> int in the cout logging lines +#ifdef _MSC_VER +#pragma warning(disable:4267) +#endif + +using GOOGLE_NAMESPACE::sparse_hash_map; +using GOOGLE_NAMESPACE::dense_hash_map; +using GOOGLE_NAMESPACE::sparse_hash_set; +using GOOGLE_NAMESPACE::dense_hash_set; +using GOOGLE_NAMESPACE::sparse_hashtable; +using GOOGLE_NAMESPACE::dense_hashtable; +using STL_NAMESPACE::map; +using STL_NAMESPACE::set; +using STL_NAMESPACE::pair; +using STL_NAMESPACE::make_pair; +using STL_NAMESPACE::string; +using STL_NAMESPACE::insert_iterator; +using STL_NAMESPACE::allocator; +using STL_NAMESPACE::equal_to; +using STL_NAMESPACE::ostream; + +#define LOGF STL_NAMESPACE::cout // where we log to; LOGF is a historical name + +#define CHECK(cond) do { \ + if (!(cond)) { \ + LOGF << "Test failed: " #cond "\n"; \ + exit(1); \ + } \ +} while (0) + +#define CHECK_EQ(a, b) CHECK((a) == (b)) +#define CHECK_LT(a, b) CHECK((a) < (b)) +#define CHECK_GE(a, b) CHECK((a) >= (b)) + +#ifndef _MSC_VER // windows defines its own version +static string TmpFile(const char* basename) { + return string("/tmp/") + basename; +} +#endif + +const char *words[] = {"Baffin\n", // in /usr/dict/words + "Boffin\n", // not in + "baffin\n", // not in + "genial\n", // last word in + "Aarhus\n", // first word alphabetically + "Zurich\n", // last word alphabetically + "Getty\n", +}; + +const char *nwords[] = {"Boffin\n", + "baffin\n", +}; + +const char *default_dict[] = {"Aarhus\n", + "aback\n", + "abandon\n", + "Baffin\n", + "baffle\n", + "bagged\n", + "congenial\n", + "genial\n", + "Getty\n", + "indiscreet\n", + "linens\n", + "pence\n", + "reassure\n", + "sequel\n", + "zoning\n", + "zoo\n", + "Zurich\n", +}; + +// Likewise, it's not standard to hash a string pre-tr1. Luckily, it is a char* +#ifdef HAVE_UNORDERED_MAP +typedef SPARSEHASH_HASH StrHash; +struct CharStarHash { + size_t operator()(const char* s) const { + return StrHash()(string(s)); + } + // These are used by MSVC: + bool operator()(const char* a, const char* b) const { + return strcmp(a, b) < 0; + } + static const size_t bucket_size = 4; // These are required by MSVC + static const size_t min_buckets = 8; // 4 and 8 are the defaults +}; +#else +typedef SPARSEHASH_HASH CharStarHash; +struct StrHash { + size_t operator()(const string& s) const { + return SPARSEHASH_HASH()(s.c_str()); + } + // These are used by MSVC: + bool operator()(const string& a, const string& b) const { + return a < b; + } + static const size_t bucket_size = 4; // These are required by MSVC + static const size_t min_buckets = 8; // 4 and 8 are the defaults +}; +#endif + +// Let us log the pairs that make up a hash_map +template +ostream& operator<<(ostream& s, const pair& p) { + s << "pair(" << p.first << ", " << p.second << ")"; + return s; +} + +struct strcmp_fnc { + bool operator()(const char* s1, const char* s2) const { + return ((s1 == 0 && s2 == 0) || + (s1 && s2 && *s1 == *s2 && strcmp(s1, s2) == 0)); + } +}; + +namespace { + +template +void set_empty_key(sparse_hashtable *ht, T val) { +} + +template +void set_empty_key(sparse_hash_set *ht, T val) { +} + +template +void set_empty_key(sparse_hash_map *ht, K val) { +} + +template +void set_empty_key(dense_hashtable *ht, T val) { + ht->set_empty_key(val); +} + +template +void set_empty_key(dense_hash_set *ht, T val) { + ht->set_empty_key(val); +} + +template +void set_empty_key(dense_hash_map *ht, K val) { + ht->set_empty_key(val); +} + +template +bool clear_no_resize(sparse_hashtable *ht) { + return false; +} + +template +bool clear_no_resize(sparse_hash_set *ht) { + return false; +} + +template +bool clear_no_resize(sparse_hash_map *ht) { + return false; +} + +template +bool clear_no_resize(dense_hashtable *ht) { + ht->clear_no_resize(); + return true; +} + +template +bool clear_no_resize(dense_hash_set *ht) { + ht->clear_no_resize(); + return true; +} + +template +bool clear_no_resize(dense_hash_map *ht) { + ht->clear_no_resize(); + return true; +} + +template +void insert(dense_hashtable *ht, T val) { + ht->insert(val); +} + +template +void insert(dense_hash_set *ht, T val) { + ht->insert(val); +} + +template +void insert(dense_hash_map *ht, K val) { + ht->insert(pair(val,V())); +} + +template +void insert(sparse_hashtable *ht, T val) { + ht->insert(val); +} + +template +void insert(sparse_hash_set *ht, T val) { + ht->insert(val); +} + +template +void insert(sparse_hash_map *ht, K val) { + ht->insert(pair(val,V())); +} + +template +void insert(HT *ht, Iterator begin, Iterator end) { + ht->insert(begin, end); +} + +// For hashtable's and hash_set's, the iterator insert works fine (and +// is used). But for the hash_map's, the iterator insert expects the +// iterators to point to pair's. So by looping over and calling insert +// on each element individually, the code below automatically expands +// into inserting a pair. +template +void insert(dense_hash_map *ht, Iterator begin, Iterator end) { + while (begin != end) { + insert(ht, *begin); + ++begin; + } +} + +template +void insert(sparse_hash_map *ht, Iterator begin, Iterator end) { + while (begin != end) { + insert(ht, *begin); + ++begin; + } +} + +// A version of insert that uses the insert_iterator. But insert_iterator +// isn't defined for the low level hashtable classes, so we just punt to insert. + +template +void iterator_insert(dense_hashtable* ht, T val, + insert_iterator >* ) { + ht->insert(val); +} + +template +void iterator_insert(dense_hash_set* , T val, + insert_iterator >* ii) { + *(*ii)++ = val; +} + +template +void iterator_insert(dense_hash_map* , K val, + insert_iterator >* ii) { + *(*ii)++ = pair(val,V()); +} + +template +void iterator_insert(sparse_hashtable* ht, T val, + insert_iterator >* ) { + ht->insert(val); +} + +template +void iterator_insert(sparse_hash_set* , T val, + insert_iterator >* ii) { + *(*ii)++ = val; +} + +template +void iterator_insert(sparse_hash_map *, K val, + insert_iterator >* ii) { + *(*ii)++ = pair(val,V()); +} + + +void write_item(FILE *fp, const char *val) { + fwrite(val, strlen(val), 1, fp); // \n serves to separate +} + +// The weird 'const' declarations are desired by the compiler. Yucko. +void write_item(FILE *fp, const pair &val) { + fwrite(val.first, strlen(val.first), 1, fp); +} + +void write_item(FILE *fp, const string &val) { + fwrite(val.data(), val.length(), 1, fp); // \n serves to separate +} + +// The weird 'const' declarations are desired by the compiler. Yucko. +void write_item(FILE *fp, const pair &val) { + fwrite(val.first.data(), val.first.length(), 1, fp); +} + +char* read_line(FILE* fp, char* line, int linesize) { + if ( fgets(line, linesize, fp) == NULL ) + return NULL; + // normalize windows files :-( + const size_t linelen = strlen(line); + if ( linelen >= 2 && line[linelen-2] == '\r' && line[linelen-1] == '\n' ) { + line[linelen-2] = '\n'; + line[linelen-1] = '\0'; + } + return line; +} + +void read_item(FILE *fp, char*const* val) { + char line[1024]; + read_line(fp, line, sizeof(line)); + char **p = const_cast(val); + *p = strdup(line); +} + +void read_item(FILE *fp, pair *val) { + char line[1024]; + read_line(fp, line, sizeof(line)); + char **p = const_cast(&val->first); + *p = strdup(line); +} + +void read_item(FILE *fp, const string* val) { + char line[1024]; + read_line(fp, line, sizeof(line)); + new(const_cast(val)) string(line); // need to use placement new +} + +void read_item(FILE *fp, pair *val) { + char line[1024]; + read_line(fp, line, sizeof(line)); + new(const_cast(&val->first)) string(line); +} + +void free_item(char*const* val) { + free(*val); +} + +void free_item(pair *val) { + free(val->first); +} + +int get_int_item(int int_item) { + return int_item; +} + +int get_int_item(pair val) { + return val.first; +} + +int getintkey(int i) { return i; } + +int getintkey(const pair &p) { return p.first; } + +} // end anonymous namespace + +// Performs tests where the hashtable's value type is assumed to be int. +template +void test_int() { + htint x; + htint y(1000); + htint z(64); + set_empty_key(&x, 0xefefef); + set_empty_key(&y, 0xefefef); + set_empty_key(&z, 0xefefef); + + CHECK(y.empty()); + insert(&y, 1); + CHECK(!y.empty()); + insert(&y, 11); + insert(&y, 111); + insert(&y, 1111); + insert(&y, 11111); + insert(&y, 111111); + insert(&y, 1111111); // 1M, more or less + insert(&y, 11111111); + insert(&y, 111111111); + insert(&y, 1111111111); // 1B, more or less + for ( int i = 0; i < 64; ++i ) + insert(&z, i); + // test the second half of the insert with an insert_iterator + insert_iterator insert_iter(z, z.begin()); + for ( int i = 32; i < 64; ++i ) + iterator_insert(&z, i, &insert_iter); + + // only perform the following CHECKs for + // dense{hashtable, _hash_set, _hash_map} + if (clear_no_resize(&x)) { + // make sure x has to increase its number of buckets + typename htint::size_type empty_bucket_count = x.bucket_count(); + int last_element = 0; + while (x.bucket_count() == empty_bucket_count) { + insert(&x, last_element); + ++last_element; + } + // if clear_no_resize is supported (i.e. htint is a + // dense{hashtable,_hash_set,_hash_map}), it should leave the bucket_count + // as is. + typename htint::size_type last_bucket_count = x.bucket_count(); + clear_no_resize(&x); + CHECK(last_bucket_count == x.bucket_count()); + CHECK(x.empty()); + LOGF << "x has " << x.bucket_count() << " buckets\n"; + LOGF << "x size " << x.size() << "\n"; + // when inserting the same number of elements again, no resize should be + // necessary + for (int i = 0; i < last_element; ++i) { + insert(&x, i); + CHECK(x.bucket_count() == last_bucket_count); + } + } + + for ( typename htint::const_iterator it = y.begin(); it != y.end(); ++it ) + LOGF << "y: " << get_int_item(*it) << "\n"; + z.insert(y.begin(), y.end()); + swap(y,z); + for ( typename htint::iterator it = y.begin(); it != y.end(); ++it ) + LOGF << "y+z: " << get_int_item(*it) << "\n"; + LOGF << "z has " << z.bucket_count() << " buckets\n"; + LOGF << "y has " << y.bucket_count() << " buckets\n"; + LOGF << "z size: " << z.size() << "\n"; + + for (int i = 0; i < 64; ++i) + CHECK(y.find(i) != y.end()); + + CHECK(z.size() == 10); + z.set_deleted_key(1010101010); // an unused value + CHECK(z.deleted_key() == 1010101010); + z.erase(11111); + CHECK(z.size() == 9); + insert(&z, 11111); // should retake deleted value + CHECK(z.size() == 10); + // Do the delete/insert again. Last time we probably resized; this time no + z.erase(11111); + insert(&z, 11111); // should retake deleted value + CHECK(z.size() == 10); + + z.erase(-11111); // shouldn't do anything + CHECK(z.size() == 10); + z.erase(1); + CHECK(z.size() == 9); + + typename htint::iterator itdel = z.find(1111); + pair itdel2 + = z.equal_range(1111); + CHECK(itdel2.first != z.end()); + CHECK(&*itdel2.first == &*itdel); // while we're here, check equal_range() + CHECK(itdel2.second == ++itdel2.first); + pair itdel3 + = const_cast(&z)->equal_range(1111); + CHECK(itdel3.first != z.end()); + CHECK(&*itdel3.first == &*itdel); + CHECK(itdel3.second == ++itdel3.first); + + z.erase(itdel); + CHECK(z.size() == 8); + itdel2 = z.equal_range(1111); + CHECK(itdel2.first == z.end()); + CHECK(itdel2.second == itdel2.first); + itdel3 = const_cast(&z)->equal_range(1111); + CHECK(itdel3.first == z.end()); + CHECK(itdel3.second == itdel3.first); + + itdel = z.find(2222); // should be end() + z.erase(itdel); // shouldn't do anything + CHECK(z.size() == 8); + for ( typename htint::const_iterator it = z.begin(); it != z.end(); ++it ) + LOGF << "y: " << get_int_item(*it) << "\n"; + z.set_deleted_key(1010101011); // a different unused value + CHECK(z.deleted_key() == 1010101011); + for ( typename htint::const_iterator it = z.begin(); it != z.end(); ++it ) + LOGF << "y: " << get_int_item(*it) << "\n"; + LOGF << "That's " << z.size() << " elements\n"; + z.erase(z.begin(), z.end()); + CHECK(z.empty()); + + y.clear(); + CHECK(y.empty()); + LOGF << "y has " << y.bucket_count() << " buckets\n"; +} + +// Performs tests where the hashtable's value type is assumed to be char*. +// The read_write parameters specifies whether the read/write tests +// should be performed. Note that densehashtable::write_metdata is not +// implemented, so we only do the read/write tests for the +// sparsehashtable varieties. +template +void test_charptr(bool read_write) { + ht w; + set_empty_key(&w, (char*) NULL); + insert(&w, const_cast(nwords), + const_cast(nwords) + sizeof(nwords) / sizeof(*nwords)); + LOGF << "w has " << w.size() << " items\n"; + CHECK(w.size() == 2); + CHECK(w == w); + + ht x; + set_empty_key(&x, (char*) NULL); + long dict_size = 1; // for size stats -- can't be 0 'cause of division + + map counts; + // Hash the dictionary + { + // automake says 'look for all data files in $srcdir.' OK. + string filestr = (string(getenv("srcdir") ? getenv("srcdir") : ".") + + "/src/words"); + const char* file = filestr.c_str(); + FILE *fp = fopen(file, "rb"); + if ( fp == NULL ) { + LOGF << "Can't open " << file << ", using small, built-in dict...\n"; + for (int i = 0; i < sizeof(default_dict)/sizeof(*default_dict); ++i) { + insert(&x, strdup(default_dict[i])); + counts[default_dict[i]] = 0; + } + } else { + char line[1024]; + while ( read_line(fp, line, sizeof(line)) ) { + insert(&x, strdup(line)); + counts[line] = 0; + } + LOGF << "Read " << x.size() << " words from " << file << "\n"; + fclose(fp); + struct stat buf; + stat(file, &buf); + dict_size = buf.st_size; + LOGF << "Size of " << file << ": " << buf.st_size << " bytes\n"; + } + for (char **word = const_cast(words); + word < const_cast(words) + sizeof(words) / sizeof(*words); + ++word ) { + if (x.find(*word) == x.end()) { + CHECK(w.find(*word) != w.end()); + } else { + CHECK(w.find(*word) == w.end()); + } + } + } + CHECK(counts.size() == x.size()); + + // Save the hashtable. + if (read_write) { + const string file_string = TmpFile(".hashtable_unittest_dicthash"); + const char* file = file_string.c_str(); + FILE *fp = fopen(file, "wb"); + if ( fp == NULL ) { + // maybe we can't write to /tmp/. Try the current directory + file = ".hashtable_unittest_dicthash"; + fp = fopen(file, "wb"); + } + if ( fp == NULL ) { + LOGF << "Can't open " << file << " skipping hashtable save...\n"; + } else { + x.write_metadata(fp); // this only writes meta-information + int write_count = 0; + for ( typename ht::iterator it = x.begin(); it != x.end(); ++it ) { + write_item(fp, *it); + free_item(&(*it)); + ++write_count; + } + LOGF << "Wrote " << write_count << " words to " << file << "\n"; + fclose(fp); + struct stat buf; + stat(file, &buf); + LOGF << "Size of " << file << ": " << buf.st_size << " bytes\n"; + LOGF << STL_NAMESPACE::setprecision(3) + << "Hashtable overhead " + << (buf.st_size - dict_size) * 100.0 / dict_size + << "% (" + << (buf.st_size - dict_size) * 8.0 / write_count + << " bits/entry)\n"; + x.clear(); + + // Load the hashtable + fp = fopen(file, "rb"); + if ( fp == NULL ) { + LOGF << "Can't open " << file << " skipping hashtable reload...\n"; + } else { + x.read_metadata(fp); // reads metainformation + LOGF << "Hashtable size: " << x.size() << "\n"; + int read_count = 0; + for ( typename ht::iterator it = x.begin(); it != x.end(); ++it ) { + read_item(fp, &(*it)); + ++read_count; + } + LOGF << "Read " << read_count << " words from " << file << "\n"; + fclose(fp); + unlink(file); + for ( char **word = const_cast(words); + word < const_cast(words) + sizeof(words) / sizeof(*words); + ++word ) { + if (x.find(*word) == x.end()) { + CHECK(w.find(*word) != w.end()); + } else { + CHECK(w.find(*word) == w.end()); + } + } + } + } + } + for ( typename ht::iterator it = x.begin(); it != x.end(); ++it ) { + free_item(&(*it)); + } +} + +// Perform tests where the hashtable's value type is assumed to +// be string. +// TODO(austern): factor out the bulk of test_charptr and test_string +// into a common function. +template +void test_string(bool read_write) { + ht w; + set_empty_key(&w, string("-*- empty key -*-")); + const int N = sizeof(nwords) / sizeof(*nwords); + string* nwords1 = new string[N]; + for (int i = 0; i < N; ++i) + nwords1[i] = nwords[i]; + insert(&w, nwords1, nwords1 + N); + delete[] nwords1; + LOGF << "w has " << w.size() << " items\n"; + CHECK(w.size() == 2); + CHECK(w == w); + + ht x; + set_empty_key(&x, string("-*- empty key -*-")); + long dict_size = 1; // for size stats -- can't be 0 'cause of division + + map counts; + // Hash the dictionary + { + // automake says 'look for all data files in $srcdir.' OK. + string filestr = (string(getenv("srcdir") ? getenv("srcdir") : ".") + + "/src/words"); + const char* file = filestr.c_str(); + FILE *fp = fopen(file, "rb"); + if ( fp == NULL ) { + LOGF << "Can't open " << file << ", using small, built-in dict...\n"; + for (int i = 0; i < sizeof(default_dict)/sizeof(*default_dict); ++i) { + insert(&x, string(default_dict[i])); + counts[default_dict[i]] = 0; + } + } else { + char line[1024]; + while ( fgets(line, sizeof(line), fp) ) { + insert(&x, string(line)); + counts[line] = 0; + } + LOGF << "Read " << x.size() << " words from " << file << "\n"; + fclose(fp); + struct stat buf; + stat(file, &buf); + dict_size = buf.st_size; + LOGF << "Size of " << file << ": " << buf.st_size << " bytes\n"; + } + for ( const char* const* word = words; + word < words + sizeof(words) / sizeof(*words); + ++word ) { + if (x.find(*word) == x.end()) { + CHECK(w.find(*word) != w.end()); + } else { + CHECK(w.find(*word) == w.end()); + } + } + } + CHECK(counts.size() == x.size()); + { + // verify that size() works correctly + int xcount = 0; + for ( typename ht::iterator it = x.begin(); it != x.end(); ++it ) { + ++xcount; + } + CHECK(x.size() == xcount); + } + + // Save the hashtable. + if (read_write) { + const string file_string = TmpFile(".hashtable_unittest_dicthash_str"); + const char* file = file_string.c_str(); + FILE *fp = fopen(file, "wb"); + if ( fp == NULL ) { + // maybe we can't write to /tmp/. Try the current directory + file = ".hashtable_unittest_dicthash_str"; + fp = fopen(file, "wb"); + } + if ( fp == NULL ) { + LOGF << "Can't open " << file << " skipping hashtable save...\n"; + } else { + x.write_metadata(fp); // this only writes meta-information + int write_count = 0; + for ( typename ht::iterator it = x.begin(); it != x.end(); ++it ) { + write_item(fp, *it); + ++write_count; + } + LOGF << "Wrote " << write_count << " words to " << file << "\n"; + fclose(fp); + struct stat buf; + stat(file, &buf); + LOGF << "Size of " << file << ": " << buf.st_size << " bytes\n"; + LOGF << STL_NAMESPACE::setprecision(3) + << "Hashtable overhead " + << (buf.st_size - dict_size) * 100.0 / dict_size + << "% (" + << (buf.st_size - dict_size) * 8.0 / write_count + << " bits/entry)\n"; + x.clear(); + + // Load the hashtable + fp = fopen(file, "rb"); + if ( fp == NULL ) { + LOGF << "Can't open " << file << " skipping hashtable reload...\n"; + } else { + x.read_metadata(fp); // reads metainformation + LOGF << "Hashtable size: " << x.size() << "\n"; + int count = 0; + for ( typename ht::iterator it = x.begin(); it != x.end(); ++it ) { + read_item(fp, &(*it)); + ++count; + } + LOGF << "Read " << count << " words from " << file << "\n"; + fclose(fp); + unlink(file); + for ( const char* const* word = words; + word < words + sizeof(words) / sizeof(*words); + ++word ) { + if (x.find(*word) == x.end()) { + CHECK(w.find(*word) != w.end()); + } else { + CHECK(w.find(*word) == w.end()); + } + } + } + } + } + + // ensure that destruction is done properly in clear_no_resize() + if (!clear_no_resize(&w)) w.clear(); +} + +// The read_write parameters specifies whether the read/write tests +// should be performed. Note that densehashtable::write_metdata is not +// implemented, so we only do the read/write tests for the +// sparsehashtable varieties. +template +void test(bool read_write) { + test_int(); + test_string(read_write); + test_charptr(read_write); +} + +// For data types with trivial copy-constructors and destructors, we +// should use an optimized routine for data-copying, that involves +// memmove. We test this by keeping count of how many times the +// copy-constructor is called; it should be much less with the +// optimized code. + +class Memmove { + public: + Memmove(): i_(0) {} + explicit Memmove(int i): i_(i) {} + Memmove(const Memmove& that) { + this->i_ = that.i_; + num_copies_++; + } + + int i_; + static int num_copies_; +}; +int Memmove::num_copies_ = 0; + + +// This is what tells the hashtable code it can use memmove for this class: +_START_GOOGLE_NAMESPACE_ +template<> struct has_trivial_copy : true_type { }; +template<> struct has_trivial_destructor : true_type { }; +_END_GOOGLE_NAMESPACE_ + +class NoMemmove { + public: + NoMemmove(): i_(0) {} + explicit NoMemmove(int i): i_(i) {} + NoMemmove(const NoMemmove& that) { + this->i_ = that.i_; + num_copies_++; + } + + int i_; + static int num_copies_; +}; +int NoMemmove::num_copies_ = 0; + +void TestSimpleDataTypeOptimizations() { + { + sparse_hash_map memmove; + sparse_hash_map nomemmove; + + Memmove::num_copies_ = 0; // reset + NoMemmove::num_copies_ = 0; // reset + for (int i = 10000; i > 0; i--) { + memmove[i] = Memmove(i); + } + for (int i = 10000; i > 0; i--) { + nomemmove[i] = NoMemmove(i); + } + LOGF << "sparse_hash_map copies for unoptimized/optimized cases: " + << NoMemmove::num_copies_ << "/" << Memmove::num_copies_ << "\n"; + CHECK(NoMemmove::num_copies_ > Memmove::num_copies_); + } + // Same should hold true for dense_hash_map + { + dense_hash_map memmove; + dense_hash_map nomemmove; + memmove.set_empty_key(0); + nomemmove.set_empty_key(0); + + Memmove::num_copies_ = 0; // reset + NoMemmove::num_copies_ = 0; // reset + for (int i = 10000; i > 0; i--) { + memmove[i] = Memmove(i); + } + for (int i = 10000; i > 0; i--) { + nomemmove[i] = NoMemmove(i); + } + LOGF << "dense_hash_map copies for unoptimized/optimized cases: " + << NoMemmove::num_copies_ << "/" << Memmove::num_copies_ << "\n"; + CHECK(NoMemmove::num_copies_ > Memmove::num_copies_); + } +} + +void TestShrinking() { + // We want to make sure that when we create a hashtable, and then + // add and delete one element, the size of the hashtable doesn't + // change. + { + sparse_hash_set s; + s.set_deleted_key(0); + const int old_bucket_count = s.bucket_count(); + s.insert(4); + s.erase(4); + s.insert(4); + s.erase(4); + CHECK_EQ(old_bucket_count, s.bucket_count()); + } + { + dense_hash_set s; + s.set_deleted_key(0); + s.set_empty_key(1); + const int old_bucket_count = s.bucket_count(); + s.insert(4); + s.erase(4); + s.insert(4); + s.erase(4); + CHECK_EQ(old_bucket_count, s.bucket_count()); + } + { + sparse_hash_set s(2); // start small: only expects 2 items + CHECK_LT(s.bucket_count(), 32); // verify we actually do start small + s.set_deleted_key(0); + const int old_bucket_count = s.bucket_count(); + s.insert(4); + s.erase(4); + s.insert(4); + s.erase(4); + CHECK_EQ(old_bucket_count, s.bucket_count()); + } + { + dense_hash_set s(2); // start small: only expects 2 items + CHECK_LT(s.bucket_count(), 32); // verify we actually do start small + s.set_deleted_key(0); + s.set_empty_key(1); + const int old_bucket_count = s.bucket_count(); + s.insert(4); + s.erase(4); + s.insert(4); + s.erase(4); + CHECK_EQ(old_bucket_count, s.bucket_count()); + } +} + +class TestHashFcn : public SPARSEHASH_HASH { + public: + explicit TestHashFcn(int i) + : id_(i) { + } + + int id() const { + return id_; + } + + private: + int id_; +}; + +class TestEqualTo : public equal_to { + public: + explicit TestEqualTo(int i) + : id_(i) { + } + + int id() const { + return id_; + } + + private: + int id_; +}; + +template