first commit
This commit is contained in:
commit
5f976e4642
|
@ -0,0 +1,8 @@
|
||||||
|
build
|
||||||
|
*.pbxuser
|
||||||
|
*.mode1v3
|
||||||
|
*.tm_build_errors
|
||||||
|
*.dmg
|
||||||
|
.DS_Store
|
||||||
|
project.xcworkspace
|
||||||
|
xcuserdata
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>English</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>CocoaDialog</string>
|
||||||
|
<key>CFBundleIconFile</key>
|
||||||
|
<string>cocoadialog</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>org.sporkstorms.CocoaDialog</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>2.1.1</string>
|
||||||
|
<key>LSUIElement</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>NSMainNibFile</key>
|
||||||
|
<string>MainMenu</string>
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string>NSApplication</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
APPL????
|
|
@ -0,0 +1,281 @@
|
||||||
|
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
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
2.1.0 April 26, 2006
|
||||||
|
- Implemented --packages-as-directories in fileselect.
|
||||||
|
|
||||||
|
2.1.0 Feb 26, 2006
|
||||||
|
- Compiled as a Universal Binary
|
||||||
|
- Intelligent resizing to accommodate --informative-text in
|
||||||
|
all inputbox dialogs, all msgbox dialogs, and textbox.
|
||||||
|
Same for --text in all dropdown dialogs.
|
||||||
|
- New "filesave" dialogs
|
||||||
|
- Added --packages-as-directories option to fileselect.
|
||||||
|
- Added --x-placement and --y-placement to bubble.
|
||||||
|
|
||||||
|
2.0.0 Jan 2, 2006
|
||||||
|
- Added bubble dialog.
|
||||||
|
- Added secure modes for inputbox and standard-inputbox.
|
||||||
|
- The application now runs as a background app. This means no more annoying
|
||||||
|
menu or dock icon!
|
||||||
|
- Some dialogs can be floated above all other applications.
|
||||||
|
- Timeouts on several dialogs.
|
||||||
|
- Intelligent button resizing
|
||||||
|
- Added custom icon support to msgbox, ok-msgbox, and standard-msgbox.
|
||||||
|
- Added --help options (still needs improvement).
|
||||||
|
- Added --select-only-directories to fileselect.
|
||||||
|
- Restructured project directory, code hierarchy, and refactored much of the code.
|
||||||
|
- Cleaned up the look of several dialogs.
|
||||||
|
- Progressbar won't be displayed right away, to prevent showing for
|
||||||
|
very short operations.
|
||||||
|
- Bug fixes (string-input on inputboxes, missing deallocs).
|
||||||
|
- New application icon.
|
||||||
|
|
||||||
|
1.2.2
|
||||||
|
- (Didn't release)
|
||||||
|
- Allan's patch
|
||||||
|
|
||||||
|
1.2.1 Jan, 2005
|
||||||
|
- (Did I even release this?).
|
||||||
|
- Wout's patch:
|
||||||
|
added --no-show, --float, --timeout and --help options
|
||||||
|
turned into a background app so that the dialog icon does not show
|
||||||
|
up in the menu bar. This, together with float, is very useful for
|
||||||
|
loginhooks.
|
||||||
|
|
||||||
|
1.2.0 Dec 28, 2004
|
||||||
|
- added dropdown and standard-dropdown controls.
|
||||||
|
|
||||||
|
1.1.3 May 11, 2004
|
||||||
|
- fixed handling of multi-line input to progressbar.
|
||||||
|
|
||||||
|
1.1.2 May 10, 2004
|
||||||
|
- fixed crash that would occur when printing return values containing
|
||||||
|
non-Roman characters. Thanks to Nobumi Iyanaga for finding this.
|
||||||
|
- added "debug" class method to CDControl and got rid of those
|
||||||
|
printf()s.
|
||||||
|
|
||||||
|
1.1.1 April 26, 2004
|
||||||
|
- starting to use x.y.z versioning (instead of x.y)
|
||||||
|
- progressbar incorrectly printed error with --debug
|
||||||
|
(runControlFromOptions: always returned nil, which should only happen
|
||||||
|
on error). This has been fixed.
|
||||||
|
- progressbar character encoding bug fixed. should now properly handle
|
||||||
|
UTF8 labels read from stdin. see bug 942012 on sf.net page. thanks to
|
||||||
|
J-F Boquillard for finding and fixing this.
|
||||||
|
|
||||||
|
1.1
|
||||||
|
- added inputbox, standard-inputbox
|
||||||
|
- textbox window no longer closes on escape unless there's a "Cancel"
|
||||||
|
button
|
||||||
|
- fixed error handling for textbox when --text-from-file file is
|
||||||
|
invalid.
|
||||||
|
|
||||||
|
1.0
|
||||||
|
- initial release
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>English</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>CocoaDialog</string>
|
||||||
|
<key>CFBundleIconFile</key>
|
||||||
|
<string>cocoadialog</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>org.sporkstorms.CocoaDialog</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>2.1.1</string>
|
||||||
|
<key>LSUIElement</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>NSMainNibFile</key>
|
||||||
|
<string>MainMenu</string>
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string>NSApplication</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
Binary file not shown.
|
@ -0,0 +1,51 @@
|
||||||
|
{
|
||||||
|
IBClasses = (
|
||||||
|
{CLASS = CDControl; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||||
|
{
|
||||||
|
CLASS = CDInputboxControl;
|
||||||
|
LANGUAGE = ObjC;
|
||||||
|
OUTLETS = {textField = NSTextField; };
|
||||||
|
SUPERCLASS = CDThreeButtonControl;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CLASS = CDMsgboxControl;
|
||||||
|
LANGUAGE = ObjC;
|
||||||
|
OUTLETS = {imageView = NSImageView; text = NSTextField; };
|
||||||
|
SUPERCLASS = CDThreeButtonControl;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ACTIONS = {selectionChanged = id; };
|
||||||
|
CLASS = CDPopUpButtonControl;
|
||||||
|
LANGUAGE = ObjC;
|
||||||
|
OUTLETS = {popup = NSPopUpButton; };
|
||||||
|
SUPERCLASS = CDThreeButtonControl;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CLASS = CDProgressbarControl;
|
||||||
|
LANGUAGE = ObjC;
|
||||||
|
OUTLETS = {label = NSTextField; panel = NSPanel; progressBar = NSProgressIndicator; };
|
||||||
|
SUPERCLASS = CDControl;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CLASS = CDTextboxControl;
|
||||||
|
LANGUAGE = ObjC;
|
||||||
|
OUTLETS = {textView = NSTextView; };
|
||||||
|
SUPERCLASS = CDThreeButtonControl;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ACTIONS = {button1Pressed = id; button2Pressed = id; button3Pressed = id; timeout = id; };
|
||||||
|
CLASS = CDThreeButtonControl;
|
||||||
|
LANGUAGE = ObjC;
|
||||||
|
OUTLETS = {
|
||||||
|
button1 = NSButton;
|
||||||
|
button2 = NSButton;
|
||||||
|
button3 = NSButton;
|
||||||
|
expandingLabel = NSTextField;
|
||||||
|
panel = NSPanel;
|
||||||
|
};
|
||||||
|
SUPERCLASS = CDControl;
|
||||||
|
},
|
||||||
|
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }
|
||||||
|
);
|
||||||
|
IBVersion = 1;
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IBDocumentLocation</key>
|
||||||
|
<string>76 119 356 240 0 0 1440 878 </string>
|
||||||
|
<key>IBFramework Version</key>
|
||||||
|
<string>443.0</string>
|
||||||
|
<key>IBOpenObjects</key>
|
||||||
|
<array>
|
||||||
|
<integer>5</integer>
|
||||||
|
</array>
|
||||||
|
<key>IBSystem Version</key>
|
||||||
|
<string>8H14</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
BIN
Installer/CocoaDialog.app/Contents/Resources/Inputbox.nib/keyedobjects.nib
generated
Normal file
BIN
Installer/CocoaDialog.app/Contents/Resources/Inputbox.nib/keyedobjects.nib
generated
Normal file
Binary file not shown.
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
IBClasses = (
|
||||||
|
{CLASS = AppController; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||||
|
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }
|
||||||
|
);
|
||||||
|
IBVersion = 1;
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IBDocumentLocation</key>
|
||||||
|
<string>373 505 356 240 0 0 1680 1028 </string>
|
||||||
|
<key>IBEditorPositions</key>
|
||||||
|
<dict>
|
||||||
|
<key>29</key>
|
||||||
|
<string>131 353 216 44 0 0 1680 1028 </string>
|
||||||
|
</dict>
|
||||||
|
<key>IBFramework Version</key>
|
||||||
|
<string>364.0</string>
|
||||||
|
<key>IBOpenObjects</key>
|
||||||
|
<array>
|
||||||
|
<integer>29</integer>
|
||||||
|
</array>
|
||||||
|
<key>IBSystem Version</key>
|
||||||
|
<string>7R28</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IBDocumentLocation</key>
|
||||||
|
<string>188 324 356 240 0 0 1024 746 </string>
|
||||||
|
<key>IBEditorPositions</key>
|
||||||
|
<dict>
|
||||||
|
<key>29</key>
|
||||||
|
<string>69 252 299 44 0 0 1024 746 </string>
|
||||||
|
</dict>
|
||||||
|
<key>IBFramework Version</key>
|
||||||
|
<string>349.0</string>
|
||||||
|
<key>IBOpenObjects</key>
|
||||||
|
<array>
|
||||||
|
<integer>29</integer>
|
||||||
|
</array>
|
||||||
|
<key>IBSystem Version</key>
|
||||||
|
<string>7F44</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
IBClasses = (
|
||||||
|
{CLASS = CDControl; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||||
|
{
|
||||||
|
CLASS = CDMsgboxControl;
|
||||||
|
LANGUAGE = ObjC;
|
||||||
|
OUTLETS = {imageView = NSImageView; text = NSTextField; };
|
||||||
|
SUPERCLASS = CDThreeButtonControl;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ACTIONS = {button1Pressed = id; button2Pressed = id; button3Pressed = id; timeout = id; };
|
||||||
|
CLASS = CDThreeButtonControl;
|
||||||
|
LANGUAGE = ObjC;
|
||||||
|
OUTLETS = {
|
||||||
|
button1 = NSButton;
|
||||||
|
button2 = NSButton;
|
||||||
|
button3 = NSButton;
|
||||||
|
expandingLabel = NSTextField;
|
||||||
|
panel = NSPanel;
|
||||||
|
};
|
||||||
|
SUPERCLASS = CDControl;
|
||||||
|
},
|
||||||
|
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||||
|
{CLASS = "java.lang.Object"; LANGUAGE = Java; }
|
||||||
|
);
|
||||||
|
IBVersion = 1;
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IBDocumentLocation</key>
|
||||||
|
<string>57 203 356 240 0 0 1440 878 </string>
|
||||||
|
<key>IBFramework Version</key>
|
||||||
|
<string>443.0</string>
|
||||||
|
<key>IBOpenObjects</key>
|
||||||
|
<array>
|
||||||
|
<integer>10</integer>
|
||||||
|
</array>
|
||||||
|
<key>IBSystem Version</key>
|
||||||
|
<string>8H14</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
Binary file not shown.
|
@ -0,0 +1,55 @@
|
||||||
|
{
|
||||||
|
IBClasses = (
|
||||||
|
{CLASS = CDControl; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||||
|
{
|
||||||
|
ACTIONS = {button1Pressed = id; button2Pressed = id; button3Pressed = id; };
|
||||||
|
CLASS = CDInputboxControl;
|
||||||
|
LANGUAGE = ObjC;
|
||||||
|
OUTLETS = {
|
||||||
|
button1 = NSButton;
|
||||||
|
button2 = NSButton;
|
||||||
|
button3 = NSButton;
|
||||||
|
label = NSTextField;
|
||||||
|
panel = NSPanel;
|
||||||
|
textField = NSTextField;
|
||||||
|
};
|
||||||
|
SUPERCLASS = CDControl;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ACTIONS = {selectionChanged = id; };
|
||||||
|
CLASS = CDPopUpButtonControl;
|
||||||
|
LANGUAGE = ObjC;
|
||||||
|
OUTLETS = {popup = NSPopUpButton; };
|
||||||
|
SUPERCLASS = CDThreeButtonControl;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ACTIONS = {button1Pressed = id; button2Pressed = id; button3Pressed = id; };
|
||||||
|
CLASS = CDTextboxControl;
|
||||||
|
LANGUAGE = ObjC;
|
||||||
|
OUTLETS = {
|
||||||
|
button1 = NSButton;
|
||||||
|
button2 = NSButton;
|
||||||
|
button3 = NSButton;
|
||||||
|
label = NSTextField;
|
||||||
|
panel = NSPanel;
|
||||||
|
textView = NSTextView;
|
||||||
|
};
|
||||||
|
SUPERCLASS = CDControl;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ACTIONS = {button1Pressed = id; button2Pressed = id; button3Pressed = id; timeout = id; };
|
||||||
|
CLASS = CDThreeButtonControl;
|
||||||
|
LANGUAGE = ObjC;
|
||||||
|
OUTLETS = {
|
||||||
|
button1 = NSButton;
|
||||||
|
button2 = NSButton;
|
||||||
|
button3 = NSButton;
|
||||||
|
expandingLabel = NSTextField;
|
||||||
|
panel = NSPanel;
|
||||||
|
};
|
||||||
|
SUPERCLASS = CDControl;
|
||||||
|
},
|
||||||
|
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }
|
||||||
|
);
|
||||||
|
IBVersion = 1;
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IBDocumentLocation</key>
|
||||||
|
<string>120 158 356 240 0 0 1440 878 </string>
|
||||||
|
<key>IBFramework Version</key>
|
||||||
|
<string>443.0</string>
|
||||||
|
<key>IBOpenObjects</key>
|
||||||
|
<array>
|
||||||
|
<integer>5</integer>
|
||||||
|
</array>
|
||||||
|
<key>IBSystem Version</key>
|
||||||
|
<string>8H14</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
BIN
Installer/CocoaDialog.app/Contents/Resources/PopUpButton.nib/keyedobjects.nib
generated
Normal file
BIN
Installer/CocoaDialog.app/Contents/Resources/PopUpButton.nib/keyedobjects.nib
generated
Normal file
Binary file not shown.
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
IBClasses = (
|
||||||
|
{CLASS = CDControl; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||||
|
{
|
||||||
|
CLASS = CDProgressbarControl;
|
||||||
|
LANGUAGE = ObjC;
|
||||||
|
OUTLETS = {label = NSTextField; panel = NSPanel; progressBar = NSProgressIndicator; };
|
||||||
|
SUPERCLASS = CDControl;
|
||||||
|
},
|
||||||
|
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }
|
||||||
|
);
|
||||||
|
IBVersion = 1;
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IBDocumentLocation</key>
|
||||||
|
<string>128 15 356 240 0 0 1600 1002 </string>
|
||||||
|
<key>IBFramework Version</key>
|
||||||
|
<string>443.0</string>
|
||||||
|
<key>IBOpenObjects</key>
|
||||||
|
<array>
|
||||||
|
<integer>5</integer>
|
||||||
|
</array>
|
||||||
|
<key>IBSystem Version</key>
|
||||||
|
<string>8F46</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
BIN
Installer/CocoaDialog.app/Contents/Resources/Progressbar.nib/keyedobjects.nib
generated
Normal file
BIN
Installer/CocoaDialog.app/Contents/Resources/Progressbar.nib/keyedobjects.nib
generated
Normal file
Binary file not shown.
40
Installer/CocoaDialog.app/Contents/Resources/SecureInputbox.nib/classes.nib
generated
Normal file
40
Installer/CocoaDialog.app/Contents/Resources/SecureInputbox.nib/classes.nib
generated
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
{
|
||||||
|
IBClasses = (
|
||||||
|
{CLASS = CDControl; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||||
|
{
|
||||||
|
CLASS = CDInputboxControl;
|
||||||
|
LANGUAGE = ObjC;
|
||||||
|
OUTLETS = {textField = NSTextField; };
|
||||||
|
SUPERCLASS = CDThreeButtonControl;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ACTIONS = {button1Pressed = id; button2Pressed = id; button3Pressed = id; };
|
||||||
|
CLASS = CDTextboxControl;
|
||||||
|
LANGUAGE = ObjC;
|
||||||
|
OUTLETS = {
|
||||||
|
button1 = NSButton;
|
||||||
|
button2 = NSButton;
|
||||||
|
button3 = NSButton;
|
||||||
|
label = NSTextField;
|
||||||
|
panel = NSPanel;
|
||||||
|
textView = NSTextView;
|
||||||
|
};
|
||||||
|
SUPERCLASS = CDControl;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ACTIONS = {button1Pressed = id; button2Pressed = id; button3Pressed = id; timeout = id; };
|
||||||
|
CLASS = CDThreeButtonControl;
|
||||||
|
LANGUAGE = ObjC;
|
||||||
|
OUTLETS = {
|
||||||
|
button1 = NSButton;
|
||||||
|
button2 = NSButton;
|
||||||
|
button3 = NSButton;
|
||||||
|
expandingLabel = NSTextField;
|
||||||
|
panel = NSPanel;
|
||||||
|
};
|
||||||
|
SUPERCLASS = CDControl;
|
||||||
|
},
|
||||||
|
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }
|
||||||
|
);
|
||||||
|
IBVersion = 1;
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IBDocumentLocation</key>
|
||||||
|
<string>82 210 356 240 0 0 1440 878 </string>
|
||||||
|
<key>IBFramework Version</key>
|
||||||
|
<string>443.0</string>
|
||||||
|
<key>IBOpenObjects</key>
|
||||||
|
<array>
|
||||||
|
<integer>5</integer>
|
||||||
|
</array>
|
||||||
|
<key>IBSystem Version</key>
|
||||||
|
<string>8H14</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
BIN
Installer/CocoaDialog.app/Contents/Resources/SecureInputbox.nib/keyedobjects.nib
generated
Normal file
BIN
Installer/CocoaDialog.app/Contents/Resources/SecureInputbox.nib/keyedobjects.nib
generated
Normal file
Binary file not shown.
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
IBClasses = (
|
||||||
|
{CLASS = CDControl; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||||
|
{
|
||||||
|
CLASS = CDTextboxControl;
|
||||||
|
LANGUAGE = ObjC;
|
||||||
|
OUTLETS = {textView = NSTextView; };
|
||||||
|
SUPERCLASS = CDThreeButtonControl;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ACTIONS = {button1Pressed = id; button2Pressed = id; button3Pressed = id; timeout = id; };
|
||||||
|
CLASS = CDThreeButtonControl;
|
||||||
|
LANGUAGE = ObjC;
|
||||||
|
OUTLETS = {
|
||||||
|
button1 = NSButton;
|
||||||
|
button2 = NSButton;
|
||||||
|
button3 = NSButton;
|
||||||
|
expandingLabel = NSTextField;
|
||||||
|
panel = NSPanel;
|
||||||
|
};
|
||||||
|
SUPERCLASS = CDControl;
|
||||||
|
},
|
||||||
|
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }
|
||||||
|
);
|
||||||
|
IBVersion = 1;
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IBDocumentLocation</key>
|
||||||
|
<string>117 70 356 240 0 0 1440 878 </string>
|
||||||
|
<key>IBFramework Version</key>
|
||||||
|
<string>443.0</string>
|
||||||
|
<key>IBOpenObjects</key>
|
||||||
|
<array>
|
||||||
|
<integer>5</integer>
|
||||||
|
</array>
|
||||||
|
<key>IBSystem Version</key>
|
||||||
|
<string>8H14</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,39 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# The following files are bundled:
|
||||||
|
#
|
||||||
|
# 'Lettuce.app'
|
||||||
|
# 'CocoaDialog.app'
|
||||||
|
# 'pic_normal.png'
|
||||||
|
#
|
||||||
|
|
||||||
|
myLicense="Copyright (c) 2011, the Openvanilla Project
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
|
||||||
|
|
||||||
|
CD="CocoaDialog.app/Contents/MacOS/CocoaDialog"
|
||||||
|
rv=$($CD yesno-msgbox --title "License Agreement" --text "Agree this before you install. :-)" --informative-text "$myLicense" --string-output --no-cancel)
|
||||||
|
|
||||||
|
if [ $rv == "No" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $(/bin/ps xww|/usr/bin/awk '/Lettuce/{bm=1}END{print bm}')"blah" != "blah1" ]; then
|
||||||
|
killall -9 Lettuce
|
||||||
|
echo PROGRESS:25
|
||||||
|
fi
|
||||||
|
if [ ! -e $HOME/Library/Input\ Methods ]; then
|
||||||
|
mkdir -p $HOME/Library/Input\ Methods
|
||||||
|
echo PROGRESS:50
|
||||||
|
else
|
||||||
|
echo PROGRESS:50
|
||||||
|
fi
|
||||||
|
cp -R Lettuce.app $HOME/Library/Input\ Methods/
|
||||||
|
echo PROGRESS:75
|
||||||
|
$HOME/Library/Input\ Methods/Lettuce.app/Contents/MacOS/Lettuce install
|
||||||
|
echo PROGRESS:100
|
||||||
|
$CD bubble --debug --title "Thank you!" --text "McBoPoMoPo has been installed." --icon-file pic_normal.png
|
Binary file not shown.
After Width: | Height: | Size: 5.0 KiB |
|
@ -0,0 +1 @@
|
||||||
|
Lettuce Project
|
|
@ -0,0 +1,50 @@
|
||||||
|
//
|
||||||
|
// AppDelegate.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011 The McBopomofo Project.
|
||||||
|
//
|
||||||
|
// Contributors:
|
||||||
|
// Mengjuei Hsieh (@mjhsieh)
|
||||||
|
// Weizhong Yang (@zonble)
|
||||||
|
//
|
||||||
|
// Based on the Syrup Project and the Formosana Library
|
||||||
|
// by Lukhnos Liu (@lukhnos).
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
@class UpdateNotificationController;
|
||||||
|
|
||||||
|
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||||
|
{
|
||||||
|
@private
|
||||||
|
NSWindow *_window;
|
||||||
|
NSURLConnection *_updateCheckConnection;
|
||||||
|
UpdateNotificationController *_updateNotificationController;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)checkForUpdate;
|
||||||
|
|
||||||
|
@property (assign) IBOutlet NSWindow *window;
|
||||||
|
@end
|
|
@ -0,0 +1,171 @@
|
||||||
|
//
|
||||||
|
// AppDelegate.m
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011 The McBopomofo Project.
|
||||||
|
//
|
||||||
|
// Contributors:
|
||||||
|
// Mengjuei Hsieh (@mjhsieh)
|
||||||
|
// Weizhong Yang (@zonble)
|
||||||
|
//
|
||||||
|
// Based on the Syrup Project and the Formosana Library
|
||||||
|
// by Lukhnos Liu (@lukhnos).
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "AppDelegate.h"
|
||||||
|
#import "UpdateNotificationController.h"
|
||||||
|
|
||||||
|
void LTLoadLanugageModel();
|
||||||
|
|
||||||
|
static NSString *kNextUpdateCheckDateKey = @"NextUpdateCheckDate";
|
||||||
|
static NSString *kUpdateInfoEndpointKey = @"UpdateInfoEndpoint";
|
||||||
|
static NSString *kUpdateInfoSiteKey = @"UpdateInfoSite";
|
||||||
|
static const NSTimeInterval kTimeoutInterval = 10.0;
|
||||||
|
static const NSTimeInterval kNextCheckInterval = 86400.0;
|
||||||
|
|
||||||
|
@implementation AppDelegate
|
||||||
|
@synthesize window = _window;
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
[_updateCheckConnection release];
|
||||||
|
[_updateNotificationController release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationDidFinishLaunching:(NSNotification *)inNotification
|
||||||
|
{
|
||||||
|
LTLoadLanugageModel();
|
||||||
|
|
||||||
|
[self checkForUpdate];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)checkForUpdate
|
||||||
|
{
|
||||||
|
NSDate *date = [[NSUserDefaults standardUserDefaults] objectForKey:kNextUpdateCheckDateKey];
|
||||||
|
if (![date isKindOfClass:[NSDate class]]) {
|
||||||
|
date = [NSDate date];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([(NSDate *)[NSDate date] compare:date] == NSOrderedAscending) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSDate *nextUpdateDate = [NSDate dateWithTimeInterval:kNextCheckInterval sinceDate:[NSDate date]];
|
||||||
|
[[NSUserDefaults standardUserDefaults] setObject:nextUpdateDate forKey:kNextUpdateCheckDateKey];
|
||||||
|
|
||||||
|
if (_updateCheckConnection) {
|
||||||
|
[_updateCheckConnection release];
|
||||||
|
_updateCheckConnection = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary];
|
||||||
|
NSString *updateInfoURLString = [infoDict objectForKey:kUpdateInfoEndpointKey];
|
||||||
|
|
||||||
|
if (![updateInfoURLString length]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSURL *updateInfoURL = [NSURL URLWithString:updateInfoURLString];
|
||||||
|
if (!updateInfoURL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSURLRequest *request = [NSURLRequest requestWithURL:updateInfoURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:kTimeoutInterval];
|
||||||
|
|
||||||
|
if (!request) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if DEBUG
|
||||||
|
NSLog(@"about to request update url %@ ",updateInfoURL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_updateCheckConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
|
||||||
|
[_updateCheckConnection start];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
|
||||||
|
{
|
||||||
|
NSLog(@"error");
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
|
||||||
|
{
|
||||||
|
id plist = [NSPropertyListSerialization propertyListFromData:data mutabilityOption:NSPropertyListImmutable format:NULL errorDescription:NULL];
|
||||||
|
#if DEBUG
|
||||||
|
NSLog(@"plist %@",plist);
|
||||||
|
#endif
|
||||||
|
if (!plist) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *remoteVersion = [plist objectForKey:(id)kCFBundleVersionKey];
|
||||||
|
#if DEBUG
|
||||||
|
NSLog(@"the remoteversion is %@",remoteVersion);
|
||||||
|
#endif
|
||||||
|
if (!remoteVersion) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Validate info (e.g. bundle identifier)
|
||||||
|
// TODO: Use HTML to display change log, need a new key like UpdateInfoChangeLogURL for this
|
||||||
|
|
||||||
|
NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary];
|
||||||
|
NSString *currentVersion = [infoDict objectForKey:(id)kCFBundleVersionKey];
|
||||||
|
NSComparisonResult result = [currentVersion compare:remoteVersion options:NSNumericSearch];
|
||||||
|
|
||||||
|
if (result != NSOrderedAscending) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NSString *siteInfoURLString = [plist objectForKey:kUpdateInfoSiteKey];
|
||||||
|
if (!siteInfoURLString) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSURL *siteInfoURL = [NSURL URLWithString:siteInfoURLString];
|
||||||
|
if (!siteInfoURL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (_updateNotificationController) {
|
||||||
|
[_updateNotificationController release], _updateNotificationController = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
_updateNotificationController = [[UpdateNotificationController alloc] initWithWindowNibName:@"UpdateNotificationController"];
|
||||||
|
|
||||||
|
_updateNotificationController.siteURL = siteInfoURL;
|
||||||
|
_updateNotificationController.infoText = [NSString stringWithFormat:NSLocalizedString(@"You are running version %@ (%@), and the new version %@ (%@) is now available.\n\nVisit the website to download it?", @""),
|
||||||
|
[infoDict objectForKey:@"CFBundleShortVersionString"],
|
||||||
|
[infoDict objectForKey:(id)kCFBundleVersionKey],
|
||||||
|
[plist objectForKey:@"CFBundleShortVersionString"],
|
||||||
|
[plist objectForKey:(id)kCFBundleVersionKey],
|
||||||
|
nil];
|
||||||
|
|
||||||
|
[_updateNotificationController showWindow:self];
|
||||||
|
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -0,0 +1,104 @@
|
||||||
|
//
|
||||||
|
// Bigram.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef Bigram_h
|
||||||
|
#define Bigram_h
|
||||||
|
|
||||||
|
#include "KeyValuePair.h"
|
||||||
|
|
||||||
|
namespace Formosa {
|
||||||
|
namespace Gramambular {
|
||||||
|
class Bigram {
|
||||||
|
public:
|
||||||
|
Bigram();
|
||||||
|
|
||||||
|
KeyValuePair preceedingKeyValue;
|
||||||
|
KeyValuePair keyValue;
|
||||||
|
double score;
|
||||||
|
|
||||||
|
bool operator==(const Bigram& inAnother) const;
|
||||||
|
bool operator<(const Bigram& inAnother) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline ostream& operator<<(ostream& inStream, const Bigram& inGram)
|
||||||
|
{
|
||||||
|
streamsize p = inStream.precision();
|
||||||
|
inStream.precision(6);
|
||||||
|
inStream << "(" << inGram.keyValue << "|" <<inGram.preceedingKeyValue << "," << inGram.score << ")";
|
||||||
|
inStream.precision(p);
|
||||||
|
return inStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ostream& operator<<(ostream& inStream, const vector<Bigram>& inGrams)
|
||||||
|
{
|
||||||
|
inStream << "[" << inGrams.size() << "]=>{";
|
||||||
|
|
||||||
|
size_t index = 0;
|
||||||
|
|
||||||
|
for (vector<Bigram>::const_iterator gi = inGrams.begin() ; gi != inGrams.end() ; ++gi, ++index) {
|
||||||
|
inStream << index << "=>";
|
||||||
|
inStream << *gi;
|
||||||
|
if (gi + 1 != inGrams.end()) {
|
||||||
|
inStream << ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inStream << "}";
|
||||||
|
return inStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Bigram::Bigram()
|
||||||
|
: score(0.0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Bigram::operator==(const Bigram& inAnother) const
|
||||||
|
{
|
||||||
|
return preceedingKeyValue == inAnother.preceedingKeyValue && keyValue == inAnother.keyValue && score == inAnother.score;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Bigram::operator<(const Bigram& inAnother) const
|
||||||
|
{
|
||||||
|
if (preceedingKeyValue < inAnother.preceedingKeyValue) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (preceedingKeyValue == inAnother.preceedingKeyValue) {
|
||||||
|
if (keyValue < inAnother.keyValue) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (keyValue == inAnother.keyValue) {
|
||||||
|
return score < inAnother.score;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,216 @@
|
||||||
|
//
|
||||||
|
// BlockReadingBuilder.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef BlockReadingBuilder_h
|
||||||
|
#define BlockReadingBuilder_h
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "Grid.h"
|
||||||
|
#include "LanguageModel.h"
|
||||||
|
|
||||||
|
namespace Formosa {
|
||||||
|
namespace Gramambular {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class BlockReadingBuilder {
|
||||||
|
public:
|
||||||
|
BlockReadingBuilder(LanguageModel *inLM);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
size_t length() const;
|
||||||
|
size_t cursorIndex() const;
|
||||||
|
void setCursorIndex(size_t inNewIndex);
|
||||||
|
void insertReadingAtCursor(const string& inReading);
|
||||||
|
bool deleteReadingBeforeCursor(); // backspace
|
||||||
|
bool deleteReadingAfterCursor(); // delete
|
||||||
|
|
||||||
|
bool removeHeadReadings(size_t count);
|
||||||
|
|
||||||
|
void setJoinSeparator(const string& separator);
|
||||||
|
const string joinSeparator() const;
|
||||||
|
|
||||||
|
Grid& grid();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void build();
|
||||||
|
|
||||||
|
static const string Join(vector<string>::const_iterator begin, vector<string>::const_iterator end, const string& separator);
|
||||||
|
|
||||||
|
static const size_t MaximumBuildSpanLength = 4;
|
||||||
|
|
||||||
|
size_t m_cursorIndex;
|
||||||
|
vector<string> m_readings;
|
||||||
|
|
||||||
|
Grid m_grid;
|
||||||
|
LanguageModel *m_LM;
|
||||||
|
string m_joinSeparator;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline BlockReadingBuilder::BlockReadingBuilder(LanguageModel *inLM)
|
||||||
|
: m_LM(inLM)
|
||||||
|
, m_cursorIndex(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void BlockReadingBuilder::clear()
|
||||||
|
{
|
||||||
|
m_cursorIndex = 0;
|
||||||
|
m_readings.clear();
|
||||||
|
m_grid.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t BlockReadingBuilder::length() const
|
||||||
|
{
|
||||||
|
return m_readings.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t BlockReadingBuilder::cursorIndex() const
|
||||||
|
{
|
||||||
|
return m_cursorIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void BlockReadingBuilder::setCursorIndex(size_t inNewIndex)
|
||||||
|
{
|
||||||
|
m_cursorIndex = inNewIndex > m_readings.size() ? m_readings.size() : inNewIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void BlockReadingBuilder::insertReadingAtCursor(const string& inReading)
|
||||||
|
{
|
||||||
|
m_readings.insert(m_readings.begin() + m_cursorIndex, inReading);
|
||||||
|
|
||||||
|
m_grid.expandGridByOneAtLocation(m_cursorIndex);
|
||||||
|
build();
|
||||||
|
m_cursorIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool BlockReadingBuilder::deleteReadingBeforeCursor()
|
||||||
|
{
|
||||||
|
if (!m_cursorIndex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_readings.erase(m_readings.begin() + m_cursorIndex - 1, m_readings.begin() + m_cursorIndex);
|
||||||
|
m_cursorIndex--;
|
||||||
|
m_grid.shrinkGridByOneAtLocation(m_cursorIndex);
|
||||||
|
build();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool BlockReadingBuilder::deleteReadingAfterCursor()
|
||||||
|
{
|
||||||
|
if (m_cursorIndex == m_readings.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_readings.erase(m_readings.begin() + m_cursorIndex, m_readings.begin() + m_cursorIndex + 1);
|
||||||
|
m_grid.shrinkGridByOneAtLocation(m_cursorIndex);
|
||||||
|
build();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool BlockReadingBuilder::removeHeadReadings(size_t count)
|
||||||
|
{
|
||||||
|
if (count > length()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
|
if (m_cursorIndex) {
|
||||||
|
m_cursorIndex--;
|
||||||
|
}
|
||||||
|
m_readings.erase(m_readings.begin(), m_readings.begin() + 1);
|
||||||
|
m_grid.shrinkGridByOneAtLocation(0);
|
||||||
|
build();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void BlockReadingBuilder::setJoinSeparator(const string& separator)
|
||||||
|
{
|
||||||
|
m_joinSeparator = separator;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const string BlockReadingBuilder::joinSeparator() const
|
||||||
|
{
|
||||||
|
return m_joinSeparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Grid& BlockReadingBuilder::grid()
|
||||||
|
{
|
||||||
|
return m_grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void BlockReadingBuilder::build()
|
||||||
|
{
|
||||||
|
if (!m_LM) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t begin = 0;
|
||||||
|
size_t end = m_cursorIndex + MaximumBuildSpanLength;
|
||||||
|
|
||||||
|
if (m_cursorIndex < MaximumBuildSpanLength) {
|
||||||
|
begin = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
begin = m_cursorIndex - MaximumBuildSpanLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end > m_readings.size()) {
|
||||||
|
end = m_readings.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t p = begin ; p < end ; p++) {
|
||||||
|
for (size_t q = 1 ; q <= MaximumBuildSpanLength && p+q <= end ; q++) {
|
||||||
|
string combinedReading = Join(m_readings.begin() + p, m_readings.begin() + p + q, m_joinSeparator);
|
||||||
|
|
||||||
|
if (m_LM->hasUnigramsForKey(combinedReading) && !m_grid.hasNodeAtLocationSpanningLengthMatchingKey(p, q, combinedReading)) {
|
||||||
|
Node n(combinedReading, m_LM->unigramsForKeys(combinedReading), vector<Bigram>());
|
||||||
|
m_grid.insertNode(n, p, q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const string BlockReadingBuilder::Join(vector<string>::const_iterator begin, vector<string>::const_iterator end, const string& separator)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
for (vector<string>::const_iterator iter = begin ; iter != end ; ) {
|
||||||
|
result += *iter;
|
||||||
|
++iter;
|
||||||
|
if (iter != end) {
|
||||||
|
result += separator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,42 @@
|
||||||
|
//
|
||||||
|
// Gramambular.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef Gramambular_h
|
||||||
|
#define Gramambular_h
|
||||||
|
|
||||||
|
#include "Bigram.h"
|
||||||
|
#include "BlockReadingBuilder.h"
|
||||||
|
#include "Grid.h"
|
||||||
|
#include "KeyValuePair.h"
|
||||||
|
#include "LanguageModel.h"
|
||||||
|
#include "Node.h"
|
||||||
|
#include "NodeAnchor.h"
|
||||||
|
#include "Span.h"
|
||||||
|
#include "Unigram.h"
|
||||||
|
#include "Walker.h"
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,221 @@
|
||||||
|
//
|
||||||
|
// Grid.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef Grid_h
|
||||||
|
#define Grid_h
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include "NodeAnchor.h"
|
||||||
|
#include "Span.h"
|
||||||
|
|
||||||
|
namespace Formosa {
|
||||||
|
namespace Gramambular {
|
||||||
|
|
||||||
|
class Grid {
|
||||||
|
public:
|
||||||
|
void clear();
|
||||||
|
void insertNode(const Node& inNode, size_t inLocation, size_t inSpanningLength);
|
||||||
|
bool hasNodeAtLocationSpanningLengthMatchingKey(size_t inLocation, size_t inSpanningLength, const string& inKey);
|
||||||
|
|
||||||
|
void expandGridByOneAtLocation(size_t inLocation);
|
||||||
|
void shrinkGridByOneAtLocation(size_t inLocation);
|
||||||
|
|
||||||
|
size_t width() const;
|
||||||
|
vector<NodeAnchor> nodesEndingAt(size_t inLocation);
|
||||||
|
vector<NodeAnchor> nodesCrossingOrEndingAt(size_t inLocation);
|
||||||
|
|
||||||
|
const string dumpDOT();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
vector<Span> m_spans;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void Grid::clear()
|
||||||
|
{
|
||||||
|
m_spans.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Grid::insertNode(const Node& inNode, size_t inLocation, size_t inSpanningLength)
|
||||||
|
{
|
||||||
|
if (inLocation >= m_spans.size()) {
|
||||||
|
size_t diff = inLocation - m_spans.size() + 1;
|
||||||
|
|
||||||
|
for (size_t i = 0 ; i < diff ; i++) {
|
||||||
|
m_spans.push_back(Span());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_spans[inLocation].insertNodeOfLength(inNode, inSpanningLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Grid::hasNodeAtLocationSpanningLengthMatchingKey(size_t inLocation, size_t inSpanningLength, const string& inKey)
|
||||||
|
{
|
||||||
|
if (inLocation > m_spans.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Node *n = m_spans[inLocation].nodeOfLength(inSpanningLength);
|
||||||
|
if (!n) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return inKey == n->key();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Grid::expandGridByOneAtLocation(size_t inLocation)
|
||||||
|
{
|
||||||
|
if (!inLocation || inLocation == m_spans.size()) {
|
||||||
|
m_spans.insert(m_spans.begin() + inLocation, Span());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_spans.insert(m_spans.begin() + inLocation, Span());
|
||||||
|
for (size_t i = 0 ; i < inLocation ; i++) {
|
||||||
|
// zaps overlapping spans
|
||||||
|
m_spans[i].removeNodeOfLengthGreaterThan(inLocation - i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Grid::shrinkGridByOneAtLocation(size_t inLocation)
|
||||||
|
{
|
||||||
|
if (inLocation >= m_spans.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_spans.erase(m_spans.begin() + inLocation);
|
||||||
|
for (size_t i = 0 ; i < inLocation ; i++) {
|
||||||
|
// zaps overlapping spans
|
||||||
|
m_spans[i].removeNodeOfLengthGreaterThan(inLocation - i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t Grid::width() const
|
||||||
|
{
|
||||||
|
return m_spans.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline vector<NodeAnchor> Grid::nodesEndingAt(size_t inLocation)
|
||||||
|
{
|
||||||
|
vector<NodeAnchor> result;
|
||||||
|
|
||||||
|
if (m_spans.size() && inLocation <= m_spans.size()) {
|
||||||
|
for (size_t i = 0 ; i < inLocation ; i++) {
|
||||||
|
Span& span = m_spans[i];
|
||||||
|
if (i + span.maximumLength() >= inLocation) {
|
||||||
|
Node *np = span.nodeOfLength(inLocation - i);
|
||||||
|
if (np) {
|
||||||
|
NodeAnchor na;
|
||||||
|
na.node = np;
|
||||||
|
na.location = i;
|
||||||
|
na.spanningLength = inLocation - i;
|
||||||
|
|
||||||
|
result.push_back(na);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline vector<NodeAnchor> Grid::nodesCrossingOrEndingAt(size_t inLocation)
|
||||||
|
{
|
||||||
|
vector<NodeAnchor> result;
|
||||||
|
|
||||||
|
if (m_spans.size() && inLocation <= m_spans.size()) {
|
||||||
|
for (size_t i = 0 ; i < inLocation ; i++) {
|
||||||
|
Span& span = m_spans[i];
|
||||||
|
|
||||||
|
if (i + span.maximumLength() >= inLocation) {
|
||||||
|
|
||||||
|
for (size_t j = 1, m = span.maximumLength(); j <= m ; j++) {
|
||||||
|
|
||||||
|
if (i + j < inLocation) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node *np = span.nodeOfLength(j);
|
||||||
|
if (np) {
|
||||||
|
NodeAnchor na;
|
||||||
|
na.node = np;
|
||||||
|
na.location = i;
|
||||||
|
na.spanningLength = inLocation - i;
|
||||||
|
|
||||||
|
result.push_back(na);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const string Grid::dumpDOT()
|
||||||
|
{
|
||||||
|
stringstream sst;
|
||||||
|
sst << "digraph {" << endl;
|
||||||
|
sst << "graph [ rankdir=LR ];" << endl;
|
||||||
|
sst << "BOS;" << endl;
|
||||||
|
|
||||||
|
for (size_t p = 0 ; p < m_spans.size() ; p++) {
|
||||||
|
Span& span = m_spans[p];
|
||||||
|
for (size_t ni = 0 ; ni <= span.maximumLength() ; ni++) {
|
||||||
|
Node* np = span.nodeOfLength(ni);
|
||||||
|
if (np) {
|
||||||
|
if (!p) {
|
||||||
|
sst << "BOS -> " << np->currentKeyValue().value << ";" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
sst << np->currentKeyValue().value << ";" << endl;
|
||||||
|
|
||||||
|
if (p + ni < m_spans.size()) {
|
||||||
|
Span& dstSpan = m_spans[p+ni];
|
||||||
|
for (size_t q = 0 ; q <= dstSpan.maximumLength() ; q++) {
|
||||||
|
Node *dn = dstSpan.nodeOfLength(q);
|
||||||
|
if (dn) {
|
||||||
|
sst << np->currentKeyValue().value << " -> " << dn->currentKeyValue().value << ";" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p + ni == m_spans.size()) {
|
||||||
|
sst << np->currentKeyValue().value << " -> " << "EOS;" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sst << "EOS;" << endl;
|
||||||
|
sst << "}";
|
||||||
|
return sst.str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,70 @@
|
||||||
|
//
|
||||||
|
// KeyValuePair.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef KeyValuePair_h
|
||||||
|
#define KeyValuePair_h
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Formosa {
|
||||||
|
namespace Gramambular {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class KeyValuePair {
|
||||||
|
public:
|
||||||
|
string key;
|
||||||
|
string value;
|
||||||
|
|
||||||
|
bool operator==(const KeyValuePair& inAnother) const;
|
||||||
|
bool operator<(const KeyValuePair& inAnother) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline ostream& operator<<(ostream& inStream, const KeyValuePair& inPair)
|
||||||
|
{
|
||||||
|
inStream << "(" << inPair.key << "," << inPair.value << ")";
|
||||||
|
return inStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool KeyValuePair::operator==(const KeyValuePair& inAnother) const
|
||||||
|
{
|
||||||
|
return key == inAnother.key && value == inAnother.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool KeyValuePair::operator<(const KeyValuePair& inAnother) const
|
||||||
|
{
|
||||||
|
if (key < inAnother.key) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (key == inAnother.key) {
|
||||||
|
return value < inAnother.value;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,52 @@
|
||||||
|
//
|
||||||
|
// LanguageModel.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef LanguageModel_h
|
||||||
|
#define LanguageModel_h
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "Bigram.h"
|
||||||
|
#include "Unigram.h"
|
||||||
|
|
||||||
|
namespace Formosa {
|
||||||
|
namespace Gramambular {
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class LanguageModel {
|
||||||
|
public:
|
||||||
|
virtual ~LanguageModel() {}
|
||||||
|
|
||||||
|
virtual const vector<Bigram> bigramsForKeys(const string &preceedingKey, const string& key) = 0;
|
||||||
|
virtual const vector<Unigram> unigramsForKeys(const string &key) = 0;
|
||||||
|
virtual bool hasUnigramsForKey(const string& key) = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,191 @@
|
||||||
|
//
|
||||||
|
// Node.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef Node_h
|
||||||
|
#define Node_h
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <vector>
|
||||||
|
#include "LanguageModel.h"
|
||||||
|
|
||||||
|
namespace Formosa {
|
||||||
|
namespace Gramambular {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class Node {
|
||||||
|
public:
|
||||||
|
Node();
|
||||||
|
Node(const string& inKey, const vector<Unigram>& inUnigrams, const vector<Bigram>& inBigrams);
|
||||||
|
|
||||||
|
void primeNodeWithPreceedingKeyValues(const vector<KeyValuePair>& inKeyValues);
|
||||||
|
|
||||||
|
bool isCandidateFixed() const;
|
||||||
|
const vector<KeyValuePair>& candidates() const;
|
||||||
|
void selectCandidateAtIndex(size_t inIndex = 0, bool inFix = true);
|
||||||
|
|
||||||
|
const string& key() const;
|
||||||
|
double score() const;
|
||||||
|
const KeyValuePair currentKeyValue() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const LanguageModel* m_LM;
|
||||||
|
|
||||||
|
string m_key;
|
||||||
|
double m_score;
|
||||||
|
|
||||||
|
vector<Unigram> m_unigrams;
|
||||||
|
vector<KeyValuePair> m_candidates;
|
||||||
|
map<string, size_t> m_valueUnigramIndexMap;
|
||||||
|
map<KeyValuePair, vector<Bigram> > m_preceedingGramBigramMap;
|
||||||
|
|
||||||
|
bool m_candidateFixed;
|
||||||
|
size_t m_selectedUnigramIndex;
|
||||||
|
|
||||||
|
friend ostream& operator<<(ostream& inStream, const Node& inNode);
|
||||||
|
};
|
||||||
|
|
||||||
|
inline ostream& operator<<(ostream& inStream, const Node& inNode)
|
||||||
|
{
|
||||||
|
inStream << "(node,key:" << inNode.m_key << ",fixed:" << (inNode.m_candidateFixed ? "true" : "false")
|
||||||
|
<< ",selected:" << inNode.m_selectedUnigramIndex
|
||||||
|
<< "," << inNode.m_unigrams << ")";
|
||||||
|
return inStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Node::Node()
|
||||||
|
: m_candidateFixed(false)
|
||||||
|
, m_selectedUnigramIndex(0)
|
||||||
|
, m_score(0.0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Node::Node(const string& inKey, const vector<Unigram>& inUnigrams, const vector<Bigram>& inBigrams)
|
||||||
|
: m_key(inKey)
|
||||||
|
, m_unigrams(inUnigrams)
|
||||||
|
, m_candidateFixed(false)
|
||||||
|
, m_selectedUnigramIndex(0)
|
||||||
|
, m_score(0.0)
|
||||||
|
{
|
||||||
|
sort(m_unigrams.begin(), m_unigrams.end(), Unigram::ScoreCompare);
|
||||||
|
|
||||||
|
if (m_unigrams.size()) {
|
||||||
|
m_score = m_unigrams[0].score;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
for (vector<Unigram>::const_iterator ui = m_unigrams.begin() ; ui != m_unigrams.end() ; ++ui) {
|
||||||
|
m_valueUnigramIndexMap[(*ui).keyValue.value] = i;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
m_candidates.push_back((*ui).keyValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (vector<Bigram>::const_iterator bi = inBigrams.begin() ; bi != inBigrams.end() ; ++bi) {
|
||||||
|
m_preceedingGramBigramMap[(*bi).preceedingKeyValue].push_back(*bi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Node::primeNodeWithPreceedingKeyValues(const vector<KeyValuePair>& inKeyValues)
|
||||||
|
{
|
||||||
|
size_t newIndex = m_selectedUnigramIndex;
|
||||||
|
double max = m_score;
|
||||||
|
|
||||||
|
if (!isCandidateFixed()) {
|
||||||
|
for (vector<KeyValuePair>::const_iterator kvi = inKeyValues.begin() ; kvi != inKeyValues.end() ; ++kvi) {
|
||||||
|
map<KeyValuePair, vector<Bigram> >::const_iterator f = m_preceedingGramBigramMap.find(*kvi);
|
||||||
|
if (f != m_preceedingGramBigramMap.end()) {
|
||||||
|
const vector<Bigram>& bigrams = (*f).second;
|
||||||
|
|
||||||
|
for (vector<Bigram>::const_iterator bi = bigrams.begin() ; bi != bigrams.end() ; ++bi) {
|
||||||
|
const Bigram& bigram = *bi;
|
||||||
|
if (bigram.score > max) {
|
||||||
|
map<string, size_t>::const_iterator uf = m_valueUnigramIndexMap.find((*bi).keyValue.value);
|
||||||
|
if (uf != m_valueUnigramIndexMap.end()) {
|
||||||
|
newIndex = (*uf).second;
|
||||||
|
max = bigram.score;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_score != max) {
|
||||||
|
m_score = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newIndex != m_selectedUnigramIndex) {
|
||||||
|
m_selectedUnigramIndex = newIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Node::isCandidateFixed() const
|
||||||
|
{
|
||||||
|
return m_candidateFixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const vector<KeyValuePair>& Node::candidates() const
|
||||||
|
{
|
||||||
|
return m_candidates;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Node::selectCandidateAtIndex(size_t inIndex, bool inFix)
|
||||||
|
{
|
||||||
|
if (inIndex >= m_unigrams.size()) {
|
||||||
|
m_selectedUnigramIndex = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_selectedUnigramIndex = inIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_candidateFixed = inFix;
|
||||||
|
m_score = 99;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const string& Node::key() const
|
||||||
|
{
|
||||||
|
return m_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double Node::score() const
|
||||||
|
{
|
||||||
|
return m_score;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const KeyValuePair Node::currentKeyValue() const
|
||||||
|
{
|
||||||
|
if(m_selectedUnigramIndex >= m_unigrams.size()) {
|
||||||
|
return KeyValuePair();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return m_candidates[m_selectedUnigramIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,79 @@
|
||||||
|
//
|
||||||
|
// NodeAnchor.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef NodeAnchor_h
|
||||||
|
#define NodeAnchor_h
|
||||||
|
|
||||||
|
#include "Node.h"
|
||||||
|
|
||||||
|
namespace Formosa {
|
||||||
|
namespace Gramambular {
|
||||||
|
class NodeAnchor {
|
||||||
|
public:
|
||||||
|
NodeAnchor();
|
||||||
|
const Node *node;
|
||||||
|
size_t location;
|
||||||
|
size_t spanningLength;
|
||||||
|
double accumulatedScore;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline NodeAnchor::NodeAnchor()
|
||||||
|
: node(0)
|
||||||
|
, location(0)
|
||||||
|
, spanningLength(0)
|
||||||
|
, accumulatedScore(0.0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ostream& operator<<(ostream& inStream, const NodeAnchor& inAnchor)
|
||||||
|
{
|
||||||
|
inStream << "{@(" << inAnchor.location << "," << inAnchor.spanningLength << "),";
|
||||||
|
if (inAnchor.node) {
|
||||||
|
inStream << *(inAnchor.node);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
inStream << "null";
|
||||||
|
}
|
||||||
|
inStream << "}";
|
||||||
|
return inStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ostream& operator<<(ostream& inStream, const vector<NodeAnchor>& inAnchor)
|
||||||
|
{
|
||||||
|
for (vector<NodeAnchor>::const_iterator i = inAnchor.begin() ; i != inAnchor.end() ; ++i) {
|
||||||
|
inStream << *i;
|
||||||
|
if (i + 1 != inAnchor.end()) {
|
||||||
|
inStream << "<-";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return inStream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,106 @@
|
||||||
|
//
|
||||||
|
// Span.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef Span_h
|
||||||
|
#define Span_h
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <sstream>
|
||||||
|
#include "Node.h"
|
||||||
|
|
||||||
|
namespace Formosa {
|
||||||
|
namespace Gramambular {
|
||||||
|
class Span {
|
||||||
|
public:
|
||||||
|
Span();
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
void insertNodeOfLength(const Node& inNode, size_t inLength);
|
||||||
|
void removeNodeOfLengthGreaterThan(size_t inLength);
|
||||||
|
|
||||||
|
Node* nodeOfLength(size_t inLength);
|
||||||
|
size_t maximumLength() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
map<size_t, Node> m_lengthNodeMap;
|
||||||
|
size_t m_maximumLength;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline Span::Span()
|
||||||
|
: m_maximumLength(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Span::clear()
|
||||||
|
{
|
||||||
|
m_lengthNodeMap.clear();
|
||||||
|
m_maximumLength = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Span::insertNodeOfLength(const Node& inNode, size_t inLength)
|
||||||
|
{
|
||||||
|
m_lengthNodeMap[inLength] = inNode;
|
||||||
|
if (inLength > m_maximumLength) {
|
||||||
|
m_maximumLength = inLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Span::removeNodeOfLengthGreaterThan(size_t inLength)
|
||||||
|
{
|
||||||
|
if (inLength > m_maximumLength) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t max = 0;
|
||||||
|
for (map<size_t, Node>::iterator i = m_lengthNodeMap.begin() ; i != m_lengthNodeMap.end() ; ++i) {
|
||||||
|
if ((*i).first > inLength) {
|
||||||
|
m_lengthNodeMap.erase(i);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ((*i).first > max) {
|
||||||
|
max = (*i).first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_maximumLength = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Node* Span::nodeOfLength(size_t inLength)
|
||||||
|
{
|
||||||
|
map<size_t, Node>::iterator f = m_lengthNodeMap.find(inLength);
|
||||||
|
return f == m_lengthNodeMap.end() ? 0 : &(*f).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t Span::maximumLength() const
|
||||||
|
{
|
||||||
|
return m_maximumLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,104 @@
|
||||||
|
//
|
||||||
|
// Unigram.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef Unigram_h
|
||||||
|
#define Unigram_h
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "KeyValuePair.h"
|
||||||
|
|
||||||
|
namespace Formosa {
|
||||||
|
namespace Gramambular {
|
||||||
|
class Unigram {
|
||||||
|
public:
|
||||||
|
Unigram();
|
||||||
|
|
||||||
|
KeyValuePair keyValue;
|
||||||
|
double score;
|
||||||
|
|
||||||
|
bool operator==(const Unigram& inAnother) const;
|
||||||
|
bool operator<(const Unigram& inAnother) const;
|
||||||
|
|
||||||
|
static bool ScoreCompare(const Unigram& a, const Unigram& b);
|
||||||
|
};
|
||||||
|
|
||||||
|
inline ostream& operator<<(ostream& inStream, const Unigram& inGram)
|
||||||
|
{
|
||||||
|
streamsize p = inStream.precision();
|
||||||
|
inStream.precision(6);
|
||||||
|
inStream << "(" << inGram.keyValue << "," << inGram.score << ")";
|
||||||
|
inStream.precision(p);
|
||||||
|
return inStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ostream& operator<<(ostream& inStream, const vector<Unigram>& inGrams)
|
||||||
|
{
|
||||||
|
inStream << "[" << inGrams.size() << "]=>{";
|
||||||
|
|
||||||
|
size_t index = 0;
|
||||||
|
|
||||||
|
for (vector<Unigram>::const_iterator gi = inGrams.begin() ; gi != inGrams.end() ; ++gi, ++index) {
|
||||||
|
inStream << index << "=>";
|
||||||
|
inStream << *gi;
|
||||||
|
if (gi + 1 != inGrams.end()) {
|
||||||
|
inStream << ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inStream << "}";
|
||||||
|
return inStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Unigram::Unigram()
|
||||||
|
: score(0.0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Unigram::operator==(const Unigram& inAnother) const
|
||||||
|
{
|
||||||
|
return keyValue == inAnother.keyValue && score == inAnother.score;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Unigram::operator<(const Unigram& inAnother) const
|
||||||
|
{
|
||||||
|
if (keyValue < inAnother.keyValue) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (keyValue == inAnother.keyValue) {
|
||||||
|
return score < inAnother.score;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Unigram::ScoreCompare(const Unigram& a, const Unigram& b)
|
||||||
|
{
|
||||||
|
return a.score > b.score;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,91 @@
|
||||||
|
//
|
||||||
|
// Walker.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef Walker_h
|
||||||
|
#define Walker_h
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include "Grid.h"
|
||||||
|
|
||||||
|
namespace Formosa {
|
||||||
|
namespace Gramambular {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class Walker {
|
||||||
|
public:
|
||||||
|
Walker(Grid* inGrid);
|
||||||
|
const vector<NodeAnchor> reverseWalk(size_t inLocation, double inAccumulatedScore = 0.0);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Grid* m_grid;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline Walker::Walker(Grid* inGrid)
|
||||||
|
: m_grid(inGrid)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const vector<NodeAnchor> Walker::reverseWalk(size_t inLocation, double inAccumulatedScore)
|
||||||
|
{
|
||||||
|
if (!inLocation || inLocation > m_grid->width()) {
|
||||||
|
return vector<NodeAnchor>();
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<vector<NodeAnchor> > paths;
|
||||||
|
|
||||||
|
vector<NodeAnchor> nodes = m_grid->nodesEndingAt(inLocation);
|
||||||
|
|
||||||
|
for (vector<NodeAnchor>::iterator ni = nodes.begin() ; ni != nodes.end() ; ++ni) {
|
||||||
|
if (!(*ni).node) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*ni).accumulatedScore = inAccumulatedScore + (*ni).node->score();
|
||||||
|
|
||||||
|
vector<NodeAnchor> path = reverseWalk(inLocation - (*ni).spanningLength, (*ni).accumulatedScore);
|
||||||
|
path.insert(path.begin(), *ni);
|
||||||
|
|
||||||
|
paths.push_back(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!paths.size()) {
|
||||||
|
return vector<NodeAnchor>();
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<NodeAnchor>* result = &*(paths.begin());
|
||||||
|
for (vector<vector<NodeAnchor> >::iterator pi = paths.begin() ; pi != paths.end() ; ++pi) {
|
||||||
|
if ((*pi).back().accumulatedScore > result->back().accumulatedScore) {
|
||||||
|
result = &*pi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return *result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,956 @@
|
||||||
|
//
|
||||||
|
// Mandarin.cpp
|
||||||
|
//
|
||||||
|
// Copyright (c) 2006-2010 Lukhnos D. Liu (http://lukhnos.org)
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <cctype>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "Mandarin.h"
|
||||||
|
|
||||||
|
#include "OVUTF8Helper.h"
|
||||||
|
#include "OVWildcard.h"
|
||||||
|
|
||||||
|
namespace Formosa {
|
||||||
|
namespace Mandarin {
|
||||||
|
|
||||||
|
using namespace OpenVanilla;
|
||||||
|
|
||||||
|
class PinyinParseHelper {
|
||||||
|
public:
|
||||||
|
static const bool ConsumePrefix(string &target, const string &prefix)
|
||||||
|
{
|
||||||
|
if (target.length() < prefix.length()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target.substr(0, prefix.length()) == prefix) {
|
||||||
|
target = target.substr(prefix.length(), target.length() - prefix.length());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class BopomofoCharacterMap {
|
||||||
|
public:
|
||||||
|
static const BopomofoCharacterMap& SharedInstance();
|
||||||
|
|
||||||
|
map<BPMF::Component, string> componentToCharacter;
|
||||||
|
map<string, BPMF::Component> characterToComponent;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BopomofoCharacterMap();
|
||||||
|
static BopomofoCharacterMap* c_map;
|
||||||
|
};
|
||||||
|
|
||||||
|
const BPMF BPMF::FromHanyuPinyin(const string& str)
|
||||||
|
{
|
||||||
|
if (!str.length()) {
|
||||||
|
return BPMF();
|
||||||
|
}
|
||||||
|
|
||||||
|
string pinyin = str;
|
||||||
|
transform(pinyin.begin(), pinyin.end(), pinyin.begin(), ::tolower);
|
||||||
|
|
||||||
|
BPMF::Component firstComponent = 0;
|
||||||
|
BPMF::Component secondComponent = 0;
|
||||||
|
BPMF::Component thirdComponent = 0;
|
||||||
|
BPMF::Component toneComponent = 0;
|
||||||
|
|
||||||
|
// lookup consonants and consume them
|
||||||
|
bool independentConsonant = false;
|
||||||
|
|
||||||
|
// the y exceptions fist
|
||||||
|
if (0) {}
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "yuan")) { secondComponent = BPMF::UE; thirdComponent = BPMF::AN; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ying")) { secondComponent = BPMF::I; thirdComponent = BPMF::ENG; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "yung")) { secondComponent = BPMF::UE; thirdComponent = BPMF::ENG; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "yong")) { secondComponent = BPMF::UE; thirdComponent = BPMF::ENG; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "yue")) { secondComponent = BPMF::UE; thirdComponent = BPMF::E; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "yun")) { secondComponent = BPMF::UE; thirdComponent = BPMF::EN; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "you")) { secondComponent = BPMF::I; thirdComponent = BPMF::OU; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "yu")) { secondComponent = BPMF::UE; }
|
||||||
|
|
||||||
|
|
||||||
|
// try the first character
|
||||||
|
char c = pinyin.length() ? pinyin[0] : 0;
|
||||||
|
switch (c) {
|
||||||
|
case 'b': firstComponent = BPMF::B; pinyin = pinyin.substr(1); break;
|
||||||
|
case 'p': firstComponent = BPMF::P; pinyin = pinyin.substr(1); break;
|
||||||
|
case 'm': firstComponent = BPMF::M; pinyin = pinyin.substr(1); break;
|
||||||
|
case 'f': firstComponent = BPMF::F; pinyin = pinyin.substr(1); break;
|
||||||
|
case 'd': firstComponent = BPMF::D; pinyin = pinyin.substr(1); break;
|
||||||
|
case 't': firstComponent = BPMF::T; pinyin = pinyin.substr(1); break;
|
||||||
|
case 'n': firstComponent = BPMF::N; pinyin = pinyin.substr(1); break;
|
||||||
|
case 'l': firstComponent = BPMF::L; pinyin = pinyin.substr(1); break;
|
||||||
|
case 'g': firstComponent = BPMF::G; pinyin = pinyin.substr(1); break;
|
||||||
|
case 'k': firstComponent = BPMF::K; pinyin = pinyin.substr(1); break;
|
||||||
|
case 'h': firstComponent = BPMF::H; pinyin = pinyin.substr(1); break;
|
||||||
|
case 'j': firstComponent = BPMF::J; pinyin = pinyin.substr(1); break;
|
||||||
|
case 'q': firstComponent = BPMF::Q; pinyin = pinyin.substr(1); break;
|
||||||
|
case 'x': firstComponent = BPMF::X; pinyin = pinyin.substr(1); break;
|
||||||
|
|
||||||
|
// special hanlding for w and y
|
||||||
|
case 'w': secondComponent = BPMF::U; pinyin = pinyin.substr(1); break;
|
||||||
|
case 'y':
|
||||||
|
if (!secondComponent && !thirdComponent) {
|
||||||
|
secondComponent = BPMF::I;
|
||||||
|
}
|
||||||
|
pinyin = pinyin.substr(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// then we try ZH, CH, SH, R, Z, C, S (in that order)
|
||||||
|
if (0) {}
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "zh")) { firstComponent = BPMF::ZH; independentConsonant = true; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ch")) { firstComponent = BPMF::CH; independentConsonant = true; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "sh")) { firstComponent = BPMF::SH; independentConsonant = true; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "r")) { firstComponent = BPMF::R; independentConsonant = true; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "z")) { firstComponent = BPMF::Z; independentConsonant = true; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "c")) { firstComponent = BPMF::C; independentConsonant = true; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "s")) { firstComponent = BPMF::S; independentConsonant = true; }
|
||||||
|
|
||||||
|
// consume exceptions first: (ien, in), (iou, iu), (uen, un), (veng, iong), (ven, vn), (uei, ui), ung
|
||||||
|
// but longer sequence takes precedence
|
||||||
|
if (0) {}
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "veng")) { secondComponent = BPMF::UE; thirdComponent = BPMF::ENG; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "iong")) { secondComponent = BPMF::UE; thirdComponent = BPMF::ENG; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ing")) { secondComponent = BPMF::I; thirdComponent = BPMF::ENG; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ien")) { secondComponent = BPMF::I; thirdComponent = BPMF::EN; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "iou")) { secondComponent = BPMF::I; thirdComponent = BPMF::OU; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "uen")) { secondComponent = BPMF::U; thirdComponent = BPMF::EN; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ven")) { secondComponent = BPMF::UE; thirdComponent = BPMF::EN; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "uei")) { secondComponent = BPMF::U; thirdComponent = BPMF::EI; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ung")) {
|
||||||
|
// f exception
|
||||||
|
if (firstComponent == BPMF::F) {
|
||||||
|
thirdComponent = BPMF::ENG;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
secondComponent = BPMF::U; thirdComponent = BPMF::ENG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ong")) {
|
||||||
|
// f exception
|
||||||
|
if (firstComponent == BPMF::F) {
|
||||||
|
thirdComponent = BPMF::ENG;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
secondComponent = BPMF::U;
|
||||||
|
thirdComponent = BPMF::ENG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "un")) {
|
||||||
|
if (firstComponent == BPMF::J || firstComponent == BPMF::Q || firstComponent == BPMF::X) {
|
||||||
|
secondComponent = BPMF::UE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
secondComponent = BPMF::U;
|
||||||
|
}
|
||||||
|
thirdComponent = BPMF::EN;
|
||||||
|
}
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "iu")) { secondComponent = BPMF::I; thirdComponent = BPMF::OU; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "in")) { secondComponent = BPMF::I; thirdComponent = BPMF::EN; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "vn")) { secondComponent = BPMF::UE; thirdComponent = BPMF::EN; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ui")) { secondComponent = BPMF::U; thirdComponent = BPMF::EI; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ue"))
|
||||||
|
{
|
||||||
|
secondComponent = BPMF::UE; thirdComponent = BPMF::E;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ü")) { secondComponent = BPMF::UE; }
|
||||||
|
#else
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "\xc3\xbc")) { secondComponent = BPMF::UE; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// then consume the middle component...
|
||||||
|
if (0) {}
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "i")) { secondComponent = independentConsonant ? 0 : BPMF::I; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "u")) {
|
||||||
|
if (firstComponent == BPMF::J || firstComponent == BPMF::Q || firstComponent == BPMF::X) {
|
||||||
|
secondComponent = BPMF::UE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
secondComponent = BPMF::U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "v")) { secondComponent = BPMF::UE; }
|
||||||
|
|
||||||
|
// the vowels, longer sequence takes precedence
|
||||||
|
if (0) {}
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ang")) { thirdComponent = BPMF::ANG; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "eng")) { thirdComponent = BPMF::ENG; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "err")) { thirdComponent = BPMF::ERR; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ai")) { thirdComponent = BPMF::AI; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ei")) { thirdComponent = BPMF::EI; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ao")) { thirdComponent = BPMF::AO; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ou")) { thirdComponent = BPMF::OU; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "an")) { thirdComponent = BPMF::AN; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "en")) { thirdComponent = BPMF::EN; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "er")) { thirdComponent = BPMF::ERR; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "a")) { thirdComponent = BPMF::A; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "o")) { thirdComponent = BPMF::O; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "e")) {
|
||||||
|
if (secondComponent) {
|
||||||
|
thirdComponent = BPMF::E;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
thirdComponent = BPMF::ER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// at last!
|
||||||
|
if (0) {}
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "1")) { toneComponent = BPMF::Tone1; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "2")) { toneComponent = BPMF::Tone2; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "3")) { toneComponent = BPMF::Tone3; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "4")) { toneComponent = BPMF::Tone4; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pinyin, "5")) { toneComponent = BPMF::Tone5; }
|
||||||
|
|
||||||
|
return BPMF(firstComponent | secondComponent | thirdComponent | toneComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
const string BPMF::HanyuPinyinString(bool includesTone, bool useVForUUmlaut) const
|
||||||
|
{
|
||||||
|
string consonant, middle, vowel, tone;
|
||||||
|
|
||||||
|
Component cc = consonantComponent(), mvc = middleVowelComponent(), vc = vowelComponent();
|
||||||
|
bool hasNoMVCOrVC = !(mvc || vc);
|
||||||
|
|
||||||
|
|
||||||
|
switch (cc) {
|
||||||
|
case B: consonant = "b"; break;
|
||||||
|
case P: consonant = "p"; break;
|
||||||
|
case M: consonant = "m"; break;
|
||||||
|
case F: consonant = "f"; break;
|
||||||
|
case D: consonant = "d"; break;
|
||||||
|
case T: consonant = "t"; break;
|
||||||
|
case N: consonant = "n"; break;
|
||||||
|
case L: consonant = "l"; break;
|
||||||
|
case G: consonant = "g"; break;
|
||||||
|
case K: consonant = "k"; break;
|
||||||
|
case H: consonant = "h"; break;
|
||||||
|
case J: consonant = "j"; if (hasNoMVCOrVC) middle = "i"; break;
|
||||||
|
case Q: consonant = "q"; if (hasNoMVCOrVC) middle = "i"; break;
|
||||||
|
case X: consonant = "x"; if (hasNoMVCOrVC) middle = "i"; break;
|
||||||
|
case ZH: consonant = "zh"; if (hasNoMVCOrVC) middle = "i"; break;
|
||||||
|
case CH: consonant = "ch"; if (hasNoMVCOrVC) middle = "i"; break;
|
||||||
|
case SH: consonant = "sh"; if (hasNoMVCOrVC) middle = "i"; break;
|
||||||
|
case R: consonant = "r"; if (hasNoMVCOrVC) middle = "i"; break;
|
||||||
|
case Z: consonant = "z"; if (hasNoMVCOrVC) middle = "i"; break;
|
||||||
|
case C: consonant = "c"; if (hasNoMVCOrVC) middle = "i"; break;
|
||||||
|
case S: consonant = "s"; if (hasNoMVCOrVC) middle = "i"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (mvc) {
|
||||||
|
case I:
|
||||||
|
if (!cc) {
|
||||||
|
consonant = "y";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
middle = (!vc || cc) ? "i" : "";
|
||||||
|
break;
|
||||||
|
case U:
|
||||||
|
if (!cc) {
|
||||||
|
consonant = "w";
|
||||||
|
}
|
||||||
|
middle = (!vc || cc) ? "u" : "";
|
||||||
|
break;
|
||||||
|
case UE:
|
||||||
|
if (!cc) {
|
||||||
|
consonant = "y";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cc == N || cc == L) && vc != E) {
|
||||||
|
middle = useVForUUmlaut ? "v" : "ü";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
middle = "u";
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (vc) {
|
||||||
|
case A: vowel = "a"; break;
|
||||||
|
case O: vowel = "o"; break;
|
||||||
|
case ER: vowel = "e"; break;
|
||||||
|
case E: vowel = "e"; break;
|
||||||
|
case AI: vowel = "ai"; break;
|
||||||
|
case EI: vowel = "ei"; break;
|
||||||
|
case AO: vowel = "ao"; break;
|
||||||
|
case OU: vowel = "ou"; break;
|
||||||
|
case AN: vowel = "an"; break;
|
||||||
|
case EN: vowel = "en"; break;
|
||||||
|
case ANG: vowel = "ang"; break;
|
||||||
|
case ENG: vowel = "eng"; break;
|
||||||
|
case ERR: vowel = "er"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// combination rules
|
||||||
|
|
||||||
|
// ueng -> ong, but note "weng"
|
||||||
|
if ((mvc == U || mvc == UE) && vc == ENG) {
|
||||||
|
middle = "";
|
||||||
|
vowel = (cc == J || cc == Q || cc == X) ? "iong" : ((!cc && mvc == U) ? "eng" : "ong");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ien, uen, üen -> in, un, ün ; but note "wen", "yin" and "yun"
|
||||||
|
if (mvc && vc == EN) {
|
||||||
|
if (cc) {
|
||||||
|
vowel = "n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (mvc == UE) {
|
||||||
|
vowel = "n"; // yun
|
||||||
|
}
|
||||||
|
else if (mvc == U) {
|
||||||
|
vowel = "en"; // wen
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
vowel = "in"; // yin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// iou -> iu
|
||||||
|
if (cc && mvc == I && vc == OU) {
|
||||||
|
middle = "";
|
||||||
|
vowel = "iu";
|
||||||
|
}
|
||||||
|
|
||||||
|
// ieng -> ing
|
||||||
|
if (mvc == I && vc == ENG) {
|
||||||
|
middle = "";
|
||||||
|
vowel = "ing";
|
||||||
|
}
|
||||||
|
|
||||||
|
// uei -> ui
|
||||||
|
if (cc && mvc == U && vc == EI) {
|
||||||
|
middle = "";
|
||||||
|
vowel = "ui";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (includesTone) {
|
||||||
|
switch (toneMarkerComponent()) {
|
||||||
|
case Tone2: tone = "2"; break;
|
||||||
|
case Tone3: tone = "3"; break;
|
||||||
|
case Tone4: tone = "4"; break;
|
||||||
|
case Tone5: tone = "5"; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consonant + middle + vowel + tone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const string BPMF::PHTString(bool includesTone) const
|
||||||
|
{
|
||||||
|
string consonant, middle, vowel, tone;
|
||||||
|
|
||||||
|
Component cc = consonantComponent(), mvc = middleVowelComponent(), vc = vowelComponent();
|
||||||
|
bool hasNoMVCOrVC = !(mvc || vc);
|
||||||
|
|
||||||
|
switch (cc) {
|
||||||
|
case B: consonant = "p"; break;
|
||||||
|
case P: consonant = "ph"; break;
|
||||||
|
case M: consonant = "m"; break;
|
||||||
|
case F: consonant = "f"; break;
|
||||||
|
case D: consonant = "t"; break;
|
||||||
|
case T: consonant = "th"; break;
|
||||||
|
case N: consonant = "n"; break;
|
||||||
|
case L: consonant = "l"; break;
|
||||||
|
case G: consonant = "k"; break;
|
||||||
|
case K: consonant = "kh"; break;
|
||||||
|
case H: consonant = "h"; break;
|
||||||
|
case J: consonant = "ch"; if (mvc != I) middle = "i"; break;
|
||||||
|
case Q: consonant = "chh"; if (mvc != I) middle = "i"; break;
|
||||||
|
case X: consonant = "hs"; if (mvc != I) middle = "i"; break;
|
||||||
|
case ZH: consonant = "ch"; if (hasNoMVCOrVC) middle = "i"; break;
|
||||||
|
case CH: consonant = "chh"; if (hasNoMVCOrVC) middle = "i"; break;
|
||||||
|
case SH: consonant = "sh"; if (hasNoMVCOrVC) middle = "i"; break;
|
||||||
|
case R: consonant = "r"; if (hasNoMVCOrVC) middle = "i"; break;
|
||||||
|
case Z: consonant = "ts"; if (hasNoMVCOrVC) middle = "i"; break;
|
||||||
|
case C: consonant = "tsh"; if (hasNoMVCOrVC) middle = "i"; break;
|
||||||
|
case S: consonant = "s"; if (hasNoMVCOrVC) middle = "i"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (mvc) {
|
||||||
|
case I:
|
||||||
|
middle = "i";
|
||||||
|
break;
|
||||||
|
case U:
|
||||||
|
middle = "u";
|
||||||
|
break;
|
||||||
|
case UE:
|
||||||
|
middle = "uu";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (vc) {
|
||||||
|
case A: vowel = "a"; break;
|
||||||
|
case O: vowel = "o"; break;
|
||||||
|
case ER: vowel = "e"; break;
|
||||||
|
case E: vowel = (!(cc || mvc)) ? "eh" : "e"; break;
|
||||||
|
case AI: vowel = "ai"; break;
|
||||||
|
case EI: vowel = "ei"; break;
|
||||||
|
case AO: vowel = "ao"; break;
|
||||||
|
case OU: vowel = "ou"; break;
|
||||||
|
case AN: vowel = "an"; break;
|
||||||
|
case EN: vowel = "en"; break;
|
||||||
|
case ANG: vowel = "ang"; break;
|
||||||
|
case ENG: vowel = "eng"; break;
|
||||||
|
case ERR: vowel = "err"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ieng -> ing
|
||||||
|
if (mvc == I && vc == ENG) {
|
||||||
|
middle = "";
|
||||||
|
vowel = "ing";
|
||||||
|
}
|
||||||
|
|
||||||
|
// zh/ch + i without third component -> append h
|
||||||
|
if (cc == BPMF::ZH || cc == BPMF::CH) {
|
||||||
|
if (!mvc && !vc) {
|
||||||
|
vowel = "h";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (includesTone) {
|
||||||
|
switch (toneMarkerComponent()) {
|
||||||
|
case Tone2: tone = "2"; break;
|
||||||
|
case Tone3: tone = "3"; break;
|
||||||
|
case Tone4: tone = "4"; break;
|
||||||
|
case Tone5: tone = "5"; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consonant + middle + vowel + tone;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const BPMF BPMF::FromPHT(const string& str)
|
||||||
|
{
|
||||||
|
if (!str.length()) {
|
||||||
|
return BPMF();
|
||||||
|
}
|
||||||
|
|
||||||
|
string pht = str;
|
||||||
|
transform(pht.begin(), pht.end(), pht.begin(), ::tolower);
|
||||||
|
|
||||||
|
BPMF::Component firstComponent = 0;
|
||||||
|
BPMF::Component secondComponent = 0;
|
||||||
|
BPMF::Component thirdComponent = 0;
|
||||||
|
BPMF::Component toneComponent = 0;
|
||||||
|
|
||||||
|
#define IF_CONSUME1(k, v) else if (PinyinParseHelper::ConsumePrefix(pht, k)) { firstComponent = v; }
|
||||||
|
|
||||||
|
// consume the first part
|
||||||
|
if (0) {}
|
||||||
|
IF_CONSUME1("ph", BPMF::P)
|
||||||
|
IF_CONSUME1("p", BPMF::B)
|
||||||
|
IF_CONSUME1("m", BPMF::M)
|
||||||
|
IF_CONSUME1("f", BPMF::F)
|
||||||
|
IF_CONSUME1("th", BPMF::T)
|
||||||
|
IF_CONSUME1("n", BPMF::N)
|
||||||
|
IF_CONSUME1("l", BPMF::L)
|
||||||
|
IF_CONSUME1("kh", BPMF::K)
|
||||||
|
IF_CONSUME1("k", BPMF::G)
|
||||||
|
IF_CONSUME1("chh", BPMF::Q)
|
||||||
|
IF_CONSUME1("ch", BPMF::J)
|
||||||
|
IF_CONSUME1("hs", BPMF::X)
|
||||||
|
IF_CONSUME1("sh", BPMF::SH)
|
||||||
|
IF_CONSUME1("r", BPMF::R)
|
||||||
|
IF_CONSUME1("tsh", BPMF::C)
|
||||||
|
IF_CONSUME1("ts", BPMF::Z)
|
||||||
|
IF_CONSUME1("s", BPMF::S)
|
||||||
|
IF_CONSUME1("t", BPMF::D)
|
||||||
|
IF_CONSUME1("h", BPMF::H)
|
||||||
|
|
||||||
|
#define IF_CONSUME2(k, v) else if (PinyinParseHelper::ConsumePrefix(pht, k)) { secondComponent = v; }
|
||||||
|
// consume the second part
|
||||||
|
if (0) {}
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "ing")) { secondComponent = BPMF::I; thirdComponent = BPMF::ENG; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "ih")) {
|
||||||
|
if (firstComponent == BPMF::J) {
|
||||||
|
firstComponent = BPMF::ZH;
|
||||||
|
}
|
||||||
|
else if (firstComponent == BPMF::Q) {
|
||||||
|
firstComponent = BPMF::CH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IF_CONSUME2("i", BPMF::I)
|
||||||
|
IF_CONSUME2("uu", BPMF::UE)
|
||||||
|
IF_CONSUME2("u", BPMF::U)
|
||||||
|
|
||||||
|
#undef IF_CONSUME1
|
||||||
|
#undef IF_CONSUME2
|
||||||
|
|
||||||
|
// the vowels, longer sequence takes precedence
|
||||||
|
if (0) {}
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "ang")) { thirdComponent = BPMF::ANG; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "eng")) { thirdComponent = BPMF::ENG; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "err")) { thirdComponent = BPMF::ERR; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "ai")) { thirdComponent = BPMF::AI; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "ei")) { thirdComponent = BPMF::EI; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "ao")) { thirdComponent = BPMF::AO; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "ou")) { thirdComponent = BPMF::OU; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "an")) { thirdComponent = BPMF::AN; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "en")) { thirdComponent = BPMF::EN; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "er")) { thirdComponent = BPMF::ERR; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "a")) { thirdComponent = BPMF::A; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "o")) { thirdComponent = BPMF::O; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "eh")) { thirdComponent = BPMF::E; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "e")) {
|
||||||
|
if (secondComponent) {
|
||||||
|
thirdComponent = BPMF::E;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
thirdComponent = BPMF::ER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fix ch/chh mappings
|
||||||
|
Component corresponding = 0;
|
||||||
|
if (firstComponent == BPMF::J) {
|
||||||
|
corresponding = BPMF::ZH;
|
||||||
|
}
|
||||||
|
else if (firstComponent == BPMF::Q) {
|
||||||
|
corresponding = BPMF::CH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (corresponding) {
|
||||||
|
if (secondComponent == BPMF::I && !thirdComponent) {
|
||||||
|
// if the second component is I and there's no third component, we use the corresponding part
|
||||||
|
// firstComponent = corresponding;
|
||||||
|
}
|
||||||
|
else if (secondComponent == BPMF::U) {
|
||||||
|
// if second component is U, we use the corresponding part
|
||||||
|
firstComponent = corresponding;
|
||||||
|
}
|
||||||
|
else if (!secondComponent) {
|
||||||
|
// if there's no second component, it must be a corresponding part
|
||||||
|
firstComponent = corresponding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (secondComponent == BPMF::I) {
|
||||||
|
// fixes a few impossible occurances
|
||||||
|
switch(firstComponent) {
|
||||||
|
case BPMF::ZH:
|
||||||
|
case BPMF::CH:
|
||||||
|
case BPMF::SH:
|
||||||
|
case BPMF::R:
|
||||||
|
case BPMF::Z:
|
||||||
|
case BPMF::C:
|
||||||
|
case BPMF::S:
|
||||||
|
secondComponent = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// at last!
|
||||||
|
if (0) {}
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "1")) { toneComponent = BPMF::Tone1; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "2")) { toneComponent = BPMF::Tone2; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "3")) { toneComponent = BPMF::Tone3; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "4")) { toneComponent = BPMF::Tone4; }
|
||||||
|
else if (PinyinParseHelper::ConsumePrefix(pht, "5")) { toneComponent = BPMF::Tone5; }
|
||||||
|
|
||||||
|
return BPMF(firstComponent | secondComponent | thirdComponent | toneComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
const BPMF BPMF::FromComposedString(const string& str)
|
||||||
|
{
|
||||||
|
BPMF syllable;
|
||||||
|
vector<string> components = OVUTF8Helper::SplitStringByCodePoint(str);
|
||||||
|
for (vector<string>::iterator iter = components.begin() ; iter != components.end() ; ++iter) {
|
||||||
|
|
||||||
|
const map<string, BPMF::Component>& charToComp = BopomofoCharacterMap::SharedInstance().characterToComponent;
|
||||||
|
map<string, BPMF::Component>::const_iterator result = charToComp.find(*iter);
|
||||||
|
if (result != charToComp.end())
|
||||||
|
syllable += BPMF((*result).second);
|
||||||
|
}
|
||||||
|
|
||||||
|
return syllable;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string BPMF::composedString() const
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
#define APPEND(c) if (m_syllable & c) result += (*BopomofoCharacterMap::SharedInstance().componentToCharacter.find(m_syllable & c)).second
|
||||||
|
APPEND(ConsonantMask);
|
||||||
|
APPEND(MiddleVowelMask);
|
||||||
|
APPEND(VowelMask);
|
||||||
|
APPEND(ToneMarkerMask);
|
||||||
|
#undef APPEND
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
BopomofoCharacterMap* BopomofoCharacterMap::c_map = 0;
|
||||||
|
|
||||||
|
const BopomofoCharacterMap& BopomofoCharacterMap::SharedInstance()
|
||||||
|
{
|
||||||
|
if (!c_map)
|
||||||
|
c_map = new BopomofoCharacterMap();
|
||||||
|
|
||||||
|
return *c_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
BopomofoCharacterMap::BopomofoCharacterMap()
|
||||||
|
{
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
characterToComponent["ㄅ"] = BPMF::B;
|
||||||
|
characterToComponent["ㄆ"] = BPMF::P;
|
||||||
|
characterToComponent["ㄇ"] = BPMF::M;
|
||||||
|
characterToComponent["ㄈ"] = BPMF::F;
|
||||||
|
characterToComponent["ㄉ"] = BPMF::D;
|
||||||
|
characterToComponent["ㄊ"] = BPMF::T;
|
||||||
|
characterToComponent["ㄋ"] = BPMF::N;
|
||||||
|
characterToComponent["ㄌ"] = BPMF::L;
|
||||||
|
characterToComponent["ㄎ"] = BPMF::K;
|
||||||
|
characterToComponent["ㄍ"] = BPMF::G;
|
||||||
|
characterToComponent["ㄏ"] = BPMF::H;
|
||||||
|
characterToComponent["ㄐ"] = BPMF::J;
|
||||||
|
characterToComponent["ㄑ"] = BPMF::Q;
|
||||||
|
characterToComponent["ㄒ"] = BPMF::X;
|
||||||
|
characterToComponent["ㄓ"] = BPMF::ZH;
|
||||||
|
characterToComponent["ㄔ"] = BPMF::CH;
|
||||||
|
characterToComponent["ㄕ"] = BPMF::SH;
|
||||||
|
characterToComponent["ㄖ"] = BPMF::R;
|
||||||
|
characterToComponent["ㄗ"] = BPMF::Z;
|
||||||
|
characterToComponent["ㄘ"] = BPMF::C;
|
||||||
|
characterToComponent["ㄙ"] = BPMF::S;
|
||||||
|
characterToComponent["ㄧ"] = BPMF::I;
|
||||||
|
characterToComponent["ㄨ"] = BPMF::U;
|
||||||
|
characterToComponent["ㄩ"] = BPMF::UE;
|
||||||
|
characterToComponent["ㄚ"] = BPMF::A;
|
||||||
|
characterToComponent["ㄛ"] = BPMF::O;
|
||||||
|
characterToComponent["ㄜ"] = BPMF::ER;
|
||||||
|
characterToComponent["ㄝ"] = BPMF::E;
|
||||||
|
characterToComponent["ㄞ"] = BPMF::AI;
|
||||||
|
characterToComponent["ㄟ"] = BPMF::EI;
|
||||||
|
characterToComponent["ㄠ"] = BPMF::AO;
|
||||||
|
characterToComponent["ㄡ"] = BPMF::OU;
|
||||||
|
characterToComponent["ㄢ"] = BPMF::AN;
|
||||||
|
characterToComponent["ㄣ"] = BPMF::EN;
|
||||||
|
characterToComponent["ㄤ"] = BPMF::ANG;
|
||||||
|
characterToComponent["ㄥ"] = BPMF::ENG;
|
||||||
|
characterToComponent["ㄦ"] = BPMF::ERR;
|
||||||
|
characterToComponent["ˊ"] = BPMF::Tone2;
|
||||||
|
characterToComponent["ˇ"] = BPMF::Tone3;
|
||||||
|
characterToComponent["ˋ"] = BPMF::Tone4;
|
||||||
|
characterToComponent["˙"] = BPMF::Tone5;
|
||||||
|
#else
|
||||||
|
characterToComponent["\xe3\x84\x85"] = BPMF::B;
|
||||||
|
characterToComponent["\xe3\x84\x86"] = BPMF::P;
|
||||||
|
characterToComponent["\xe3\x84\x87"] = BPMF::M;
|
||||||
|
characterToComponent["\xe3\x84\x88"] = BPMF::F;
|
||||||
|
characterToComponent["\xe3\x84\x89"] = BPMF::D;
|
||||||
|
characterToComponent["\xe3\x84\x8a"] = BPMF::T;
|
||||||
|
characterToComponent["\xe3\x84\x8b"] = BPMF::N;
|
||||||
|
characterToComponent["\xe3\x84\x8c"] = BPMF::L;
|
||||||
|
characterToComponent["\xe3\x84\x8e"] = BPMF::K;
|
||||||
|
characterToComponent["\xe3\x84\x8d"] = BPMF::G;
|
||||||
|
characterToComponent["\xe3\x84\x8f"] = BPMF::H;
|
||||||
|
characterToComponent["\xe3\x84\x90"] = BPMF::J;
|
||||||
|
characterToComponent["\xe3\x84\x91"] = BPMF::Q;
|
||||||
|
characterToComponent["\xe3\x84\x92"] = BPMF::X;
|
||||||
|
characterToComponent["\xe3\x84\x93"] = BPMF::ZH;
|
||||||
|
characterToComponent["\xe3\x84\x94"] = BPMF::CH;
|
||||||
|
characterToComponent["\xe3\x84\x95"] = BPMF::SH;
|
||||||
|
characterToComponent["\xe3\x84\x96"] = BPMF::R;
|
||||||
|
characterToComponent["\xe3\x84\x97"] = BPMF::Z;
|
||||||
|
characterToComponent["\xe3\x84\x98"] = BPMF::C;
|
||||||
|
characterToComponent["\xe3\x84\x99"] = BPMF::S;
|
||||||
|
characterToComponent["\xe3\x84\xa7"] = BPMF::I;
|
||||||
|
characterToComponent["\xe3\x84\xa8"] = BPMF::U;
|
||||||
|
characterToComponent["\xe3\x84\xa9"] = BPMF::UE;
|
||||||
|
characterToComponent["\xe3\x84\x9a"] = BPMF::A;
|
||||||
|
characterToComponent["\xe3\x84\x9b"] = BPMF::O;
|
||||||
|
characterToComponent["\xe3\x84\x9c"] = BPMF::ER;
|
||||||
|
characterToComponent["\xe3\x84\x9d"] = BPMF::E;
|
||||||
|
characterToComponent["\xe3\x84\x9e"] = BPMF::AI;
|
||||||
|
characterToComponent["\xe3\x84\x9f"] = BPMF::EI;
|
||||||
|
characterToComponent["\xe3\x84\xa0"] = BPMF::AO;
|
||||||
|
characterToComponent["\xe3\x84\xa1"] = BPMF::OU;
|
||||||
|
characterToComponent["\xe3\x84\xa2"] = BPMF::AN;
|
||||||
|
characterToComponent["\xe3\x84\xa3"] = BPMF::EN;
|
||||||
|
characterToComponent["\xe3\x84\xa4"] = BPMF::ANG;
|
||||||
|
characterToComponent["\xe3\x84\xa5"] = BPMF::ENG;
|
||||||
|
characterToComponent["\xe3\x84\xa6"] = BPMF::ERR;
|
||||||
|
characterToComponent["\xcb\x8a"] = BPMF::Tone2;
|
||||||
|
characterToComponent["\xcb\x87"] = BPMF::Tone3;
|
||||||
|
characterToComponent["\xcb\x8b"] = BPMF::Tone4;
|
||||||
|
characterToComponent["\xcb\x99"] = BPMF::Tone5;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (map<string, BPMF::Component>::iterator iter = characterToComponent.begin() ; iter != characterToComponent.end() ; ++iter)
|
||||||
|
componentToCharacter[(*iter).second] = (*iter).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::c_StandardLayout = 0;
|
||||||
|
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::c_ETenLayout = 0;
|
||||||
|
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::c_HsuLayout = 0;
|
||||||
|
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::c_ETen26Layout = 0;
|
||||||
|
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::c_HanyuPinyinLayout = 0;
|
||||||
|
|
||||||
|
void BopomofoKeyboardLayout::FinalizeLayouts()
|
||||||
|
{
|
||||||
|
#define FL(x) if (x) { delete x; } x = 0
|
||||||
|
FL(c_StandardLayout);
|
||||||
|
FL(c_ETen26Layout);
|
||||||
|
FL(c_HsuLayout);
|
||||||
|
FL(c_ETen26Layout);
|
||||||
|
FL(c_HanyuPinyinLayout);
|
||||||
|
#undef FL
|
||||||
|
}
|
||||||
|
|
||||||
|
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::LayoutForName(const string& name)
|
||||||
|
{
|
||||||
|
if (OVWildcard::Match(name, "standard"))
|
||||||
|
return StandardLayout();
|
||||||
|
|
||||||
|
if (OVWildcard::Match(name, "eten"))
|
||||||
|
return ETenLayout();
|
||||||
|
|
||||||
|
if (OVWildcard::Match(name, "hsu"))
|
||||||
|
return HsuLayout();
|
||||||
|
|
||||||
|
if (OVWildcard::Match(name, "eten26"))
|
||||||
|
return ETen26Layout();
|
||||||
|
|
||||||
|
if (OVWildcard::Match(name, "hanyupinyin") || OVWildcard::Match(name, "hanyu pinyin") || OVWildcard::Match(name, "hanyu-pinyin") || OVWildcard::Match(name, "pinyin"))
|
||||||
|
return HanyuPinyinLayout();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASSIGNKEY1(m, vec, k, val) m[k] = (vec.clear(), vec.push_back((BPMF::Component)val), vec)
|
||||||
|
#define ASSIGNKEY2(m, vec, k, val1, val2) m[k] = (vec.clear(), vec.push_back((BPMF::Component)val1), vec.push_back((BPMF::Component)val2), vec)
|
||||||
|
#define ASSIGNKEY3(m, vec, k, val1, val2, val3) m[k] = (vec.clear(), vec.push_back((BPMF::Component)val1), vec.push_back((BPMF::Component)val2), vec.push_back((BPMF::Component)val3), vec)
|
||||||
|
|
||||||
|
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::StandardLayout()
|
||||||
|
{
|
||||||
|
if (!c_StandardLayout) {
|
||||||
|
vector<BPMF::Component> vec;
|
||||||
|
BopomofoKeyToComponentMap ktcm;
|
||||||
|
|
||||||
|
ASSIGNKEY1(ktcm, vec, '1', BPMF::B);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'q', BPMF::P);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'a', BPMF::M);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'z', BPMF::F);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '2', BPMF::D);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'w', BPMF::T);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 's', BPMF::N);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'x', BPMF::L);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'e', BPMF::G);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'd', BPMF::K);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'c', BPMF::H);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'r', BPMF::J);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'f', BPMF::Q);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'v', BPMF::X);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '5', BPMF::ZH);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 't', BPMF::CH);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'g', BPMF::SH);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'b', BPMF::R);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'y', BPMF::Z);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'h', BPMF::C);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'n', BPMF::S);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'u', BPMF::I);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'j', BPMF::U);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'm', BPMF::UE);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '8', BPMF::A);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'i', BPMF::O);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'k', BPMF::ER);
|
||||||
|
ASSIGNKEY1(ktcm, vec, ',', BPMF::E);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '9', BPMF::AI);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'o', BPMF::EI);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'l', BPMF::AO);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '.', BPMF::OU);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '0', BPMF::AN);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'p', BPMF::EN);
|
||||||
|
ASSIGNKEY1(ktcm, vec, ';', BPMF::ANG);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '/', BPMF::ENG);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '-', BPMF::ERR);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '3', BPMF::Tone3);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '4', BPMF::Tone4);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '6', BPMF::Tone2);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '7', BPMF::Tone5);
|
||||||
|
|
||||||
|
c_StandardLayout = new BopomofoKeyboardLayout(ktcm, "Standard");
|
||||||
|
}
|
||||||
|
|
||||||
|
return c_StandardLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::ETenLayout()
|
||||||
|
{
|
||||||
|
if (!c_ETenLayout) {
|
||||||
|
vector<BPMF::Component> vec;
|
||||||
|
BopomofoKeyToComponentMap ktcm;
|
||||||
|
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'b', BPMF::B);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'p', BPMF::P);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'm', BPMF::M);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'f', BPMF::F);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'd', BPMF::D);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 't', BPMF::T);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'n', BPMF::N);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'l', BPMF::L);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'v', BPMF::G);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'k', BPMF::K);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'h', BPMF::H);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'g', BPMF::J);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '7', BPMF::Q);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'c', BPMF::X);
|
||||||
|
ASSIGNKEY1(ktcm, vec, ',', BPMF::ZH);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '.', BPMF::CH);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '/', BPMF::SH);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'j', BPMF::R);
|
||||||
|
ASSIGNKEY1(ktcm, vec, ';', BPMF::Z);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '\'', BPMF::C);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 's', BPMF::S);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'e', BPMF::I);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'x', BPMF::U);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'u', BPMF::UE);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'a', BPMF::A);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'o', BPMF::O);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'r', BPMF::ER);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'w', BPMF::E);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'i', BPMF::AI);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'q', BPMF::EI);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'z', BPMF::AO);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'y', BPMF::OU);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '8', BPMF::AN);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '9', BPMF::EN);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '0', BPMF::ANG);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '-', BPMF::ENG);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '=', BPMF::ERR);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '2', BPMF::Tone2);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '3', BPMF::Tone3);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '4', BPMF::Tone4);
|
||||||
|
ASSIGNKEY1(ktcm, vec, '1', BPMF::Tone5);
|
||||||
|
|
||||||
|
c_ETenLayout = new BopomofoKeyboardLayout(ktcm, "ETen");
|
||||||
|
}
|
||||||
|
|
||||||
|
return c_ETenLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::HsuLayout()
|
||||||
|
{
|
||||||
|
if (!c_HsuLayout) {
|
||||||
|
vector<BPMF::Component> vec;
|
||||||
|
BopomofoKeyToComponentMap ktcm;
|
||||||
|
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'b', BPMF::B);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'p', BPMF::P);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'm', BPMF::M, BPMF::AN);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'f', BPMF::F, BPMF::Tone3);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'd', BPMF::D, BPMF::Tone2);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 't', BPMF::T);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'n', BPMF::N, BPMF::EN);
|
||||||
|
ASSIGNKEY3(ktcm, vec, 'l', BPMF::L, BPMF::ENG, BPMF::ERR);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'g', BPMF::G, BPMF::ER);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'k', BPMF::K, BPMF::ANG);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'h', BPMF::H, BPMF::O);
|
||||||
|
ASSIGNKEY3(ktcm, vec, 'j', BPMF::J, BPMF::ZH, BPMF::Tone4);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'v', BPMF::Q, BPMF::CH);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'c', BPMF::X, BPMF::SH);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'r', BPMF::R);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'z', BPMF::Z);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'a', BPMF::C, BPMF::EI);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 's', BPMF::S, BPMF::Tone5);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'e', BPMF::I, BPMF::E);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'x', BPMF::U);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'u', BPMF::UE);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'y', BPMF::A);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'i', BPMF::AI);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'w', BPMF::AO);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'o', BPMF::OU);
|
||||||
|
|
||||||
|
c_HsuLayout = new BopomofoKeyboardLayout(ktcm, "Hsu");
|
||||||
|
}
|
||||||
|
|
||||||
|
return c_HsuLayout;
|
||||||
|
}
|
||||||
|
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::ETen26Layout()
|
||||||
|
{
|
||||||
|
if (!c_ETen26Layout) {
|
||||||
|
vector<BPMF::Component> vec;
|
||||||
|
BopomofoKeyToComponentMap ktcm;
|
||||||
|
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'b', BPMF::B);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'p', BPMF::P, BPMF::OU);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'm', BPMF::M, BPMF::AN);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'f', BPMF::F, BPMF::Tone2);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'd', BPMF::D, BPMF::Tone5);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 't', BPMF::T, BPMF::ANG);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'n', BPMF::N, BPMF::EN);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'l', BPMF::L, BPMF::ENG);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'v', BPMF::G, BPMF::Q);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'k', BPMF::K, BPMF::Tone4);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'h', BPMF::H, BPMF::ERR);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'g', BPMF::ZH, BPMF::J);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'c', BPMF::SH, BPMF::X);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'y', BPMF::CH);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'j', BPMF::R, BPMF::Tone3);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'q', BPMF::Z, BPMF::EI);
|
||||||
|
ASSIGNKEY2(ktcm, vec, 'w', BPMF::C, BPMF::E);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 's', BPMF::S);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'e', BPMF::I);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'x', BPMF::U);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'u', BPMF::UE);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'a', BPMF::A);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'o', BPMF::O);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'r', BPMF::ER);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'i', BPMF::AI);
|
||||||
|
ASSIGNKEY1(ktcm, vec, 'z', BPMF::AO);
|
||||||
|
|
||||||
|
c_ETen26Layout = new BopomofoKeyboardLayout(ktcm, "ETen26");
|
||||||
|
}
|
||||||
|
|
||||||
|
return c_ETen26Layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::HanyuPinyinLayout()
|
||||||
|
{
|
||||||
|
if (!c_HanyuPinyinLayout) {
|
||||||
|
BopomofoKeyToComponentMap ktcm;
|
||||||
|
c_HanyuPinyinLayout = new BopomofoKeyboardLayout(ktcm, "HanyuPinyin");
|
||||||
|
}
|
||||||
|
return c_HanyuPinyinLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace Mandarin
|
||||||
|
} // namespace Formosa
|
|
@ -0,0 +1,605 @@
|
||||||
|
//
|
||||||
|
// Mandarin.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2006-2010 Lukhnos D. Liu (http://lukhnos.org)
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef Mandarin_h
|
||||||
|
#define Mandarin_h
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace Formosa {
|
||||||
|
namespace Mandarin {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class BopomofoSyllable {
|
||||||
|
public:
|
||||||
|
typedef unsigned int Component;
|
||||||
|
BopomofoSyllable(Component syllable = 0)
|
||||||
|
: m_syllable(syllable)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BopomofoSyllable(const BopomofoSyllable& another)
|
||||||
|
: m_syllable(another.m_syllable)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~BopomofoSyllable()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BopomofoSyllable& operator=(const BopomofoSyllable& another)
|
||||||
|
{
|
||||||
|
m_syllable = another.m_syllable;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// takes the ASCII-form, "v"-tolerant, TW-style Hanyu Pinyin (fong, pong, bong acceptable)
|
||||||
|
static const BopomofoSyllable FromHanyuPinyin(const string& str);
|
||||||
|
|
||||||
|
// TO DO: Support accented vowels
|
||||||
|
const string HanyuPinyinString(bool includesTone, bool useVForUUmlaut) const;
|
||||||
|
// const string HanyuPinyinString(bool includesTone, bool useVForUUmlaut, bool composeAccentedVowel) const;
|
||||||
|
|
||||||
|
// PHT = Pai-hua-tsi
|
||||||
|
static const BopomofoSyllable FromPHT(const string& str);
|
||||||
|
const string PHTString(bool includesTone) const;
|
||||||
|
|
||||||
|
static const BopomofoSyllable FromComposedString(const string& str);
|
||||||
|
const string composedString() const;
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
m_syllable = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEmpty() const
|
||||||
|
{
|
||||||
|
return !m_syllable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasConsonant() const
|
||||||
|
{
|
||||||
|
return !!(m_syllable & ConsonantMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasMiddleVowel() const
|
||||||
|
{
|
||||||
|
return !!(m_syllable & MiddleVowelMask);
|
||||||
|
}
|
||||||
|
bool hasVowel() const
|
||||||
|
{
|
||||||
|
return !!(m_syllable & VowelMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasToneMarker() const
|
||||||
|
{
|
||||||
|
return !!(m_syllable & ToneMarkerMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
Component consonantComponent() const
|
||||||
|
{
|
||||||
|
return m_syllable & ConsonantMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
Component middleVowelComponent() const
|
||||||
|
{
|
||||||
|
return m_syllable & MiddleVowelMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
Component vowelComponent() const
|
||||||
|
{
|
||||||
|
return m_syllable & VowelMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
Component toneMarkerComponent() const
|
||||||
|
{
|
||||||
|
return m_syllable & ToneMarkerMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const BopomofoSyllable& another) const
|
||||||
|
{
|
||||||
|
return m_syllable == another.m_syllable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const BopomofoSyllable& another) const
|
||||||
|
{
|
||||||
|
return m_syllable != another.m_syllable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isOverlappingWith(const BopomofoSyllable& another) const
|
||||||
|
{
|
||||||
|
#define IOW_SAND(mask) ((m_syllable & mask) && (another.m_syllable & mask))
|
||||||
|
return IOW_SAND(ConsonantMask) || IOW_SAND(MiddleVowelMask) || IOW_SAND(VowelMask) || IOW_SAND(ToneMarkerMask);
|
||||||
|
#undef IOW_SAND
|
||||||
|
}
|
||||||
|
|
||||||
|
// consonants J, Q, X all require the existence of vowel I or UE
|
||||||
|
bool belongsToJQXClass() const
|
||||||
|
{
|
||||||
|
Component consonant = m_syllable & ConsonantMask;
|
||||||
|
return (consonant == J || consonant == Q || consonant == X);
|
||||||
|
}
|
||||||
|
|
||||||
|
// zi, ci, si, chi, chi, shi, ri
|
||||||
|
bool belongsToZCSRClass() const
|
||||||
|
{
|
||||||
|
Component consonant = m_syllable & ConsonantMask;
|
||||||
|
return (consonant >= ZH && consonant <= S);
|
||||||
|
}
|
||||||
|
|
||||||
|
Component maskType() const
|
||||||
|
{
|
||||||
|
Component mask = 0;
|
||||||
|
mask |= (m_syllable & ConsonantMask) ? ConsonantMask : 0;
|
||||||
|
mask |= (m_syllable & MiddleVowelMask) ? MiddleVowelMask : 0;
|
||||||
|
mask |= (m_syllable & VowelMask) ? VowelMask : 0;
|
||||||
|
mask |= (m_syllable & ToneMarkerMask) ? ToneMarkerMask : 0;
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BopomofoSyllable operator+(const BopomofoSyllable& another) const
|
||||||
|
{
|
||||||
|
Component newSyllable = m_syllable;
|
||||||
|
#define OP_SOVER(mask) if (another.m_syllable & mask) newSyllable = (newSyllable & ~mask) | (another.m_syllable & mask)
|
||||||
|
OP_SOVER(ConsonantMask);
|
||||||
|
OP_SOVER(MiddleVowelMask);
|
||||||
|
OP_SOVER(VowelMask);
|
||||||
|
OP_SOVER(ToneMarkerMask);
|
||||||
|
#undef OP_SOVER
|
||||||
|
return BopomofoSyllable(newSyllable);
|
||||||
|
}
|
||||||
|
|
||||||
|
BopomofoSyllable& operator+=(const BopomofoSyllable& another)
|
||||||
|
{
|
||||||
|
#define OPE_SOVER(mask) if (another.m_syllable & mask) m_syllable = (m_syllable & ~mask) | (another.m_syllable & mask)
|
||||||
|
OPE_SOVER(ConsonantMask);
|
||||||
|
OPE_SOVER(MiddleVowelMask);
|
||||||
|
OPE_SOVER(VowelMask);
|
||||||
|
OPE_SOVER(ToneMarkerMask);
|
||||||
|
#undef OPE_SOVER
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
short absoluteOrder() const
|
||||||
|
{
|
||||||
|
// turn BPMF syllable into a 4*14*4*22 number
|
||||||
|
return (short)(m_syllable & ConsonantMask) +
|
||||||
|
(short)((m_syllable & MiddleVowelMask) >> 5) * 22 +
|
||||||
|
(short)((m_syllable & VowelMask) >> 7) * 22 * 4 +
|
||||||
|
(short)((m_syllable & ToneMarkerMask) >> 11) * 22 * 4 * 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string absoluteOrderString() const
|
||||||
|
{
|
||||||
|
// 5*14*4*22 = 6160, we use a 79*79 encoding to represent that
|
||||||
|
short order = absoluteOrder();
|
||||||
|
char low = 48 + (char)(order % 79);
|
||||||
|
char high = 48 + (char)(order / 79);
|
||||||
|
string result(2, ' ');
|
||||||
|
result[0] = low;
|
||||||
|
result[1] = high;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BopomofoSyllable FromAbsoluteOrder(short order)
|
||||||
|
{
|
||||||
|
return BopomofoSyllable(
|
||||||
|
(order % 22) |
|
||||||
|
((order / 22) % 4) << 5 |
|
||||||
|
((order / (22 * 4)) % 14) << 7 |
|
||||||
|
((order / (22 * 4 * 14)) % 5) << 11
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BopomofoSyllable FromAbsoluteOrderString(const string& str)
|
||||||
|
{
|
||||||
|
if (str.length() != 2)
|
||||||
|
return BopomofoSyllable();
|
||||||
|
|
||||||
|
return FromAbsoluteOrder((short)(str[1] - 48) * 79 + (short)(str[0] - 48));
|
||||||
|
}
|
||||||
|
|
||||||
|
friend ostream& operator<<(ostream& stream, const BopomofoSyllable& syllable);
|
||||||
|
|
||||||
|
static const Component
|
||||||
|
ConsonantMask = 0x001f, // 0000 0000 0001 1111, 21 consonants
|
||||||
|
MiddleVowelMask = 0x0060, // 0000 0000 0110 0000, 3 middle vowels
|
||||||
|
VowelMask = 0x0780, // 0000 0111 1000 0000, 13 vowels
|
||||||
|
ToneMarkerMask = 0x3800, // 0011 1000 0000 0000, 5 tones (tone1 = 0x00)
|
||||||
|
B = 0x0001, P = 0x0002, M = 0x0003, F = 0x0004,
|
||||||
|
D = 0x0005, T = 0x0006, N = 0x0007, L = 0x0008,
|
||||||
|
G = 0x0009, K = 0x000a, H = 0x000b,
|
||||||
|
J = 0x000c, Q = 0x000d, X = 0x000e,
|
||||||
|
ZH = 0x000f, CH = 0x0010, SH = 0x0011, R = 0x0012,
|
||||||
|
Z = 0x0013, C = 0x0014, S = 0x0015,
|
||||||
|
I = 0x0020, U = 0x0040, UE = 0x0060, // ue = u umlaut (we use the German convention here as an ersatz to the /ju:/ sound)
|
||||||
|
A = 0x0080, O = 0x0100, ER = 0x0180, E = 0x0200,
|
||||||
|
AI = 0x0280, EI = 0x0300, AO = 0x0380, OU = 0x0400,
|
||||||
|
AN = 0x0480, EN = 0x0500, ANG = 0x0580, ENG = 0x0600,
|
||||||
|
ERR = 0x0680,
|
||||||
|
Tone1 = 0x0000, Tone2 = 0x0800, Tone3 = 0x1000, Tone4 = 0x1800, Tone5 = 0x2000;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Component m_syllable;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline ostream& operator<<(ostream& stream, const BopomofoSyllable& syllable)
|
||||||
|
{
|
||||||
|
stream << syllable.composedString();
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef BopomofoSyllable BPMF;
|
||||||
|
|
||||||
|
typedef map<char, vector<BPMF::Component> > BopomofoKeyToComponentMap;
|
||||||
|
typedef map<BPMF::Component, char> BopomofoComponentToKeyMap;
|
||||||
|
|
||||||
|
class BopomofoKeyboardLayout {
|
||||||
|
public:
|
||||||
|
static void FinalizeLayouts();
|
||||||
|
static const BopomofoKeyboardLayout* StandardLayout();
|
||||||
|
static const BopomofoKeyboardLayout* ETenLayout();
|
||||||
|
static const BopomofoKeyboardLayout* HsuLayout();
|
||||||
|
static const BopomofoKeyboardLayout* ETen26Layout();
|
||||||
|
static const BopomofoKeyboardLayout* HanyuPinyinLayout();
|
||||||
|
|
||||||
|
// recognizes (case-insensitive): standard, eten, hsu, eten26
|
||||||
|
static const BopomofoKeyboardLayout* LayoutForName(const string& name);
|
||||||
|
|
||||||
|
BopomofoKeyboardLayout(const BopomofoKeyToComponentMap& ktcm, const string& name)
|
||||||
|
: m_keyToComponent(ktcm)
|
||||||
|
, m_name(name)
|
||||||
|
{
|
||||||
|
for (BopomofoKeyToComponentMap::const_iterator miter = m_keyToComponent.begin() ; miter != m_keyToComponent.end() ; ++miter)
|
||||||
|
for (vector<BPMF::Component>::const_iterator viter = (*miter).second.begin() ; viter != (*miter).second.end() ; ++viter)
|
||||||
|
m_componentToKey[*viter] = (*miter).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string name() const
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
char componentToKey(BPMF::Component component) const
|
||||||
|
{
|
||||||
|
BopomofoComponentToKeyMap::const_iterator iter = m_componentToKey.find(component);
|
||||||
|
return (iter == m_componentToKey.end()) ? 0 : (*iter).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
const vector<BPMF::Component> keyToComponents(char key) const
|
||||||
|
{
|
||||||
|
BopomofoKeyToComponentMap::const_iterator iter = m_keyToComponent.find(key);
|
||||||
|
return (iter == m_keyToComponent.end()) ? vector<BPMF::Component>() : (*iter).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string keySequenceFromSyllable(BPMF syllable) const
|
||||||
|
{
|
||||||
|
string sequence;
|
||||||
|
|
||||||
|
BPMF::Component c;
|
||||||
|
char k;
|
||||||
|
#define STKS_COMBINE(component) if ((c = component)) { if ((k = componentToKey(c))) sequence += string(1, k); }
|
||||||
|
STKS_COMBINE(syllable.consonantComponent());
|
||||||
|
STKS_COMBINE(syllable.middleVowelComponent());
|
||||||
|
STKS_COMBINE(syllable.vowelComponent());
|
||||||
|
STKS_COMBINE(syllable.toneMarkerComponent());
|
||||||
|
#undef STKS_COMBINE
|
||||||
|
return sequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BPMF syllableFromKeySequence(const string& sequence) const
|
||||||
|
{
|
||||||
|
BPMF syllable;
|
||||||
|
|
||||||
|
for (string::const_iterator iter = sequence.begin() ; iter != sequence.end() ; ++iter)
|
||||||
|
{
|
||||||
|
bool beforeSeqHasIorUE = sequenceContainsIorUE(sequence.begin(), iter);
|
||||||
|
bool aheadSeqHasIorUE = sequenceContainsIorUE(iter + 1, sequence.end());
|
||||||
|
|
||||||
|
vector<BPMF::Component> components = keyToComponents(*iter);
|
||||||
|
|
||||||
|
if (!components.size())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (components.size() == 1) {
|
||||||
|
syllable += BPMF(components[0]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
BPMF head = BPMF(components[0]);
|
||||||
|
BPMF follow = BPMF(components[1]);
|
||||||
|
BPMF ending = components.size() > 2 ? BPMF(components[2]) : follow;
|
||||||
|
|
||||||
|
// apply the I/UE + E rule
|
||||||
|
if (head.vowelComponent() == BPMF::E && follow.vowelComponent() != BPMF::E)
|
||||||
|
{
|
||||||
|
syllable += beforeSeqHasIorUE ? head : follow;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (head.vowelComponent() != BPMF::E && follow.vowelComponent() == BPMF::E)
|
||||||
|
{
|
||||||
|
syllable += beforeSeqHasIorUE ? follow : head;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply the J/Q/X + I/UE rule, only two components are allowed in the components vector here
|
||||||
|
if (head.belongsToJQXClass() && !follow.belongsToJQXClass()) {
|
||||||
|
if (!syllable.isEmpty()) {
|
||||||
|
if (ending != follow)
|
||||||
|
syllable += ending;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
syllable += aheadSeqHasIorUE ? head : follow;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!head.belongsToJQXClass() && follow.belongsToJQXClass()) {
|
||||||
|
if (!syllable.isEmpty()) {
|
||||||
|
if (ending != follow)
|
||||||
|
syllable += ending;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
syllable += aheadSeqHasIorUE ? follow : head;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the nasty issue of only one char in the buffer
|
||||||
|
if (iter == sequence.begin() && iter + 1 == sequence.end()) {
|
||||||
|
if (head.hasVowel() || follow.hasToneMarker() || head.belongsToZCSRClass())
|
||||||
|
syllable += head;
|
||||||
|
else {
|
||||||
|
if (follow.hasVowel() || ending.hasToneMarker())
|
||||||
|
syllable += follow;
|
||||||
|
else
|
||||||
|
syllable += ending;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(syllable.maskType() & head.maskType()) && !endAheadOrAheadHasToneMarkKey(iter + 1, sequence.end())) {
|
||||||
|
syllable += head;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (endAheadOrAheadHasToneMarkKey(iter + 1, sequence.end()) && head.belongsToZCSRClass() && syllable.isEmpty()) {
|
||||||
|
syllable += head;
|
||||||
|
}
|
||||||
|
else if (syllable.maskType() < follow.maskType()) {
|
||||||
|
syllable += follow;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
syllable += ending;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// heuristics for Hsu keyboard layout
|
||||||
|
if (this == HsuLayout()) {
|
||||||
|
// fix the left out L to ERR when it has sound, and GI, GUE -> JI, JUE
|
||||||
|
if (syllable.vowelComponent() == BPMF::ENG && !syllable.hasConsonant() && !syllable.hasMiddleVowel()) {
|
||||||
|
syllable += BPMF(BPMF::ERR);
|
||||||
|
}
|
||||||
|
else if (syllable.consonantComponent() == BPMF::G && (syllable.middleVowelComponent() == BPMF::I || syllable.middleVowelComponent() == BPMF::UE)) {
|
||||||
|
syllable += BPMF(BPMF::J);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return syllable;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool endAheadOrAheadHasToneMarkKey(string::const_iterator ahead, string::const_iterator end) const
|
||||||
|
{
|
||||||
|
if (ahead == end)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
char tone1 = componentToKey(BPMF::Tone1);
|
||||||
|
char tone2 = componentToKey(BPMF::Tone2);
|
||||||
|
char tone3 = componentToKey(BPMF::Tone3);
|
||||||
|
char tone4 = componentToKey(BPMF::Tone4);
|
||||||
|
char tone5 = componentToKey(BPMF::Tone5);
|
||||||
|
|
||||||
|
if (tone1)
|
||||||
|
if (*ahead == tone1) return true;
|
||||||
|
|
||||||
|
if (*ahead == tone2 || *ahead == tone3 || *ahead == tone4 || *ahead == tone5)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sequenceContainsIorUE(string::const_iterator start, string::const_iterator end) const
|
||||||
|
{
|
||||||
|
char iChar = componentToKey(BPMF::I);
|
||||||
|
char ueChar = componentToKey(BPMF::UE);
|
||||||
|
|
||||||
|
for (; start != end; ++start)
|
||||||
|
if (*start == iChar || *start == ueChar)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string m_name;
|
||||||
|
BopomofoKeyToComponentMap m_keyToComponent;
|
||||||
|
BopomofoComponentToKeyMap m_componentToKey;
|
||||||
|
|
||||||
|
static const BopomofoKeyboardLayout* c_StandardLayout;
|
||||||
|
static const BopomofoKeyboardLayout* c_ETenLayout;
|
||||||
|
static const BopomofoKeyboardLayout* c_HsuLayout;
|
||||||
|
static const BopomofoKeyboardLayout* c_ETen26Layout;
|
||||||
|
|
||||||
|
// this is essentially an empty layout, but we use pointer semantic to tell the differences--and pass on the responsibility to BopomofoReadingBuffer
|
||||||
|
static const BopomofoKeyboardLayout* c_HanyuPinyinLayout;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BopomofoReadingBuffer {
|
||||||
|
public:
|
||||||
|
BopomofoReadingBuffer(const BopomofoKeyboardLayout* layout)
|
||||||
|
: m_layout(layout)
|
||||||
|
, m_pinyinMode(false)
|
||||||
|
{
|
||||||
|
if (layout == BopomofoKeyboardLayout::HanyuPinyinLayout()) {
|
||||||
|
m_pinyinMode = true;
|
||||||
|
m_pinyinSequence = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setKeyboardLayout(const BopomofoKeyboardLayout* layout)
|
||||||
|
{
|
||||||
|
m_layout = layout;
|
||||||
|
|
||||||
|
if (layout == BopomofoKeyboardLayout::HanyuPinyinLayout()) {
|
||||||
|
m_pinyinMode = true;
|
||||||
|
m_pinyinSequence = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isValidKey(char k) const
|
||||||
|
{
|
||||||
|
if (!m_pinyinMode) {
|
||||||
|
return m_layout ? (m_layout->keyToComponents(k)).size() > 0 : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char lk = tolower(k);
|
||||||
|
if (lk >= 'a' && lk <= 'z') {
|
||||||
|
// if a tone marker is already in place
|
||||||
|
if (m_pinyinSequence.length()) {
|
||||||
|
char lastc = m_pinyinSequence[m_pinyinSequence.length() - 1];
|
||||||
|
if (lastc >= '2' && lastc <= '5') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_pinyinSequence.length() && (lk >= '2' && lk <= '5')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool combineKey(char k)
|
||||||
|
{
|
||||||
|
if (!isValidKey(k))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (m_pinyinMode) {
|
||||||
|
m_pinyinSequence += string(1, tolower(k));
|
||||||
|
m_syllable = BPMF::FromHanyuPinyin(m_pinyinSequence);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
string sequence = m_layout->keySequenceFromSyllable(m_syllable) + string(1, k);
|
||||||
|
m_syllable = m_layout->syllableFromKeySequence(sequence);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
m_pinyinSequence.clear();
|
||||||
|
m_syllable.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void backspace()
|
||||||
|
{
|
||||||
|
if (!m_layout)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_pinyinMode) {
|
||||||
|
if (m_pinyinSequence.length()) {
|
||||||
|
m_pinyinSequence = m_pinyinSequence.substr(0, m_pinyinSequence.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_syllable = BPMF::FromHanyuPinyin(m_pinyinSequence);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string sequence = m_layout->keySequenceFromSyllable(m_syllable);
|
||||||
|
if (sequence.length()) {
|
||||||
|
sequence = sequence.substr(0, sequence.length() - 1);
|
||||||
|
m_syllable = m_layout->syllableFromKeySequence(sequence);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEmpty() const
|
||||||
|
{
|
||||||
|
return m_syllable.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
const string composedString() const
|
||||||
|
{
|
||||||
|
if (m_pinyinMode) {
|
||||||
|
return m_pinyinSequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_syllable.composedString();
|
||||||
|
}
|
||||||
|
|
||||||
|
const BPMF syllable() const
|
||||||
|
{
|
||||||
|
return m_syllable;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string standardLayoutQueryString() const
|
||||||
|
{
|
||||||
|
return BopomofoKeyboardLayout::StandardLayout()->keySequenceFromSyllable(m_syllable);
|
||||||
|
}
|
||||||
|
|
||||||
|
const string absoluteOrderQueryString() const
|
||||||
|
{
|
||||||
|
return m_syllable.absoluteOrderString();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasToneMarker() const
|
||||||
|
{
|
||||||
|
return m_syllable.hasToneMarker();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const BopomofoKeyboardLayout* m_layout;
|
||||||
|
BPMF m_syllable;
|
||||||
|
|
||||||
|
bool m_pinyinMode;
|
||||||
|
string m_pinyinSequence;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,49 @@
|
||||||
|
//
|
||||||
|
// OVAroundFilter.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVAroundFilter_h
|
||||||
|
#define OVAroundFilter_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVModule.h>
|
||||||
|
#else
|
||||||
|
#include "OVModule.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVAroundFilter : public OVModule {
|
||||||
|
public:
|
||||||
|
virtual bool isAroundFilter() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,46 @@
|
||||||
|
//
|
||||||
|
// OVBase.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVBase_h
|
||||||
|
#define OVBase_h
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVBase {
|
||||||
|
public:
|
||||||
|
virtual ~OVBase()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,102 @@
|
||||||
|
//
|
||||||
|
// OVBenchmark.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVBenchmark_h
|
||||||
|
#define OVBenchmark_h
|
||||||
|
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVBenchmark
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OVBenchmark()
|
||||||
|
: m_used(false)
|
||||||
|
, m_running(false)
|
||||||
|
, m_start(0)
|
||||||
|
, m_elapsedTicks(0)
|
||||||
|
, m_elapsedSeconds(0.0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void start()
|
||||||
|
{
|
||||||
|
m_used = true;
|
||||||
|
m_running = true;
|
||||||
|
m_elapsedSeconds = 0.0;
|
||||||
|
m_elapsedTicks = 0;
|
||||||
|
m_start = clock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop()
|
||||||
|
{
|
||||||
|
if (m_running) {
|
||||||
|
update();
|
||||||
|
m_running = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clock_t elapsedTicks()
|
||||||
|
{
|
||||||
|
if (!m_used)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (m_running)
|
||||||
|
update();
|
||||||
|
|
||||||
|
return m_elapsedTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
double elapsedSeconds()
|
||||||
|
{
|
||||||
|
if (!m_used)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (m_running)
|
||||||
|
update();
|
||||||
|
|
||||||
|
return m_elapsedSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void update()
|
||||||
|
{
|
||||||
|
m_elapsedTicks = clock() - m_start;
|
||||||
|
m_elapsedSeconds = static_cast<double>(m_elapsedTicks) / CLOCKS_PER_SEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool m_used;
|
||||||
|
bool m_running;
|
||||||
|
clock_t m_start;
|
||||||
|
clock_t m_elapsedTicks;
|
||||||
|
double m_elapsedSeconds;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,806 @@
|
||||||
|
//
|
||||||
|
// OVCINDataTable.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVCINDataTable_h
|
||||||
|
#define OVCINDataTable_h
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "OVFileHelper.h"
|
||||||
|
#include "OVUTF8Helper.h"
|
||||||
|
#include "OVWildcard.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// CIN := (COMMENT | PROPERTY | KEYNAME | CHARDEF)*
|
||||||
|
// EOL := \n|\r
|
||||||
|
// COMMENT := ^#.*(EOL)
|
||||||
|
// KEY := \w+
|
||||||
|
// VALUE := \w([\w\s]*\w)*
|
||||||
|
// PROPERTY: ^%(KEY)\s+(VALUE)(EOL)
|
||||||
|
// KEYNAME :=
|
||||||
|
// ^%keyname\s+begin(EOL)
|
||||||
|
// ^(KEY)\s+(VALUE)(EOL)
|
||||||
|
// ^%keyname\s+end(EOL)
|
||||||
|
// CHARDEF:
|
||||||
|
// ^%chardef\s+begin(EOL)
|
||||||
|
// ^(KEY)\s+(VALUE)(EOL)
|
||||||
|
// ^%chardef\s+end(EOL)
|
||||||
|
|
||||||
|
class OVCINDataTableParser;
|
||||||
|
|
||||||
|
class OVFastKeyValuePairMap {
|
||||||
|
public:
|
||||||
|
~OVFastKeyValuePairMap()
|
||||||
|
{
|
||||||
|
free(m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size()
|
||||||
|
{
|
||||||
|
return m_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
pair<string, string> keyValuePairAtIndex(size_t index)
|
||||||
|
{
|
||||||
|
if (index >= m_index)
|
||||||
|
return pair<string, string>();
|
||||||
|
|
||||||
|
KVPair* entry = m_data + index;
|
||||||
|
return pair<string, string>(entry->key, entry->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<pair<string, string> > findPairsWithKey(const char* key)
|
||||||
|
{
|
||||||
|
return fetchValuesFromIndex(findFirstOccuranceOfKey(key), key);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<pair<string, string> > findPairsWithWildcard(const OVWildcard& pWildcard)
|
||||||
|
{
|
||||||
|
const OVWildcard* ptrWildcard = &pWildcard;
|
||||||
|
|
||||||
|
if (pWildcard.isCaseSensitive() != m_caseSensitive) {
|
||||||
|
OVWildcard newWildcard(pWildcard.expression(), pWildcard.matchOneChar(), pWildcard.matchZeroOrMoreChar(), m_caseSensitive);
|
||||||
|
ptrWildcard = &newWildcard;
|
||||||
|
}
|
||||||
|
|
||||||
|
const OVWildcard& wildcard = *ptrWildcard;
|
||||||
|
|
||||||
|
string headString = wildcard.longestHeadMatchString();
|
||||||
|
insensitivizeString(headString);
|
||||||
|
size_t hSLength = headString.length();
|
||||||
|
|
||||||
|
size_t start = findFirstOccuranceOfKey(headString.c_str(), true);
|
||||||
|
vector<pair<string, string> > result;
|
||||||
|
|
||||||
|
for (size_t index = start; index < m_index; index++) {
|
||||||
|
KVPair* entry = m_data + index;
|
||||||
|
string keyString = entry->key;
|
||||||
|
|
||||||
|
// if no more head matchZeroOrMoreChar
|
||||||
|
string keySubstr = keyString.substr(0, hSLength);
|
||||||
|
insensitivizeString(keySubstr);
|
||||||
|
if (keySubstr > headString)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (wildcard.match(keyString))
|
||||||
|
result.push_back(pair<string, string>(keyString, entry->value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
friend class OVCINDataTableParser;
|
||||||
|
|
||||||
|
OVFastKeyValuePairMap(size_t initSize, size_t growSize, bool caseSensitive = false)
|
||||||
|
: m_index(0)
|
||||||
|
, m_size(initSize ? initSize : 1)
|
||||||
|
, m_growSize(growSize)
|
||||||
|
, m_caseSensitive(caseSensitive)
|
||||||
|
{
|
||||||
|
m_data = (KVPair*)calloc(1, sizeof(KVPair) * m_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void add(char* key, char* value)
|
||||||
|
{
|
||||||
|
KVPair* entry = m_data + m_index;
|
||||||
|
entry->key = key;
|
||||||
|
entry->value = value;
|
||||||
|
|
||||||
|
m_index++;
|
||||||
|
if (m_index == m_size)
|
||||||
|
grow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sortAndFreeze()
|
||||||
|
{
|
||||||
|
m_size = m_index;
|
||||||
|
|
||||||
|
if (m_caseSensitive)
|
||||||
|
qsort(m_data, m_index, sizeof(KVPair), OVFastKeyValuePairMap::qsortCompareCaseSensitive);
|
||||||
|
else
|
||||||
|
qsort(m_data, m_index, sizeof(KVPair), OVFastKeyValuePairMap::qsortCompare);
|
||||||
|
}
|
||||||
|
|
||||||
|
void insensitivizeString(string& str)
|
||||||
|
{
|
||||||
|
if (m_caseSensitive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (string::iterator iter = str.begin() ; iter != str.end() ; ++iter)
|
||||||
|
*iter = tolower(*iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
vector<pair<string, string> > fetchValuesFromIndex(size_t start, const char* key)
|
||||||
|
{
|
||||||
|
vector<pair<string, string> > result;
|
||||||
|
for (size_t index = start ; index < m_index; index++) {
|
||||||
|
KVPair* entry = m_data + index;
|
||||||
|
|
||||||
|
if (compareString(entry->key, key) <= 0) {
|
||||||
|
result.push_back(pair<string, string>(entry->key, entry->value));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t findFirstOccuranceOfKey(const char* key, bool closest = false)
|
||||||
|
{
|
||||||
|
if (!m_index)
|
||||||
|
return m_index;
|
||||||
|
|
||||||
|
size_t mid, low = 0, high = m_index - 1;
|
||||||
|
|
||||||
|
while (low <= high) {
|
||||||
|
mid = (low + high) / 2;
|
||||||
|
|
||||||
|
char* entryKey = (m_data + mid)->key;
|
||||||
|
int cmp = compareString(key, entryKey);
|
||||||
|
|
||||||
|
if (!cmp) {
|
||||||
|
if (!mid)
|
||||||
|
return mid;
|
||||||
|
|
||||||
|
size_t oneUp = mid - 1;
|
||||||
|
if (!compareString(key, (m_data + oneUp)->key))
|
||||||
|
high = oneUp;
|
||||||
|
else
|
||||||
|
return mid;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (closest) {
|
||||||
|
if (mid > 0) {
|
||||||
|
if (compareString(key, (m_data + mid - 1)->key) > 0 && compareString(key, entryKey) <= 0)
|
||||||
|
return mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmp < 0) {
|
||||||
|
if (!mid) {
|
||||||
|
if (closest)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return m_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
high = mid - 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (low + 1 >= m_index)
|
||||||
|
return m_index;
|
||||||
|
|
||||||
|
low = mid + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int compareString(const char* a, const char* b)
|
||||||
|
{
|
||||||
|
#ifndef WIN32
|
||||||
|
return m_caseSensitive ? strcmp(a, b) : strcasecmp(a, b);
|
||||||
|
#else
|
||||||
|
return m_caseSensitive ? strcmp(a, b) : _stricmp(a, b);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qsortCompare(const void* a, const void* b)
|
||||||
|
{
|
||||||
|
int cmp;
|
||||||
|
char* aa = ((const KVPair*)a)->key;
|
||||||
|
char* bb = ((const KVPair*)b)->key;
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
if (!(cmp = strcasecmp(aa, bb)))
|
||||||
|
#else
|
||||||
|
if (!(cmp = _stricmp(aa, bb)))
|
||||||
|
#endif
|
||||||
|
return aa == bb ? 0 : (aa > bb ? 1 : -1);
|
||||||
|
else
|
||||||
|
return cmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qsortCompareCaseSensitive(const void* a, const void* b)
|
||||||
|
{
|
||||||
|
int cmp;
|
||||||
|
char* aa = ((const KVPair*)a)->key;
|
||||||
|
char* bb = ((const KVPair*)b)->key;
|
||||||
|
|
||||||
|
if (!(cmp = strcmp(aa, bb)))
|
||||||
|
return aa == bb ? 0 : (aa > bb ? 1 : -1);
|
||||||
|
else
|
||||||
|
return cmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void grow()
|
||||||
|
{
|
||||||
|
size_t growSize = m_growSize ? m_growSize : m_size;
|
||||||
|
KVPair* newData = (KVPair*)malloc(sizeof(KVPair) * (m_size + growSize));
|
||||||
|
memcpy(newData, m_data, sizeof(KVPair) * m_size);
|
||||||
|
memset(newData + m_size, 0, sizeof(KVPair) * growSize);
|
||||||
|
|
||||||
|
KVPair* tmp = m_data;
|
||||||
|
m_data = newData;
|
||||||
|
free(tmp);
|
||||||
|
|
||||||
|
m_size += growSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct KVPair {
|
||||||
|
char* key;
|
||||||
|
char* value;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool m_caseSensitive;
|
||||||
|
size_t m_growSize;
|
||||||
|
size_t m_size;
|
||||||
|
size_t m_index;
|
||||||
|
KVPair* m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVCINDataTable {
|
||||||
|
public:
|
||||||
|
~OVCINDataTable()
|
||||||
|
{
|
||||||
|
if (m_propertyMap)
|
||||||
|
delete m_propertyMap;
|
||||||
|
if (m_keynameMap)
|
||||||
|
delete m_keynameMap;
|
||||||
|
if (m_chardefMap)
|
||||||
|
delete m_chardefMap;
|
||||||
|
if (m_data)
|
||||||
|
free (m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
string findProperty(const string& key)
|
||||||
|
{
|
||||||
|
vector<pair<string, string> > result = m_propertyMap->findPairsWithKey(key.c_str());
|
||||||
|
if (result.size()) return result[0].second;
|
||||||
|
return string();
|
||||||
|
}
|
||||||
|
|
||||||
|
string findKeyname(const string& key)
|
||||||
|
{
|
||||||
|
vector<pair<string, string> > result = m_keynameMap->findPairsWithKey(key.c_str());
|
||||||
|
if (result.size()) return result[0].second;
|
||||||
|
return string();
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<string> findChardef(const string& key)
|
||||||
|
{
|
||||||
|
vector<pair<string, string> > ret = m_chardefMap->findPairsWithKey(key.c_str());
|
||||||
|
vector<string> result;
|
||||||
|
vector<pair<string, string> >::iterator iter= ret.begin();
|
||||||
|
|
||||||
|
for ( ; iter != ret.end(); iter++)
|
||||||
|
result.push_back((*iter).second);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<pair<string, string> > findChardefWithWildcard(const OVWildcard& wildcard)
|
||||||
|
{
|
||||||
|
return m_chardefMap->findPairsWithWildcard(wildcard);
|
||||||
|
}
|
||||||
|
|
||||||
|
OVFastKeyValuePairMap* propertyMap()
|
||||||
|
{
|
||||||
|
return m_propertyMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
OVFastKeyValuePairMap* keynameMap()
|
||||||
|
{
|
||||||
|
return m_keynameMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
OVFastKeyValuePairMap* chardefMap()
|
||||||
|
{
|
||||||
|
return m_chardefMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
friend class OVCINDataTableParser;
|
||||||
|
OVCINDataTable(char* data, OVFastKeyValuePairMap* propertyMap, OVFastKeyValuePairMap* keynameMap, OVFastKeyValuePairMap* chardefMap)
|
||||||
|
: m_data(data)
|
||||||
|
, m_propertyMap(propertyMap)
|
||||||
|
, m_keynameMap(keynameMap)
|
||||||
|
, m_chardefMap(chardefMap)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
char* m_data;
|
||||||
|
OVFastKeyValuePairMap* m_propertyMap;
|
||||||
|
OVFastKeyValuePairMap* m_keynameMap;
|
||||||
|
OVFastKeyValuePairMap* m_chardefMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class OVCINDataTableParser {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
NoFileError,
|
||||||
|
SeekError,
|
||||||
|
EmptyFileError,
|
||||||
|
MemoryAllocationError,
|
||||||
|
ReadError,
|
||||||
|
NoDataError = EmptyFileError
|
||||||
|
};
|
||||||
|
|
||||||
|
OVCINDataTableParser()
|
||||||
|
: m_data(0)
|
||||||
|
, m_lastError(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~OVCINDataTableParser()
|
||||||
|
{
|
||||||
|
if (m_data)
|
||||||
|
free(m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int lastError()
|
||||||
|
{
|
||||||
|
return m_lastError;
|
||||||
|
}
|
||||||
|
|
||||||
|
OVCINDataTable* CINDataTableFromFileName(const string& filename, bool caseSensitive = false)
|
||||||
|
{
|
||||||
|
if (m_data) {
|
||||||
|
free(m_data);
|
||||||
|
m_data = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* f = OVFileHelper::OpenStream(filename);
|
||||||
|
if (!f) {
|
||||||
|
m_lastError = NoFileError;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
OVCINDataTable* table;
|
||||||
|
OVCINDataTableParser parser;
|
||||||
|
table = parser.CINDataTableFromFileStream(f, caseSensitive);
|
||||||
|
fclose(f);
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
OVCINDataTable* CINDataTableFromString(const char* string, bool caseSensitive = false)
|
||||||
|
{
|
||||||
|
if (m_data) {
|
||||||
|
free(m_data);
|
||||||
|
m_data = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t len = strlen(string);
|
||||||
|
if (!len) {
|
||||||
|
m_lastError = NoDataError;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_data = (char*)calloc(1, len + 1);
|
||||||
|
if (!m_data) {
|
||||||
|
m_lastError = MemoryAllocationError;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(m_data, string, len);
|
||||||
|
|
||||||
|
return CINDataTableFromRetainedData(caseSensitive);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OVCINDataTable* CINDataTableFromFileStream(FILE* stream, bool caseSensitive = false)
|
||||||
|
{
|
||||||
|
if (m_data) {
|
||||||
|
free(m_data);
|
||||||
|
m_data = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stream) {
|
||||||
|
m_lastError = NoFileError;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fseek(stream, 0, SEEK_END) == -1) {
|
||||||
|
m_lastError = SeekError;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size;
|
||||||
|
if (!(size = ftell(stream))) {
|
||||||
|
m_lastError = EmptyFileError;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fseek(stream, 0, SEEK_SET) == -1) {
|
||||||
|
m_lastError = SeekError;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_data = (char*)calloc(1, size + 1);
|
||||||
|
if (!m_data) {
|
||||||
|
m_lastError = MemoryAllocationError;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fread(m_data, 1, size, stream) != size) {
|
||||||
|
m_lastError = ReadError;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CINDataTableFromRetainedData(caseSensitive);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
OVCINDataTable* CINDataTableFromRetainedData(bool caseSensitive)
|
||||||
|
{
|
||||||
|
OVFastKeyValuePairMap* propertyMap = new OVFastKeyValuePairMap(16, 0, caseSensitive);
|
||||||
|
if (!propertyMap) {
|
||||||
|
free(m_data);
|
||||||
|
m_lastError = MemoryAllocationError;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
OVFastKeyValuePairMap* keynameMap = new OVFastKeyValuePairMap(64, 0, caseSensitive);
|
||||||
|
if (!keynameMap) {
|
||||||
|
free(m_data);
|
||||||
|
delete propertyMap;
|
||||||
|
m_lastError = MemoryAllocationError;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
OVFastKeyValuePairMap* chardefMap = new OVFastKeyValuePairMap(1024, 0, caseSensitive);
|
||||||
|
if (!chardefMap) {
|
||||||
|
free(m_data);
|
||||||
|
delete propertyMap;
|
||||||
|
delete keynameMap;
|
||||||
|
m_lastError = MemoryAllocationError;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_scanner = m_data;
|
||||||
|
|
||||||
|
char first;
|
||||||
|
int blockMode = 0;
|
||||||
|
|
||||||
|
while (first = *m_scanner) {
|
||||||
|
if (blockMode) {
|
||||||
|
if (first == '\r' || first == '\n') {
|
||||||
|
m_scanner++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* key = m_scanner;
|
||||||
|
char* value = const_cast<char*>("");
|
||||||
|
char endingChar = skipToSpaceCharOrLineEndAndMarkAndForward();
|
||||||
|
|
||||||
|
if (endingChar == '\r' || endingChar == '\n') {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
endingChar = skipUntilNonSpaceChar();
|
||||||
|
if (endingChar == '\r' || endingChar == '\n') {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
value = m_scanner;
|
||||||
|
skipToLineEndAndMarkAndForwardWithoutTrailingSpace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blockMode == 1) {
|
||||||
|
if (!strcmp(key, "%keyname") && !strcmp(value, "end")) {
|
||||||
|
blockMode = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!caseSensitive)
|
||||||
|
makeLowerCase(key);
|
||||||
|
|
||||||
|
keynameMap->add(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (blockMode == 2) {
|
||||||
|
if (!strcmp(key, "%chardef") && !strcmp(value, "end")) {
|
||||||
|
blockMode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
if (!caseSensitive)
|
||||||
|
makeLowerCase(key);
|
||||||
|
|
||||||
|
chardefMap->add(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (first == '#') {
|
||||||
|
skipUntilNextLine();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first == '%') {
|
||||||
|
m_scanner++;
|
||||||
|
|
||||||
|
char* key;
|
||||||
|
char* value = const_cast<char*>("");
|
||||||
|
|
||||||
|
if (*(key = m_scanner)) {
|
||||||
|
char endingChar = skipToSpaceCharOrLineEndAndMarkAndForward();
|
||||||
|
|
||||||
|
if (endingChar == '\r' || endingChar == '\n') {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
endingChar = skipUntilNonSpaceChar();
|
||||||
|
if (endingChar == '\r' || endingChar == '\n') {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
value = m_scanner;
|
||||||
|
skipToLineEndAndMarkAndForwardWithoutTrailingSpace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(key, "keyname") && !strcmp(value, "begin")) {
|
||||||
|
blockMode = 1;
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "chardef") && !strcmp(value, "begin")) {
|
||||||
|
blockMode = 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
propertyMap->add(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_scanner++;
|
||||||
|
}
|
||||||
|
|
||||||
|
propertyMap->sortAndFreeze();
|
||||||
|
keynameMap->sortAndFreeze();
|
||||||
|
chardefMap->sortAndFreeze();
|
||||||
|
|
||||||
|
OVCINDataTable* table = new OVCINDataTable(m_data, propertyMap, keynameMap, chardefMap);
|
||||||
|
|
||||||
|
if (!table) {
|
||||||
|
free(m_data);
|
||||||
|
delete propertyMap;
|
||||||
|
delete keynameMap;
|
||||||
|
delete chardefMap;
|
||||||
|
m_lastError = MemoryAllocationError;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_data = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
void skipUntilNextLine()
|
||||||
|
{
|
||||||
|
skipUntilEitherCRLF();
|
||||||
|
skipUntilNeitherCRLF();
|
||||||
|
}
|
||||||
|
|
||||||
|
void skipUntilEitherCRLF()
|
||||||
|
{
|
||||||
|
char nextChar;
|
||||||
|
while (nextChar = *m_scanner) {
|
||||||
|
if (nextChar == '\r' || nextChar == '\n') break;
|
||||||
|
m_scanner++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void skipUntilNeitherCRLF()
|
||||||
|
{
|
||||||
|
char nextChar;
|
||||||
|
while (nextChar = *m_scanner) {
|
||||||
|
if (!(nextChar == '\r' || nextChar == '\n')) break;
|
||||||
|
m_scanner++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void skipToLineEndAndMarkAndForwardWithoutTrailingSpace()
|
||||||
|
{
|
||||||
|
char nextChar;
|
||||||
|
while (nextChar = *m_scanner) {
|
||||||
|
if (nextChar == ' ' || nextChar == '\t') {
|
||||||
|
char* begin = m_scanner;
|
||||||
|
|
||||||
|
m_scanner++;
|
||||||
|
while (nextChar = *m_scanner) {
|
||||||
|
if (!(nextChar == ' ' || nextChar == '\t')) break;
|
||||||
|
m_scanner++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextChar == '\n' || nextChar == '\r') {
|
||||||
|
*begin = 0;
|
||||||
|
m_scanner++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_scanner++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextChar == '\n' || nextChar == '\r') {
|
||||||
|
*m_scanner = 0;
|
||||||
|
m_scanner++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_scanner++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char skipToSpaceCharOrLineEndAndMarkAndForward()
|
||||||
|
{
|
||||||
|
char nextChar;
|
||||||
|
while (nextChar = *m_scanner) {
|
||||||
|
if (nextChar == ' ' || nextChar == '\t' || nextChar == '\n' || nextChar == '\r') {
|
||||||
|
*m_scanner = 0;
|
||||||
|
m_scanner++;
|
||||||
|
return nextChar;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_scanner++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char skipUntilNonSpaceChar()
|
||||||
|
{
|
||||||
|
char nextChar;
|
||||||
|
while (nextChar = *m_scanner) {
|
||||||
|
if (!(nextChar == ' ' || nextChar == '\t'))
|
||||||
|
return nextChar;
|
||||||
|
|
||||||
|
m_scanner++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void makeLowerCase(char* ptr)
|
||||||
|
{
|
||||||
|
while (*ptr) {
|
||||||
|
*ptr = tolower(*ptr);
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
char* m_data;
|
||||||
|
char* m_scanner;
|
||||||
|
int m_lastError;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const map<string, string> QuickParseProperty(const string& filename)
|
||||||
|
{
|
||||||
|
map<string, string> properties;
|
||||||
|
FILE* stream = OVFileHelper::OpenStream(filename);
|
||||||
|
|
||||||
|
if (!stream)
|
||||||
|
return properties;
|
||||||
|
|
||||||
|
while (!feof(stream)) {
|
||||||
|
char buffer[256];
|
||||||
|
fgets(buffer, sizeof(buffer) - 1, stream);
|
||||||
|
|
||||||
|
if (!*buffer)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (*buffer == '#')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
pair<string, string> pv = SplitPropertyString(buffer + 1);
|
||||||
|
if (pv.first == "keyname")
|
||||||
|
break;
|
||||||
|
|
||||||
|
properties[pv.first] = pv.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(stream);
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
static pair<string, string> SplitPropertyString(const char* str)
|
||||||
|
{
|
||||||
|
const char* scanner = str;
|
||||||
|
while (*scanner) {
|
||||||
|
if (*scanner == ' ' || *scanner == '\t' || *scanner == '\r' || *scanner == '\n')
|
||||||
|
break;
|
||||||
|
scanner++;
|
||||||
|
}
|
||||||
|
|
||||||
|
string property = string(str, (size_t)(scanner - str));
|
||||||
|
|
||||||
|
while (*scanner) {
|
||||||
|
if (*scanner != ' ' && *scanner != '\t')
|
||||||
|
break;
|
||||||
|
scanner++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* begin = scanner;
|
||||||
|
while (*scanner) {
|
||||||
|
if (*scanner == '\r' || *scanner == '\n')
|
||||||
|
break;
|
||||||
|
scanner++;
|
||||||
|
}
|
||||||
|
|
||||||
|
string value = string(begin, (size_t)(scanner - begin));
|
||||||
|
return pair<string, string>(property, value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,189 @@
|
||||||
|
//
|
||||||
|
// OVCINDatabaseService.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVCINDatabaseService_h
|
||||||
|
#define OVCINDatabaseService_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVCINDataTable.h>
|
||||||
|
#include <OpenVanilla/OVDatabaseService.h>
|
||||||
|
#else
|
||||||
|
#include "OVCINDataTable.h"
|
||||||
|
#include "OVDatabaseService.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVCINDatabaseService;
|
||||||
|
|
||||||
|
class OVCINKeyValueDataTable : public OVKeyValueDataTableInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~OVCINKeyValueDataTable()
|
||||||
|
{
|
||||||
|
delete m_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const vector<string> valuesForKey(const string& key)
|
||||||
|
{
|
||||||
|
return m_table->findChardef(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const vector<pair<string, string> > valuesForKey(const OVWildcard& expression)
|
||||||
|
{
|
||||||
|
return m_table->findChardefWithWildcard(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const string valueForProperty(const string& property)
|
||||||
|
{
|
||||||
|
if (OVKeynamePropertyHelper::IsPropertyKeyname(property))
|
||||||
|
return m_table->findKeyname(OVKeynamePropertyHelper::KeynameFromProperty(property));
|
||||||
|
else
|
||||||
|
return m_table->findProperty(property);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
OVCINDataTable* m_table;
|
||||||
|
|
||||||
|
friend class OVCINDatabaseService;
|
||||||
|
|
||||||
|
OVCINKeyValueDataTable(OVCINDataTable* table)
|
||||||
|
: m_table(table)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class OVCINDatabaseService : public OVDatabaseService {
|
||||||
|
public:
|
||||||
|
OVCINDatabaseService()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
OVCINDatabaseService(const string& pathToScan, const string& includePattern = "*.cin", const string& excludePattern = "", size_t depth = 1)
|
||||||
|
{
|
||||||
|
addDirectory(pathToScan, includePattern, excludePattern, depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
// note addDirectory overwrites the table data, so scan user directory after scan the systems if you want to give precedence to user' tables
|
||||||
|
void addDirectory(const string& pathToScan, const string& includePattern = "*.cin", const string& excludePattern = "", size_t depth = 1)
|
||||||
|
{
|
||||||
|
string pathPrefix = OVPathHelper::NormalizeByExpandingTilde(pathToScan) + OVPathHelper::Separator();
|
||||||
|
size_t prefixLength = pathPrefix.length();
|
||||||
|
|
||||||
|
vector<string> tables = OVDirectoryHelper::Glob(pathPrefix, includePattern, excludePattern, depth);
|
||||||
|
|
||||||
|
vector<string>::iterator iter = tables.begin();
|
||||||
|
for ( ; iter != tables.end(); ++iter) {
|
||||||
|
const string& path = *iter;
|
||||||
|
string shortPath = *iter;
|
||||||
|
shortPath.erase(0, prefixLength);
|
||||||
|
|
||||||
|
string tableName = OVCINDatabaseService::TableNameFromPath(shortPath);
|
||||||
|
m_tables[tableName] = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const vector<string> tables(const OVWildcard& filter = string("*"))
|
||||||
|
{
|
||||||
|
vector<string> result;
|
||||||
|
|
||||||
|
for (map<string, string>::iterator iter = m_tables.begin() ; iter != m_tables.end(); ++iter) {
|
||||||
|
if (filter.match((*iter).first))
|
||||||
|
result.push_back((*iter).first);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool tableSupportsValueToKeyLookup(const string &tableName)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual OVKeyValueDataTableInterface* createKeyValueDataTableInterface(const string& name, bool suggestedCaseSensitivity = false)
|
||||||
|
{
|
||||||
|
map<string, string>::iterator iter = m_tables.find(name);
|
||||||
|
if (iter == m_tables.end())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
OVCINDataTableParser parser;
|
||||||
|
OVCINDataTable* table = parser.CINDataTableFromFileName((*iter).second, suggestedCaseSensitivity);
|
||||||
|
|
||||||
|
if (!table)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return new OVCINKeyValueDataTable(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual const string valueForPropertyInTable(const string& property, const string& name)
|
||||||
|
{
|
||||||
|
map<string, string>::iterator iter;
|
||||||
|
|
||||||
|
if (name != m_cachedTableName)
|
||||||
|
{
|
||||||
|
iter = m_tables.find(name);
|
||||||
|
if (iter == m_tables.end())
|
||||||
|
return string();
|
||||||
|
|
||||||
|
m_cachedProperties = OVCINDataTableParser::QuickParseProperty((*iter).second);
|
||||||
|
m_cachedTableName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
iter = m_cachedProperties.find(property);
|
||||||
|
if (iter != m_cachedProperties.end())
|
||||||
|
return (*iter).second;
|
||||||
|
|
||||||
|
return string();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
map<string, string> m_tables;
|
||||||
|
map<string, string> m_cachedProperties;
|
||||||
|
string m_cachedTableName;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const string TableNameFromPath(const string& path)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
char separator = OVPathHelper::Separator();
|
||||||
|
|
||||||
|
string::const_iterator iter = path.begin();
|
||||||
|
for ( ; iter != path.end(); ++iter)
|
||||||
|
if (*iter == separator || *iter == '.')
|
||||||
|
result += '-';
|
||||||
|
else
|
||||||
|
result += *iter;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,125 @@
|
||||||
|
//
|
||||||
|
// OVCINToSQLiteConvertor.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVCINToSQLiteConvertor_h
|
||||||
|
#define OVCINToSQLiteConvertor_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVCINDataTable.h>
|
||||||
|
#include <OpenVanilla/OVSQLiteWrapper.h>
|
||||||
|
#else
|
||||||
|
#include "OVCINDataTable.h"
|
||||||
|
#include "OVSQLiteWrapper.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVCINToSQLiteConvertor {
|
||||||
|
protected:
|
||||||
|
static bool InsertKeyValue(OVFastKeyValuePairMap* map, OVSQLiteStatement* statement, const char* prefix = 0)
|
||||||
|
{
|
||||||
|
string prefixString = prefix ? prefix : "";
|
||||||
|
|
||||||
|
size_t size = map->size();
|
||||||
|
|
||||||
|
for (size_t index = 0; index < size; index++) {
|
||||||
|
pair<string, string> kvpair = map->keyValuePairAtIndex(index);
|
||||||
|
|
||||||
|
const string& key = prefix ? prefixString + kvpair.first : kvpair.first;
|
||||||
|
|
||||||
|
statement->bindTextToColumn(key, 1);
|
||||||
|
statement->bindTextToColumn(kvpair.second, 2);
|
||||||
|
|
||||||
|
if (statement->step() != SQLITE_DONE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
statement->reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool Convert(OVCINDataTable* table, OVSQLiteConnection* connection, const string& tableName, bool overwriteTable = true)
|
||||||
|
{
|
||||||
|
const char* nameStr = tableName.c_str();
|
||||||
|
// query if the table exists
|
||||||
|
OVSQLiteStatement* statement;
|
||||||
|
|
||||||
|
statement = connection->prepare("SELECT name FROM sqlite_master WHERE name = %Q", nameStr);
|
||||||
|
|
||||||
|
if (!statement)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (statement->step() == SQLITE_ROW && overwriteTable)
|
||||||
|
{
|
||||||
|
delete statement;
|
||||||
|
|
||||||
|
if (connection->execute("DROP TABLE %Q", nameStr) != SQLITE_OK) {
|
||||||
|
delete statement;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
delete statement;
|
||||||
|
|
||||||
|
if (connection->execute("CREATE TABLE %Q (key, value)", nameStr) != SQLITE_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
string indexName = tableName + "_index";
|
||||||
|
if (connection->execute("CREATE INDEX %Q on %Q (key)", indexName.c_str(), nameStr) != SQLITE_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
statement = connection->prepare("INSERT INTO %Q VALUES (?, ?)", nameStr);
|
||||||
|
if (!statement) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connection->execute("BEGIN") != SQLITE_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string keynameProperty = string(OVPropertyStringInternalPrefix) + string(OVCINKeynameString);
|
||||||
|
|
||||||
|
if (InsertKeyValue(table->propertyMap(), statement, OVPropertyStringInternalPrefix))
|
||||||
|
if (InsertKeyValue(table->keynameMap(), statement, keynameProperty.c_str()))
|
||||||
|
InsertKeyValue(table->chardefMap(), statement);
|
||||||
|
|
||||||
|
delete statement;
|
||||||
|
|
||||||
|
if (connection->execute("COMMIT") != SQLITE_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,208 @@
|
||||||
|
//
|
||||||
|
// OVCandidateService.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVCandidateService_h
|
||||||
|
#define OVCandidateService_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVBase.h>
|
||||||
|
#include <OpenVanilla/OVKey.h>
|
||||||
|
#include <OpenVanilla/OVLoaderService.h>
|
||||||
|
#else
|
||||||
|
#include "OVBase.h"
|
||||||
|
#include "OVKey.h"
|
||||||
|
#include "OVLoaderService.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVCandidateList : public OVBase {
|
||||||
|
public:
|
||||||
|
virtual void clear() = 0;
|
||||||
|
virtual size_t size() const = 0;
|
||||||
|
virtual string candidateAtIndex(size_t index) const = 0;
|
||||||
|
virtual void setCandidate(size_t index, const string& candidate) = 0;
|
||||||
|
virtual void setCandidates(const vector<string>& candidates) = 0;
|
||||||
|
virtual void addCandidate(const string& candidate) = 0;
|
||||||
|
virtual void addCandidates(const vector<string>& candidates) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVCandidatePanel;
|
||||||
|
class OVOneDimensionalCandidatePanel;
|
||||||
|
// class OVTwoDimensionalCandidatePanel;
|
||||||
|
class OVFreeContentPanel;
|
||||||
|
class OVPlainTextCandidatePanel;
|
||||||
|
class OVHTMLCandidatePanel;
|
||||||
|
|
||||||
|
class OVCandidatePanel : public OVBase {
|
||||||
|
public:
|
||||||
|
virtual bool isOneDimensionalPanel() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isTwoDimensionalPanel() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isPlainTextPanelPanel() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isHTMLPanel() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void hide() = 0;
|
||||||
|
virtual void show() = 0;
|
||||||
|
virtual void updateDisplay() = 0;
|
||||||
|
virtual bool isVisible() = 0;
|
||||||
|
|
||||||
|
virtual void setPrompt(const string& prompt) = 0;
|
||||||
|
virtual string prompt() = 0;
|
||||||
|
|
||||||
|
virtual bool yieldToCandidateEventHandler() = 0;
|
||||||
|
virtual void cancelEventHandler() = 0;
|
||||||
|
|
||||||
|
virtual void reset() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVOneDimensionalCandidatePanel : public OVCandidatePanel {
|
||||||
|
public:
|
||||||
|
virtual bool isOneDimensionalPanel() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isHorizontal() const = 0;
|
||||||
|
virtual bool isVertical() const = 0;
|
||||||
|
|
||||||
|
virtual OVCandidateList* candidateList() = 0;
|
||||||
|
|
||||||
|
virtual size_t candidatesPerPage() const = 0;
|
||||||
|
virtual void setCandidatesPerPage(size_t number) = 0;
|
||||||
|
virtual size_t pageCount() const = 0;
|
||||||
|
virtual size_t currentPage() const = 0;
|
||||||
|
virtual size_t currentPageCandidateCount() const = 0;
|
||||||
|
virtual bool allowsPageWrapping() const = 0;
|
||||||
|
virtual void setAllowsPageWrapping(bool allowsPageWrapping) = 0;
|
||||||
|
|
||||||
|
virtual size_t currentHightlightIndex() const = 0;
|
||||||
|
virtual void setHighlightIndex(size_t index) = 0;
|
||||||
|
virtual size_t currentHightlightIndexInCandidateList() const = 0;
|
||||||
|
|
||||||
|
virtual size_t goToNextPage() = 0;
|
||||||
|
virtual size_t goToPreviousPage() = 0;
|
||||||
|
virtual size_t goToPage(size_t page) = 0;
|
||||||
|
|
||||||
|
virtual const OVKey candidateKeyAtIndex(size_t index) = 0;
|
||||||
|
virtual void setCandidateKeys(const string& asciiKeys, OVLoaderService* loaderService)
|
||||||
|
{
|
||||||
|
OVKeyVector keys;
|
||||||
|
for (size_t index = 0; index < asciiKeys.length(); index++) {
|
||||||
|
keys.push_back(loaderService->makeOVKey(asciiKeys[index]));
|
||||||
|
}
|
||||||
|
|
||||||
|
setCandidateKeys(keys);
|
||||||
|
setCandidatesPerPage(asciiKeys.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setCandidateKeys(const OVKeyVector& keys) = 0;
|
||||||
|
virtual void setNextPageKeys(const OVKeyVector& keys) = 0;
|
||||||
|
virtual void setPreviousPageKeys(const OVKeyVector& keys) = 0;
|
||||||
|
virtual void setNextCandidateKeys(const OVKeyVector& keys) = 0;
|
||||||
|
virtual void setPreviousCandidateKeys(const OVKeyVector& keys) = 0;
|
||||||
|
virtual void setCancelKeys(const OVKeyVector& keys) = 0;
|
||||||
|
virtual void setChooseHighlightedCandidateKeys(const OVKeyVector& keys) = 0;
|
||||||
|
|
||||||
|
virtual const OVKeyVector defaultCandidateKeys() const = 0;
|
||||||
|
virtual const OVKeyVector defaultNextPageKeys() const = 0;
|
||||||
|
virtual const OVKeyVector defaultNextCandidateKeys() const = 0;
|
||||||
|
virtual const OVKeyVector defaultPreviousPageKeys() const = 0;
|
||||||
|
virtual const OVKeyVector defaultPreviousCandidateKeys() const = 0;
|
||||||
|
virtual const OVKeyVector defaultCancelKeys() const = 0;
|
||||||
|
virtual const OVKeyVector defaultChooseHighlightedCandidateKeys() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVFreeContentStorage : public OVBase {
|
||||||
|
public:
|
||||||
|
virtual void clear() = 0;
|
||||||
|
virtual void setContent(const string& content) = 0;
|
||||||
|
virtual void appendContent(const string& content) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVPlainTextCandidatePanel : public OVCandidatePanel {
|
||||||
|
public:
|
||||||
|
virtual bool isPlainTextPanelPanel()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual OVFreeContentStorage* textStorage() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVHTMLCandidatePanel : public OVCandidatePanel {
|
||||||
|
public:
|
||||||
|
virtual OVFreeContentStorage* HTMLSourceStorage() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVCandidateService : public OVBase {
|
||||||
|
public:
|
||||||
|
virtual OVOneDimensionalCandidatePanel* useHorizontalCandidatePanel()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual OVOneDimensionalCandidatePanel* useVerticalCandidatePanel()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual OVOneDimensionalCandidatePanel* useOneDimensionalCandidatePanel()
|
||||||
|
{
|
||||||
|
return useVerticalCandidatePanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
// virtual OVTwoDimensionalCandidatePanel* twoDimensionalCandidatePanel();
|
||||||
|
|
||||||
|
virtual OVPlainTextCandidatePanel* usePlainTextCandidatePanel()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual OVHTMLCandidatePanel* useHTMLCandidatePanel()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,101 @@
|
||||||
|
//
|
||||||
|
// OVDatabaseService.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVDatabaseService_h
|
||||||
|
#define OVDatabaseService_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVBase.h>
|
||||||
|
#include <OpenVanilla/OVCINDataTable.h>
|
||||||
|
#include <OpenVanilla/OVFileHelper.h>
|
||||||
|
#include <OpenVanilla/OVWildcard.h>
|
||||||
|
#else
|
||||||
|
#include "OVBase.h"
|
||||||
|
#include "OVCINDataTable.h"
|
||||||
|
#include "OVFileHelper.h"
|
||||||
|
#include "OVWildcard.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// database-backed table uses this prefix to store properties ina key-value data table
|
||||||
|
#define OVPropertyStringInternalPrefix "__property_"
|
||||||
|
|
||||||
|
#define OVCINKeynameString "keyname-"
|
||||||
|
#define OVCINKeynameStringLength 8
|
||||||
|
|
||||||
|
// keyname is defined in the .cin format, not to be confused with the key in key-value pairs
|
||||||
|
class OVKeynamePropertyHelper : public OVBase {
|
||||||
|
public:
|
||||||
|
static bool IsPropertyKeyname(const string& property)
|
||||||
|
{
|
||||||
|
return (property.substr(0, OVCINKeynameStringLength) == OVCINKeynameString);
|
||||||
|
}
|
||||||
|
|
||||||
|
// passes property and gets back the keyname
|
||||||
|
static const string KeynameFromProperty(const string& property)
|
||||||
|
{
|
||||||
|
return IsPropertyKeyname(property) ? property.substr(OVCINKeynameStringLength, property.length() - OVCINKeynameStringLength) : string();
|
||||||
|
}
|
||||||
|
|
||||||
|
// passes keyname and gets the combined property
|
||||||
|
static const string KeynameToProperty(const string& keyname)
|
||||||
|
{
|
||||||
|
return string(OVCINKeynameString) + keyname;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVKeyValueDataTableInterface : public OVBase {
|
||||||
|
public:
|
||||||
|
virtual const vector<string> valuesForKey(const string& key) = 0;
|
||||||
|
virtual const vector<pair<string, string> > valuesForKey(const OVWildcard& expression) = 0;
|
||||||
|
virtual const string valueForProperty(const string& property) = 0;
|
||||||
|
|
||||||
|
// only supported by database services that support value-to-key lookup, the default implementation is an empty vector<string>
|
||||||
|
virtual const vector<string> keysForValue(const string& value)
|
||||||
|
{
|
||||||
|
return vector<string>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVDatabaseService : public OVBase {
|
||||||
|
public:
|
||||||
|
virtual const vector<string> tables(const OVWildcard& filter = string("*")) = 0;
|
||||||
|
virtual bool tableSupportsValueToKeyLookup(const string &tableName) = 0;
|
||||||
|
|
||||||
|
virtual OVKeyValueDataTableInterface* createKeyValueDataTableInterface(const string& name, bool suggestedCaseSensitivity = false) = 0;
|
||||||
|
|
||||||
|
// this is needed so that modules like OVIMGeneric can know table localized names in advance, without really loading them
|
||||||
|
virtual const string valueForPropertyInTable(const string& property, const string& name) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,149 @@
|
||||||
|
//
|
||||||
|
// OVDateTimeHelper.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVDateTimeHelper_h
|
||||||
|
#define OVDateTimeHelper_h
|
||||||
|
|
||||||
|
#include <ctime>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVDateTimeHelper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static time_t GetTimeIntervalSince1970()
|
||||||
|
{
|
||||||
|
return time(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static time_t GetTimeIntervalSince1970FromString(const string& s)
|
||||||
|
{
|
||||||
|
stringstream sst;
|
||||||
|
sst << s;
|
||||||
|
time_t t;
|
||||||
|
sst >> t;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string GetTimeIntervalSince1970AsString()
|
||||||
|
{
|
||||||
|
stringstream sst;
|
||||||
|
sst << time(NULL);
|
||||||
|
return sst.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
static time_t GetTimeIntervalSince1970AtBeginningOfTodayLocalTime()
|
||||||
|
{
|
||||||
|
time_t t = time(NULL);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
struct tm tdata;
|
||||||
|
struct tm* td = &tdata;
|
||||||
|
if (localtime_s(td, &t))
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
struct tm* td;
|
||||||
|
td = localtime(&t);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
td->tm_hour = 0;
|
||||||
|
td->tm_min = 0;
|
||||||
|
td->tm_sec = 0;
|
||||||
|
|
||||||
|
return mktime(td);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string LocalTimeString()
|
||||||
|
{
|
||||||
|
time_t t = time(NULL);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
struct tm tdata;
|
||||||
|
struct tm* td = &tdata;
|
||||||
|
if (localtime_s(td, &t))
|
||||||
|
return string();
|
||||||
|
#else
|
||||||
|
struct tm* td;
|
||||||
|
td = localtime(&t);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ostringstream sstr;
|
||||||
|
sstr.width(2);
|
||||||
|
sstr.fill('0');
|
||||||
|
sstr << td->tm_hour << ":";
|
||||||
|
sstr.width(2);
|
||||||
|
sstr.fill('0');
|
||||||
|
sstr << td->tm_min << ":";
|
||||||
|
sstr.width(2);
|
||||||
|
sstr.fill('0');
|
||||||
|
sstr << td->tm_sec;
|
||||||
|
return sstr.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string LocalDateTimeString()
|
||||||
|
{
|
||||||
|
time_t t = time(NULL);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
struct tm tdata;
|
||||||
|
struct tm* td = &tdata;
|
||||||
|
if (localtime_s(td, &t))
|
||||||
|
return string();
|
||||||
|
#else
|
||||||
|
struct tm* td;
|
||||||
|
td = localtime(&t);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ostringstream sstr;
|
||||||
|
sstr.width(4);
|
||||||
|
sstr << td->tm_year + 1900 << "-";
|
||||||
|
sstr.width(2);
|
||||||
|
sstr.fill('0');
|
||||||
|
sstr << td->tm_mon + 1 << "-";
|
||||||
|
sstr.width(2);
|
||||||
|
sstr.fill('0');
|
||||||
|
sstr << td->tm_mday << " ";
|
||||||
|
|
||||||
|
sstr.width(2);
|
||||||
|
sstr.fill('0');
|
||||||
|
sstr << td->tm_hour << ":";
|
||||||
|
sstr.width(2);
|
||||||
|
sstr.fill('0');
|
||||||
|
sstr << td->tm_min << ":";
|
||||||
|
sstr.width(2);
|
||||||
|
sstr.fill('0');
|
||||||
|
sstr << td->tm_sec;
|
||||||
|
return sstr.str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,72 @@
|
||||||
|
//
|
||||||
|
// OVEncodingService.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVEncodingService_h
|
||||||
|
#define OVEncodingService_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVUTF8Helper.h>
|
||||||
|
#else
|
||||||
|
#include "OVUTF8Helper.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVEncodingService : public OVBase {
|
||||||
|
public:
|
||||||
|
virtual bool stringSupportedByEncoding(const string& text, const string& encoding)
|
||||||
|
{
|
||||||
|
vector<string> svec = OVUTF8Helper::SplitStringByCodePoint(text);
|
||||||
|
for (vector<string>::iterator iter = svec.begin() ; iter != svec.end() ; ++iter)
|
||||||
|
if (!codepointSupportedByEncoding(*iter, encoding))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool stringSupportedBySystem(const string& text)
|
||||||
|
{
|
||||||
|
vector<string> svec = OVUTF8Helper::SplitStringByCodePoint(text);
|
||||||
|
for (vector<string>::iterator iter = svec.begin() ; iter != svec.end() ; ++iter)
|
||||||
|
if (!codepointSupportedBySystem(*iter))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool codepointSupportedByEncoding(const string& codepoint, const string& encoding) = 0;
|
||||||
|
virtual bool codepointSupportedBySystem(const string& codepoint) = 0;
|
||||||
|
virtual const vector<string> supportedEncodings() = 0;
|
||||||
|
virtual bool isEncodingSupported(const string& encoding) = 0;
|
||||||
|
|
||||||
|
virtual bool isEncodingConversionSupported(const string& fromEncoding, const string& toEncoding) = 0;
|
||||||
|
virtual const pair<bool, string> convertEncoding(const string& fromEncoding, const string& toEncoding, const string& text) = 0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,102 @@
|
||||||
|
//
|
||||||
|
// OVEventHandlingContext.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVEventHandlingContext_h
|
||||||
|
#define OVEventHandlingContext_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVBase.h>
|
||||||
|
#include <OpenVanilla/OVCandidateService.h>
|
||||||
|
#include <OpenVanilla/OVStringHelper.h>
|
||||||
|
#include <OpenVanilla/OVTextBuffer.h>
|
||||||
|
#include <OpenVanilla/OVKey.h>
|
||||||
|
#include <OpenVanilla/OVLoaderService.h>
|
||||||
|
#else
|
||||||
|
#include "OVBase.h"
|
||||||
|
#include "OVCandidateService.h"
|
||||||
|
#include "OVStringHelper.h"
|
||||||
|
#include "OVTextBuffer.h"
|
||||||
|
#include "OVKey.h"
|
||||||
|
#include "OVLoaderService.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVEventHandlingContext : public OVBase {
|
||||||
|
public:
|
||||||
|
virtual void startSession(OVLoaderService* loaderService)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void stopSession(OVLoaderService* loaderService)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void clear(OVLoaderService* loaderService)
|
||||||
|
{
|
||||||
|
stopSession(loaderService);
|
||||||
|
startSession(loaderService);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool handleKey(OVKey* key, OVTextBuffer* readingText, OVTextBuffer* composingText, OVCandidateService* candidateService, OVLoaderService* loaderService)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool handleDirectText(const vector<string>& segments, OVTextBuffer* readingText, OVTextBuffer* composingText, OVCandidateService* candidateService, OVLoaderService* loaderService)
|
||||||
|
{
|
||||||
|
return handleDirectText(OVStringHelper::Join(segments), readingText, composingText, candidateService, loaderService);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool handleDirectText(const string&, OVTextBuffer* readingText, OVTextBuffer* composingText, OVCandidateService* candidateService, OVLoaderService* loaderService)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void candidateCanceled(OVCandidateService* candidateService, OVTextBuffer* readingText, OVTextBuffer* composingText, OVLoaderService* loaderService)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool candidateSelected(OVCandidateService* candidateService, const string& text, size_t index, OVTextBuffer* readingText, OVTextBuffer* composingText, OVLoaderService* loaderService)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool candidateNonPanelKeyReceived(OVCandidateService* candidateService, const OVKey* key, OVTextBuffer* readingText, OVTextBuffer* composingText, OVLoaderService* loaderService)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const string filterText(const string& inputText, OVLoaderService* loaderService)
|
||||||
|
{
|
||||||
|
return inputText;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,46 @@
|
||||||
|
//
|
||||||
|
// OVException.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVException_h
|
||||||
|
#define OVException_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVBase.h>
|
||||||
|
#else
|
||||||
|
#include "OVBase.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVException {
|
||||||
|
public:
|
||||||
|
class OverflowException {};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,627 @@
|
||||||
|
//
|
||||||
|
// OVFileHelper.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVFileHelper_h
|
||||||
|
#define OVFileHelper_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#else
|
||||||
|
#include <windows.h>
|
||||||
|
#include <shlobj.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
#include "OVWildcard.h"
|
||||||
|
#include "OVUTF8Helper.h"
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVFileHelper {
|
||||||
|
public:
|
||||||
|
static FILE* OpenStream(const string& filename, const string& mode = "rb")
|
||||||
|
{
|
||||||
|
#ifndef WIN32
|
||||||
|
return fopen(filename.c_str(), mode.c_str());
|
||||||
|
#else
|
||||||
|
FILE* stream = NULL;
|
||||||
|
errno_t err = _wfopen_s(&stream, OVUTF16::FromUTF8(filename).c_str(), OVUTF16::FromUTF8(mode).c_str());
|
||||||
|
return err ? 0 : stream;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OpenOFStream(ofstream& stream, const string& filename, ios_base::openmode openMode)
|
||||||
|
{
|
||||||
|
#ifndef WIN32
|
||||||
|
stream.open(filename.c_str(), openMode);
|
||||||
|
#else
|
||||||
|
stream.open(OVUTF16::FromUTF8(filename).c_str(), openMode);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OpenIFStream(ifstream& stream, const string& filename, ios_base::openmode openMode)
|
||||||
|
{
|
||||||
|
#ifndef WIN32
|
||||||
|
stream.open(filename.c_str(), openMode);
|
||||||
|
#else
|
||||||
|
stream.open(OVUTF16::FromUTF8(filename).c_str(), openMode);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// use free(), not delete[], to free the block allocated
|
||||||
|
static pair<char*, size_t> SlurpFile(const string& filename, bool addOneByteOfStringTerminationPadding = false)
|
||||||
|
{
|
||||||
|
FILE* stream = OpenStream(filename);
|
||||||
|
char* buf = 0;
|
||||||
|
size_t size = 0;
|
||||||
|
if (stream) {
|
||||||
|
if (!fseek(stream, 0, SEEK_END)) {
|
||||||
|
long lsize = ftell(stream);
|
||||||
|
if (lsize) {
|
||||||
|
size = (size_t)lsize;
|
||||||
|
if (!fseek(stream, 0, SEEK_SET)) {
|
||||||
|
buf = (char*)calloc(1, (size_t)size + (addOneByteOfStringTerminationPadding ? 1 : 0));
|
||||||
|
if (buf) {
|
||||||
|
if (fread(buf, size, 1, stream) != 1) {
|
||||||
|
free(buf);
|
||||||
|
buf = 0;
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pair<char*, size_t>(buf, size);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVFileTimestamp {
|
||||||
|
public:
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
OVFileTimestamp(__darwin_time_t timestamp = 0, long subtimestamp = 0)
|
||||||
|
#elif defined(WIN32)
|
||||||
|
OVFileTimestamp(time_t timestamp = 0, time_t subtimestamp = 0)
|
||||||
|
#else
|
||||||
|
#error We don't know about Linux yet, sorry.
|
||||||
|
#endif
|
||||||
|
: m_timestamp(timestamp)
|
||||||
|
, m_subtimestamp(subtimestamp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
OVFileTimestamp(const OVFileTimestamp& timestamp)
|
||||||
|
: m_timestamp(timestamp.m_timestamp)
|
||||||
|
, m_subtimestamp(timestamp.m_subtimestamp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
OVFileTimestamp& operator=(const OVFileTimestamp& timestamp)
|
||||||
|
{
|
||||||
|
m_timestamp = timestamp.m_timestamp;
|
||||||
|
m_subtimestamp = timestamp.m_subtimestamp;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool operator==(OVFileTimestamp& another)
|
||||||
|
{
|
||||||
|
return (m_timestamp == another.m_timestamp) && (m_subtimestamp == another.m_subtimestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(OVFileTimestamp& another)
|
||||||
|
{
|
||||||
|
return (m_timestamp != another.m_timestamp) || (m_subtimestamp != another.m_subtimestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(OVFileTimestamp& another)
|
||||||
|
{
|
||||||
|
return (m_timestamp < another.m_timestamp) || ((m_timestamp == another.m_timestamp) && m_subtimestamp < another.m_subtimestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>(OVFileTimestamp& another)
|
||||||
|
{
|
||||||
|
return (m_timestamp > another.m_timestamp) || ((m_timestamp == another.m_timestamp) && m_subtimestamp > another.m_subtimestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
__darwin_time_t m_timestamp;
|
||||||
|
long m_subtimestamp;
|
||||||
|
#elif defined(WIN32)
|
||||||
|
time_t m_timestamp;
|
||||||
|
time_t m_subtimestamp;
|
||||||
|
#else
|
||||||
|
#error We don't know about Linux yet, sorry.
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class OVPathHelper {
|
||||||
|
public:
|
||||||
|
static char Separator()
|
||||||
|
{
|
||||||
|
#ifndef WIN32
|
||||||
|
return '/';
|
||||||
|
#else
|
||||||
|
return '\\';
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const string DirectoryFromPath(const string& path)
|
||||||
|
{
|
||||||
|
string realPath = OVPathHelper::NormalizeByExpandingTilde(path);
|
||||||
|
if (OVPathHelper::PathExists(realPath) && OVPathHelper::IsDirectory(realPath))
|
||||||
|
return realPath;
|
||||||
|
|
||||||
|
char separator = OVPathHelper::Separator();
|
||||||
|
|
||||||
|
if (!realPath.length())
|
||||||
|
return string(".");
|
||||||
|
|
||||||
|
for (size_t index = realPath.length() - 1; index >= 0 ; index--) {
|
||||||
|
if (realPath[index] == separator) {
|
||||||
|
if (index) {
|
||||||
|
// reserve the \\ on Windows
|
||||||
|
if (realPath[index-1] == '\\')
|
||||||
|
return realPath.substr(0, index + 1);
|
||||||
|
else
|
||||||
|
return realPath.substr(0, index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return realPath.substr(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we run into : (like C:) on Windows
|
||||||
|
if (realPath[index] == ':')
|
||||||
|
return realPath.substr(0, index + 1) + Separator();
|
||||||
|
|
||||||
|
if (!index) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(".");
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string FilenameWithoutPath(const string &path)
|
||||||
|
{
|
||||||
|
char separator = OVPathHelper::Separator();
|
||||||
|
|
||||||
|
if (!path.length())
|
||||||
|
return string();
|
||||||
|
|
||||||
|
for (size_t index = path.length() - 1; index >= 0 ; index--) {
|
||||||
|
if (path[index] == separator)
|
||||||
|
return path.substr(index + 1, path.length() - (index + 1));
|
||||||
|
|
||||||
|
if (!index) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string FilenameWithoutExtension(const string &path)
|
||||||
|
{
|
||||||
|
char separator = OVPathHelper::Separator();
|
||||||
|
if (!path.length())
|
||||||
|
return string();
|
||||||
|
|
||||||
|
for (size_t index = path.length() - 1; index >= 0 ; index--) {
|
||||||
|
if (path[index] == separator)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (path[index] == '.')
|
||||||
|
return path.substr(0, index);
|
||||||
|
|
||||||
|
if (!index) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string ChopTrailingSeparator(const string& path)
|
||||||
|
{
|
||||||
|
if (path.length() == 1 && path[0] == Separator())
|
||||||
|
return path;
|
||||||
|
|
||||||
|
string result;
|
||||||
|
|
||||||
|
if (path.length()) {
|
||||||
|
if (path[path.length() - 1] == Separator())
|
||||||
|
result = path.substr(0, path.length() - 1);
|
||||||
|
else
|
||||||
|
result = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string ChopLeadingSeparator(const string& path)
|
||||||
|
{
|
||||||
|
if (path.length() == 1 && path[0] == Separator())
|
||||||
|
return path;
|
||||||
|
|
||||||
|
string result;
|
||||||
|
if (path.length()) {
|
||||||
|
if (path[0] == Separator()) {
|
||||||
|
result = path.substr(1, path.length() - 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string PathCat(const string& s1, const string& s2)
|
||||||
|
{
|
||||||
|
if (s2.length())
|
||||||
|
return ChopTrailingSeparator(s1) + Separator() + ChopLeadingSeparator(s2);
|
||||||
|
else
|
||||||
|
return s1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string Normalize(const string& path)
|
||||||
|
{
|
||||||
|
string newPath;
|
||||||
|
size_t length = path.length();
|
||||||
|
for (size_t index = 0; index < length; index++) {
|
||||||
|
if (path[index] == '/' || path[index] == '\\') {
|
||||||
|
if (index < length - 1) {
|
||||||
|
if (path[index+1] == '/' || path[index+1] == '\\')
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
newPath += Separator();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
newPath += path[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ChopTrailingSeparator(newPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const bool PathExists(const string& path)
|
||||||
|
{
|
||||||
|
#ifndef WIN32
|
||||||
|
struct stat buf;
|
||||||
|
return !stat(path.c_str(), &buf);
|
||||||
|
#else
|
||||||
|
struct _stat buf;
|
||||||
|
wstring wpath = OVUTF16::FromUTF8(path);
|
||||||
|
return !_wstat(wpath.c_str(), &buf);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static const bool IsDirectory(const string& path)
|
||||||
|
{
|
||||||
|
#ifndef WIN32
|
||||||
|
struct stat buf;
|
||||||
|
if (!stat(path.c_str(), &buf))
|
||||||
|
{
|
||||||
|
if (buf.st_mode & S_IFDIR)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
struct _stat buf;
|
||||||
|
wstring wpath = OVUTF16::FromUTF8(path);
|
||||||
|
if (!_wstat(wpath.c_str(), &buf))
|
||||||
|
{
|
||||||
|
if (buf.st_mode & S_IFDIR)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const OVFileTimestamp TimestampForPath(const string& path)
|
||||||
|
{
|
||||||
|
OVFileTimestamp timestamp;
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
struct stat buf;
|
||||||
|
if (!stat(path.c_str(), &buf))
|
||||||
|
{
|
||||||
|
timestamp = OVFileTimestamp(buf.st_mtimespec.tv_sec, buf.st_mtimespec.tv_nsec);
|
||||||
|
}
|
||||||
|
#elif defined(WIN32)
|
||||||
|
struct _stat buf;
|
||||||
|
wstring wpath = OVUTF16::FromUTF8(path);
|
||||||
|
if (!_wstat(wpath.c_str(), &buf))
|
||||||
|
{
|
||||||
|
timestamp = OVFileTimestamp(buf.st_mtime);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#error Sorry, no idea for Linux yet.
|
||||||
|
#endif
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool RemoveEverythingAtPath(const string& path);
|
||||||
|
static const string NormalizeByExpandingTilde(const string& path);
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVDirectoryHelper {
|
||||||
|
public:
|
||||||
|
static bool MakeDirectory(const string& path)
|
||||||
|
{
|
||||||
|
#ifndef WIN32
|
||||||
|
return !mkdir(path.c_str(), S_IRWXU);
|
||||||
|
#else
|
||||||
|
wstring wpath = OVUTF16::FromUTF8(path);
|
||||||
|
return CreateDirectoryW(wpath.c_str(), NULL) == TRUE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool MakeDirectoryWithImmediates(const string& path)
|
||||||
|
{
|
||||||
|
string realPath = OVPathHelper::NormalizeByExpandingTilde(path);
|
||||||
|
|
||||||
|
if (OVPathHelper::PathExists(realPath) && OVPathHelper::IsDirectory(realPath)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
string lastPart = OVPathHelper::DirectoryFromPath(realPath);
|
||||||
|
|
||||||
|
if (lastPart != realPath && !OVPathHelper::PathExists(lastPart)) {
|
||||||
|
if (!MakeDirectoryWithImmediates(lastPart))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MakeDirectory(realPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool CheckDirectory(const string& path)
|
||||||
|
{
|
||||||
|
string realPath = OVPathHelper::NormalizeByExpandingTilde(path);
|
||||||
|
if (OVPathHelper::PathExists(realPath))
|
||||||
|
return OVPathHelper::IsDirectory(realPath);
|
||||||
|
|
||||||
|
return MakeDirectoryWithImmediates(realPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const vector<string> Glob(const string& directory, const string& pattern = "*", const string& excludePattern = "", size_t depth = 1)
|
||||||
|
{
|
||||||
|
string sanitizedDirectory = OVPathHelper::NormalizeByExpandingTilde(directory);
|
||||||
|
|
||||||
|
OVWildcard expression(pattern);
|
||||||
|
OVWildcard negativeExpression(excludePattern);
|
||||||
|
vector<string> dirResult;
|
||||||
|
vector<string> fileResult;
|
||||||
|
struct dirent** namelist = NULL;
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
int count = scandir(sanitizedDirectory.c_str(), &namelist, NULL, NULL);
|
||||||
|
for (int index = 0; index < count; index++) {
|
||||||
|
struct dirent* entry = namelist[index];
|
||||||
|
bool isDir = entry->d_type == DT_DIR;
|
||||||
|
string name = entry->d_name;
|
||||||
|
#else
|
||||||
|
vector<pair<string, bool> > foundFiles;
|
||||||
|
WIN32_FIND_DATAW findData;
|
||||||
|
HANDLE findHandle = FindFirstFileW(OVUTF16::FromUTF8(OVPathHelper::PathCat(sanitizedDirectory, "*.*")).c_str(), &findData);
|
||||||
|
if (findHandle != INVALID_HANDLE_VALUE) {
|
||||||
|
foundFiles.push_back(pair<string, bool>(OVUTF8::FromUTF16(findData.cFileName), (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0));
|
||||||
|
|
||||||
|
while (FindNextFileW(findHandle, &findData))
|
||||||
|
{
|
||||||
|
foundFiles.push_back(pair<string, bool>(OVUTF8::FromUTF16(findData.cFileName), (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0));
|
||||||
|
}
|
||||||
|
FindClose(findHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t count = foundFiles.size();
|
||||||
|
for (size_t index = 0; index < count; index++) {
|
||||||
|
string name = foundFiles[index].first;
|
||||||
|
bool isDir = foundFiles[index].second;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((!depth || depth > 1) && isDir && name != "." && name != "..") {
|
||||||
|
vector<string> subResult = Glob(OVPathHelper::PathCat(sanitizedDirectory, name), pattern, excludePattern, depth ? depth - 1 : 0);
|
||||||
|
vector<string>::iterator iter = subResult.begin();
|
||||||
|
for ( ; iter != subResult.end() ; iter++)
|
||||||
|
dirResult.push_back(*iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name != "." && name != ".." && expression.match(name) && !negativeExpression.match(name)) {
|
||||||
|
fileResult.push_back(OVPathHelper::PathCat(sanitizedDirectory, name));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
free(entry);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
if (count != -1)
|
||||||
|
free(namelist);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sort(dirResult.begin(), dirResult.end());
|
||||||
|
sort(fileResult.begin(), fileResult.end());
|
||||||
|
for (vector<string>::iterator iter = dirResult.begin() ; iter != dirResult.end(); iter++)
|
||||||
|
fileResult.push_back(*iter);
|
||||||
|
|
||||||
|
return fileResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string TempDirectory()
|
||||||
|
{
|
||||||
|
#ifndef WIN32
|
||||||
|
return string("/tmp");
|
||||||
|
#else
|
||||||
|
WCHAR path[MAX_PATH + 1];
|
||||||
|
GetTempPathW(MAX_PATH, path);
|
||||||
|
return OVUTF8::FromUTF16(path);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string GenerateTempFilename(const string& prefix = "temp")
|
||||||
|
{
|
||||||
|
string pattern = OVPathHelper::PathCat(TempDirectory(), prefix + "-" + "XXXXXXXX");
|
||||||
|
#ifndef WIN32
|
||||||
|
char *p = (char*)calloc(1, pattern.length() + 1);
|
||||||
|
strcpy(p, pattern.c_str());
|
||||||
|
char *r = mktemp(p);
|
||||||
|
if (!r) {
|
||||||
|
free(p);
|
||||||
|
return string();
|
||||||
|
}
|
||||||
|
string result = r;
|
||||||
|
free(p);
|
||||||
|
return result;
|
||||||
|
#else
|
||||||
|
wstring wp = OVUTF16::FromUTF8(pattern);
|
||||||
|
size_t length = wp.length() + 1;
|
||||||
|
wchar_t* p = (wchar_t*)calloc(1, length * sizeof(wchar_t));
|
||||||
|
wcscpy_s(p, length, wp.c_str());
|
||||||
|
errno_t err = _wmktemp_s(p, length);
|
||||||
|
if (err != 0) {
|
||||||
|
free(p);
|
||||||
|
return string();
|
||||||
|
}
|
||||||
|
|
||||||
|
string result = OVUTF8::FromUTF16(p);
|
||||||
|
free(p);
|
||||||
|
return result;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string UserHomeDirectory()
|
||||||
|
{
|
||||||
|
#ifndef WIN32
|
||||||
|
const char* homePath = getenv("HOME");
|
||||||
|
if (homePath)
|
||||||
|
return string(homePath);
|
||||||
|
return TempDirectory();
|
||||||
|
#else
|
||||||
|
WCHAR path[MAX_PATH + 1];
|
||||||
|
HRESULT error = SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, path);
|
||||||
|
if (!error) {
|
||||||
|
return OVUTF8::FromUTF16(path);
|
||||||
|
}
|
||||||
|
return TempDirectory();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string UserApplicationDataDirectory(const string& applicationName)
|
||||||
|
{
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
return OVPathHelper::PathCat(UserHomeDirectory(), OVPathHelper::PathCat("/Library/", applicationName));
|
||||||
|
#elif defined(WIN32)
|
||||||
|
WCHAR path[MAX_PATH + 1];
|
||||||
|
HRESULT error = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, path);
|
||||||
|
if (!error) {
|
||||||
|
return OVPathHelper::PathCat(OVUTF8::FromUTF16(path), applicationName);
|
||||||
|
}
|
||||||
|
return OVPathHelper::PathCat(TempDirectory(), applicationName);
|
||||||
|
#else
|
||||||
|
return OVPathHelper::PathCat(UserHomeDirectory(), string(".") + applicationName);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string UserApplicationSupportDataDirectory(const string& applicationName)
|
||||||
|
{
|
||||||
|
#ifdef __APPLE__
|
||||||
|
return OVPathHelper::PathCat(UserHomeDirectory(), OVPathHelper::PathCat("/Library/Application Support", applicationName));
|
||||||
|
#else
|
||||||
|
return UserApplicationDataDirectory(applicationName);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string UserPreferencesDirectory(const string& applicationName)
|
||||||
|
{
|
||||||
|
#ifdef __APPLE__
|
||||||
|
return OVPathHelper::NormalizeByExpandingTilde("~/Library/Preferences");
|
||||||
|
#else
|
||||||
|
return UserApplicationDataDirectory(applicationName);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const string OVPathHelper::NormalizeByExpandingTilde(const string& path)
|
||||||
|
{
|
||||||
|
string newPath = Normalize(path);
|
||||||
|
|
||||||
|
if (newPath.length()) {
|
||||||
|
if (newPath[0] == '~') {
|
||||||
|
newPath = OVPathHelper::PathCat(OVDirectoryHelper::UserHomeDirectory(), newPath.substr(1, newPath.length()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool OVPathHelper::RemoveEverythingAtPath(const string& path)
|
||||||
|
{
|
||||||
|
if (!PathExists(path)) return false;
|
||||||
|
|
||||||
|
if (IsDirectory(path)) {
|
||||||
|
vector<string> files = OVDirectoryHelper::Glob(path, "*", "", 0);
|
||||||
|
vector<string>::iterator iter = files.begin();
|
||||||
|
for ( ; iter != files.end(); iter++) {
|
||||||
|
if (!RemoveEverythingAtPath(*iter))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
return !rmdir(path.c_str());
|
||||||
|
#else
|
||||||
|
wstring wpath = OVUTF16::FromUTF8(path);
|
||||||
|
return RemoveDirectoryW(wpath.c_str()) == TRUE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#ifndef WIN32
|
||||||
|
return !unlink(path.c_str());
|
||||||
|
#else
|
||||||
|
wstring wpath = OVUTF16::FromUTF8(path);
|
||||||
|
return DeleteFileW(wpath.c_str()) == TRUE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,92 @@
|
||||||
|
//
|
||||||
|
// OVFrameworkInfo.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVFrameworkVersion_h
|
||||||
|
#define OVFrameworkVersion_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVBase.h>
|
||||||
|
#else
|
||||||
|
#include "OVBase.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVFrameworkInfo {
|
||||||
|
public:
|
||||||
|
static unsigned int MajorVersion()
|
||||||
|
{
|
||||||
|
return c_MajorVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int MinorVersion()
|
||||||
|
{
|
||||||
|
return c_MinorVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int TinyVersion()
|
||||||
|
{
|
||||||
|
return c_TinyVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int Version()
|
||||||
|
{
|
||||||
|
return ((c_MajorVersion & 0xff) << 24) | ((c_MinorVersion & 0xff)<< 16) | (c_TinyVersion & 0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int BuildNumber()
|
||||||
|
{
|
||||||
|
return c_FrameworkBuildNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string VersionString(bool withBuildNumber = false)
|
||||||
|
{
|
||||||
|
stringstream s;
|
||||||
|
s << c_MajorVersion << "." << c_MinorVersion << "." << c_TinyVersion;
|
||||||
|
if (withBuildNumber)
|
||||||
|
s << "." << c_FrameworkBuildNumber;
|
||||||
|
|
||||||
|
return s.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string VersionStringWithBuildNumber()
|
||||||
|
{
|
||||||
|
return VersionString(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static const unsigned int c_MajorVersion;
|
||||||
|
static const unsigned int c_MinorVersion;
|
||||||
|
static const unsigned int c_TinyVersion;
|
||||||
|
static const unsigned int c_FrameworkBuildNumber;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,49 @@
|
||||||
|
//
|
||||||
|
// OVInputMethod.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVInputMethod_h
|
||||||
|
#define OVInputMethod_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVModule.h>
|
||||||
|
#else
|
||||||
|
#include "OVModule.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVInputMethod : public OVModule {
|
||||||
|
public:
|
||||||
|
virtual bool isInputMethod() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,303 @@
|
||||||
|
//
|
||||||
|
// OVKey.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu and Weizhong Yang
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVKey_h
|
||||||
|
#define OVKey_h
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// keyCode() is 0 if receivedString() is a non-ASCII glyph/string
|
||||||
|
class OVKeyInterface : public OVBase {
|
||||||
|
public:
|
||||||
|
virtual const string receivedString() const = 0;
|
||||||
|
virtual unsigned int keyCode() const = 0;
|
||||||
|
virtual bool isAltPressed() const = 0;
|
||||||
|
virtual bool isOptPressed() const = 0;
|
||||||
|
virtual bool isCtrlPressed() const = 0;
|
||||||
|
virtual bool isShiftPressed() const = 0;
|
||||||
|
virtual bool isCommandPressed() const = 0;
|
||||||
|
virtual bool isNumLockOn() const = 0;
|
||||||
|
virtual bool isCapsLockOn() const = 0;
|
||||||
|
|
||||||
|
// a direct text key carries a composed glyph (or a string) that semantically differs from the intended keystroke
|
||||||
|
// (i.e. a half-width char stroke but with a composed, full-width char output)
|
||||||
|
virtual bool isDirectTextKey() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVKeyImpl : public OVKeyInterface {
|
||||||
|
public:
|
||||||
|
virtual bool shouldDelete() const = 0;
|
||||||
|
virtual OVKeyImpl* copy() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVKey : public OVKeyInterface {
|
||||||
|
public:
|
||||||
|
OVKey(OVKeyImpl* keyImpl = 0)
|
||||||
|
: m_keyImpl(keyImpl)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
OVKey(const OVKey& aKey)
|
||||||
|
{
|
||||||
|
m_keyImpl = aKey.m_keyImpl ? aKey.m_keyImpl->copy() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
~OVKey()
|
||||||
|
{
|
||||||
|
if (m_keyImpl) {
|
||||||
|
if (m_keyImpl->shouldDelete()) {
|
||||||
|
delete m_keyImpl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OVKey& operator=(const OVKey& aKey)
|
||||||
|
{
|
||||||
|
if (m_keyImpl) {
|
||||||
|
if (m_keyImpl->shouldDelete()) {
|
||||||
|
delete m_keyImpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_keyImpl = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_keyImpl = aKey.m_keyImpl ? aKey.m_keyImpl->copy() : 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool operator==(const OVKey& key) const
|
||||||
|
{
|
||||||
|
if (isAltPressed() == key.isAltPressed() && isOptPressed() == key.isOptPressed() && isCtrlPressed() == key.isCtrlPressed() && isShiftPressed() == key.isShiftPressed() && isCommandPressed() == key.isCommandPressed())
|
||||||
|
if (!keyCode() && !key.keyCode())
|
||||||
|
return receivedString() == key.receivedString();
|
||||||
|
else
|
||||||
|
return keyCode() == key.keyCode();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool operator<(const OVKey& key) const
|
||||||
|
{
|
||||||
|
if (keyCode() < key.keyCode()) return true;
|
||||||
|
if (keyCode() > key.keyCode()) return false;
|
||||||
|
|
||||||
|
if (!keyCode() && !key.keyCode()) {
|
||||||
|
if (receivedString() < key.receivedString()) return true;
|
||||||
|
if (receivedString() > key.receivedString()) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isAltPressed() != key.isAltPressed()) {
|
||||||
|
if (key.isAltPressed()) return true;
|
||||||
|
if (isAltPressed()) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isOptPressed() != key.isOptPressed()) {
|
||||||
|
if (key.isOptPressed()) return true;
|
||||||
|
if (isOptPressed()) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCtrlPressed() != key.isCtrlPressed()) {
|
||||||
|
if (key.isCtrlPressed()) return true;
|
||||||
|
if (isCtrlPressed()) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isShiftPressed() != key.isShiftPressed()) {
|
||||||
|
if (key.isShiftPressed()) return true;
|
||||||
|
if (isShiftPressed()) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCommandPressed() != key.isCommandPressed()) {
|
||||||
|
if (key.isCommandPressed()) return true;
|
||||||
|
if (isCommandPressed()) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNumLockOn() != key.isNumLockOn()) {
|
||||||
|
if (key.isNumLockOn()) return true;
|
||||||
|
if (isNumLockOn()) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCapsLockOn() != key.isCapsLockOn()) {
|
||||||
|
if (key.isCapsLockOn()) return true;
|
||||||
|
if (isCapsLockOn()) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual const string receivedString() const
|
||||||
|
{
|
||||||
|
return m_keyImpl ? m_keyImpl->receivedString() : string();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual unsigned int keyCode() const
|
||||||
|
{
|
||||||
|
return m_keyImpl ? m_keyImpl->keyCode() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isAltPressed() const
|
||||||
|
{
|
||||||
|
return m_keyImpl ? m_keyImpl->isAltPressed() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isOptPressed() const
|
||||||
|
{
|
||||||
|
return m_keyImpl ? m_keyImpl->isOptPressed() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isCtrlPressed() const
|
||||||
|
{
|
||||||
|
return m_keyImpl ? m_keyImpl->isCtrlPressed() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isShiftPressed() const
|
||||||
|
{
|
||||||
|
return m_keyImpl ? m_keyImpl->isShiftPressed() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isCommandPressed() const
|
||||||
|
{
|
||||||
|
return m_keyImpl ? m_keyImpl->isCommandPressed() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isNumLockOn() const
|
||||||
|
{
|
||||||
|
return m_keyImpl ? m_keyImpl->isNumLockOn() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isCapsLockOn() const
|
||||||
|
{
|
||||||
|
return m_keyImpl ? m_keyImpl->isCapsLockOn() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isDirectTextKey() const
|
||||||
|
{
|
||||||
|
return m_keyImpl ? m_keyImpl->isDirectTextKey() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isKeyCodePrintable() const
|
||||||
|
{
|
||||||
|
if (keyCode() >= 32 && keyCode() <= 126)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isKeyCodeNumeric() const
|
||||||
|
{
|
||||||
|
if (keyCode() >= '0' && keyCode() <= '9')
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isKeyCodeAlpha() const
|
||||||
|
{
|
||||||
|
if (keyCode() >= 'A' && keyCode() <= 'Z' || keyCode() >= 'a' && keyCode() <= 'z')
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isCombinedFunctionKey() const
|
||||||
|
{
|
||||||
|
return isCtrlPressed() || isAltPressed() || isOptPressed() || isCommandPressed();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isPrintable() const
|
||||||
|
{
|
||||||
|
size_t rssize = receivedString().size();
|
||||||
|
unsigned int code = keyCode();
|
||||||
|
|
||||||
|
if (!rssize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (rssize > 1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return ((code < 128 && isprint((char)code)) || code > 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
OVKeyImpl* m_keyImpl;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef vector<OVKey> OVKeyVector;
|
||||||
|
|
||||||
|
class OVKeyCode {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
Delete = 127,
|
||||||
|
Backspace = 8,
|
||||||
|
Up = 30,
|
||||||
|
Down = 31,
|
||||||
|
Left = 28,
|
||||||
|
Right = 29,
|
||||||
|
Home = 1,
|
||||||
|
End = 4,
|
||||||
|
PageUp = 11,
|
||||||
|
PageDown = 12,
|
||||||
|
Tab = 9,
|
||||||
|
Esc = 27,
|
||||||
|
Space = 32,
|
||||||
|
Return = 13,
|
||||||
|
Enter = Return,
|
||||||
|
LeftShift = 0x10001,
|
||||||
|
RightShift = 0x10002,
|
||||||
|
CapsLock = 0x10010,
|
||||||
|
MacEnter = 0x10020,
|
||||||
|
F1 = 0x11001,
|
||||||
|
F2 = 0x11002,
|
||||||
|
F3 = 0x11003,
|
||||||
|
F4 = 0x11004,
|
||||||
|
F5 = 0x11005,
|
||||||
|
F6 = 0x11006,
|
||||||
|
F7 = 0x11007,
|
||||||
|
F8 = 0x11008,
|
||||||
|
F9 = 0x11009,
|
||||||
|
F10 = 0x11010,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVKeyMask {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
Alt = 0x0001,
|
||||||
|
Opt = 0x0002,
|
||||||
|
AltOpt = 0x0003,
|
||||||
|
Ctrl = 0x0004,
|
||||||
|
Shift = 0x008,
|
||||||
|
Command = 0x0010,
|
||||||
|
NumLock = 0x0020,
|
||||||
|
CapsLock = 0x0040,
|
||||||
|
DirectText = 0x0080
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,49 @@
|
||||||
|
//
|
||||||
|
// OVKeyPreprocessor.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVKeyPreprocessor_h
|
||||||
|
#define OVKeyPreprocessor_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVModule.h>
|
||||||
|
#else
|
||||||
|
#include "OVModule.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVKeyPreprocessor : public OVModule {
|
||||||
|
public:
|
||||||
|
virtual bool isPreprocessor() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,175 @@
|
||||||
|
//
|
||||||
|
// OVKeyValueMap.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVKeyValueMap_h
|
||||||
|
#define OVKeyValueMap_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVBase.h>
|
||||||
|
#else
|
||||||
|
#include "OVBase.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVKeyValueMapInterface : public OVBase {
|
||||||
|
public:
|
||||||
|
virtual bool isReadOnly() = 0;
|
||||||
|
virtual bool setKeyStringValue(const string& key, const string& value) = 0;
|
||||||
|
virtual bool hasKey(const string& key) = 0;
|
||||||
|
virtual const string stringValueForKey(const string& key) = 0;
|
||||||
|
|
||||||
|
virtual bool setKeyIntValue(const string& key, int value)
|
||||||
|
{
|
||||||
|
stringstream sstr;
|
||||||
|
sstr << value;
|
||||||
|
return setKeyStringValue(key, sstr.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool setKeyBoolValue(const string& key, bool value)
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
return setKeyStringValue(key, "true");
|
||||||
|
|
||||||
|
return setKeyStringValue(key, "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int intValueForKey(const string& key)
|
||||||
|
{
|
||||||
|
string value = stringValueForKey(key);
|
||||||
|
return atoi(value.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const string stringValueForKeyWithDefault(const string& key, const string& defaultValue = "", bool setIfNotFound = true)
|
||||||
|
{
|
||||||
|
if (hasKey(key))
|
||||||
|
return stringValueForKey(key);
|
||||||
|
|
||||||
|
if (setIfNotFound)
|
||||||
|
setKeyStringValue(key, defaultValue);
|
||||||
|
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const string operator[](const string& key)
|
||||||
|
{
|
||||||
|
return stringValueForKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isKeyTrue(const string& key)
|
||||||
|
{
|
||||||
|
if (!hasKey(key))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
string value = stringValueForKey(key);
|
||||||
|
|
||||||
|
if (atoi(value.c_str()) > 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (value == "true")
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVKeyValueMapImpl : public OVKeyValueMapInterface {
|
||||||
|
public:
|
||||||
|
virtual bool shouldDelete() = 0;
|
||||||
|
virtual OVKeyValueMapImpl* copy() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVKeyValueMap : public OVKeyValueMapInterface {
|
||||||
|
public:
|
||||||
|
OVKeyValueMap(OVKeyValueMapImpl* keyValueMapImpl = 0)
|
||||||
|
: m_keyValueMapImpl(keyValueMapImpl)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
OVKeyValueMap(const OVKeyValueMap& aKeyValueMap)
|
||||||
|
{
|
||||||
|
m_keyValueMapImpl = aKeyValueMap.m_keyValueMapImpl ? aKeyValueMap.m_keyValueMapImpl->copy() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
~OVKeyValueMap()
|
||||||
|
{
|
||||||
|
if (m_keyValueMapImpl) {
|
||||||
|
if (m_keyValueMapImpl->shouldDelete()) {
|
||||||
|
delete m_keyValueMapImpl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OVKeyValueMap& operator=(const OVKeyValueMap& aKeyValueMap)
|
||||||
|
{
|
||||||
|
if (m_keyValueMapImpl) {
|
||||||
|
if (m_keyValueMapImpl->shouldDelete()) {
|
||||||
|
delete m_keyValueMapImpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_keyValueMapImpl = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_keyValueMapImpl = aKeyValueMap.m_keyValueMapImpl ? aKeyValueMap.m_keyValueMapImpl->copy() : 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual bool isReadOnly()
|
||||||
|
{
|
||||||
|
return m_keyValueMapImpl ? m_keyValueMapImpl->isReadOnly() : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool setKeyStringValue(const string& key, const string& value)
|
||||||
|
{
|
||||||
|
return m_keyValueMapImpl ? m_keyValueMapImpl->setKeyStringValue(key, value) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool hasKey(const string& key)
|
||||||
|
{
|
||||||
|
return m_keyValueMapImpl ? m_keyValueMapImpl->hasKey(key) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const string stringValueForKey(const string& key)
|
||||||
|
{
|
||||||
|
return m_keyValueMapImpl ? m_keyValueMapImpl->stringValueForKey(key) : string();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const string stringValueForKeyWithDefault(const string& key, const string& defaultValue = "", bool setIfNotFound = true)
|
||||||
|
{
|
||||||
|
return m_keyValueMapImpl ? m_keyValueMapImpl->stringValueForKeyWithDefault(key, defaultValue, setIfNotFound) : string();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
OVKeyValueMapImpl* m_keyValueMapImpl;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,50 @@
|
||||||
|
//
|
||||||
|
// OVLoaderBase.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVLoaderBase_h
|
||||||
|
#define OVLoaderBase_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVModule.h>
|
||||||
|
#else
|
||||||
|
#include "OVModule.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVLoader : public OVBase {
|
||||||
|
public:
|
||||||
|
virtual OVLoaderService* loaderService() = 0;
|
||||||
|
virtual OVModule* moduleForIdentifier(const string& identifier) = 0;
|
||||||
|
virtual vector<string> moduleIdentifiers() = 0;
|
||||||
|
virtual vector<string> moduleIdentifiersForConditions(bool preprocessor, bool inputMethod, bool outputFilter) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,120 @@
|
||||||
|
//
|
||||||
|
// OVLoaderService.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVLoaderService_h
|
||||||
|
#define OVLoaderService_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVBase.h>
|
||||||
|
#include <OpenVanilla/OVDatabaseService.h>
|
||||||
|
#include <OpenVanilla/OVEncodingService.h>
|
||||||
|
#include <OpenVanilla/OVKey.h>
|
||||||
|
#else
|
||||||
|
#include "OVBase.h"
|
||||||
|
#include "OVDatabaseService.h"
|
||||||
|
#include "OVEncodingService.h"
|
||||||
|
#include "OVKey.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVLogEmitter : public OVBase {
|
||||||
|
public:
|
||||||
|
virtual const string sectionName() const = 0;
|
||||||
|
virtual void setSectionName(const string& sectionName) = 0;
|
||||||
|
virtual void emitLog(const string& logEntry) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVLogStringBuffer : public stringbuf {
|
||||||
|
public:
|
||||||
|
OVLogStringBuffer(OVLogEmitter* logEmitter = 0)
|
||||||
|
: m_logEmitter(logEmitter)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int sync() {
|
||||||
|
if (str().length()) {
|
||||||
|
if (m_logEmitter)
|
||||||
|
m_logEmitter->emitLog(str());
|
||||||
|
else
|
||||||
|
cerr << "Log: " << str();
|
||||||
|
|
||||||
|
str(string());
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear the buffer
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual OVLogEmitter* logEmitter() const
|
||||||
|
{
|
||||||
|
return m_logEmitter;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setLogEmitter(OVLogEmitter* logEmitter)
|
||||||
|
{
|
||||||
|
m_logEmitter = logEmitter;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
OVLogEmitter* m_logEmitter;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVLoaderService : public OVBase {
|
||||||
|
public:
|
||||||
|
virtual void beep() = 0;
|
||||||
|
virtual void notify(const string& message) = 0;
|
||||||
|
virtual void HTMLNotify(const string& content) = 0;
|
||||||
|
|
||||||
|
virtual const string locale() const = 0;
|
||||||
|
virtual const OVKey makeOVKey(int characterCode, bool alt = false, bool opt = false, bool ctrl = false, bool shift = false, bool command = false, bool capsLock = false, bool numLock = false) = 0;
|
||||||
|
virtual const OVKey makeOVKey(const string& receivedString, bool alt = false, bool opt = false, bool ctrl = false, bool shift = false, bool command = false, bool capsLock = false, bool numLock = false) = 0;
|
||||||
|
|
||||||
|
virtual ostream& logger(const string& sectionName = "") = 0;
|
||||||
|
|
||||||
|
virtual OVDatabaseService* defaultDatabaseService() = 0;
|
||||||
|
virtual OVDatabaseService* CINDatabaseService() = 0;
|
||||||
|
virtual OVDatabaseService* SQLiteDatabaseService() = 0;
|
||||||
|
|
||||||
|
virtual OVEncodingService* encodingService() = 0;
|
||||||
|
|
||||||
|
virtual void __reserved1(const string&) = 0;
|
||||||
|
virtual void __reserved2(const string&) = 0;
|
||||||
|
virtual void __reserved3(const string&) = 0;
|
||||||
|
virtual void __reserved4(const string&) = 0;
|
||||||
|
virtual const string __reserved5() const = 0;
|
||||||
|
virtual void __reserved6(const string&) = 0;
|
||||||
|
virtual void __reserved7(const string&, const string &) = 0;
|
||||||
|
virtual void* __reserved8(const string&) = 0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,136 @@
|
||||||
|
//
|
||||||
|
// OVLocalization.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVLocalization_h
|
||||||
|
#define OVLocalization_h
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include "OVStringHelper.h"
|
||||||
|
#include "OVWildcard.h"
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVLocale {
|
||||||
|
public:
|
||||||
|
static const string POSIXLocaleID(const string& locale)
|
||||||
|
{
|
||||||
|
string n = OVStringHelper::StringByReplacingOccurrencesOfStringWithString(locale, "-", "_");
|
||||||
|
|
||||||
|
if (OVWildcard::Match(n, "zh_Hant")) {
|
||||||
|
return "zh_TW";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OVWildcard::Match(n, "zh_Hans")) {
|
||||||
|
return "zh_CN";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OVWildcard::Match(n, "zh_HK")) {
|
||||||
|
return "zh_TW";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OVWildcard::Match(n, "zh_SG")) {
|
||||||
|
return "zh_CN";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OVWildcard::Match(n, "en_*")) {
|
||||||
|
return "en";
|
||||||
|
}
|
||||||
|
|
||||||
|
return locale;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<class T> class OVLocalization {
|
||||||
|
public:
|
||||||
|
static const void SetDefaultLocale(const string& locale)
|
||||||
|
{
|
||||||
|
SharedInstance()->m_defaultLocale = locale.length() ? OVLocale::POSIXLocaleID(locale) : string("en");
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string S(const string& locale, const string& text)
|
||||||
|
{
|
||||||
|
return SharedInstance()->m_table(locale, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string S(const string& text)
|
||||||
|
{
|
||||||
|
return SharedInstance()->m_table(SharedInstance()->m_defaultLocale, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static OVLocalization<T>* SharedInstance()
|
||||||
|
{
|
||||||
|
static OVLocalization<T>* instance = 0;
|
||||||
|
if (!instance) {
|
||||||
|
instance = new OVLocalization<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
OVLocalization<T>()
|
||||||
|
: m_defaultLocale("en")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
T m_table;
|
||||||
|
string m_defaultLocale;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVLocalizationStringTable {
|
||||||
|
public:
|
||||||
|
const string operator()(const string& locale, const string& text) const
|
||||||
|
{
|
||||||
|
// maybe we'll have fallback logic later here
|
||||||
|
map<string, map<string, string> >::const_iterator i = m_table.find(locale);
|
||||||
|
if (i == m_table.end()) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
map<string, string>::const_iterator j = (*i).second.find(text);
|
||||||
|
if (j == (*i).second.end()) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (*j).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void add(const string& locale, const string& original, const string& localized)
|
||||||
|
{
|
||||||
|
m_table[locale][original] = localized;
|
||||||
|
}
|
||||||
|
|
||||||
|
map<string, map<string, string> > m_table;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,146 @@
|
||||||
|
//
|
||||||
|
// OVModule.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVModule_h
|
||||||
|
#define OVModule_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVEventHandlingContext.h>
|
||||||
|
#include <OpenVanilla/OVKeyValueMap.h>
|
||||||
|
#include <OpenVanilla/OVPathInfo.h>
|
||||||
|
#else
|
||||||
|
#include "OVEventHandlingContext.h"
|
||||||
|
#include "OVKeyValueMap.h"
|
||||||
|
#include "OVPathInfo.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVModule : public OVBase {
|
||||||
|
public:
|
||||||
|
OVModule()
|
||||||
|
: m_initialized(false)
|
||||||
|
, m_usable(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isInitialized() const
|
||||||
|
{
|
||||||
|
return m_initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isUsable() const
|
||||||
|
{
|
||||||
|
return m_usable;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isPreprocessor() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isInputMethod() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isOutputFilter() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isAroundFilter() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the smaller it gets, the closer the the filter gets to the commit event
|
||||||
|
virtual int suggestedOrder() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual OVEventHandlingContext* createContext()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const string identifier() const = 0;
|
||||||
|
|
||||||
|
virtual const string localizedName(const string& locale)
|
||||||
|
{
|
||||||
|
return identifier();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool moduleInitialize(OVPathInfo* pathInfo, OVLoaderService* loaderService)
|
||||||
|
{
|
||||||
|
if (m_initialized)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_usable = initialize(pathInfo, loaderService);
|
||||||
|
m_initialized = true;
|
||||||
|
return m_usable;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool initialize(OVPathInfo* pathInfo, OVLoaderService* loaderService)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void finalize()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void loadConfig(OVKeyValueMap* moduleConfig, OVLoaderService* loaderService)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void saveConfig(OVKeyValueMap* moduleConfig, OVLoaderService* loaderService)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AroundFilterDisplayOption {
|
||||||
|
ShownAsPreprocessor,
|
||||||
|
ShownAsOutputFilter,
|
||||||
|
ShownAsBoth
|
||||||
|
};
|
||||||
|
|
||||||
|
// around filter modules need to tell loader how it wishes to be placed in the menu
|
||||||
|
virtual AroundFilterDisplayOption aroundFilterPreferredDisplayOption()
|
||||||
|
{
|
||||||
|
return ShownAsBoth;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool m_initialized;
|
||||||
|
bool m_usable;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,100 @@
|
||||||
|
//
|
||||||
|
// OVModulePackage.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVModulePackage_h
|
||||||
|
#define OVModulePackage_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVFrameworkInfo.h>
|
||||||
|
#include <OpenVanilla/OVModule.h>
|
||||||
|
#else
|
||||||
|
#include "OVFrameworkInfo.h"
|
||||||
|
#include "OVModule.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#define OVEXPORT __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define OVEXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVModuleClassWrapperBase : public OVBase {
|
||||||
|
public:
|
||||||
|
virtual OVModule* newModule()
|
||||||
|
{
|
||||||
|
// this member function can't be abstract, or vector<OVModuleClassWrapperBase> wouldn't instantiate under VC++ 2005
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T> class OVModuleClassWrapper : public OVModuleClassWrapperBase {
|
||||||
|
public:
|
||||||
|
virtual OVModule* newModule()
|
||||||
|
{
|
||||||
|
return new T;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// we encourage people to do the real initialization in initialize
|
||||||
|
class OVModulePackage : OVBase {
|
||||||
|
public:
|
||||||
|
~OVModulePackage()
|
||||||
|
{
|
||||||
|
vector<OVModuleClassWrapperBase*>::iterator iter = m_moduleVector.begin();
|
||||||
|
for ( ; iter != m_moduleVector.end(); ++iter)
|
||||||
|
delete *iter;
|
||||||
|
}
|
||||||
|
virtual bool initialize(OVPathInfo* , OVLoaderService* loaderService)
|
||||||
|
{
|
||||||
|
// in your derived class, add class wrappers to m_moduleVector
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void finalize()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual size_t numberOfModules(OVLoaderService*)
|
||||||
|
{
|
||||||
|
return m_moduleVector.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual OVModule* moduleAtIndex(size_t index, OVLoaderService*)
|
||||||
|
{
|
||||||
|
if (index > m_moduleVector.size()) return 0;
|
||||||
|
return m_moduleVector[index]->newModule();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
vector<OVModuleClassWrapperBase*> m_moduleVector;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,49 @@
|
||||||
|
//
|
||||||
|
// OVOutputFilter.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVOutputFilter_h
|
||||||
|
#define OVOutputFilter_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVModule.h>
|
||||||
|
#else
|
||||||
|
#include "OVModule.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVOutputFilter : public OVModule {
|
||||||
|
public:
|
||||||
|
virtual bool isOutputFilter() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,63 @@
|
||||||
|
//
|
||||||
|
// OVPathInfo.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVPathInfo_h
|
||||||
|
#define OVPathInfo_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVFileHelper.h>
|
||||||
|
#else
|
||||||
|
#include "OVFileHelper.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
struct OVPathInfo {
|
||||||
|
string loadedPath;
|
||||||
|
string resourcePath;
|
||||||
|
string writablePath;
|
||||||
|
|
||||||
|
static const OVPathInfo DefaultPathInfo() {
|
||||||
|
string tmpdir = OVDirectoryHelper::TempDirectory();
|
||||||
|
OVPathInfo pathInfo;
|
||||||
|
|
||||||
|
pathInfo.loadedPath = tmpdir;
|
||||||
|
pathInfo.resourcePath = tmpdir;
|
||||||
|
pathInfo.writablePath = tmpdir;
|
||||||
|
return pathInfo;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline ostream& operator<<(ostream& stream, const OVPathInfo& info)
|
||||||
|
{
|
||||||
|
stream << "OVPathInfo = (loaded path = " << info.loadedPath << ", resource path = " << info.resourcePath << ", writable path = " << info.writablePath << ")";
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,249 @@
|
||||||
|
//
|
||||||
|
// OVSQLiteDatabaseService.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVSQLiteDatabaseService_h
|
||||||
|
#define OVSQLiteDatabaseService_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVDatabaseService.h>
|
||||||
|
#include <OpenVanilla/OVSQLiteWrapper.h>
|
||||||
|
#include <OpenVanilla/OVWildcard.h>
|
||||||
|
#else
|
||||||
|
#include "OVDatabaseService.h"
|
||||||
|
#include "OVSQLiteWrapper.h"
|
||||||
|
#include "OVWildcard.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVSQLiteHelper {
|
||||||
|
public:
|
||||||
|
static const pair<string, string> SQLiteStringFromWildcard(const OVWildcard& wildcard)
|
||||||
|
{
|
||||||
|
const string& expression = wildcard.expression();
|
||||||
|
string sqlstr;
|
||||||
|
|
||||||
|
char mOC = wildcard.matchOneChar();
|
||||||
|
char mZOMC = wildcard.matchZeroOrMoreChar();
|
||||||
|
char escChar = mZOMC ? mZOMC : mOC;
|
||||||
|
|
||||||
|
for (string::const_iterator iter = expression.begin() ; iter != expression.end() ; ++iter) {
|
||||||
|
if (*iter == mOC) {
|
||||||
|
sqlstr += '_';
|
||||||
|
}
|
||||||
|
else if (*iter == mZOMC) {
|
||||||
|
sqlstr += '%';
|
||||||
|
}
|
||||||
|
else if (*iter == '_') {
|
||||||
|
sqlstr += escChar;
|
||||||
|
sqlstr += '_';
|
||||||
|
}
|
||||||
|
else if (*iter == '%') {
|
||||||
|
sqlstr += escChar;
|
||||||
|
sqlstr += '%';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sqlstr += *iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pair<string, string>(sqlstr, string(1, escChar));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVSQLiteDatabaseService;
|
||||||
|
|
||||||
|
class OVSQLiteKeyValueDataTable : public OVKeyValueDataTableInterface {
|
||||||
|
public:
|
||||||
|
virtual const vector<string> valuesForKey(const string& key);
|
||||||
|
virtual const vector<pair<string, string> > valuesForKey(const OVWildcard& expression);
|
||||||
|
virtual const string valueForProperty(const string& property);
|
||||||
|
virtual const vector<string> keysForValue(const string& value);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
OVSQLiteDatabaseService* m_source;
|
||||||
|
string m_tableName;
|
||||||
|
|
||||||
|
friend class OVSQLiteDatabaseService;
|
||||||
|
OVSQLiteKeyValueDataTable(OVSQLiteDatabaseService* source, const string& tableName)
|
||||||
|
: m_source(source)
|
||||||
|
, m_tableName(tableName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVSQLiteDatabaseService : public OVDatabaseService {
|
||||||
|
public:
|
||||||
|
~OVSQLiteDatabaseService()
|
||||||
|
{
|
||||||
|
if (m_ownsConnection)
|
||||||
|
delete m_connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const vector<string> tables(const OVWildcard& filter = string("*"))
|
||||||
|
{
|
||||||
|
pair<string, string> exp = OVSQLiteHelper::SQLiteStringFromWildcard(filter);
|
||||||
|
|
||||||
|
vector<string> result;
|
||||||
|
OVSQLiteStatement* statement = m_connection->prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name LIKE %Q ESCAPE %Q ORDER BY name", exp.first.c_str(), exp.second.c_str());
|
||||||
|
if (statement) {
|
||||||
|
while (statement->step() == SQLITE_ROW) {
|
||||||
|
result.push_back(statement->textOfColumn(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
delete statement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool tableSupportsValueToKeyLookup(const string &tableName)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual OVKeyValueDataTableInterface* createKeyValueDataTableInterface(const string& name, bool suggestedCaseSensitivity = false)
|
||||||
|
{
|
||||||
|
return new OVSQLiteKeyValueDataTable(this, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const string valueForPropertyInTable(const string& property, const string& name)
|
||||||
|
{
|
||||||
|
OVSQLiteStatement* statement = m_connection->prepare("SELECT VALUE FROM %Q WHERE KEY = ?", name.c_str());
|
||||||
|
string result;
|
||||||
|
|
||||||
|
if (statement) {
|
||||||
|
statement->bindTextToColumn(string(OVPropertyStringInternalPrefix) + property, 1);
|
||||||
|
|
||||||
|
if (statement->step() == SQLITE_ROW) {
|
||||||
|
result = statement->textOfColumn(0);
|
||||||
|
while (statement->step() == SQLITE_ROW) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete statement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const string filename()
|
||||||
|
{
|
||||||
|
return m_connection->filename();
|
||||||
|
}
|
||||||
|
|
||||||
|
static OVSQLiteDatabaseService* Create(const string& filename = ":memory:")
|
||||||
|
{
|
||||||
|
OVSQLiteConnection* connection = OVSQLiteConnection::Open(filename);
|
||||||
|
if (!connection)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return new OVSQLiteDatabaseService(connection, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static OVSQLiteDatabaseService* ServiceWithExistingConnection(OVSQLiteConnection* connection, bool ownsConnection = false)
|
||||||
|
{
|
||||||
|
return new OVSQLiteDatabaseService(connection, ownsConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
OVSQLiteConnection* connection()
|
||||||
|
{
|
||||||
|
return m_connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
friend class OVSQLiteKeyValueDataTable;
|
||||||
|
|
||||||
|
OVSQLiteDatabaseService(OVSQLiteConnection* connection, bool ownsConnection = false)
|
||||||
|
: m_connection(connection)
|
||||||
|
, m_ownsConnection(ownsConnection)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
OVSQLiteConnection* m_connection;
|
||||||
|
bool m_ownsConnection;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const vector<string> OVSQLiteKeyValueDataTable::valuesForKey(const string& key)
|
||||||
|
{
|
||||||
|
vector<string> result;
|
||||||
|
OVSQLiteStatement* statement = m_source->connection()->prepare("SELECT value FROM %Q WHERE key = %Q", m_tableName.c_str(), key.c_str());
|
||||||
|
if (statement) {
|
||||||
|
while (statement->step() == SQLITE_ROW) {
|
||||||
|
result.push_back(statement->textOfColumn(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
delete statement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const vector<string> OVSQLiteKeyValueDataTable::keysForValue(const string& value)
|
||||||
|
{
|
||||||
|
vector<string> result;
|
||||||
|
OVSQLiteStatement* statement = m_source->connection()->prepare("SELECT key FROM %Q WHERE value = %Q", m_tableName.c_str(), value.c_str());
|
||||||
|
if (statement) {
|
||||||
|
while (statement->step() == SQLITE_ROW) {
|
||||||
|
string key = statement->textOfColumn(0);
|
||||||
|
|
||||||
|
// we don't want property get into it
|
||||||
|
if (!OVWildcard::Match(key, OVPropertyStringInternalPrefix "*")) {
|
||||||
|
result.push_back(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete statement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const vector<pair<string, string> > OVSQLiteKeyValueDataTable::valuesForKey(const OVWildcard& expression)
|
||||||
|
{
|
||||||
|
pair<string, string> exp = OVSQLiteHelper::SQLiteStringFromWildcard(expression);
|
||||||
|
|
||||||
|
vector<pair<string, string> > result;
|
||||||
|
OVSQLiteStatement* statement = m_source->connection()->prepare("SELECT key, value FROM %Q WHERE key like %Q escape %Q", m_tableName.c_str(), exp.first.c_str(), exp.second.c_str());
|
||||||
|
if (statement) {
|
||||||
|
while (statement->step() == SQLITE_ROW) {
|
||||||
|
result.push_back(pair<string, string>(statement->textOfColumn(0), statement->textOfColumn(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
delete statement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const string OVSQLiteKeyValueDataTable::valueForProperty(const string& property)
|
||||||
|
{
|
||||||
|
return m_source->valueForPropertyInTable(property, m_tableName);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,278 @@
|
||||||
|
//
|
||||||
|
// OVSQLiteWrapper.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVSQLite3Wrapper
|
||||||
|
#define OVSQLite3Wrapper
|
||||||
|
|
||||||
|
#include <sqlite3.h>
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OpenVanilla.h>
|
||||||
|
#else
|
||||||
|
#include "OpenVanilla.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// For status codes (SQLITE_OK, SQLITE_ERROR, etc.), please refer to sqlite3.h
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVSQLiteStatement;
|
||||||
|
|
||||||
|
class OVSQLiteConnection {
|
||||||
|
public:
|
||||||
|
// remember to manage the object returned by this class member function
|
||||||
|
static OVSQLiteConnection* Open(const string& filename = ":memory:");
|
||||||
|
~OVSQLiteConnection();
|
||||||
|
|
||||||
|
int lastError();
|
||||||
|
const char* lastErrorMessage();
|
||||||
|
|
||||||
|
int execute(const char* sqlcmd, ...);
|
||||||
|
OVSQLiteStatement* prepare(const char* sqlcmd, ...);
|
||||||
|
|
||||||
|
// helper for table creation and detection
|
||||||
|
bool hasTable(const string& tableName);
|
||||||
|
bool dropTable(const string& tableName);
|
||||||
|
bool createTable(const string& tableName, const string& columnString = "key, value", bool dropIfExists = false);
|
||||||
|
bool createIndexOnTable(const string& indexName, const string& tableName, const string& indexColumns = "key");
|
||||||
|
|
||||||
|
sqlite3* connection();
|
||||||
|
const string filename();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
sqlite3* m_connection;
|
||||||
|
string m_filename;
|
||||||
|
OVSQLiteConnection(sqlite3* connection, const string& filename);
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVSQLiteStatement {
|
||||||
|
public:
|
||||||
|
~OVSQLiteStatement();
|
||||||
|
|
||||||
|
int reset();
|
||||||
|
|
||||||
|
// *nota bene* column starts from 1 !
|
||||||
|
int bindTextToColumn(const char*str, int column);
|
||||||
|
int bindTextToColumn(const string& str, int column);
|
||||||
|
int bindIntToColumn(int value, int column);
|
||||||
|
int bindDoubleToColumn(double value, int column);
|
||||||
|
|
||||||
|
int step();
|
||||||
|
int columnCount();
|
||||||
|
const char* textOfColumn(int column);
|
||||||
|
int intOfColumn(int column);
|
||||||
|
double doubleOfColumn(int column);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
sqlite3_stmt* m_statement;
|
||||||
|
|
||||||
|
friend class OVSQLiteConnection;
|
||||||
|
OVSQLiteStatement(sqlite3_stmt* statement);
|
||||||
|
};
|
||||||
|
|
||||||
|
inline sqlite3* OVSQLiteConnection::connection()
|
||||||
|
{
|
||||||
|
return m_connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline OVSQLiteConnection* OVSQLiteConnection::Open(const string& filename)
|
||||||
|
{
|
||||||
|
sqlite3* connection;
|
||||||
|
|
||||||
|
if (sqlite3_open(filename.c_str(), &connection) != SQLITE_OK)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!connection)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return new OVSQLiteConnection(connection, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline OVSQLiteConnection::OVSQLiteConnection(sqlite3* connection, const string& filename)
|
||||||
|
: m_connection(connection)
|
||||||
|
, m_filename(filename)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline OVSQLiteConnection::~OVSQLiteConnection()
|
||||||
|
{
|
||||||
|
|
||||||
|
int result = sqlite3_close(m_connection);
|
||||||
|
if (result) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const string OVSQLiteConnection::filename()
|
||||||
|
{
|
||||||
|
return m_filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int OVSQLiteConnection::lastError()
|
||||||
|
{
|
||||||
|
return sqlite3_errcode(m_connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char* OVSQLiteConnection::lastErrorMessage()
|
||||||
|
{
|
||||||
|
return sqlite3_errmsg(m_connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int OVSQLiteConnection::execute(const char* sqlcmd, ...)
|
||||||
|
{
|
||||||
|
va_list l;
|
||||||
|
va_start(l, sqlcmd);
|
||||||
|
char* cmd = sqlite3_vmprintf(sqlcmd, l);
|
||||||
|
va_end(l);
|
||||||
|
int result = sqlite3_exec(m_connection, cmd, NULL, NULL, NULL);
|
||||||
|
sqlite3_free(cmd);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline OVSQLiteStatement* OVSQLiteConnection::prepare(const char* sqlcmd, ...)
|
||||||
|
{
|
||||||
|
va_list l;
|
||||||
|
va_start(l, sqlcmd);
|
||||||
|
char* cmd = sqlite3_vmprintf(sqlcmd, l);
|
||||||
|
va_end(l);
|
||||||
|
|
||||||
|
sqlite3_stmt* stmt;
|
||||||
|
OVSQLiteStatement* result = 0;
|
||||||
|
|
||||||
|
const char* remainingSt = 0;
|
||||||
|
if (sqlite3_prepare_v2(m_connection, cmd, -1, &stmt, &remainingSt) == SQLITE_OK)
|
||||||
|
result = new OVSQLiteStatement(stmt);
|
||||||
|
sqlite3_free(cmd);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool OVSQLiteConnection::hasTable(const string& tableName)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
OVSQLiteStatement* statement = prepare("SELECT name FROM sqlite_master WHERE name = %Q", tableName.c_str());
|
||||||
|
if (statement) {
|
||||||
|
if (statement->step() == SQLITE_ROW) {
|
||||||
|
result = true;
|
||||||
|
while (statement->step() == SQLITE_ROW) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete statement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool OVSQLiteConnection::dropTable(const string& tableName)
|
||||||
|
{
|
||||||
|
return SQLITE_OK == execute("DROP TABLE %Q", tableName.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool OVSQLiteConnection::createTable(const string& tableName, const string& columnString, bool dropIfExists)
|
||||||
|
{
|
||||||
|
if (hasTable(tableName)) {
|
||||||
|
if (dropIfExists) {
|
||||||
|
if (!dropTable(tableName))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return SQLITE_OK == execute("CREATE TABLE %Q (%s)", tableName.c_str(), columnString.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool OVSQLiteConnection::createIndexOnTable(const string& indexName, const string& tableName, const string& indexColumns)
|
||||||
|
{
|
||||||
|
return SQLITE_OK == execute("CREATE INDEX %Q on %Q (%s)", indexName.c_str(), tableName.c_str(), indexColumns.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline OVSQLiteStatement::OVSQLiteStatement(sqlite3_stmt* statement)
|
||||||
|
: m_statement(statement)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline OVSQLiteStatement::~OVSQLiteStatement()
|
||||||
|
{
|
||||||
|
sqlite3_finalize(m_statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int OVSQLiteStatement::reset()
|
||||||
|
{
|
||||||
|
return sqlite3_reset(m_statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int OVSQLiteStatement::bindTextToColumn(const char* str, int column)
|
||||||
|
{
|
||||||
|
return sqlite3_bind_text(m_statement, column, str, -1, SQLITE_TRANSIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int OVSQLiteStatement::bindTextToColumn(const string& str, int column)
|
||||||
|
{
|
||||||
|
return bindTextToColumn(str.c_str(), column);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int OVSQLiteStatement::bindIntToColumn(int value, int column)
|
||||||
|
{
|
||||||
|
return sqlite3_bind_int(m_statement, column, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int OVSQLiteStatement::bindDoubleToColumn(double value, int column)
|
||||||
|
{
|
||||||
|
return sqlite3_bind_double(m_statement, column, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int OVSQLiteStatement::step()
|
||||||
|
{
|
||||||
|
return sqlite3_step(m_statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int OVSQLiteStatement::columnCount()
|
||||||
|
{
|
||||||
|
return sqlite3_column_count(m_statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char* OVSQLiteStatement::textOfColumn(int column)
|
||||||
|
{
|
||||||
|
return (const char*)sqlite3_column_text(m_statement, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int OVSQLiteStatement::intOfColumn(int column)
|
||||||
|
{
|
||||||
|
return sqlite3_column_int(m_statement, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double OVSQLiteStatement::doubleOfColumn(int column)
|
||||||
|
{
|
||||||
|
return sqlite3_column_double(m_statement, column);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,218 @@
|
||||||
|
//
|
||||||
|
// OVStringHelper.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVStringHelper_h
|
||||||
|
#define OVStringHelper_h
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVStringHelper {
|
||||||
|
public:
|
||||||
|
static const vector<string> SplitBySpacesOrTabsWithDoubleQuoteSupport(const string& text)
|
||||||
|
{
|
||||||
|
vector<string> result;
|
||||||
|
size_t index = 0, last = 0, length = text.length();
|
||||||
|
while (index < length) {
|
||||||
|
if (text[index] == '\"') {
|
||||||
|
index++;
|
||||||
|
string tmp;
|
||||||
|
while (index < length) {
|
||||||
|
if (text[index] == '\"') {
|
||||||
|
index++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text[index] == '\\' && index + 1 < length) {
|
||||||
|
index++;
|
||||||
|
char c = text[index];
|
||||||
|
switch (c) {
|
||||||
|
case 'r':
|
||||||
|
tmp += '\r';
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
tmp += '\n';
|
||||||
|
break;
|
||||||
|
case '\"':
|
||||||
|
tmp += '\"';
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
tmp += '\\';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tmp += text[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
result.push_back(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text[index] != ' ' && text[index] != '\t') {
|
||||||
|
last = index;
|
||||||
|
while (index < length) {
|
||||||
|
if (text[index] == ' ' || text[index] == '\t') {
|
||||||
|
if (index - last)
|
||||||
|
result.push_back(text.substr(last, index - last));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == length && index - last)
|
||||||
|
result.push_back(text.substr(last, index - last));
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const vector<string> SplitBySpacesOrTabs(const string& text)
|
||||||
|
{
|
||||||
|
vector<string> result;
|
||||||
|
size_t index = 0, last = 0, length = text.length();
|
||||||
|
while (index < length) {
|
||||||
|
if (text[index] != ' ' && text[index] != '\t') {
|
||||||
|
last = index;
|
||||||
|
while (index < length) {
|
||||||
|
if (text[index] == ' ' || text[index] == '\t') {
|
||||||
|
if (index - last)
|
||||||
|
result.push_back(text.substr(last, index - last));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == length && index - last)
|
||||||
|
result.push_back(text.substr(last, index - last));
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const vector<string> Split(const string& text, char c)
|
||||||
|
{
|
||||||
|
vector<std::string> result;
|
||||||
|
size_t index = 0, last = 0, length = text.length();
|
||||||
|
while (index < length) {
|
||||||
|
while (index < length) {
|
||||||
|
if (text[index] == c) {
|
||||||
|
result.push_back(text.substr(last, index - last));
|
||||||
|
last = index + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last <= index) {
|
||||||
|
result.push_back(text.substr(last, index - last));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// named after Cocoa's NSString -stringByReplacingOccurrencesOfString:WithString:, horrible
|
||||||
|
static const string StringByReplacingOccurrencesOfStringWithString(const string& source, const string& substr, const string& replacement)
|
||||||
|
{
|
||||||
|
if (!substr.length())
|
||||||
|
return source;
|
||||||
|
|
||||||
|
size_t pos;
|
||||||
|
if ((pos = source.find(substr)) >= source.length())
|
||||||
|
return source;
|
||||||
|
|
||||||
|
return source.substr(0, pos) + replacement + StringByReplacingOccurrencesOfStringWithString(source.substr(pos + substr.length()), substr, replacement);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string Join(const vector<string>& vec)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
for (vector<string>::const_iterator iter = vec.begin(); iter != vec.end() ; ++iter)
|
||||||
|
result += *iter;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string Join(const vector<string>& vec, const string& separator)
|
||||||
|
{
|
||||||
|
return Join(vec.begin(), vec.end(), separator);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string Join(const vector<string>& vec, size_t from, size_t size, const string& separator)
|
||||||
|
{
|
||||||
|
return Join(vec.begin() + from, vec.begin() + from + size, separator);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string Join(vector<string>::const_iterator begin, vector<string>::const_iterator end, const string& separator)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
for (vector<string>::const_iterator iter = begin ; iter != end ; ) {
|
||||||
|
result += *iter;
|
||||||
|
if (++iter != end)
|
||||||
|
result += separator;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string PercentEncode(const string& text)
|
||||||
|
{
|
||||||
|
stringstream sst;
|
||||||
|
sst << hex;
|
||||||
|
|
||||||
|
for (string::const_iterator i = text.begin() ; i != text.end() ; ++i) {
|
||||||
|
if ((*i >= '0' && *i <= '9') || (*i >= 'A' && *i <= 'Z') || (*i >= 'a' && *i <= 'z') || *i == '-' || *i == '_' || *i == '.' || *i == '~') {
|
||||||
|
sst << (char)*i;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sst << '%';
|
||||||
|
sst.width(2);
|
||||||
|
sst.fill('0');
|
||||||
|
unsigned char c = *i;
|
||||||
|
sst << (unsigned int)c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sst.str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,102 @@
|
||||||
|
//
|
||||||
|
// OVTextBuffer.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVTextBuffer_h
|
||||||
|
#define OVTextBuffer_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVBase.h>
|
||||||
|
#else
|
||||||
|
#include "OVBase.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// Terminologies:
|
||||||
|
// * Text buffer = a generic term
|
||||||
|
// * Composing text = composing buffer = composition buffer
|
||||||
|
// In Windows speak, "composition buffer" doesn't contain reading
|
||||||
|
// (Reading is a separate concept in Windows)
|
||||||
|
// In Mac speak, "composing buffer" == composing text + reading text
|
||||||
|
// * Reading text = currently in-wait-state radicals
|
||||||
|
// * Pre-edit, pre-edit area or pre-edit buffer (X11 speak) = composing text + reading
|
||||||
|
// Mac's composing buffer is actually pre-edit in this sense
|
||||||
|
|
||||||
|
|
||||||
|
class OVTextBuffer : public OVBase {
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void clear() = 0;
|
||||||
|
virtual void setText(const string& text) = 0;
|
||||||
|
virtual void appendText(const string& text, bool moveCursor = true) = 0;
|
||||||
|
|
||||||
|
// when the text buffer is committed, the buffer itself, along with settings like cursor, and tooltip (for both composing text and reading text), highlight, word segments, and suggested display style (for reading text) are cleared; the combined committed string will be available at composedCommittedText()
|
||||||
|
virtual void commit() = 0;
|
||||||
|
virtual void commitAsTextSegment() = 0;
|
||||||
|
virtual void commit(const string& text) = 0;
|
||||||
|
virtual void commitAsTextSegment(const string& text) = 0;
|
||||||
|
|
||||||
|
virtual void updateDisplay() = 0;
|
||||||
|
virtual bool isEmpty() const = 0;
|
||||||
|
virtual size_t codePointCount() const = 0;
|
||||||
|
virtual const string codePointAt(size_t index) const = 0;
|
||||||
|
virtual const string composedText() const = 0;
|
||||||
|
virtual const string composedCommittedText() const = 0;
|
||||||
|
virtual const vector<string> composedCommittedTextSegments() const = 0;
|
||||||
|
|
||||||
|
// Composing text (composing buffer, composition buffer)-only members
|
||||||
|
public:
|
||||||
|
typedef pair<size_t, size_t> RangePair;
|
||||||
|
|
||||||
|
// composing buffer should support these four, but reading buffer doesn't need to (anyway it's meaningless)
|
||||||
|
virtual void setCursorPosition(size_t position) = 0;
|
||||||
|
virtual size_t cursorPosition() const = 0;
|
||||||
|
virtual void showToolTip(const string& text) = 0;
|
||||||
|
virtual void clearToolTip() = 0;
|
||||||
|
|
||||||
|
// implementation details: composing buffer might support this, but reading buffer doesn't
|
||||||
|
virtual void setHighlightMark(const RangePair& range) = 0;
|
||||||
|
|
||||||
|
// word segments: on Windows, this is an independent (though application-dependent) feature, on Mac OS X, word segments cannot overlap with the highlight mark, and also, when the highlight mark is on, the cursor is off
|
||||||
|
virtual void setWordSegments(const vector<RangePair>& segments) = 0;
|
||||||
|
|
||||||
|
// Reading text only members
|
||||||
|
public:
|
||||||
|
enum ReadingTextStyle {
|
||||||
|
Horizontal = 0,
|
||||||
|
Vertical = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
// this is only for the reading buffer, and is not a required implementation
|
||||||
|
virtual void setSuggestedReadingTextStyle(ReadingTextStyle style) = 0;
|
||||||
|
virtual ReadingTextStyle defaultReadingTextStyle() const = 0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,194 @@
|
||||||
|
//
|
||||||
|
// OVUTF8Helper.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVUTF8Helper_h
|
||||||
|
#define OVUTF8Helper_h
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVUTF8Helper {
|
||||||
|
public:
|
||||||
|
static const vector<string> SplitStringByCodePoint(const string& utf8String)
|
||||||
|
{
|
||||||
|
size_t index, length = utf8String.length();
|
||||||
|
vector<string> result;
|
||||||
|
|
||||||
|
for (index = 0; index < length; index++) {
|
||||||
|
unsigned char c = utf8String[index];
|
||||||
|
|
||||||
|
if (!(c & 0x80)) {
|
||||||
|
result.push_back(utf8String.substr(index, 1));
|
||||||
|
}
|
||||||
|
else if ((c & (0x80 | 0x40)) && !(c & 0x20)) {
|
||||||
|
result.push_back(utf8String.substr(index, 2));
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
else if ((c & (0x80 | 0x40 | 0x20)) && !(c & 0x10)) {
|
||||||
|
result.push_back(utf8String.substr(index, 3));
|
||||||
|
index += 2;
|
||||||
|
}
|
||||||
|
else if ((c & (0x80 | 0x40 | 0x20 | 0x10)) && !(c & 0x8)) {
|
||||||
|
result.push_back(utf8String.substr(index, 4));
|
||||||
|
index += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string CombineCodePoints(const vector<string>& codePoints)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
for (vector<string>::const_iterator iter = codePoints.begin(); iter != codePoints.end() ; ++iter)
|
||||||
|
result += *iter;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const wstring ConvertStringToUTF16WideString(const string& utf8String)
|
||||||
|
{
|
||||||
|
wstring wideString;
|
||||||
|
vector<string> charVector = OVUTF8Helper::SplitStringByCodePoint(utf8String);
|
||||||
|
|
||||||
|
size_t length = charVector.size();
|
||||||
|
for (size_t index = 0; index < length; index++)
|
||||||
|
{
|
||||||
|
unsigned int codePoint = OVUTF8Helper::CodePointFromSingleUTF8String(charVector[index]);
|
||||||
|
|
||||||
|
if (codePoint < 0x10000) {
|
||||||
|
wideString += (wchar_t)codePoint;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const unsigned int leadOffset = 0xD800 - (0x10000 >> 10);
|
||||||
|
unsigned int lead = leadOffset + (codePoint >> 10);
|
||||||
|
unsigned int trail = 0xdc00 + (codePoint & 0x3ff);
|
||||||
|
wideString += (wchar_t)lead;
|
||||||
|
wideString += (wchar_t)trail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return wideString;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string StringFromUTF16WideString(const wstring& utf16WideString)
|
||||||
|
{
|
||||||
|
string utf8String;
|
||||||
|
size_t length = utf16WideString.length();
|
||||||
|
|
||||||
|
unsigned int u16;
|
||||||
|
for (size_t index = 0; index < length; index++) {
|
||||||
|
u16 = utf16WideString[index];
|
||||||
|
|
||||||
|
if (u16 >= 0xd800 && u16 <= 0xdbff) {
|
||||||
|
if (index + 1 < length) {
|
||||||
|
unsigned int trailing = utf16WideString[index + 1];
|
||||||
|
if (trailing >= 0xdc00 && trailing <= 0xdfff) {
|
||||||
|
index++;
|
||||||
|
|
||||||
|
const unsigned int surrogateOffset = 0x10000 - (0xD800 << 10) - 0xDC00;
|
||||||
|
unsigned int codePoint = (u16 << 10) + trailing + surrogateOffset;
|
||||||
|
utf8String += OVUTF8Helper::SingleUTF8StringFromCodePoint(codePoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!(u16 >= 0xdc00 && u16 <= 0xdfff))
|
||||||
|
{
|
||||||
|
utf8String += OVUTF8Helper::SingleUTF8StringFromCodePoint(u16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return utf8String;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string SingleUTF8StringFromCodePoint(unsigned int codePoint)
|
||||||
|
{
|
||||||
|
string utf8String;
|
||||||
|
|
||||||
|
if (codePoint < 0x80) {
|
||||||
|
utf8String += (unsigned char)codePoint;
|
||||||
|
}
|
||||||
|
else if (codePoint < 0x800) {
|
||||||
|
utf8String += (unsigned char)((codePoint >> 6) | 0xc0);
|
||||||
|
utf8String += (unsigned char)((codePoint & 0x3f) | 0x80);
|
||||||
|
}
|
||||||
|
else if (codePoint < 0x10000) {
|
||||||
|
utf8String += (unsigned char)((codePoint >> 12) | 0xe0);
|
||||||
|
utf8String += (unsigned char)(((codePoint >> 6) & 0x3f) | 0x80);
|
||||||
|
utf8String += (unsigned char)((codePoint & 0x3f) | 0x80);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
utf8String += (unsigned char)((codePoint >> 18) | 0xf0);
|
||||||
|
utf8String += (unsigned char)((codePoint >> 12) | 0x80);
|
||||||
|
utf8String += (unsigned char)(((codePoint >> 6) & 0x3f) | 0x80);
|
||||||
|
utf8String += (unsigned char)((codePoint & 0x3f) | 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
return utf8String;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int CodePointFromSingleUTF8String(const string& utf8String)
|
||||||
|
{
|
||||||
|
switch(utf8String.length()) {
|
||||||
|
case 1:
|
||||||
|
return (unsigned int)utf8String[0];
|
||||||
|
case 2:
|
||||||
|
return (((unsigned char)utf8String[0] << 6) & 0x7ff) + ((unsigned char)utf8String[1] & 0x3f);
|
||||||
|
case 3:
|
||||||
|
return (((unsigned char)utf8String[0] << 12) & 0xffff) + (((unsigned char)utf8String[1] << 6) & 0xfff) + ((unsigned char)utf8String[2] & 0x3f);
|
||||||
|
case 4:
|
||||||
|
return (((unsigned char)utf8String[0] << 18) & 0x1fffff) + (((unsigned char)utf8String[1] << 12) & 0x3ffff) + (((unsigned char)utf8String[2] << 6) & 0xfff) + ((unsigned char)utf8String[3] & 0x3f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVUTF8 {
|
||||||
|
public:
|
||||||
|
static const string FromUTF16(const wstring& utf16String)
|
||||||
|
{
|
||||||
|
return OVUTF8Helper::StringFromUTF16WideString(utf16String);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OVUTF16 {
|
||||||
|
public:
|
||||||
|
static const wstring FromUTF8(const string& utf8String)
|
||||||
|
{
|
||||||
|
return OVUTF8Helper::ConvertStringToUTF16WideString(utf8String);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,248 @@
|
||||||
|
//
|
||||||
|
// OVWildcard.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVWildcard_h
|
||||||
|
#define OVWildcard_h
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
|
namespace OpenVanilla {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OVWildcard {
|
||||||
|
public:
|
||||||
|
OVWildcard(const string& expression, char matchOneChar = '?', char matchZeroOrMoreChar = '*', bool matchEndOfLine = true, bool caseSensitive = false)
|
||||||
|
: m_caseSensitive(caseSensitive)
|
||||||
|
, m_expression(expression)
|
||||||
|
, m_matchEndOfLine(matchEndOfLine)
|
||||||
|
, m_matchOneChar(matchOneChar)
|
||||||
|
, m_matchZeroOrMoreChar(matchZeroOrMoreChar)
|
||||||
|
{
|
||||||
|
size_t index;
|
||||||
|
for (index = 0; index < expression.length(); index++) {
|
||||||
|
if (expression[index] == matchOneChar || expression[index] == matchZeroOrMoreChar) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_longestHeadMatchString = expression.substr(0, index);
|
||||||
|
|
||||||
|
for (string::size_type i = 0; i < expression.length(); i++) {
|
||||||
|
char c = expression[i];
|
||||||
|
if (c == matchOneChar) {
|
||||||
|
m_states.push_back(State(AnyOne, 0));
|
||||||
|
}
|
||||||
|
else if (c == matchZeroOrMoreChar) {
|
||||||
|
char nextChar = 0;
|
||||||
|
string::size_type j;
|
||||||
|
for (j = i + 1; j < expression.length(); j++) {
|
||||||
|
char k = expression[j];
|
||||||
|
if (k != matchZeroOrMoreChar) {
|
||||||
|
if (k == matchOneChar) k = -1;
|
||||||
|
|
||||||
|
nextChar = k;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i = j;
|
||||||
|
m_states.push_back(State(AnyUntil, nextChar));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_states.push_back(State(Exact, c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool match(const string& target, size_t fromState = 0) const
|
||||||
|
{
|
||||||
|
string::size_type i = 0, slength = target.length();
|
||||||
|
vector<State>::size_type j, vlength = m_states.size();
|
||||||
|
|
||||||
|
for (j = fromState; j < vlength; j++) {
|
||||||
|
State state = m_states[j];
|
||||||
|
Directive d = state.first;
|
||||||
|
int k = state.second;
|
||||||
|
|
||||||
|
if (i >= slength) {
|
||||||
|
if (d == AnyUntil && !k) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (d) {
|
||||||
|
case Exact:
|
||||||
|
if (!equalChars(target[i], k)) return false;
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AnyOne:
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AnyUntil:
|
||||||
|
if (k == -1) {
|
||||||
|
// means *?, equals ?, so just advance one character
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else if (k == 0) {
|
||||||
|
// until end, always true
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bool found = false;
|
||||||
|
string::size_type backIndex;
|
||||||
|
|
||||||
|
for (backIndex = slength - 1; backIndex >= i; backIndex--) {
|
||||||
|
if (equalChars(target[backIndex], k)) {
|
||||||
|
string substring = target.substr(backIndex + 1, slength - (backIndex + 1));
|
||||||
|
|
||||||
|
if (match(substring, j + 1)) {
|
||||||
|
found = true;
|
||||||
|
i = backIndex + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!backIndex)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_matchEndOfLine && i != slength)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string longestHeadMatchString() const
|
||||||
|
{
|
||||||
|
return m_longestHeadMatchString;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string expression() const
|
||||||
|
{
|
||||||
|
return m_expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isCaseSensitive() const
|
||||||
|
{
|
||||||
|
return m_caseSensitive;
|
||||||
|
}
|
||||||
|
|
||||||
|
char matchOneChar() const
|
||||||
|
{
|
||||||
|
return m_matchOneChar;
|
||||||
|
}
|
||||||
|
|
||||||
|
char matchZeroOrMoreChar() const
|
||||||
|
{
|
||||||
|
return m_matchZeroOrMoreChar;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend ostream& operator<<(ostream& stream, const OVWildcard& wildcard);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
enum Directive {
|
||||||
|
Exact,
|
||||||
|
AnyOne,
|
||||||
|
AnyUntil
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef pair<Directive, int> State;
|
||||||
|
|
||||||
|
bool equalChars(char a, char b) const
|
||||||
|
{
|
||||||
|
if (m_caseSensitive)
|
||||||
|
return a == b;
|
||||||
|
else
|
||||||
|
return tolower(a) == tolower(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool m_caseSensitive;
|
||||||
|
bool m_matchEndOfLine;
|
||||||
|
char m_matchOneChar;
|
||||||
|
char m_matchZeroOrMoreChar;
|
||||||
|
vector<State> m_states;
|
||||||
|
|
||||||
|
string m_expression;
|
||||||
|
string m_longestHeadMatchString;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const bool Match(const string& text, const string& expression, char matchOneChar = '?', char matchZeroOrMoreChar = '*', bool matchEndOfLine = true, bool caseSensitive = false)
|
||||||
|
{
|
||||||
|
OVWildcard exp(expression, matchOneChar, matchZeroOrMoreChar, matchEndOfLine, caseSensitive);
|
||||||
|
return exp.match(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const vector<OVWildcard> WildcardsFromStrings(const vector<string>& expressions, char matchOneChar = '?', char matchZeroOrMoreChar = '*', bool matchEndOfLine = true, bool caseSensitive = false)
|
||||||
|
{
|
||||||
|
vector<OVWildcard> result;
|
||||||
|
vector<string>::const_iterator iter = expressions.begin();
|
||||||
|
for ( ; iter != expressions.end(); iter++)
|
||||||
|
result.push_back(OVWildcard(*iter, matchOneChar, matchZeroOrMoreChar, matchEndOfLine, caseSensitive));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool MultiWildcardMatchAny(const string& target, const vector<string>& expressions, char matchOneChar = '?', char matchZeroOrMoreChar = '*', bool matchEndOfLine = true, bool caseSensitive = false)
|
||||||
|
{
|
||||||
|
return MultiWildcardMatchAny(target, WildcardsFromStrings(expressions, matchOneChar, matchZeroOrMoreChar, matchEndOfLine, caseSensitive));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool MultiWildcardMatchAny(const string& target, const vector<OVWildcard>& expressions)
|
||||||
|
{
|
||||||
|
vector<OVWildcard>::const_iterator iter = expressions.begin();
|
||||||
|
for ( ; iter != expressions.end(); iter++) {
|
||||||
|
if ((*iter).match(target))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline ostream& operator<<(ostream& stream, const OVWildcard& wildcard)
|
||||||
|
{
|
||||||
|
vector<OVWildcard::State>::size_type i, size = wildcard.m_states.size();
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
|
const OVWildcard::State& state = wildcard.m_states[i];
|
||||||
|
stream << "State " << i << ": " << state.first << ", " << state.second << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,97 @@
|
||||||
|
//
|
||||||
|
// OpenVanilla.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2010 Lukhnos D. Liu
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OpenVanilla_h
|
||||||
|
#define OpenVanilla_h
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenVanilla/OVAroundFilter.h>
|
||||||
|
#include <OpenVanilla/OVBase.h>
|
||||||
|
#include <OpenVanilla/OVBenchmark.h>
|
||||||
|
#include <OpenVanilla/OVCandidateService.h>
|
||||||
|
#include <OpenVanilla/OVCINDataTable.h>
|
||||||
|
#include <OpenVanilla/OVCINDatabaseService.h>
|
||||||
|
#include <OpenVanilla/OVDatabaseService.h>
|
||||||
|
#include <OpenVanilla/OVDateTimeHelper.h>
|
||||||
|
#include <OpenVanilla/OVEventHandlingContext.h>
|
||||||
|
#include <OpenVanilla/OVFileHelper.h>
|
||||||
|
#include <OpenVanilla/OVFrameworkInfo.h>
|
||||||
|
#include <OpenVanilla/OVInputMethod.h>
|
||||||
|
#include <OpenVanilla/OVLocalization.h>
|
||||||
|
#include <OpenVanilla/OVKey.h>
|
||||||
|
#include <OpenVanilla/OVKeyValueMap.h>
|
||||||
|
#include <OpenVanilla/OVLoaderService.h>
|
||||||
|
#include <OpenVanilla/OVModule.h>
|
||||||
|
#include <OpenVanilla/OVModulePackage.h>
|
||||||
|
#include <OpenVanilla/OVOutputFilter.h>
|
||||||
|
#include <OpenVanilla/OVPathInfo.h>
|
||||||
|
#include <OpenVanilla/OVStringHelper.h>
|
||||||
|
#include <OpenVanilla/OVTextBuffer.h>
|
||||||
|
#include <OpenVanilla/OVUTF8Helper.h>
|
||||||
|
#include <OpenVanilla/OVWildcard.h>
|
||||||
|
|
||||||
|
#ifdef OV_USE_SQLITE
|
||||||
|
#include <OpenVanilla/OVSQLiteDatabaseService.h>
|
||||||
|
#include <OpenVanilla/OVSQLiteWrapper.h>
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "OVAroundFilter.h"
|
||||||
|
#include "OVBase.h"
|
||||||
|
#include "OVBenchmark.h"
|
||||||
|
#include "OVCandidateService.h"
|
||||||
|
#include "OVCINDataTable.h"
|
||||||
|
#include "OVCINDatabaseService.h"
|
||||||
|
#include "OVDatabaseService.h"
|
||||||
|
#include "OVDateTimeHelper.h"
|
||||||
|
#include "OVEventHandlingContext.h"
|
||||||
|
#include "OVFileHelper.h"
|
||||||
|
#include "OVFrameworkInfo.h"
|
||||||
|
#include "OVInputMethod.h"
|
||||||
|
#include "OVLocalization.h"
|
||||||
|
#include "OVKey.h"
|
||||||
|
#include "OVKeyValueMap.h"
|
||||||
|
#include "OVLoaderService.h"
|
||||||
|
#include "OVModule.h"
|
||||||
|
#include "OVModulePackage.h"
|
||||||
|
#include "OVOutputFilter.h"
|
||||||
|
#include "OVPathInfo.h"
|
||||||
|
#include "OVStringHelper.h"
|
||||||
|
#include "OVTextBuffer.h"
|
||||||
|
#include "OVUTF8Helper.h"
|
||||||
|
#include "OVWildcard.h"
|
||||||
|
|
||||||
|
#ifdef OV_USE_SQLITE
|
||||||
|
#include "OVSQLiteDatabaseService.h"
|
||||||
|
#include "OVSQLiteWrapper.h"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue