add upstream source (adch++ 2.12.1 from sourceforge)
This commit is contained in:
parent
3574617350
commit
2cfbcf1301
|
@ -0,0 +1,5 @@
|
|||
repo: 41072e8158463f921a1157e780a40dd82b2ddbf6
|
||||
node: feedb6b4a3381644034fd3e5fbfcdc91be7e31ce
|
||||
branch: default
|
||||
latesttag: 2.3
|
||||
latesttagdistance: 486
|
|
@ -0,0 +1,15 @@
|
|||
^doc$
|
||||
^logs$
|
||||
^build$
|
||||
^custom\.py$
|
||||
^openssl$
|
||||
\.pdb$
|
||||
\.gch$
|
||||
\.pot$
|
||||
\.pyc$
|
||||
\.csettings$
|
||||
\.sconsign\.dblite$
|
||||
^php/include/
|
||||
^php/lib/
|
||||
^php/x64/include/
|
||||
^php/x64/lib/
|
|
@ -0,0 +1 @@
|
|||
807c6d3c5e39c1eeb2625351dc82ac231175947e 2.3
|
|
@ -0,0 +1,279 @@
|
|||
; Script generated by the HM NIS Edit Script Wizard.
|
||||
|
||||
; HM NIS Edit Wizard helper defines
|
||||
!define PRODUCT_NAME "ADCH++"
|
||||
!define PRODUCT_PUBLISHER "Jacek Sieka"
|
||||
!define PRODUCT_WEB_SITE "http://adchpp.sourceforge.net"
|
||||
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\adchppd.exe"
|
||||
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
|
||||
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
|
||||
|
||||
Function GetAdchppdVersion
|
||||
Exch $0
|
||||
GetDllVersion "$INSTDIR\$0" $R0 $R1
|
||||
IntOp $R2 $R0 >> 16
|
||||
IntOp $R2 $R2 & 0x0000FFFF
|
||||
IntOp $R3 $R0 & 0x0000FFFF
|
||||
IntOp $R4 $R1 >> 16
|
||||
IntOp $R4 $R4 & 0x0000FFFF
|
||||
StrCpy $1 "$R2.$R3.$R4"
|
||||
Exch $1
|
||||
FunctionEnd
|
||||
|
||||
SetCompressor lzma
|
||||
|
||||
; MUI 1.67 compatible ------
|
||||
!include "MUI.nsh"
|
||||
|
||||
; MUI Settings
|
||||
!define MUI_ABORTWARNING
|
||||
!define MUI_ICON "adchppd.ico"
|
||||
!define MUI_UNICON "adchppd.ico"
|
||||
|
||||
; Welcome page
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
; Directory page
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
; Instfiles page
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
; Finish page
|
||||
!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\readme.txt"
|
||||
!define MUI_FINISHPAGE_RUN "$INSTDIR\adchppd.exe"
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
|
||||
; Uninstaller pages
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
|
||||
; Language files
|
||||
!insertmacro MUI_LANGUAGE "English"
|
||||
|
||||
; Reserve files
|
||||
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
|
||||
|
||||
; MUI end ------
|
||||
|
||||
Name "${PRODUCT_NAME}"
|
||||
OutFile "ADCHPP-xxx.exe"
|
||||
InstallDir "$PROGRAMFILES\ADCH++"
|
||||
InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
|
||||
ShowInstDetails show
|
||||
ShowUnInstDetails show
|
||||
|
||||
Section "MainSection" SEC01
|
||||
SetOutPath "$INSTDIR"
|
||||
SetOverwrite ifnewer
|
||||
File "aboost_date_time.dll"
|
||||
File "aboost_system.dll"
|
||||
File "adchpp.dll"
|
||||
File "adchppd.exe"
|
||||
File "alua.dll"
|
||||
File "Bloom.dll"
|
||||
File "changelog.txt"
|
||||
File "lfs.dll"
|
||||
File "libgcc_s_dw2-1.dll"
|
||||
File "libstdc++-6.dll"
|
||||
File "License.txt"
|
||||
File "luadchpp.dll"
|
||||
File "pyadchpp.py"
|
||||
File "Script.dll"
|
||||
File "luadchppbloom.dll"
|
||||
File "aboost_locale.dll"
|
||||
File "readme.txt"
|
||||
File "FirstReg.cmd"
|
||||
File "Generate_certs.cmd"
|
||||
CreateShortCut "$DESKTOP\ADCH++.lnk" "$INSTDIR\adchppd.exe"
|
||||
CreateDirectory "$SMPROGRAMS\ADCH++"
|
||||
CreateShortCut "$SMPROGRAMS\ADCH++\ADCH++ Help.lnk" "$INSTDIR\readme.txt"
|
||||
CreateShortCut "$SMPROGRAMS\ADCH++\Install ADCH++ as windows service.lnk" "$INSTDIR\adchppd.exe" "-i adchppd"
|
||||
CreateShortCut "$SMPROGRAMS\ADCH++\Remove ADCH++ windows service.lnk" "$INSTDIR\adchppd.exe" "-u adchppd"
|
||||
SetOutPath "$INSTDIR\lua"
|
||||
File "lua\*.lua"
|
||||
SetOutPath "$INSTDIR\lua\socket"
|
||||
File "lua\socket\*.lua"
|
||||
SetOutPath "$INSTDIR\mime"
|
||||
File "mime\*"
|
||||
SetOutPath "$INSTDIR\socket"
|
||||
File "socket\*"
|
||||
SetOutPath "$INSTDIR\Scripts"
|
||||
File "Scripts\access.lua"
|
||||
File "Scripts\access.bans.lua"
|
||||
File "Scripts\access.bot.lua"
|
||||
IfFileExists $INSTDIR\Scripts\access.limits.lua 0 +2
|
||||
Rename $INSTDIR\Scripts\access.limits.lua $INSTDIR\Scripts\access.limits.lua.old
|
||||
File "Scripts\access.guard.lua"
|
||||
File "Scripts\access.op.lua"
|
||||
File "Scripts\autil.lua"
|
||||
File "Scripts\aio.lua"
|
||||
File "Scripts\example.lua"
|
||||
File "Scripts\history.lua"
|
||||
File "Scripts\json.lua"
|
||||
File "Scripts\motd.lua"
|
||||
File "Scripts\checkemptyinbloom.lua"
|
||||
CreateDirectory $INSTDIR\Scripts\FL_Database
|
||||
SetOutPath "$INSTDIR\Docs"
|
||||
File "Docs\*.conf"
|
||||
File "Docs\*.html"
|
||||
File "Docs\*.txt"
|
||||
SetOutPath "$INSTDIR\Docs\images"
|
||||
File "Docs\images\*.png"
|
||||
SetOutPath "$INSTDIR\Docs\images\icons"
|
||||
File "Docs\images\icons\*.png"
|
||||
SetOverwrite off
|
||||
SetOutPath "$INSTDIR\config"
|
||||
File "config\motd.txt"
|
||||
File "config\adchpp.xml"
|
||||
File "config\Script.xml"
|
||||
SectionEnd
|
||||
|
||||
Section -AdditionalIcons
|
||||
SetOutPath $INSTDIR
|
||||
WriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}"
|
||||
CreateShortCut "$SMPROGRAMS\ADCH++\Website.lnk" "$INSTDIR\${PRODUCT_NAME}.url"
|
||||
CreateShortCut "$SMPROGRAMS\ADCH++\ADCH++.lnk" "$INSTDIR\adchppd.exe"
|
||||
CreateShortCut "$SMPROGRAMS\ADCH++\Uninstall.lnk" "$INSTDIR\uninst.exe"
|
||||
SectionEnd
|
||||
|
||||
Section -Service
|
||||
MessageBox MB_ICONQUESTION|MB_YESNO "Do you wish to install ADCH++ as a service?" IDYES Service IDNO End
|
||||
Service: Exec '"$INSTDIR\adchppd.exe" -i adchppd'
|
||||
End:
|
||||
SectionEnd
|
||||
|
||||
Section -Post
|
||||
WriteUninstaller "$INSTDIR\uninst.exe"
|
||||
|
||||
; Get adchppd version we just installed and store in $1
|
||||
Push "adchppd.exe"
|
||||
Call "GetAdchppdVersion"
|
||||
Pop $1
|
||||
|
||||
WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\adchppd.exe"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name) $1"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\adchppd.exe"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "$1"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
|
||||
SectionEnd
|
||||
|
||||
|
||||
Function un.onUninstSuccess
|
||||
HideWindow
|
||||
MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) was successfully removed from your computer."
|
||||
FunctionEnd
|
||||
|
||||
Function un.onInit
|
||||
MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Are you sure you want to completely remove $(^Name) and all of its components?" IDYES +2
|
||||
Abort
|
||||
FunctionEnd
|
||||
|
||||
Section -un.Service
|
||||
Exec 'sc delete adchppd'
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section -un.remSettings
|
||||
MessageBox MB_ICONQUESTION|MB_YESNO "Do you wish to remove all the ADCH++ configuration files, statistics, logs and accounts?" IDYES Remove IDNO NoRemove
|
||||
Remove:
|
||||
Delete "$INSTDIR\config\users.txt"
|
||||
Delete "$INSTDIR\config\history.txt"
|
||||
Delete "$INSTDIR\config\settings.txt"
|
||||
Delete "$INSTDIR\config\motd.txt"
|
||||
Delete "$INSTDIR\config\bans.txt"
|
||||
Delete "$INSTDIR\config\en_settings.txt"
|
||||
Delete "$INSTDIR\config\fl_settings.txt"
|
||||
Delete "$INSTDIR\config\li_settings.txt"
|
||||
Delete "$INSTDIR\config\users.txt.tmp"
|
||||
Delete "$INSTDIR\config\history.txt.tmp"
|
||||
Delete "$INSTDIR\config\settings.txt.tmp"
|
||||
Delete "$INSTDIR\config\motd.txt.tmp"
|
||||
Delete "$INSTDIR\config\bans.txt.tmp"
|
||||
Delete "$INSTDIR\config\en_settings.txt.tmp"
|
||||
Delete "$INSTDIR\config\fl_settings.txt.tmp"
|
||||
Delete "$INSTDIR\config\li_settings.txt.tmp"
|
||||
Delete "$INSTDIR\config\Script.xml"
|
||||
Delete "$INSTDIR\config\adchpp.xml"
|
||||
Delete "$INSTDIR\config\logs\*.log"
|
||||
Delete "$INSTDIR\Scripts\FL_Database\commandstats.txt"
|
||||
Delete "$INSTDIR\Scripts\FL_Database\entitystats.txt"
|
||||
Delete "$INSTDIR\Scripts\FL_Database\kickstats.txt"
|
||||
Delete "$INSTDIR\Scripts\FL_Database\limitstats.txt"
|
||||
Delete "$INSTDIR\Scripts\FL_Database\tmpbanstats.txt"
|
||||
Delete "$INSTDIR\Scripts\FL_Database\commandstats.txt.tmp"
|
||||
Delete "$INSTDIR\Scripts\FL_Database\entitystats.txt.tmp"
|
||||
Delete "$INSTDIR\Scripts\FL_Database\kickstats.txt.tmp"
|
||||
Delete "$INSTDIR\Scripts\FL_Database\limitstats.txt.tmp"
|
||||
Delete "$INSTDIR\Scripts\FL_Database\tmpbanstats.txt.tmp"
|
||||
NoRemove:
|
||||
SectionEnd
|
||||
|
||||
Section Uninstall
|
||||
Delete "$INSTDIR\${PRODUCT_NAME}.url"
|
||||
Delete "$INSTDIR\aboost_date_time.dll"
|
||||
Delete "$INSTDIR\aboost_system.dll"
|
||||
Delete "$INSTDIR\adchpp.dll"
|
||||
Delete "$INSTDIR\adchppd.exe"
|
||||
Delete "$INSTDIR\alua.dll"
|
||||
Delete "$INSTDIR\Bloom.dll"
|
||||
Delete "$INSTDIR\changelog.txt"
|
||||
Delete "$INSTDIR\lfs.dll"
|
||||
Delete "$INSTDIR\libgcc_s_dw2-1.dll"
|
||||
Delete "$INSTDIR\libstdc++-6.dll"
|
||||
Delete "$INSTDIR\License.txt"
|
||||
Delete "$INSTDIR\luadchpp.dll"
|
||||
Delete "$INSTDIR\pyadchpp.py"
|
||||
Delete "$INSTDIR\Script.dll"
|
||||
Delete "$INSTDIR\luadchppbloom.dll"
|
||||
Delete "$INSTDIR\aboost_locale.dll"
|
||||
Delete "$INSTDIR\readme.txt"
|
||||
Delete "$INSTDIR\FirstReg.cmd"
|
||||
Delete "$INSTDIR\Generate_certs.cmd"
|
||||
Delete "$INSTDIR\lua\*.lua"
|
||||
Delete "$INSTDIR\lua\socket\*.lua"
|
||||
Delete "$INSTDIR\mime\core.dll"
|
||||
Delete "$INSTDIR\socket\core.dll"
|
||||
Delete "$INSTDIR\Scripts\access.lua"
|
||||
Delete "$INSTDIR\Scripts\access.bans.lua"
|
||||
Delete "$INSTDIR\Scripts\access.bot.lua"
|
||||
Delete "$INSTDIR\Scripts\access.guard.lua"
|
||||
Delete "$INSTDIR\Scripts\access.limits.lua"
|
||||
Delete "$INSTDIR\Scripts\access.limits.lua.old"
|
||||
Delete "$INSTDIR\Scripts\access.op.lua"
|
||||
Delete "$INSTDIR\Scripts\aio.lua"
|
||||
Delete "$INSTDIR\Scripts\autil.lua"
|
||||
Delete "$INSTDIR\Scripts\example.lua"
|
||||
Delete "$INSTDIR\Scripts\history.lua"
|
||||
Delete "$INSTDIR\Scripts\json.lua"
|
||||
Delete "$INSTDIR\Scripts\motd.lua"
|
||||
Delete "$INSTDIR\Scripts\checkemptyinbloom.lua"
|
||||
Delete "$INSTDIR\Docs\images\icons\*.*"
|
||||
Delete "$INSTDIR\Docs\images\*.*"
|
||||
Delete "$INSTDIR\Docs\*.*"
|
||||
Delete "$INSTDIR\uninst.exe"
|
||||
|
||||
Delete "$SMPROGRAMS\ADCH++\Uninstall.lnk"
|
||||
Delete "$SMPROGRAMS\ADCH++\ADCH++.lnk"
|
||||
Delete "$SMPROGRAMS\ADCH++\Website.lnk"
|
||||
Delete "$SMPROGRAMS\ADCH++\ADCH++ Help.lnk"
|
||||
Delete "$SMPROGRAMS\ADCH++\Remove ADCH++ windows service.lnk"
|
||||
Delete "$SMPROGRAMS\ADCH++\Install ADCH++ as windows service.lnk"
|
||||
Delete "$DESKTOP\ADCH++.lnk"
|
||||
|
||||
RMDir "$SMPROGRAMS\ADCH++"
|
||||
RMDir "$INSTDIR\lua\socket"
|
||||
RMDir "$INSTDIR\lua"
|
||||
RMDir "$INSTDIR\mime"
|
||||
RMDir "$INSTDIR\socket"
|
||||
RMDir "$INSTDIR\Scripts\FL_Database"
|
||||
RMDir "$INSTDIR\Scripts"
|
||||
RMDir "$INSTDIR\config\logs"
|
||||
RMDir "$INSTDIR\config"
|
||||
RMDir "$INSTDIR\Docs\images\icons"
|
||||
RMDir "$INSTDIR\Docs\images"
|
||||
RMDir "$INSTDIR\Docs"
|
||||
RMDir "$INSTDIR"
|
||||
|
||||
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
|
||||
DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
|
||||
SetAutoClose true
|
||||
SectionEnd
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,345 @@
|
|||
adchpp
|
||||
Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
|
||||
Here follows the full text of the GPL-2:
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
|
@ -0,0 +1,285 @@
|
|||
# vim: set filetype: py
|
||||
|
||||
EnsureSConsVersion(1, 2)
|
||||
|
||||
import os,sys
|
||||
from build_util import Dev
|
||||
|
||||
gcc_flags = {
|
||||
'common': ['-g', '-Wall', '-Wextra', '-Wno-unused-parameter', '-Wno-unused-value', '-Wno-missing-field-initializers', '-Wno-address', '-Wno-unknown-pragmas', '-fexceptions'],
|
||||
'debug': [],
|
||||
'release' : ['-O3', '-fno-ipa-cp-clone']
|
||||
}
|
||||
|
||||
gcc_xxflags = {
|
||||
'common' : ['-std=gnu++0x'],
|
||||
'debug' : [],
|
||||
'release' : []
|
||||
}
|
||||
|
||||
msvc_flags = {
|
||||
# 4100: unreferenced formal parameter
|
||||
# 4121: alignment of member sensitive to packing
|
||||
# 4127: conditional expression is constant
|
||||
# 4189: var init'd, unused
|
||||
# 4244: possible loss of data on conversion
|
||||
# 4290: exception spec ignored
|
||||
# 4355: "this" used in a constructor
|
||||
# 4510: no default constructor
|
||||
# 4512: assn not generated
|
||||
# 4610: no default constructor
|
||||
# 4706: assignment within conditional expression
|
||||
# 4800: converting from BOOL to bool
|
||||
# 4996: fn unsafe, use fn_s
|
||||
'common' : ['/W4', '/EHsc', '/Zi', '/Zm200', '/GR', '/FC', '/wd4100', '/wd4121', '/wd4127', '/wd4189', '/wd4244', '/wd4290', '/wd4355', '/wd4510', '/wd4512', '/wd4610', '/wd4706', '/wd4800', '/wd4996'],
|
||||
'debug' : ['/MDd', '/LDd'],
|
||||
'release' : ['/O2', '/MD', '/LD']
|
||||
}
|
||||
# we set /LD(d) by default for all sub-projects, since most of them are DLLs. don't forget to
|
||||
# remove it when building executables!
|
||||
|
||||
msvc_xxflags = {
|
||||
'common' : [],
|
||||
'debug' : [],
|
||||
'release' : []
|
||||
}
|
||||
|
||||
gcc_link_flags = {
|
||||
'common' : ['-g', '$UNDEF', '-time'],
|
||||
'debug' : [],
|
||||
'release' : ['-O3']
|
||||
}
|
||||
|
||||
msvc_link_flags = {
|
||||
'common' : ['/DEBUG', '/FIXED:NO', '/INCREMENTAL:NO'],
|
||||
'debug' : [],
|
||||
'release' : []
|
||||
}
|
||||
|
||||
msvc_defs = {
|
||||
'common' : ['_REENTRANT'],
|
||||
'debug' : ['_DEBUG', '_HAS_ITERATOR_DEBUGGING=0', '_SECURE_SCL=0'],
|
||||
'release' : ['NDEBUG']
|
||||
}
|
||||
|
||||
gcc_defs = {
|
||||
# _BSD_SOURCE is for some int types in LuaSocket on Linux.
|
||||
'common' : ['_REENTRANT', '_BSD_SOURCE'],
|
||||
'debug' : ['_DEBUG'],
|
||||
'release' : ['NDEBUG']
|
||||
}
|
||||
|
||||
# --- cut ---
|
||||
|
||||
import os,sys,distutils.sysconfig
|
||||
|
||||
plugins = filter(lambda x: os.path.isfile(os.path.join('plugins', x, 'SConscript')), os.listdir('plugins'))
|
||||
langs = ['lua', 'python', 'ruby']
|
||||
|
||||
defEnv = Environment(ENV = os.environ)
|
||||
opts = Variables('custom.py', ARGUMENTS)
|
||||
|
||||
if sys.platform == 'win32':
|
||||
tooldef = 'mingw'
|
||||
else:
|
||||
tooldef = 'default'
|
||||
|
||||
opts.AddVariables(
|
||||
EnumVariable('tools', 'Toolset to compile with, default = platform default (msvc under windows)', tooldef, ['mingw', 'default', 'clang', 'clang-analyzer']),
|
||||
EnumVariable('mode', 'Compile mode', 'debug', ['debug', 'release']),
|
||||
ListVariable('plugins', 'The plugins to compile', 'all', plugins),
|
||||
ListVariable('langs', 'The language bindings to compile', 'all', langs),
|
||||
BoolVariable('secure', 'Add support for secure TLS connections via OpenSSL', 'yes'),
|
||||
BoolVariable('gch', 'Use GCH when compiling GUI (disable if you have linking problems with mingw)', 'yes'),
|
||||
BoolVariable('verbose', 'Show verbose command lines', 'no'),
|
||||
BoolVariable('savetemps', 'Save intermediate compilation files (assembly output)', 'no'),
|
||||
('prefix', 'Prefix to use when cross compiling', ''),
|
||||
EnumVariable('arch', 'Target architecture', 'x86', ['x86', 'x64', 'ia64']),
|
||||
('python', 'Python path to use when compiling python extensions', distutils.sysconfig.get_config_var('prefix')),
|
||||
('ruby', 'Path to the ruby binary', 'ruby'),
|
||||
('lua', 'Path to the lua binary', 'lua'),
|
||||
BoolVariable('systemlua', 'Try to use the system lua libraries', 'no'),
|
||||
BoolVariable('systemboost', 'Use the system boost libraries', 'no'),
|
||||
BoolVariable('docs', 'Build docs (requires asciidoc)', 'no')
|
||||
)
|
||||
|
||||
opts.Update(defEnv)
|
||||
Help(opts.GenerateHelpText(defEnv))
|
||||
|
||||
# workaround for SCons 1.2 which hard-codes possible archs (only allows 'x86' and 'amd64'...)
|
||||
# TODO remove when SCons knows about all available archs
|
||||
TARGET_ARCH = defEnv['arch']
|
||||
if TARGET_ARCH == 'x64':
|
||||
TARGET_ARCH = 'amd64'
|
||||
|
||||
env = Environment(ENV = os.environ, tools = [defEnv['tools'], 'swig'], toolpath = ['tools'], options = opts, TARGET_ARCH = TARGET_ARCH, MSVS_ARCH = TARGET_ARCH)
|
||||
|
||||
# filter out boost from dependencies to get a speedier rebuild scan
|
||||
# this means that if boost changes, scons -c needs to be run
|
||||
# delete .sconsign.dblite to see the effects of this if you're upgrading
|
||||
def filterBoost(x):
|
||||
return [y for y in x if str(y).find('boost') == -1]
|
||||
|
||||
SourceFileScanner.function['.c'].recurse_nodes = filterBoost
|
||||
SourceFileScanner.function['.cpp'].recurse_nodes = filterBoost
|
||||
SourceFileScanner.function['.h'].recurse_nodes = filterBoost
|
||||
SourceFileScanner.function['.hpp'].recurse_nodes = filterBoost
|
||||
|
||||
dev = Dev(env)
|
||||
dev.prepare()
|
||||
|
||||
env.SConsignFile()
|
||||
|
||||
conf = Configure(env, conf_dir = dev.get_build_path('.sconf_temp'), log_file = dev.get_build_path('config.log'), clean = False, help = False, custom_tests = { 'CheckBoost' : dev.CheckBoost })
|
||||
|
||||
if dev.env['systemboost']:
|
||||
sysBoostLibs = []
|
||||
def checkBoostLib_(lib, header, call):
|
||||
if conf.CheckLibWithHeader(lib, header, 'C++', call, 0):
|
||||
sysBoostLibs.append(lib)
|
||||
return True
|
||||
return False
|
||||
def checkBoostLib(lib, header, call): return (checkBoostLib_(lib, header, call) or
|
||||
checkBoostLib_(lib + '-mt', header, call)) # Cygwin boost libs are named that way
|
||||
if (not conf.CheckBoost('1.49.0') or
|
||||
not checkBoostLib('libboost_system', 'boost/system/error_code.hpp', 'boost::system::error_code ec;') or
|
||||
not checkBoostLib('libboost_date_time', 'boost/date_time/posix_time/posix_time.hpp', 'boost::posix_time::microsec_clock::local_time();') or
|
||||
not checkBoostLib('libboost_locale', 'boost/locale.hpp', 'boost::locale::generator().generate("");')):
|
||||
raise Exception('Cannot use system boost libraries - try with systemboost=0')
|
||||
|
||||
if not dev.env['systemboost']:
|
||||
env.Append(CPPPATH = ['#/boost/'])
|
||||
env.Append(CPPDEFINES = ['BOOST_ALL_DYN_LINK=1'])
|
||||
if env['CC'] == 'cl': # MSVC
|
||||
env.Append(CPPDEFINES = ['BOOST_ALL_NO_LIB=1'])
|
||||
|
||||
if not dev.is_win32():
|
||||
env.Append(CPPDEFINES = ['_XOPEN_SOURCE=500'] )
|
||||
env.Append(CCFLAGS=['-fvisibility=hidden'])
|
||||
env.Append(LIBS = ['stdc++', 'm'])
|
||||
|
||||
if 'gcc' in env['TOOLS']:
|
||||
if dev.is_win32():
|
||||
env.Append(LINKFLAGS = ['-Wl,--enable-auto-import'])
|
||||
|
||||
if env['savetemps']:
|
||||
env.Append(CCFLAGS = ['-save-temps', '-fverbose-asm'])
|
||||
else:
|
||||
env.Append(CCFLAGS = ['-pipe'])
|
||||
|
||||
# require i686 instructions for atomic<int64_t>, used by boost::lockfree (otherwise lockfree
|
||||
# lists won't actually be lock-free).
|
||||
if env['arch'] == 'x86':
|
||||
env.Append(CCFLAGS = ['-march=i686'])
|
||||
|
||||
if env['CC'] == 'cl': # MSVC
|
||||
flags = msvc_flags
|
||||
xxflags = msvc_xxflags
|
||||
link_flags = msvc_link_flags
|
||||
defs = msvc_defs
|
||||
|
||||
if env['arch'] == 'x86':
|
||||
env.Append(CPPDEFINES = ['_USE_32BIT_TIME_T=1']) # for compatibility with PHP
|
||||
|
||||
else:
|
||||
flags = gcc_flags
|
||||
xxflags = gcc_xxflags
|
||||
link_flags = gcc_link_flags
|
||||
defs = gcc_defs
|
||||
|
||||
env.Tool("gch", toolpath=".")
|
||||
|
||||
env.Append(CPPDEFINES = defs[env['mode']])
|
||||
env.Append(CPPDEFINES = defs['common'])
|
||||
|
||||
env.Append(CCFLAGS = flags[env['mode']])
|
||||
env.Append(CCFLAGS = flags['common'])
|
||||
|
||||
env.Append(CXXFLAGS = xxflags[env['mode']])
|
||||
env.Append(CXXFLAGS = xxflags['common'])
|
||||
|
||||
env.Append(LINKFLAGS = link_flags[env['mode']])
|
||||
env.Append(LINKFLAGS = link_flags['common'])
|
||||
env.Append(UNDEF = '-Wl,--no-undefined')
|
||||
|
||||
if dev.is_win32():
|
||||
env.Append(LIBS = ['ws2_32', 'mswsock'])
|
||||
|
||||
env.SourceCode('.', None)
|
||||
|
||||
import SCons.Scanner
|
||||
SWIGScanner = SCons.Scanner.ClassicCPP(
|
||||
"SWIGScan",
|
||||
".i",
|
||||
"CPPPATH",
|
||||
'^[ \t]*[%,#][ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")'
|
||||
)
|
||||
env.Append(SCANNERS=[SWIGScanner])
|
||||
|
||||
if not env.GetOption('clean') and not env.GetOption("help"):
|
||||
|
||||
if not dev.is_win32():
|
||||
if conf.CheckCHeader('poll.h'):
|
||||
conf.env.Append(CPPDEFINES='HAVE_POLL_H')
|
||||
if conf.CheckCHeader('sys/epoll.h'):
|
||||
conf.env.Append(CPPDEFINES=['HAVE_SYS_EPOLL_H'])
|
||||
if conf.CheckLib('pthread', 'pthread_create'):
|
||||
conf.env.Append(CPPDEFINES=['HAVE_PTHREAD'])
|
||||
if env['secure'] and conf.CheckLib('ssl', 'SSL_connect'):
|
||||
conf.env.Append(CPPDEFINES=['HAVE_OPENSSL'])
|
||||
if conf.CheckLib('dl', 'dlopen'):
|
||||
conf.env.Append(CPPDEFINES=['HAVE_DL'])
|
||||
else:
|
||||
if env['secure'] and os.path.exists(Dir('#/openssl/include').abspath):
|
||||
conf.env.Append(CPPDEFINES=['HAVE_OPENSSL'])
|
||||
|
||||
env = conf.Finish()
|
||||
|
||||
env.Append(LIBPATH = env.Dir(dev.get_build_root() + 'bin/').abspath)
|
||||
if not dev.is_win32():
|
||||
dev.env.Append(RPATH = env.Literal('\\$$ORIGIN'))
|
||||
|
||||
if dev.env['systemboost']:
|
||||
env.Append(LIBS = sysBoostLibs)
|
||||
|
||||
else:
|
||||
dev.boost_system = dev.build('boost/libs/system/src/')
|
||||
dev.boost_date_time = dev.build('boost/libs/date_time/src/')
|
||||
dev.boost_locale = dev.build('boost/libs/locale/src/')
|
||||
|
||||
env.Append(LIBS = ['aboost_system', 'aboost_date_time', 'aboost_locale'])
|
||||
|
||||
dev.adchpp = dev.build('adchpp/')
|
||||
|
||||
dev.build('adchppd/')
|
||||
|
||||
# Lua for plugins & swig
|
||||
if 'Script' in env['plugins'] or 'lua' in env['langs']:
|
||||
dev.build('lua/')
|
||||
|
||||
# Library wrappers
|
||||
dev.build('swig/')
|
||||
|
||||
# Plugins
|
||||
for plugin in env['plugins']:
|
||||
dev.build('plugins/' + plugin + '/')
|
||||
|
||||
if env['docs']:
|
||||
asciidoc_cmd = dev.get_asciidoc()
|
||||
if asciidoc_cmd is None:
|
||||
print 'asciidoc not found, docs won\'t be built'
|
||||
|
||||
else:
|
||||
env['asciidoc_cmd'] = asciidoc_cmd
|
||||
def asciidoc(target, source, env):
|
||||
env.Execute(env['asciidoc_cmd'] + ' -o"' + str(target[0]) + '" "' + str(source[0]) + '"')
|
||||
|
||||
doc_path = '#/build/docs/'
|
||||
|
||||
env.Command(doc_path + 'readme.html', '#/readme.txt', asciidoc)
|
||||
|
||||
guide_path = '#/docs/user_guide/'
|
||||
env.Command(doc_path + 'user_guide/basic_guide.html', guide_path + 'basic_guide.txt', asciidoc)
|
||||
env.Command(doc_path + 'user_guide/expert_guide.html', guide_path + 'expert_guide.txt', asciidoc)
|
||||
env.Command(doc_path + 'user_guide/images', guide_path + 'images', Copy('$TARGET', '$SOURCE'))
|
||||
|
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
|
||||
#include "AdcCommand.h"
|
||||
|
||||
#include "Text.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
#ifdef __GNUC__ /// @todo go figure why some GCCs need these...
|
||||
const char AdcCommand::TYPE_BROADCAST;
|
||||
const char AdcCommand::TYPE_CLIENT;
|
||||
const char AdcCommand::TYPE_DIRECT;
|
||||
const char AdcCommand::TYPE_ECHO;
|
||||
const char AdcCommand::TYPE_FEATURE;
|
||||
const char AdcCommand::TYPE_INFO;
|
||||
const char AdcCommand::TYPE_HUB;
|
||||
const char AdcCommand::TYPE_UDP;
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
AdcCommand::AdcCommand() : cmdInt(0), priority(PRIORITY_NORMAL), from(INVALID_SID), to(INVALID_SID), type(TYPE_INFO) { }
|
||||
|
||||
AdcCommand::AdcCommand(Severity sev, Error err, const string& desc, char aType /* = TYPE_INFO */) : cmdInt(CMD_STA), priority(PRIORITY_NORMAL), from(HUB_SID), to(INVALID_SID), type(aType) {
|
||||
addParam(Util::toString(sev * 100 + err));
|
||||
addParam(desc);
|
||||
}
|
||||
|
||||
void AdcCommand::escape(const string& s, string& out) {
|
||||
out.reserve(out.length() + static_cast<size_t>(s.length() * 1.1));
|
||||
|
||||
for(string::const_iterator i = s.begin(), iend = s.end(); i != iend; ++i) {
|
||||
switch(*i) {
|
||||
case ' ': out += '\\'; out += 's'; break;
|
||||
case '\n': out += '\\'; out += 'n'; break;
|
||||
case '\\': out += '\\'; out += '\\'; break;
|
||||
default: out += *i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AdcCommand::parse(const char* buf, size_t len) throw(ParseException) {
|
||||
if(len < 5) {
|
||||
throw ParseException("Command too short");
|
||||
}
|
||||
|
||||
type = buf[0];
|
||||
|
||||
if(type != TYPE_BROADCAST && type != TYPE_CLIENT && type != TYPE_DIRECT && type != TYPE_ECHO && type != TYPE_FEATURE && type != TYPE_INFO && type != TYPE_HUB && type != TYPE_UDP) {
|
||||
throw ParseException("Invalid type");
|
||||
}
|
||||
|
||||
if(type == TYPE_HUB) {
|
||||
to = HUB_SID;
|
||||
}
|
||||
|
||||
cmd[0] = buf[1];
|
||||
cmd[1] = buf[2];
|
||||
cmd[2] = buf[3];
|
||||
|
||||
if(buf[4] != ' ') {
|
||||
throw ParseException("Missing space after command");
|
||||
}
|
||||
|
||||
// Skip trailing LF
|
||||
len--;
|
||||
|
||||
parameters.reserve(8);
|
||||
|
||||
string cur;
|
||||
cur.reserve(64);
|
||||
|
||||
bool toSet = false;
|
||||
bool featureSet = false;
|
||||
bool fromSet = false;
|
||||
|
||||
string::size_type i = 5;
|
||||
while(i < len) {
|
||||
switch(buf[i]) {
|
||||
case '\\':
|
||||
++i;
|
||||
if(i == len)
|
||||
throw ParseException("Escape at eol");
|
||||
if(buf[i] == 's')
|
||||
cur += ' ';
|
||||
else if(buf[i] == 'n')
|
||||
cur += '\n';
|
||||
else if(buf[i] == '\\')
|
||||
cur += '\\';
|
||||
else
|
||||
throw ParseException("Unknown escape");
|
||||
break;
|
||||
case ' ':
|
||||
// New parameter...
|
||||
{
|
||||
if((type == TYPE_BROADCAST || type == TYPE_DIRECT || type == TYPE_ECHO || type == TYPE_FEATURE) && !fromSet) {
|
||||
if(cur.length() != 4) {
|
||||
throw ParseException("Invalid SID length");
|
||||
}
|
||||
from = toSID(cur);
|
||||
fromSet = true;
|
||||
} else if((type == TYPE_DIRECT || type == TYPE_ECHO) && !toSet) {
|
||||
if(cur.length() != 4) {
|
||||
throw ParseException("Invalid SID length");
|
||||
}
|
||||
to = toSID(cur);
|
||||
toSet = true;
|
||||
} else if(type == TYPE_FEATURE && !featureSet) {
|
||||
if(cur.length() % 5 != 0) {
|
||||
throw ParseException("Invalid feature length");
|
||||
}
|
||||
features = cur;
|
||||
featureSet = true;
|
||||
} else {
|
||||
if(!Text::validateUtf8(cur)) {
|
||||
throw ParseException("Invalid UTF-8 sequence");
|
||||
}
|
||||
parameters.push_back(cur);
|
||||
}
|
||||
cur.clear();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cur += buf[i];
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
if(!cur.empty()) {
|
||||
if((type == TYPE_BROADCAST || type == TYPE_DIRECT || type == TYPE_ECHO || type == TYPE_FEATURE) && !fromSet) {
|
||||
if(cur.length() != 4) {
|
||||
throw ParseException("Invalid SID length");
|
||||
}
|
||||
from = toSID(cur);
|
||||
fromSet = true;
|
||||
} else if((type == TYPE_DIRECT || type == TYPE_ECHO) && !toSet) {
|
||||
if(cur.length() != 4) {
|
||||
throw ParseException("Invalid SID length");
|
||||
}
|
||||
to = toSID(cur);
|
||||
toSet = true;
|
||||
} else if(type == TYPE_FEATURE && !featureSet) {
|
||||
if(cur.length() % 5 != 0) {
|
||||
throw ParseException("Invalid feature length");
|
||||
}
|
||||
features = cur;
|
||||
featureSet = true;
|
||||
} else {
|
||||
if(!Text::validateUtf8(cur)) {
|
||||
throw ParseException("Invalid UTF-8 sequence");
|
||||
}
|
||||
parameters.push_back(cur);
|
||||
}
|
||||
}
|
||||
|
||||
if((type == TYPE_BROADCAST || type == TYPE_DIRECT || type == TYPE_ECHO || type == TYPE_FEATURE) && !fromSet) {
|
||||
throw ParseException("Missing from_sid");
|
||||
}
|
||||
|
||||
if(type == TYPE_FEATURE && !featureSet) {
|
||||
throw ParseException("Missing feature");
|
||||
}
|
||||
|
||||
if((type == TYPE_DIRECT || type == TYPE_ECHO) && !toSet) {
|
||||
throw ParseException("Missing to_sid");
|
||||
}
|
||||
}
|
||||
|
||||
const BufferPtr& AdcCommand::getBuffer() const {
|
||||
if(!buffer) {
|
||||
buffer = make_shared<Buffer>(toString());
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
string AdcCommand::toString() const {
|
||||
if(buffer) {
|
||||
return string((char*)buffer->data(), buffer->size());
|
||||
}
|
||||
string tmp;
|
||||
|
||||
tmp.reserve(128);
|
||||
|
||||
tmp += type;
|
||||
tmp += cmdChar;
|
||||
|
||||
if(type == TYPE_BROADCAST || type == TYPE_DIRECT || type == TYPE_ECHO || type == TYPE_FEATURE) {
|
||||
tmp += ' ';
|
||||
appendSID(tmp, from);
|
||||
}
|
||||
|
||||
if(type == TYPE_DIRECT || type == TYPE_ECHO) {
|
||||
tmp += ' ';
|
||||
appendSID(tmp, to);
|
||||
}
|
||||
|
||||
if(type == TYPE_FEATURE) {
|
||||
tmp += ' ';
|
||||
tmp += features;
|
||||
}
|
||||
|
||||
for(StringIterC i = getParameters().begin(); i != getParameters().end(); ++i) {
|
||||
tmp += ' ';
|
||||
escape(*i, tmp);
|
||||
}
|
||||
|
||||
tmp += '\n';
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool AdcCommand::getParam(const char* name, size_t start, string& ret) const {
|
||||
for(string::size_type i = start; i < getParameters().size(); ++i) {
|
||||
if(toField(name) == toField(getParameters()[i].c_str())) {
|
||||
ret = getParameters()[i].substr(2);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AdcCommand::delParam(const char* name, size_t start) {
|
||||
for(string::size_type i = start; i < getParameters().size(); ++i) {
|
||||
if(toField(name) == toField(getParameters()[i].c_str())) {
|
||||
getParameters().erase(getParameters().begin() + i);
|
||||
resetBuffer();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AdcCommand::hasFlag(const char* name, size_t start) const {
|
||||
for(string::size_type i = start; i < getParameters().size(); ++i) {
|
||||
if(toField(name) == toField(getParameters()[i].c_str()) &&
|
||||
getParameters()[i].size() == 3 &&
|
||||
getParameters()[i][2] == '1')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_ADC_COMMAND_H
|
||||
#define ADCHPP_ADC_COMMAND_H
|
||||
|
||||
#include "common.h"
|
||||
#include "Exception.h"
|
||||
#include "Util.h"
|
||||
#include "Buffer.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
STANDARD_EXCEPTION(ParseException);
|
||||
|
||||
class AdcCommand : private boost::noncopyable {
|
||||
public:
|
||||
template<uint32_t T>
|
||||
struct Type {
|
||||
enum { CMD = T };
|
||||
};
|
||||
|
||||
enum Error {
|
||||
ERROR_GENERIC = 0,
|
||||
ERROR_HUB_GENERIC = 10,
|
||||
ERROR_HUB_FULL = 11,
|
||||
ERROR_HUB_DISABLED = 12,
|
||||
ERROR_LOGIN_GENERIC = 20,
|
||||
ERROR_NICK_INVALID = 21,
|
||||
ERROR_NICK_TAKEN = 22,
|
||||
ERROR_BAD_PASSWORD = 23,
|
||||
ERROR_CID_TAKEN = 24,
|
||||
ERROR_COMMAND_ACCESS = 25,
|
||||
ERROR_REGGED_ONLY = 26,
|
||||
ERROR_INVALID_PID = 27,
|
||||
ERROR_BANNED_GENERIC = 30,
|
||||
ERROR_PERM_BANNED = 31,
|
||||
ERROR_TEMP_BANNED = 32,
|
||||
ERROR_PROTOCOL_GENERIC = 40,
|
||||
ERROR_PROTOCOL_UNSUPPORTED = 41,
|
||||
ERROR_CONNECT_FAILED = 42,
|
||||
ERROR_INF_MISSING = 43,
|
||||
ERROR_BAD_STATE = 44,
|
||||
ERROR_FEATURE_MISSING = 45,
|
||||
ERROR_BAD_IP = 46,
|
||||
ERROR_NO_HUB_HASH = 47,
|
||||
ERROR_TRANSFER_GENERIC = 50,
|
||||
ERROR_FILE_NOT_AVAILABLE = 51,
|
||||
ERROR_FILE_PART_NOT_AVAILABLE = 52,
|
||||
ERROR_SLOTS_FULL = 53,
|
||||
ERROR_NO_CLIENT_HASH = 54
|
||||
};
|
||||
|
||||
enum Severity {
|
||||
SEV_SUCCESS = 0,
|
||||
SEV_RECOVERABLE = 1,
|
||||
SEV_FATAL = 2
|
||||
};
|
||||
|
||||
enum Priority {
|
||||
PRIORITY_NORMAL, ///< Default priority, command will be sent out normally
|
||||
PRIORITY_LOW, ///< Low priority, command will only be sent if connection isn't saturated
|
||||
PRIORITY_IGNORE ///< Ignore, command will not be put in send queue
|
||||
};
|
||||
|
||||
static const char TYPE_BROADCAST = 'B';
|
||||
static const char TYPE_CLIENT = 'C';
|
||||
static const char TYPE_DIRECT = 'D';
|
||||
static const char TYPE_ECHO = 'E';
|
||||
static const char TYPE_FEATURE = 'F';
|
||||
static const char TYPE_INFO = 'I';
|
||||
static const char TYPE_HUB = 'H';
|
||||
static const char TYPE_UDP = 'U';
|
||||
|
||||
// Known commands...
|
||||
#define C(n, a, b, c) static const uint32_t CMD_##n = (((uint32_t)a) | (((uint32_t)b)<<8) | (((uint32_t)c)<<16)); typedef Type<CMD_##n> n
|
||||
// Base commands
|
||||
C(SUP, 'S','U','P');
|
||||
C(STA, 'S','T','A');
|
||||
C(INF, 'I','N','F');
|
||||
C(MSG, 'M','S','G');
|
||||
C(SCH, 'S','C','H');
|
||||
C(RES, 'R','E','S');
|
||||
C(CTM, 'C','T','M');
|
||||
C(RCM, 'R','C','M');
|
||||
C(GPA, 'G','P','A');
|
||||
C(PAS, 'P','A','S');
|
||||
C(QUI, 'Q','U','I');
|
||||
C(GET, 'G','E','T');
|
||||
C(GFI, 'G','F','I');
|
||||
C(SND, 'S','N','D');
|
||||
C(SID, 'S','I','D');
|
||||
// Extensions
|
||||
C(CMD, 'C','M','D');
|
||||
C(NAT, 'N','A','T');
|
||||
C(RNT, 'R','N','T');
|
||||
#undef C
|
||||
|
||||
static const uint32_t HUB_SID = static_cast<uint32_t>(-1);
|
||||
static const uint32_t INVALID_SID = static_cast<uint32_t>(-2);
|
||||
|
||||
static uint32_t toSID(const std::string& aSID) { return *reinterpret_cast<const uint32_t*>(aSID.data()); }
|
||||
static std::string fromSID(const uint32_t aSID) { return std::string(reinterpret_cast<const char*>(&aSID), sizeof(aSID)); }
|
||||
static void appendSID(std::string& str, uint32_t aSID) { str.append(reinterpret_cast<const char*>(&aSID), sizeof(aSID)); }
|
||||
|
||||
static uint32_t toCMD(uint8_t a, uint8_t b, uint8_t c) { return (((uint32_t)a) | (((uint32_t)b)<<8) | (((uint32_t)c)<<16)); }
|
||||
static uint32_t toCMD(const char* str) { return toCMD(str[0], str[1], str[2]); }
|
||||
|
||||
static uint16_t toField(const char* x) { return *((uint16_t*)x); }
|
||||
static std::string fromField(const uint16_t aField) { return std::string(reinterpret_cast<const char*>(&aField), sizeof(aField)); }
|
||||
|
||||
static uint32_t toFourCC(const char* x) { return *reinterpret_cast<const uint32_t*>(x); }
|
||||
static std::string fromFourCC(uint32_t x) { return std::string(reinterpret_cast<const char*>(&x), sizeof(x)); }
|
||||
|
||||
ADCHPP_DLL AdcCommand();
|
||||
ADCHPP_DLL explicit AdcCommand(Severity sev, Error err, const std::string& desc, char aType = TYPE_INFO);
|
||||
explicit AdcCommand(uint32_t cmd, char aType = TYPE_INFO, uint32_t aFrom = HUB_SID) : cmdInt(cmd), priority(PRIORITY_NORMAL), from(aFrom), to(INVALID_SID), type(aType) { }
|
||||
explicit AdcCommand(const std::string& aLine) throw(ParseException) : cmdInt(0), priority(PRIORITY_NORMAL), from(INVALID_SID), to(INVALID_SID), type(0) { parse(aLine); }
|
||||
explicit AdcCommand(const BufferPtr& buffer_) throw(ParseException) : buffer(buffer_), cmdInt(0), priority(PRIORITY_NORMAL), from(INVALID_SID), to(INVALID_SID), type(0) { parse((const char*)buffer->data(), buffer->size()); }
|
||||
|
||||
void parse(const std::string& str) throw(ParseException) { parse(str.data(), str.size()); }
|
||||
ADCHPP_DLL void parse(const char* buf, size_t len) throw(ParseException);
|
||||
uint32_t getCommand() const { return cmdInt; }
|
||||
char getType() const { return type; }
|
||||
std::string getFourCC() const { std::string tmp(4, 0); tmp[0] = type; tmp[1] = cmd[0]; tmp[2] = cmd[1]; tmp[3] = cmd[2]; return tmp; }
|
||||
StringList& getParameters() { return parameters; }
|
||||
const StringList& getParameters() const { return parameters; }
|
||||
ADCHPP_DLL std::string toString() const;
|
||||
|
||||
AdcCommand& addParam(const std::string& param) {
|
||||
parameters.push_back(param);
|
||||
resetBuffer();
|
||||
return *this;
|
||||
}
|
||||
|
||||
AdcCommand& addParam(const std::string& name, const std::string& value) {
|
||||
return addParam(name + value);
|
||||
}
|
||||
|
||||
const std::string& getParam(size_t n) const {
|
||||
return getParameters().size() > n ? getParameters()[n] : Util::emptyString;
|
||||
}
|
||||
|
||||
void resetBuffer() { buffer.reset(); }
|
||||
|
||||
const std::string& getFeatures() const { return features; }
|
||||
|
||||
/** Return a named parameter where the name is a two-letter code */
|
||||
ADCHPP_DLL bool getParam(const char* name, size_t start, std::string& ret) const;
|
||||
ADCHPP_DLL bool delParam(const char* name, size_t start);
|
||||
|
||||
ADCHPP_DLL bool hasFlag(const char* name, size_t start) const;
|
||||
|
||||
bool operator==(uint32_t aCmd) const { return cmdInt == aCmd; }
|
||||
|
||||
ADCHPP_DLL static void escape(const std::string& s, std::string& out);
|
||||
|
||||
ADCHPP_DLL const BufferPtr& getBuffer() const;
|
||||
|
||||
uint32_t getTo() const { return to; }
|
||||
void setTo(uint32_t aTo) { to = aTo; }
|
||||
uint32_t getFrom() const { return from; }
|
||||
void setFrom(uint32_t aFrom) { from = aFrom; }
|
||||
|
||||
Priority getPriority() const { return priority; }
|
||||
void setPriority(Priority priority_) { priority = priority_; }
|
||||
|
||||
private:
|
||||
StringList parameters;
|
||||
std::string features;
|
||||
|
||||
mutable BufferPtr buffer;
|
||||
|
||||
union {
|
||||
char cmdChar[4];
|
||||
uint8_t cmd[4];
|
||||
uint32_t cmdInt;
|
||||
};
|
||||
|
||||
Priority priority;
|
||||
uint32_t from;
|
||||
uint32_t to;
|
||||
char type;
|
||||
};
|
||||
|
||||
class Client;
|
||||
class Entity;
|
||||
|
||||
template<class T>
|
||||
class CommandHandler {
|
||||
public:
|
||||
bool dispatch(Entity& c, AdcCommand& cmd) {
|
||||
#define C(n) case AdcCommand::CMD_##n: return ((T*)this)->handle(AdcCommand::n(), c, cmd); break;
|
||||
switch(cmd.getCommand()) {
|
||||
C(SUP);
|
||||
C(STA);
|
||||
C(INF);
|
||||
C(MSG);
|
||||
C(SCH);
|
||||
C(RES);
|
||||
C(CTM);
|
||||
C(RCM);
|
||||
C(GPA);
|
||||
C(PAS);
|
||||
C(QUI);
|
||||
C(GET);
|
||||
C(GFI);
|
||||
C(SND);
|
||||
C(SID);
|
||||
C(CMD);
|
||||
C(NAT);
|
||||
C(RNT);
|
||||
default:
|
||||
dcdebug("Unknown ADC command: %.50s\n", cmd.toString().c_str());
|
||||
return true;
|
||||
#undef C
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // ADC_COMMAND_H
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include "Buffer.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
class AsyncStream : private boost::noncopyable {
|
||||
public:
|
||||
typedef std::function<void (const boost::system::error_code& ec, size_t)> Handler;
|
||||
|
||||
virtual size_t available() = 0;
|
||||
virtual void init(const std::function<void ()>& postInit) = 0;
|
||||
virtual void setOptions(size_t bufferSize) = 0;
|
||||
virtual std::string getIp() = 0;
|
||||
virtual void prepareRead(const BufferPtr& buf, const Handler& handler) = 0;
|
||||
virtual size_t read(const BufferPtr& buf) = 0;
|
||||
virtual void write(const BufferList& bufs, const Handler& handler) = 0;
|
||||
virtual void shutdown(const Handler& handler) = 0;
|
||||
virtual void close() = 0;
|
||||
|
||||
virtual ~AsyncStream() { }
|
||||
};
|
||||
|
||||
typedef shared_ptr<AsyncStream> AsyncStreamPtr;
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
|
||||
#include "Bot.h"
|
||||
|
||||
#include "ClientManager.h"
|
||||
#include "SocketManager.h"
|
||||
#include "Core.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
// TODO replace with lambda
|
||||
struct BotRemover {
|
||||
BotRemover(Bot* bot_,Util::Reason reason, const std::string &info) : bot(bot_), reason(reason), info(info) { }
|
||||
void operator()() {
|
||||
bot->die(reason, info);
|
||||
}
|
||||
|
||||
Bot* bot;
|
||||
Util::Reason reason;
|
||||
std::string info;
|
||||
};
|
||||
|
||||
Bot::Bot(ClientManager &cm, uint32_t sid, const Bot::SendHandler& handler_) : Entity(cm, sid), handler(handler_), disconnecting(false) {
|
||||
setFlag(FLAG_BOT);
|
||||
|
||||
// Fake a CID, the script can change this if it wants to
|
||||
setCID(CID::generate());
|
||||
}
|
||||
|
||||
void Bot::disconnect(Util::Reason reason, const std::string &info) throw() {
|
||||
if(!disconnecting) {
|
||||
disconnecting = true;
|
||||
|
||||
handler = SendHandler();
|
||||
cm.getCore().addJob(BotRemover(this, reason, info));
|
||||
}
|
||||
}
|
||||
|
||||
void Bot::die(Util::Reason reason, const std::string &info) {
|
||||
cm.removeEntity(*this, reason, info);
|
||||
delete this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef BOT_H_
|
||||
#define BOT_H_
|
||||
|
||||
#include "forward.h"
|
||||
|
||||
#include "Entity.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
struct BotRemover;
|
||||
|
||||
class ADCHPP_VISIBLE Bot : public Entity {
|
||||
public:
|
||||
typedef std::function<void (Bot& bot, const BufferPtr& cmd)> SendHandler;
|
||||
|
||||
ADCHPP_DLL Bot(ClientManager &cm, uint32_t sid, const SendHandler& handler_);
|
||||
|
||||
virtual void send(const BufferPtr& cmd) { if(handler) handler(*this, cmd); }
|
||||
|
||||
ADCHPP_DLL virtual void disconnect(Util::Reason reason, const std::string &info) throw();
|
||||
|
||||
using Entity::send;
|
||||
private:
|
||||
friend struct BotRemover;
|
||||
|
||||
SendHandler handler;
|
||||
bool disconnecting;
|
||||
|
||||
void die(Util::Reason reason, const std::string &info);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* BOT_H_ */
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
|
||||
#include "Buffer.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
size_t Buffer::defaultBufferSize = 128;
|
||||
|
||||
SimplePool<ByteVector, Buffer::Clear> Buffer::pool;
|
||||
|
||||
void Buffer::Clear::operator()(ByteVector& v) {
|
||||
if(v.capacity() > static_cast<size_t>(getDefaultBufferSize())) {
|
||||
ByteVector().swap(v);
|
||||
} else {
|
||||
v.clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef BUFFER_H_
|
||||
#define BUFFER_H_
|
||||
|
||||
#include "Pool.h"
|
||||
#include "FastAlloc.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
/**
|
||||
* Reference-counted buffer
|
||||
*/
|
||||
class Buffer :
|
||||
public FastAlloc<Buffer>,
|
||||
private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
Buffer(const std::string& str) : bufp(pool.get()) { append((uint8_t*)str.data(), (uint8_t*)str.data() + str.size()); }
|
||||
Buffer(const void* ptr, const size_t size) : bufp(pool.get()) { append((uint8_t*) ptr, ((uint8_t*)ptr)+size); }
|
||||
Buffer(const size_t size) : bufp(pool.get()) { resize(size); }
|
||||
|
||||
operator const ByteVector&() const { return buf(); }
|
||||
operator ByteVector&() { return buf(); }
|
||||
|
||||
void resize(size_t new_size) { buf().resize(new_size); }
|
||||
size_t size() const { return buf().size(); }
|
||||
const uint8_t* data() const { return &buf()[0]; }
|
||||
uint8_t* data() { return &buf()[0]; }
|
||||
|
||||
/** Erase the first n bytes */
|
||||
void erase_first(size_t n) { buf().erase(buf().begin(), buf().begin() + n); }
|
||||
|
||||
template<typename InputIterator>
|
||||
void append(InputIterator start, InputIterator end) { buf().insert(buf().end(), start, end); }
|
||||
|
||||
static void setDefaultBufferSize(size_t newSize) { defaultBufferSize = newSize; }
|
||||
static size_t getDefaultBufferSize() { return defaultBufferSize; }
|
||||
|
||||
virtual ~Buffer() { pool.put(bufp); }
|
||||
private:
|
||||
static size_t defaultBufferSize;
|
||||
|
||||
const ByteVector& buf() const { return *bufp; }
|
||||
ByteVector& buf() { return *bufp; }
|
||||
|
||||
ByteVector* bufp;
|
||||
|
||||
struct Clear {
|
||||
ADCHPP_DLL void operator()(ByteVector& x);
|
||||
};
|
||||
|
||||
ADCHPP_DLL static SimplePool<ByteVector, Clear> pool;
|
||||
};
|
||||
|
||||
typedef shared_ptr<Buffer> BufferPtr;
|
||||
typedef std::vector<BufferPtr> BufferList;
|
||||
|
||||
}
|
||||
|
||||
#endif /*BUFFER_H_*/
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_CID_H
|
||||
#define ADCHPP_CID_H
|
||||
|
||||
#include "Util.h"
|
||||
#include "Encoder.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
class CID {
|
||||
public:
|
||||
enum { SIZE = 192 / 8 };
|
||||
enum { BASE32_SIZE = 39 };
|
||||
|
||||
CID() { memset(cid, 0, sizeof(cid)); }
|
||||
explicit CID(const uint8_t* data) { memcpy(cid, data, sizeof(cid)); }
|
||||
explicit CID(const std::string& base32) { Encoder::fromBase32(base32.c_str(), cid, sizeof(cid)); }
|
||||
|
||||
CID(const CID& rhs) { memcpy(cid, rhs.cid, sizeof(cid)); }
|
||||
CID& operator=(const CID& rhs) { memcpy(cid, rhs.cid, sizeof(cid)); return *this; }
|
||||
|
||||
bool operator==(const CID& rhs) const { return memcmp(cid, rhs.cid, sizeof(cid)) == 0; }
|
||||
bool operator<(const CID& rhs) const { return memcmp(cid, rhs.cid, sizeof(cid)) < 0; }
|
||||
|
||||
std::string toBase32() const { return Encoder::toBase32(cid, sizeof(cid)); }
|
||||
std::string& toBase32(std::string& tmp) const { return Encoder::toBase32(cid, sizeof(cid), tmp); }
|
||||
|
||||
size_t toHash() const { static_assert(sizeof(cid) >= sizeof(cidHash), "cid too small, cidHash invalid"); return cidHash; }
|
||||
const uint8_t* data() const { return cid; }
|
||||
|
||||
bool isZero() const { return std::find_if(cid, cid+SIZE, std::bind2nd(std::not_equal_to<uint8_t>(), 0)) == (cid+SIZE); }
|
||||
|
||||
static CID generate() {
|
||||
uint8_t data[CID::SIZE];
|
||||
for(size_t i = 0; i < sizeof(data); ++i) {
|
||||
data[i] = (uint8_t)Util::rand();
|
||||
}
|
||||
return CID(data);
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
uint8_t cid[SIZE];
|
||||
size_t cidHash;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<adchpp::CID> {
|
||||
size_t operator()(const adchpp::CID& cid) const {
|
||||
return cid.toHash();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
|
||||
#include "Client.h"
|
||||
|
||||
#include "ClientManager.h"
|
||||
#include "TimeUtil.h"
|
||||
#include "SocketManager.h"
|
||||
#include "Core.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
using namespace std;
|
||||
using namespace std::placeholders;
|
||||
|
||||
Client* Client::create(ClientManager &cm, const ManagedSocketPtr& ms, uint32_t sid) throw() {
|
||||
Client* c = new Client(cm, sid);
|
||||
c->setSocket(ms);
|
||||
return c;
|
||||
}
|
||||
|
||||
Client::Client(ClientManager &cm, uint32_t sid_) throw() :
|
||||
Entity(cm, sid_),
|
||||
disconnecting(false),
|
||||
dataBytes(0)
|
||||
{
|
||||
}
|
||||
|
||||
Client::~Client() {
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Lightweight call forwarders, instead of std::bind
|
||||
template<void (Client::*F)()>
|
||||
struct Handler0 {
|
||||
Handler0(Client* c_) : c(c_) { }
|
||||
void operator()() { (c->*F)(); }
|
||||
Client* c;
|
||||
};
|
||||
|
||||
template<typename T, void (Client::*F)(const T&)>
|
||||
struct Handler1 {
|
||||
Handler1(Client* c_) : c(c_) { }
|
||||
void operator()(const T& bv) { (c->*F)(bv); }
|
||||
Client* c;
|
||||
};
|
||||
|
||||
template<typename T, typename T2, void (Client::*F)(T, const T2&)>
|
||||
struct Handler2 {
|
||||
Handler2(Client* c_) : c(c_) { }
|
||||
void operator()(const T& t, const T2& t2) { (c->*F)(t, t2); }
|
||||
Client* c;
|
||||
};
|
||||
}
|
||||
|
||||
void Client::setSocket(const ManagedSocketPtr& aSocket) throw() {
|
||||
dcassert(!socket);
|
||||
socket = aSocket;
|
||||
socket->setConnectedHandler(Handler0<&Client::onConnected>(this));
|
||||
socket->setReadyHandler(Handler0<&Client::onReady>(this));
|
||||
socket->setDataHandler(Handler1<BufferPtr, &Client::onData>(this));
|
||||
socket->setFailedHandler(Handler2<Util::Reason, std::string, &Client::onFailed>(this));
|
||||
}
|
||||
|
||||
void Client::onConnected() throw() {
|
||||
cm.onConnected(*this);
|
||||
}
|
||||
|
||||
void Client::onReady() throw() {
|
||||
cm.onReady(*this);
|
||||
}
|
||||
|
||||
void Client::onData(const BufferPtr& buf) throw() {
|
||||
uint8_t* data = buf->data();
|
||||
size_t done = 0;
|
||||
size_t len = buf->size();
|
||||
while(!disconnecting && done < len) {
|
||||
if(dataBytes > 0) {
|
||||
size_t n = (size_t)min(dataBytes, (int64_t)(len - done));
|
||||
dataHandler(*this, data + done, n);
|
||||
dataBytes -= n;
|
||||
done += n;
|
||||
} else {
|
||||
size_t j = done;
|
||||
while(j < len && data[j] != '\n')
|
||||
++j;
|
||||
|
||||
if(j == len) {
|
||||
if(!buffer) {
|
||||
if(done == 0) {
|
||||
buffer = buf;
|
||||
} else {
|
||||
buffer = make_shared<Buffer>(data + done, len - done);
|
||||
}
|
||||
} else {
|
||||
buffer->append(data + done, data + len);
|
||||
}
|
||||
return;
|
||||
} else if(!buffer) {
|
||||
if(done == 0 && j == len-1) {
|
||||
buffer = buf;
|
||||
} else {
|
||||
buffer = make_shared<Buffer>(data + done, j - done + 1);
|
||||
}
|
||||
} else {
|
||||
buffer->append(data + done, data + j + 1);
|
||||
}
|
||||
|
||||
done = j + 1;
|
||||
|
||||
if(cm.getMaxCommandSize() > 0 && buffer->size() > cm.getMaxCommandSize()) {
|
||||
send(AdcCommand(AdcCommand::SEV_FATAL, AdcCommand::ERROR_PROTOCOL_GENERIC, "Command too long"));
|
||||
disconnect(Util::REASON_MAX_COMMAND_SIZE);
|
||||
return;
|
||||
}
|
||||
|
||||
if(buffer->size() == 1) {
|
||||
buffer.reset();
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
AdcCommand cmd(buffer);
|
||||
|
||||
if(cmd.getType() == 'H') {
|
||||
cmd.setFrom(getSID());
|
||||
} else if(cmd.getFrom() != getSID()) {
|
||||
disconnect(Util::REASON_INVALID_SID);
|
||||
return;
|
||||
}
|
||||
|
||||
cm.onReceive(*this, cmd);
|
||||
} catch(const ParseException&) {
|
||||
cm.onBadLine(*this, string((char*)buffer->data(), buffer->size()));
|
||||
}
|
||||
|
||||
buffer.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Client::disconnect(Util::Reason reason, const std::string &info) throw() {
|
||||
dcassert(socket);
|
||||
if(!disconnecting) {
|
||||
dcdebug("%s disconnecting because %d\n", AdcCommand::fromSID(getSID()).c_str(), reason);
|
||||
disconnecting = true;
|
||||
socket->disconnect(reason, info);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::onFailed(Util::Reason reason, const std::string &info) throw() {
|
||||
cm.onFailed(*this, reason, info);
|
||||
delete this;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_CLIENT_H
|
||||
#define ADCHPP_CLIENT_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "ManagedSocket.h"
|
||||
#include "FastAlloc.h"
|
||||
#include "AdcCommand.h"
|
||||
#include "CID.h"
|
||||
#include "Entity.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
/**
|
||||
* The client represents one connection to a user.
|
||||
*/
|
||||
class ADCHPP_VISIBLE Client : public Entity, public FastAlloc<Client> {
|
||||
public:
|
||||
static Client* create(ClientManager &cm, const ManagedSocketPtr& ms_, uint32_t sid_) throw();
|
||||
|
||||
using Entity::send;
|
||||
|
||||
virtual void send(const BufferPtr& command) { socket->write(command); }
|
||||
|
||||
/** @param reason The statistic to update */
|
||||
ADCHPP_DLL virtual void disconnect(Util::Reason reason, const std::string &info = Util::emptyString) throw();
|
||||
const std::string& getIp() const throw() { return socket->getIp(); }
|
||||
|
||||
/**
|
||||
* Set data mode for aBytes bytes.
|
||||
* May only be called from on(ClientListener::Command...).
|
||||
*/
|
||||
typedef std::function<void (Client&, const uint8_t*, size_t)> DataFunction;
|
||||
void setDataMode(const DataFunction& handler, int64_t aBytes) { dataHandler = handler; dataBytes = aBytes; }
|
||||
|
||||
virtual size_t getQueuedBytes() const { return socket->getQueuedBytes(); }
|
||||
virtual time::ptime getOverflow() const { return socket->getOverflow(); }
|
||||
|
||||
private:
|
||||
Client(ClientManager &cm, uint32_t sid_) throw();
|
||||
virtual ~Client();
|
||||
|
||||
bool disconnecting;
|
||||
|
||||
BufferPtr buffer;
|
||||
ManagedSocketPtr socket;
|
||||
int64_t dataBytes;
|
||||
|
||||
DataFunction dataHandler;
|
||||
void setSocket(const ManagedSocketPtr& aSocket) throw();
|
||||
|
||||
void onConnected() throw();
|
||||
void onReady() throw();
|
||||
void onData(const BufferPtr&) throw();
|
||||
void onFailed(Util::Reason reason, const std::string &info) throw();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // CLIENT_H
|
|
@ -0,0 +1,647 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
|
||||
#include "ClientManager.h"
|
||||
|
||||
#include "File.h"
|
||||
#include "Client.h"
|
||||
#include "LogManager.h"
|
||||
#include "SocketManager.h"
|
||||
#include "TigerHash.h"
|
||||
#include "Encoder.h"
|
||||
#include "version.h"
|
||||
|
||||
#include <boost/asio/ip/address.hpp>
|
||||
#include <boost/asio/ip/address_v4.hpp>
|
||||
#include <boost/asio/ip/address_v6.hpp>
|
||||
#include <boost/locale.hpp>
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
using namespace std;
|
||||
|
||||
const string ClientManager::className = "ClientManager";
|
||||
|
||||
ClientManager::ClientManager(Core &core) throw() :
|
||||
core(core),
|
||||
hub(*this),
|
||||
maxCommandSize(16 * 1024),
|
||||
logTimeout(30 * 1000)
|
||||
{
|
||||
hub.addSupports(AdcCommand::toFourCC("BASE"));
|
||||
hub.addSupports(AdcCommand::toFourCC("TIGR"));
|
||||
}
|
||||
|
||||
Bot* ClientManager::createBot(const Bot::SendHandler& handler) {
|
||||
Bot* ret = new Bot(*this, makeSID(), handler);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ClientManager::regBot(Bot& bot) {
|
||||
enterIdentify(bot, false);
|
||||
enterNormal(bot, false, true);
|
||||
cids.insert(make_pair(bot.getCID(), &bot));
|
||||
nicks.insert(make_pair(bot.getField("NI"), &bot));
|
||||
}
|
||||
|
||||
void ClientManager::send(const AdcCommand& cmd) throw() {
|
||||
if(cmd.getPriority() == AdcCommand::PRIORITY_IGNORE) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool all = false;
|
||||
switch(cmd.getType()) {
|
||||
case AdcCommand::TYPE_BROADCAST:
|
||||
all = true; // Fallthrough
|
||||
case AdcCommand::TYPE_FEATURE: {
|
||||
for(EntityIter i = entities.begin(); i != entities.end(); ++i) {
|
||||
if(all || !i->second->isFiltered(cmd.getFeatures())) {
|
||||
maybeSend(*i->second, cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AdcCommand::TYPE_DIRECT: // Fallthrough
|
||||
case AdcCommand::TYPE_ECHO: {
|
||||
Entity* e = getEntity(cmd.getTo());
|
||||
if(e) {
|
||||
maybeSend(*e, cmd);
|
||||
|
||||
if(cmd.getType() == AdcCommand::TYPE_ECHO) {
|
||||
e = getEntity(cmd.getFrom());
|
||||
if(e) {
|
||||
maybeSend(*e, cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ClientManager::maybeSend(Entity& c, const AdcCommand& cmd) {
|
||||
bool ok = true;
|
||||
signalSend_(c, cmd, ok);
|
||||
if(ok) {
|
||||
c.send(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientManager::sendToAll(const BufferPtr& buf) throw() {
|
||||
for(EntityIter i = entities.begin(); i != entities.end(); ++i) {
|
||||
i->second->send(buf);
|
||||
}
|
||||
}
|
||||
|
||||
size_t ClientManager::getQueuedBytes() throw() {
|
||||
size_t total = 0;
|
||||
|
||||
for(EntityIter i = entities.begin(); i != entities.end(); ++i) {
|
||||
total += i->second->getQueuedBytes();
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
void ClientManager::sendTo(const BufferPtr& buffer, uint32_t to) {
|
||||
EntityIter i = entities.find(to);
|
||||
if(i != entities.end()) {
|
||||
i->second->send(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientManager::handleIncoming(const ManagedSocketPtr& socket) throw() {
|
||||
Client::create(*this, socket, makeSID());
|
||||
}
|
||||
|
||||
uint32_t ClientManager::makeSID() {
|
||||
while(true) {
|
||||
union {
|
||||
uint32_t sid;
|
||||
char chars[4];
|
||||
} sid;
|
||||
sid.chars[0] = Encoder::base32Alphabet[Util::rand(sizeof(Encoder::base32Alphabet))];
|
||||
sid.chars[1] = Encoder::base32Alphabet[Util::rand(sizeof(Encoder::base32Alphabet))];
|
||||
sid.chars[2] = Encoder::base32Alphabet[Util::rand(sizeof(Encoder::base32Alphabet))];
|
||||
sid.chars[3] = Encoder::base32Alphabet[Util::rand(sizeof(Encoder::base32Alphabet))];
|
||||
if(sid.sid != 0 && entities.find(sid.sid) == entities.end()) {
|
||||
return sid.sid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientManager::onConnected(Client& c) throw() {
|
||||
dcdebug("%s connected\n", AdcCommand::fromSID(c.getSID()).c_str());
|
||||
// First let's check if any clients have passed the login timeout...
|
||||
auto timeout = time::now() - time::millisec(getLogTimeout());
|
||||
|
||||
while(!logins.empty() && (timeout > logins.front().second)) {
|
||||
Client* cc = logins.front().first;
|
||||
|
||||
dcdebug("ClientManager: Login timeout in state %d\n", cc->getState());
|
||||
cc->disconnect(Util::REASON_LOGIN_TIMEOUT);
|
||||
logins.pop_front();
|
||||
}
|
||||
|
||||
logins.push_back(make_pair(&c, time::now()));
|
||||
|
||||
signalConnected_(c);
|
||||
}
|
||||
|
||||
void ClientManager::onReady(Client& c) throw() {
|
||||
dcdebug("%s ready\n", AdcCommand::fromSID(c.getSID()).c_str());
|
||||
signalReady_(c);
|
||||
}
|
||||
|
||||
void ClientManager::onReceive(Entity& c, AdcCommand& cmd) throw() {
|
||||
if(c.isSet(Entity::FLAG_GHOST)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!(cmd.getType() == AdcCommand::TYPE_BROADCAST || cmd.getType() == AdcCommand::TYPE_DIRECT || cmd.getType()
|
||||
== AdcCommand::TYPE_ECHO || cmd.getType() == AdcCommand::TYPE_FEATURE || cmd.getType() == AdcCommand::TYPE_HUB))
|
||||
{
|
||||
disconnect(c, Util::REASON_INVALID_COMMAND_TYPE, "Invalid command type");
|
||||
return;
|
||||
}
|
||||
|
||||
bool ok = true;
|
||||
signalReceive_(c, cmd, ok);
|
||||
|
||||
if(ok) {
|
||||
if(!dispatch(c, cmd)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
send(cmd);
|
||||
}
|
||||
|
||||
void ClientManager::onBadLine(Client& c, const string& aLine) throw() {
|
||||
if(c.isSet(Entity::FLAG_GHOST)) {
|
||||
return;
|
||||
}
|
||||
|
||||
signalBadLine_(c, aLine);
|
||||
}
|
||||
|
||||
void ClientManager::badState(Entity& c, const AdcCommand& cmd) throw() {
|
||||
disconnect(c, Util::REASON_BAD_STATE, "Invalid state for command", AdcCommand::ERROR_BAD_STATE, "FC" + cmd.getFourCC());
|
||||
}
|
||||
|
||||
bool ClientManager::handleDefault(Entity& c, AdcCommand& cmd) throw() {
|
||||
if(c.getState() != Entity::STATE_NORMAL) {
|
||||
badState(c, cmd);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientManager::handle(AdcCommand::SUP, Entity& c, AdcCommand& cmd) throw() {
|
||||
if(!verifySUP(c, cmd)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(c.getState() == Entity::STATE_PROTOCOL) {
|
||||
enterIdentify(c, true);
|
||||
} else if(c.getState() != Entity::STATE_NORMAL) {
|
||||
badState(c, cmd);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientManager::verifySUP(Entity& c, AdcCommand& cmd) throw() {
|
||||
c.updateSupports(cmd);
|
||||
|
||||
if(!c.hasSupport(AdcCommand::toFourCC("BASE"))) {
|
||||
disconnect(c, Util::REASON_NO_BASE_SUPPORT, "This hub requires BASE support");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!c.hasSupport(AdcCommand::toFourCC("TIGR"))) {
|
||||
disconnect(c, Util::REASON_NO_TIGR_SUPPORT, "This hub requires TIGR support");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientManager::verifyINF(Entity& c, AdcCommand& cmd) throw() {
|
||||
Client* cc = dynamic_cast<Client*>(&c);
|
||||
|
||||
if(cc) {
|
||||
if(!verifyIp(*cc, cmd))
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!verifyCID(c, cmd))
|
||||
return false;
|
||||
|
||||
if(!verifyNick(c, cmd))
|
||||
return false;
|
||||
|
||||
if(cmd.getParam("DE", 0, strtmp)) {
|
||||
if(!Util::validateCharset(strtmp, 32)) {
|
||||
disconnect(c, Util::REASON_INVALID_DESCRIPTION, "Invalid character in description");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
c.updateFields(cmd);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientManager::verifyPassword(Entity& c, const string& password, const ByteVector& salt,
|
||||
const string& suppliedHash, TigerHash&& tiger) {
|
||||
tiger.update(&password[0], password.size());
|
||||
tiger.update(&salt[0], salt.size());
|
||||
uint8_t tmp[TigerHash::BYTES];
|
||||
Encoder::fromBase32(suppliedHash.c_str(), tmp, TigerHash::BYTES);
|
||||
if(memcmp(tiger.finalize(), tmp, TigerHash::BYTES) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ClientManager::verifyPassword(Entity& c, const string& password, const ByteVector& salt,
|
||||
const string& suppliedHash) {
|
||||
return verifyPassword(c, password, salt, suppliedHash, TigerHash());
|
||||
}
|
||||
|
||||
bool ClientManager::verifyHashedPassword(Entity& c, const ByteVector& hashedPassword, int64_t hashedPasswordLen,
|
||||
const ByteVector& salt, const string& suppliedHash) {
|
||||
// hashedPassword must be in little-endian order; this code itself is endian-independent.
|
||||
uint64_t initial_res[TigerHash::BYTES/8];
|
||||
for (auto i = 0; i < 3; ++i) {
|
||||
initial_res[i] = 0;
|
||||
for (auto j = 0; j < 8; ++j)
|
||||
initial_res[i] = initial_res[i] * 256 + hashedPassword[8*i+(7-j)];
|
||||
}
|
||||
return verifyPassword(c, "", salt, suppliedHash, TigerHash(hashedPasswordLen, initial_res));
|
||||
}
|
||||
|
||||
bool ClientManager::verifyOverflow(Entity& c) {
|
||||
size_t overflowing = 0;
|
||||
for(EntityIter i = entities.begin(), iend = entities.end(); i != iend; ++i) {
|
||||
if(!i->second->getOverflow().is_not_a_date_time()) {
|
||||
overflowing++;
|
||||
}
|
||||
}
|
||||
|
||||
if(overflowing > 3 && overflowing > (entities.size() / 4)) {
|
||||
disconnect(c, Util::REASON_NO_BANDWIDTH, "Not enough bandwidth available, please try again later", AdcCommand::ERROR_HUB_FULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientManager::handle(AdcCommand::INF, Entity& c, AdcCommand& cmd) throw() {
|
||||
if(c.getState() != Entity::STATE_IDENTIFY && c.getState() != Entity::STATE_NORMAL) {
|
||||
badState(c, cmd);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!verifyINF(c, cmd))
|
||||
return false;
|
||||
|
||||
if(c.getState() == Entity::STATE_IDENTIFY) {
|
||||
if(!verifyOverflow(c)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
enterNormal(c, true, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientManager::verifyIp(Client& c, AdcCommand& cmd) throw() {
|
||||
if(c.isSet(Entity::FLAG_OK_IP))
|
||||
return true;
|
||||
|
||||
using namespace boost::asio::ip;
|
||||
|
||||
auto remote = address::from_string(c.getIp());
|
||||
std::string ip;
|
||||
|
||||
if(remote.is_v4() || (remote.is_v6() && remote.to_v6().is_v4_mapped())) {
|
||||
auto v4 = remote.is_v4() ? remote.to_v4() : remote.to_v6().to_v4();
|
||||
|
||||
if(cmd.getParam("I4", 0, ip)) {
|
||||
dcdebug("%s verifying IP %s\n", AdcCommand::fromSID(c.getSID()).c_str(), ip.c_str());
|
||||
if(ip.empty() || address_v4::from_string(ip) == address_v4::any()) {
|
||||
cmd.delParam("I4", 0);
|
||||
} else if(address_v4::from_string(ip) != v4 && !Util::isPrivateIp(c.getIp())) {
|
||||
disconnect(c, Util::REASON_INVALID_IP, "Your IP is " + c.getIp() +
|
||||
", reconfigure your client settings", AdcCommand::ERROR_BAD_IP, "IP" + c.getIp());
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!c.hasField("I4")) {
|
||||
c.setField("I4", v4.to_string());
|
||||
}
|
||||
|
||||
if(c.getState() != Entity::STATE_NORMAL) {
|
||||
cmd.addParam("I4", v4.to_string());
|
||||
}
|
||||
|
||||
cmd.delParam("I6", 0); // We can't check this so we remove it instead...fix?
|
||||
} else if(remote.is_v6()) {
|
||||
if(cmd.getParam("I6", 0, ip)) {
|
||||
dcdebug("%s verifying IPv6 %s\n", AdcCommand::fromSID(c.getSID()).c_str(), ip.c_str());
|
||||
if(ip.empty() || address_v6::from_string(ip) == address_v6::any()) {
|
||||
cmd.delParam("I6", 0);
|
||||
} else if(address_v6::from_string(ip) != remote.to_v6() && !Util::isPrivateIp(c.getIp())) {
|
||||
disconnect(c, Util::REASON_INVALID_IP, "Your IP is " + c.getIp() +
|
||||
", reconfigure your client settings", AdcCommand::ERROR_BAD_IP, "IP" + c.getIp());
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!c.hasField("I6")) {
|
||||
c.setField("I6", c.getIp());
|
||||
}
|
||||
|
||||
if(c.getState() != Entity::STATE_NORMAL) {
|
||||
cmd.addParam("I6", c.getIp());
|
||||
}
|
||||
|
||||
cmd.delParam("I4", 0); // We can't check this so we remove it instead...fix?
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientManager::verifyCID(Entity& c, AdcCommand& cmd) throw() {
|
||||
if(cmd.getParam("ID", 0, strtmp)) {
|
||||
dcdebug("%s verifying CID %s\n", AdcCommand::fromSID(c.getSID()).c_str(), strtmp.c_str());
|
||||
if(c.getState() != Entity::STATE_IDENTIFY) {
|
||||
disconnect(c, Util::REASON_CID_CHANGE, "CID changes not allowed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(strtmp.size() != CID::BASE32_SIZE) {
|
||||
disconnect(c, Util::REASON_PID_CID_LENGTH, "Invalid CID length");
|
||||
return false;
|
||||
}
|
||||
|
||||
CID cid(strtmp);
|
||||
|
||||
strtmp.clear();
|
||||
|
||||
if(!cmd.getParam("PD", 0, strtmp)) {
|
||||
disconnect(c, Util::REASON_PID_MISSING, "PID missing", AdcCommand::ERROR_INF_MISSING, "FLPD");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(strtmp.size() != CID::BASE32_SIZE) {
|
||||
disconnect(c, Util::REASON_PID_CID_LENGTH, "Invalid PID length");
|
||||
return false;
|
||||
}
|
||||
|
||||
CID pid(strtmp);
|
||||
|
||||
TigerHash th;
|
||||
th.update(pid.data(), CID::SIZE);
|
||||
if(!(CID(th.finalize()) == cid)) {
|
||||
disconnect(c, Util::REASON_PID_CID_MISMATCH, "PID does not correspond to CID", AdcCommand::ERROR_INVALID_PID);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto other = cids.find(cid);
|
||||
if(other != cids.end()) {
|
||||
// disconnect the ghost
|
||||
disconnect(*other->second, Util::REASON_CID_TAKEN, "CID taken", AdcCommand::ERROR_CID_TAKEN);
|
||||
removeEntity(*other->second, Util::REASON_CID_TAKEN, Util::emptyString);
|
||||
}
|
||||
|
||||
c.setCID(cid);
|
||||
|
||||
cids.insert(make_pair(c.getCID(), &c));
|
||||
cmd.delParam("PD", 0);
|
||||
}
|
||||
|
||||
if(cmd.getParam("PD", 0, strtmp)) {
|
||||
disconnect(c, Util::REASON_PID_WITHOUT_CID, "CID required when sending PID");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool validateNickF(wchar_t c) { /// @todo lambda
|
||||
|
||||
// the following are explicitly allowed (isprint sometimes differs)
|
||||
if(c >= L'\u2100' && c <= L'\u214F' /* letter-like symbols */) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// the following are explicitly disallowed (isprint sometimes differs)
|
||||
if(c == L'\u00AD' /* soft hyphen */) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::locale loc = boost::locale::generator().generate("");
|
||||
return !std::isprint(c, loc);
|
||||
}
|
||||
|
||||
bool validateNick(const string& nick) {
|
||||
if(!Util::validateCharset(nick, 33)) { // chars < 33 forbidden (including the space char)
|
||||
return false;
|
||||
}
|
||||
|
||||
// avoid impersonators
|
||||
std::wstring nickW = boost::locale::conv::utf_to_utf<wchar_t>(nick);
|
||||
if(std::find_if(nickW.begin(), nickW.end(), validateNickF) != nickW.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientManager::verifyNick(Entity& c, const AdcCommand& cmd) throw() {
|
||||
if(cmd.getParam("NI", 0, strtmp)) {
|
||||
dcdebug("%s verifying nick %s\n", AdcCommand::fromSID(c.getSID()).c_str(), strtmp.c_str());
|
||||
|
||||
if(!validateNick(strtmp)) {
|
||||
disconnect(c, Util::REASON_NICK_INVALID, "Invalid character in nick", AdcCommand::ERROR_NICK_INVALID);
|
||||
return false;
|
||||
}
|
||||
|
||||
const string& oldNick = c.getField("NI");
|
||||
if(!oldNick.empty())
|
||||
nicks.erase(oldNick);
|
||||
|
||||
if(nicks.find(strtmp) != nicks.end()) {
|
||||
disconnect(c, Util::REASON_NICK_TAKEN, "Nick taken, please pick another one", AdcCommand::ERROR_NICK_TAKEN);
|
||||
return false;
|
||||
}
|
||||
|
||||
nicks.insert(make_pair(strtmp, &c));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClientManager::setState(Entity& c, Entity::State newState) throw() {
|
||||
Entity::State oldState = c.getState();
|
||||
c.setState(newState);
|
||||
signalState_(c, oldState);
|
||||
}
|
||||
|
||||
void ClientManager::disconnect(Entity& c, Util::Reason reason, const std::string& info, AdcCommand::Error error, const std::string& staParam) {
|
||||
// send a fatal STA
|
||||
AdcCommand sta(AdcCommand::SEV_FATAL, error, info);
|
||||
if(!staParam.empty())
|
||||
sta.addParam(staParam);
|
||||
c.send(sta);
|
||||
|
||||
// send a QUI
|
||||
c.send(AdcCommand(AdcCommand::CMD_QUI).addParam(AdcCommand::fromSID(c.getSID()))
|
||||
.addParam("DI", "1").addParam("MS", info).addParam("TL", "-1"));
|
||||
|
||||
c.disconnect(reason);
|
||||
}
|
||||
|
||||
void ClientManager::enterIdentify(Entity& c, bool sendData) throw() {
|
||||
dcassert(c.getState() == Entity::STATE_PROTOCOL);
|
||||
dcdebug("%s entering IDENTIFY\n", AdcCommand::fromSID(c.getSID()).c_str());
|
||||
if(sendData) {
|
||||
c.send(hub.getSUP());
|
||||
c.send(AdcCommand(AdcCommand::CMD_SID).addParam(AdcCommand::fromSID(c.getSID())));
|
||||
c.send(hub.getINF());
|
||||
}
|
||||
|
||||
setState(c, Entity::STATE_IDENTIFY);
|
||||
}
|
||||
|
||||
ByteVector ClientManager::enterVerify(Entity& c, bool sendData) throw() {
|
||||
dcassert(c.getState() == Entity::STATE_IDENTIFY);
|
||||
dcdebug("%s entering VERIFY\n", AdcCommand::fromSID(c.getSID()).c_str());
|
||||
|
||||
ByteVector challenge;
|
||||
challenge.reserve(32);
|
||||
for(int i = 0; i < 32 / 4; ++i) {
|
||||
uint32_t r = Util::rand();
|
||||
challenge.insert(challenge.end(), (uint8_t*) &r, 4 + (uint8_t*) &r);
|
||||
}
|
||||
|
||||
if(sendData) {
|
||||
c.send(AdcCommand(AdcCommand::CMD_GPA).addParam(Encoder::toBase32(&challenge[0], challenge.size())));
|
||||
}
|
||||
|
||||
setState(c, Entity::STATE_VERIFY);
|
||||
return challenge;
|
||||
}
|
||||
|
||||
bool ClientManager::enterNormal(Entity& c, bool sendData, bool sendOwnInf) throw() {
|
||||
dcassert(c.getState() == Entity::STATE_IDENTIFY || c.getState() == Entity::STATE_VERIFY);
|
||||
dcdebug("%s entering NORMAL\n", AdcCommand::fromSID(c.getSID()).c_str());
|
||||
|
||||
if(sendData) {
|
||||
for(EntityIter i = entities.begin(); i != entities.end(); ++i) {
|
||||
c.send(i->second->getINF());
|
||||
}
|
||||
}
|
||||
|
||||
if(sendOwnInf) {
|
||||
sendToAll(c.getINF());
|
||||
if(sendData) {
|
||||
c.send(c.getINF());
|
||||
}
|
||||
}
|
||||
|
||||
removeLogins(c);
|
||||
|
||||
entities.insert(make_pair(c.getSID(), &c));
|
||||
|
||||
setState(c, Entity::STATE_NORMAL);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClientManager::removeLogins(Entity& e) throw() {
|
||||
Client* c = dynamic_cast<Client*>(&e);
|
||||
if(!c) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto i = find_if(logins.begin(), logins.end(), CompareFirst<Client*, time::ptime> (c));
|
||||
if(i != logins.end()) {
|
||||
logins.erase(i);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientManager::removeEntity(Entity& c, Util::Reason reason, const std::string &info) throw() {
|
||||
if(c.isSet(Entity::FLAG_GHOST))
|
||||
return;
|
||||
|
||||
dcdebug("Removing %s - %s\n", AdcCommand::fromSID(c.getSID()).c_str(), c.getCID().toBase32().c_str());
|
||||
c.setFlag(Entity::FLAG_GHOST);
|
||||
|
||||
signalDisconnected_(c, reason, info);
|
||||
|
||||
if(c.getState() == Entity::STATE_NORMAL) {
|
||||
entities.erase(c.getSID());
|
||||
sendToAll(AdcCommand(AdcCommand::CMD_QUI).addParam(AdcCommand::fromSID(c.getSID())).addParam("DI", "1").getBuffer());
|
||||
} else {
|
||||
removeLogins(c);
|
||||
}
|
||||
|
||||
nicks.erase(c.getField("NI"));
|
||||
cids.erase(c.getCID());
|
||||
}
|
||||
|
||||
Entity* ClientManager::getEntity(uint32_t aSid) throw() {
|
||||
switch(aSid) {
|
||||
case AdcCommand::INVALID_SID: return nullptr;
|
||||
case AdcCommand::HUB_SID: return &hub;
|
||||
default:
|
||||
{
|
||||
EntityIter i = entities.find(aSid);
|
||||
return (i == entities.end()) ? nullptr : i->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ClientManager::getSID(const string& aNick) const throw() {
|
||||
NickMap::const_iterator i = nicks.find(aNick);
|
||||
return (i == nicks.end()) ? AdcCommand::INVALID_SID : i->second->getSID();
|
||||
}
|
||||
|
||||
uint32_t ClientManager::getSID(const CID& cid) const throw() {
|
||||
CIDMap::const_iterator i = cids.find(cid);
|
||||
return (i == cids.end()) ? AdcCommand::INVALID_SID : i->second->getSID();
|
||||
}
|
||||
|
||||
void ClientManager::onFailed(Client& c, Util::Reason reason, const std::string &info) throw() {
|
||||
removeEntity(c, reason, info);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_CLIENTMANAGER_H
|
||||
#define ADCHPP_CLIENTMANAGER_H
|
||||
|
||||
#include "CID.h"
|
||||
#include "AdcCommand.h"
|
||||
#include "Signal.h"
|
||||
#include "Client.h"
|
||||
#include "Hub.h"
|
||||
#include "Bot.h"
|
||||
#include "TimeUtil.h"
|
||||
#include "TigerHash.h"
|
||||
|
||||
#include "forward.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
class ManagedSocket;
|
||||
|
||||
/**
|
||||
* The ClientManager takes care of all protocol details, clients and so on. This is the very
|
||||
* heart of ADCH++ together with SocketManager and ManagedSocket.
|
||||
*/
|
||||
class ClientManager : public CommandHandler<ClientManager>
|
||||
{
|
||||
public:
|
||||
typedef std::unordered_map<uint32_t, Entity*> EntityMap;
|
||||
typedef EntityMap::iterator EntityIter;
|
||||
|
||||
/** @return SID of entity or AdcCommand::INVALID_SID if not found */
|
||||
ADCHPP_DLL uint32_t getSID(const std::string& nick) const throw();
|
||||
/** @return SID of entity or AdcCommand::INVALID_SID if not found */
|
||||
ADCHPP_DLL uint32_t getSID(const CID& cid) const throw();
|
||||
|
||||
/** @return The entity associated with a certain SID, NULL if not found */
|
||||
ADCHPP_DLL Entity* getEntity(uint32_t aSid) throw();
|
||||
|
||||
/** @return A new Bot instance in STATE_IDENTIFY; set CID, nick etc and call regBot */
|
||||
ADCHPP_DLL Bot* createBot(const Bot::SendHandler& handler);
|
||||
ADCHPP_DLL void regBot(Bot& bot);
|
||||
|
||||
/**
|
||||
* Get a list of all currently connected clients. (Don't change it, it's non-const
|
||||
* so that you'll be able to get non-const clients out of it...)!!!)
|
||||
*/
|
||||
EntityMap& getEntities() throw() { return entities; }
|
||||
|
||||
/** Send a command to according to its type */
|
||||
ADCHPP_DLL void send(const AdcCommand& cmd) throw();
|
||||
|
||||
/** Send a buffer to all connected entities */
|
||||
ADCHPP_DLL void sendToAll(const BufferPtr& buffer) throw();
|
||||
|
||||
/** Send buffer to a single client regardless of type */
|
||||
ADCHPP_DLL void sendTo(const BufferPtr& buffer, uint32_t to);
|
||||
|
||||
/**
|
||||
* Enter IDENTIFY state.
|
||||
* Call this if you stop the SUP command when in PROTOCOL state.
|
||||
*
|
||||
* @param sendData Send ISUP & IINF.
|
||||
*/
|
||||
ADCHPP_DLL void enterIdentify(Entity& c, bool sendData) throw();
|
||||
|
||||
/**
|
||||
* Enter VERIFY state. Call this if you stop
|
||||
* an INF in the IDENTIFY state and want to check a password.
|
||||
*
|
||||
* @param sendData Send GPA.
|
||||
* @return The random data that was sent to the client (if sendData was true, undefined otherwise).
|
||||
*/
|
||||
ADCHPP_DLL ByteVector enterVerify(Entity& c, bool sendData) throw();
|
||||
|
||||
/**
|
||||
* Enter NORMAL state. Call this if you stop an INF of a password-less
|
||||
* client in IDENTIFY state or a PAS in VERIFY state.
|
||||
*
|
||||
* @param sendData Send all data as mandated by the protocol, including list of connected clients.
|
||||
* @param sendOwnInf Set to true to broadcast the client's inf (i e when a plugin asks
|
||||
* for password)
|
||||
* @return false if the client was disconnected
|
||||
*/
|
||||
ADCHPP_DLL bool enterNormal(Entity& c, bool sendData, bool sendOwnInf) throw();
|
||||
|
||||
/**
|
||||
* Do all SUP verifications and update client data. Call if you stop SUP but still want the default processing.
|
||||
*/
|
||||
ADCHPP_DLL bool verifySUP(Entity& c, AdcCommand& cmd) throw();
|
||||
|
||||
/**
|
||||
* Do all INF verifications and update client data. Call if you stop INF but still want the default processing.
|
||||
*/
|
||||
ADCHPP_DLL bool verifyINF(Entity& c, AdcCommand& cmd) throw();
|
||||
|
||||
/**
|
||||
* Verify nick on INF (check that its not a dupe etc...)
|
||||
* @return false if the client was disconnected
|
||||
*/
|
||||
ADCHPP_DLL bool verifyNick(Entity& c, const AdcCommand& cmd) throw();
|
||||
|
||||
/**
|
||||
* Verify password
|
||||
*/
|
||||
ADCHPP_DLL bool verifyPassword(Entity& c, const std::string& password, const ByteVector& salt, const std::string& suppliedHash);
|
||||
bool verifyPassword(Entity& c, const std::string& password, const ByteVector& salt,
|
||||
const std::string& suppliedHash, TigerHash&& tiger);
|
||||
|
||||
/**
|
||||
* Verify hashed password; based on http://www.dcbase.org/forums/viewtopic.php?p=2861#p2861
|
||||
*/
|
||||
ADCHPP_DLL bool verifyHashedPassword(Entity& c, const ByteVector& hashedPassword, int64_t hashedPasswordLen,
|
||||
const ByteVector& salt, const std::string& suppliedHash);
|
||||
|
||||
/**
|
||||
* Verify that IP is correct and replace any zero addresses.
|
||||
*/
|
||||
ADCHPP_DLL bool verifyIp(Client& c, AdcCommand& cmd) throw();
|
||||
|
||||
/**
|
||||
* Verify that CID is correct and corresponds to PID
|
||||
*/
|
||||
ADCHPP_DLL bool verifyCID(Entity& c, AdcCommand& cmd) throw();
|
||||
|
||||
/**
|
||||
* Verify that there aren't too many sockets overflowing (indicates lack of bandwidth)
|
||||
*/
|
||||
ADCHPP_DLL bool verifyOverflow(Entity& c);
|
||||
|
||||
/** Update the state of c (this fires signalState as well) */
|
||||
ADCHPP_DLL void setState(Entity& c, Entity::State newState) throw();
|
||||
|
||||
ADCHPP_DLL size_t getQueuedBytes() throw();
|
||||
|
||||
typedef SignalTraits<void (Entity&)> SignalConnected;
|
||||
typedef SignalTraits<void (Entity&)> SignalReady;
|
||||
typedef SignalTraits<void (Entity&, AdcCommand&, bool&)> SignalReceive;
|
||||
typedef SignalTraits<void (Entity&, const std::string&)> SignalBadLine;
|
||||
typedef SignalTraits<void (Entity&, const AdcCommand&, bool&)> SignalSend;
|
||||
typedef SignalTraits<void (Entity&, int)> SignalState;
|
||||
typedef SignalTraits<void (Entity&, Util::Reason, const std::string&)> SignalDisconnected;
|
||||
|
||||
/** A client has just connected. */
|
||||
SignalConnected::Signal& signalConnected() { return signalConnected_; }
|
||||
/** A client is now ready for read / write operations (TLS handshake completed). */
|
||||
SignalConnected::Signal& signalReady() { return signalReady_; }
|
||||
SignalReceive::Signal& signalReceive() { return signalReceive_; }
|
||||
SignalBadLine::Signal& signalBadLine() { return signalBadLine_; }
|
||||
SignalSend::Signal& signalSend() { return signalSend_; }
|
||||
SignalState::Signal& signalState() { return signalState_; }
|
||||
SignalDisconnected::Signal& signalDisconnected() { return signalDisconnected_; }
|
||||
|
||||
void setMaxCommandSize(size_t newSize) { maxCommandSize = newSize; }
|
||||
size_t getMaxCommandSize() const { return maxCommandSize; }
|
||||
|
||||
void setLogTimeout(size_t millis) { logTimeout = millis; }
|
||||
size_t getLogTimeout() const { return logTimeout; }
|
||||
|
||||
Core &getCore() const { return core; }
|
||||
private:
|
||||
friend class Core;
|
||||
friend class Client;
|
||||
friend class Entity;
|
||||
friend class Bot;
|
||||
|
||||
Core &core;
|
||||
|
||||
std::list<std::pair<Client*, time::ptime> > logins;
|
||||
|
||||
EntityMap entities;
|
||||
typedef std::unordered_map<std::string, Entity*> NickMap;
|
||||
NickMap nicks;
|
||||
typedef std::unordered_map<CID, Entity*> CIDMap;
|
||||
CIDMap cids;
|
||||
|
||||
Hub hub;
|
||||
|
||||
size_t maxCommandSize;
|
||||
size_t logTimeout;
|
||||
|
||||
// Temporary string to use whenever a temporary string is needed (to avoid (de)allocating memory all the time...)
|
||||
std::string strtmp;
|
||||
|
||||
static const std::string className;
|
||||
|
||||
friend class CommandHandler<ClientManager>;
|
||||
|
||||
uint32_t makeSID();
|
||||
|
||||
void maybeSend(Entity& c, const AdcCommand& cmd);
|
||||
|
||||
void removeLogins(Entity& c) throw();
|
||||
void removeEntity(Entity& c, Util::Reason reason, const std::string &info) throw();
|
||||
|
||||
bool handle(AdcCommand::SUP, Entity& c, AdcCommand& cmd) throw();
|
||||
bool handle(AdcCommand::INF, Entity& c, AdcCommand& cmd) throw();
|
||||
bool handleDefault(Entity& c, AdcCommand& cmd) throw();
|
||||
|
||||
template<typename T> bool handle(T, Entity& c, AdcCommand& cmd) throw() { return handleDefault(c, cmd); }
|
||||
|
||||
void handleIncoming(const ManagedSocketPtr& sock) throw();
|
||||
|
||||
void onConnected(Client&) throw();
|
||||
void onReady(Client&) throw();
|
||||
void onReceive(Entity&, AdcCommand&) throw();
|
||||
void onBadLine(Client&, const std::string&) throw();
|
||||
void onFailed(Client&, Util::Reason reason, const std::string &info) throw();
|
||||
|
||||
void badState(Entity& c, const AdcCommand& cmd) throw();
|
||||
/** send a fatal STA, a QUI with TL-1, then disconnect. */
|
||||
void disconnect(Entity& c, Util::Reason reason, const std::string& info,
|
||||
AdcCommand::Error error = AdcCommand::ERROR_PROTOCOL_GENERIC, const std::string& staParam = Util::emptyString);
|
||||
|
||||
SignalConnected::Signal signalConnected_;
|
||||
SignalReady::Signal signalReady_;
|
||||
SignalReceive::Signal signalReceive_;
|
||||
SignalBadLine::Signal signalBadLine_;
|
||||
SignalSend::Signal signalSend_;
|
||||
SignalState::Signal signalState_;
|
||||
SignalDisconnected::Signal signalDisconnected_;
|
||||
|
||||
ClientManager(Core &core) throw();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // CLIENTMANAGER_H
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
|
||||
#include "Core.h"
|
||||
|
||||
#include "LogManager.h"
|
||||
#include "SocketManager.h"
|
||||
#include "ClientManager.h"
|
||||
#include "PluginManager.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
shared_ptr<Core> Core::create(const std::string &configPath) {
|
||||
auto ret = shared_ptr<Core>(new Core(configPath));
|
||||
ret->init();
|
||||
return ret;
|
||||
}
|
||||
|
||||
Core::Core(const std::string &configPath) : configPath(configPath), startTime(time::now())
|
||||
{
|
||||
}
|
||||
|
||||
Core::~Core() {
|
||||
lm->log("core", "Shutting down...");
|
||||
// Order is significant...
|
||||
pm.reset();
|
||||
cm.reset();
|
||||
sm.reset();
|
||||
lm.reset();
|
||||
}
|
||||
|
||||
void Core::init() {
|
||||
lm.reset(new LogManager(*this));
|
||||
sm.reset(new SocketManager(*this));
|
||||
cm.reset(new ClientManager(*this));
|
||||
pm.reset(new PluginManager(*this));
|
||||
|
||||
sm->setIncomingHandler(std::bind(&ClientManager::handleIncoming, cm.get(), std::placeholders::_1));
|
||||
//lm->log("core", "Core initialized"); @todo logfile path setting isn't processed yet so this may litter log files to unwanted places, see L#907372
|
||||
printf("\nCore initialized\n"); // Console print only for now...
|
||||
|
||||
}
|
||||
|
||||
void Core::run() {
|
||||
pm->load();
|
||||
|
||||
sm->run();
|
||||
}
|
||||
|
||||
void Core::shutdown() {
|
||||
// make sure we run shutdown routines from the right thread.
|
||||
addJob(std::bind(&Core::doShutdown, this));
|
||||
}
|
||||
|
||||
void Core::doShutdown() {
|
||||
sm->shutdown();
|
||||
pm->shutdown();
|
||||
}
|
||||
|
||||
const std::string &Core::getConfigPath() const { return configPath; }
|
||||
LogManager &Core::getLogManager() { return *lm; }
|
||||
SocketManager &Core::getSocketManager() { return *sm; }
|
||||
PluginManager &Core::getPluginManager() { return *pm; }
|
||||
ClientManager &Core::getClientManager() { return *cm; }
|
||||
|
||||
void Core::addJob(const Callback& callback) throw() { sm->addJob(callback); }
|
||||
|
||||
void Core::addJob(const long msec, const Callback& callback) { sm->addJob(msec, callback); }
|
||||
|
||||
void Core::addJob(const std::string& time, const Callback& callback) { sm->addJob(time, callback); }
|
||||
|
||||
Core::Callback Core::addTimedJob(const long msec, const Callback& callback) { return sm->addTimedJob(msec, callback); }
|
||||
|
||||
Core::Callback Core::addTimedJob(const std::string& time, const Callback& callback) { return sm->addTimedJob(time, callback); }
|
||||
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_ADCHPP_CORE_H_
|
||||
#define ADCHPP_ADCHPP_CORE_H_
|
||||
|
||||
#include "common.h"
|
||||
#include "TimeUtil.h"
|
||||
|
||||
#include "forward.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
/** A single instance of an entire hub with plugins, settings and listening sockets */
|
||||
class Core {
|
||||
public:
|
||||
typedef std::function<void()> Callback;
|
||||
ADCHPP_DLL ~Core();
|
||||
|
||||
ADCHPP_DLL static shared_ptr<Core> create(const std::string &configPath);
|
||||
|
||||
ADCHPP_DLL void run();
|
||||
|
||||
ADCHPP_DLL void shutdown();
|
||||
|
||||
ADCHPP_DLL LogManager &getLogManager();
|
||||
ADCHPP_DLL SocketManager &getSocketManager();
|
||||
ADCHPP_DLL PluginManager &getPluginManager();
|
||||
ADCHPP_DLL ClientManager &getClientManager();
|
||||
|
||||
ADCHPP_DLL const std::string &getConfigPath() const;
|
||||
|
||||
/** execute a function asynchronously */
|
||||
ADCHPP_DLL void addJob(const Callback& callback) throw();
|
||||
|
||||
/** execute a function after the specified amount of time
|
||||
* @param msec milliseconds
|
||||
*/
|
||||
ADCHPP_DLL void addJob(const long msec, const Callback& callback);
|
||||
|
||||
/** execute a function after the specified amount of time
|
||||
* @param time a string that obeys to the "[-]h[h][:mm][:ss][.fff]" format
|
||||
*/
|
||||
ADCHPP_DLL void addJob(const std::string& time, const Callback& callback);
|
||||
|
||||
/** execute a function at regular intervals
|
||||
* @param msec milliseconds
|
||||
* @return function one must call to cancel the timer (its callback will still be executed)
|
||||
*/
|
||||
ADCHPP_DLL Callback addTimedJob(const long msec, const Callback& callback);
|
||||
|
||||
/** execute a function at regular intervals
|
||||
* @param time a string that obeys to the "[-]h[h][:mm][:ss][.fff]" format
|
||||
* @return function one must call to cancel the timer (its callback will still be executed)
|
||||
*/
|
||||
ADCHPP_DLL Callback addTimedJob(const std::string& time, const Callback& callback);
|
||||
|
||||
time::ptime getStartTime() const { return startTime; }
|
||||
|
||||
private:
|
||||
Core(const std::string &configPath);
|
||||
|
||||
void init();
|
||||
|
||||
void doShutdown(); /// @todo remove when we have lambdas
|
||||
|
||||
std::unique_ptr<LogManager> lm;
|
||||
std::unique_ptr<SocketManager> sm;
|
||||
std::unique_ptr<PluginManager> pm;
|
||||
std::unique_ptr<ClientManager> cm;
|
||||
|
||||
std::string configPath;
|
||||
time::ptime startTime;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* CORE_H_ */
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
|
||||
#include "Encoder.h"
|
||||
#include "common.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
using namespace std;
|
||||
|
||||
const int8_t Encoder::base32Table[256] = {
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,26,27,28,29,30,31,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
|
||||
15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
|
||||
15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
};
|
||||
|
||||
const char Encoder::base32Alphabet[32] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', '2', '3', '4', '5', '6', '7'
|
||||
};
|
||||
|
||||
string& Encoder::toBase32(const uint8_t* src, size_t len, string& dst) {
|
||||
// Code snagged from the bitzi bitcollider
|
||||
size_t i, index;
|
||||
uint8_t word;
|
||||
dst.reserve(((len * 8) / 5) + 1);
|
||||
|
||||
for(i = 0, index = 0; i < len;) {
|
||||
/* Is the current word going to span a byte boundary? */
|
||||
if (index > 3) {
|
||||
word = (uint8_t)(src[i] & (0xFF >> index));
|
||||
index = (index + 5) % 8;
|
||||
word <<= index;
|
||||
if ((i + 1) < len)
|
||||
word |= src[i + 1] >> (8 - index);
|
||||
|
||||
i++;
|
||||
} else {
|
||||
word = (uint8_t)(src[i] >> (8 - (index + 5))) & 0x1F;
|
||||
index = (index + 5) % 8;
|
||||
if (index == 0)
|
||||
i++;
|
||||
}
|
||||
|
||||
dcassert(word < 32);
|
||||
dst += base32Alphabet[word];
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
void Encoder::fromBase32(const char* src, uint8_t* dst, size_t len) {
|
||||
size_t i, index, offset;
|
||||
|
||||
memset(dst, 0, len);
|
||||
for(i = 0, index = 0, offset = 0; src[i]; i++) {
|
||||
// Skip what we don't recognise
|
||||
int8_t tmp = base32Table[(unsigned char)src[i]];
|
||||
|
||||
if(tmp == -1)
|
||||
continue;
|
||||
|
||||
if (index <= 3) {
|
||||
index = (index + 5) % 8;
|
||||
if (index == 0) {
|
||||
dst[offset] |= tmp;
|
||||
offset++;
|
||||
if(offset == len)
|
||||
break;
|
||||
} else {
|
||||
dst[offset] |= tmp << (8 - index);
|
||||
}
|
||||
} else {
|
||||
index = (index + 5) % 8;
|
||||
dst[offset] |= (tmp >> index);
|
||||
offset++;
|
||||
if(offset == len)
|
||||
break;
|
||||
dst[offset] |= tmp << (8 - index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_ENCODER_H
|
||||
#define ADCHPP_ENCODER_H
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
class Encoder
|
||||
{
|
||||
public:
|
||||
ADCHPP_DLL static std::string& toBase32(const uint8_t* src, size_t len, std::string& tgt);
|
||||
static std::string toBase32(const uint8_t* src, size_t len) {
|
||||
std::string tmp;
|
||||
return toBase32(src, len, tmp);
|
||||
}
|
||||
ADCHPP_DLL static void fromBase32(const char* src, uint8_t* dst, size_t len);
|
||||
|
||||
ADCHPP_DLL static const int8_t base32Table[256];
|
||||
ADCHPP_DLL static const char base32Alphabet[32];
|
||||
private:
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _ENCODER
|
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
|
||||
#include "Entity.h"
|
||||
|
||||
#include "ClientManager.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
Entity::~Entity() {
|
||||
for(PluginDataMap::iterator i = pluginData.begin(), iend = pluginData.end(); i != iend; ++i) {
|
||||
(*i->first)(i->second);
|
||||
}
|
||||
}
|
||||
|
||||
void Entity::inject(AdcCommand& cmd) {
|
||||
cm.onReceive(*this, cmd);
|
||||
}
|
||||
|
||||
const std::string& Entity::getField(const char* name) const {
|
||||
auto i = fields.find(AdcCommand::toField(name));
|
||||
return i == fields.end() ? Util::emptyString : i->second;
|
||||
}
|
||||
|
||||
bool Entity::hasField(const char* name) const {
|
||||
return fields.find(AdcCommand::toField(name)) != fields.end();
|
||||
}
|
||||
|
||||
void Entity::setField(const char* name, const std::string& value) {
|
||||
uint16_t code = AdcCommand::toField(name);
|
||||
|
||||
if(code == AdcCommand::toField("SU")) {
|
||||
filters.clear();
|
||||
|
||||
if((value.size() + 1) % 5 == 0) {
|
||||
filters.reserve((value.size() + 1) / 5);
|
||||
for(size_t i = 0; i < value.size(); i += 5) {
|
||||
filters.push_back(AdcCommand::toFourCC(value.data() + i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(value.empty()) {
|
||||
fields.erase(code);
|
||||
} else {
|
||||
fields[code] = value;
|
||||
}
|
||||
|
||||
INF = BufferPtr();
|
||||
}
|
||||
|
||||
bool Entity::getAllFields(AdcCommand& cmd) const throw() {
|
||||
for(auto i = fields.begin(); i != fields.end(); ++i)
|
||||
cmd.addParam(AdcCommand::fromField(i->first), i->second);
|
||||
return !fields.empty();
|
||||
}
|
||||
|
||||
void Entity::updateFields(const AdcCommand& cmd) {
|
||||
dcassert(cmd.getCommand() == AdcCommand::CMD_INF);
|
||||
for(StringIterC j = cmd.getParameters().begin(); j != cmd.getParameters().end(); ++j) {
|
||||
if(j->size() < 2)
|
||||
continue;
|
||||
setField(j->c_str(), j->substr(2));
|
||||
}
|
||||
}
|
||||
|
||||
const BufferPtr& Entity::getINF() const {
|
||||
if(!INF) {
|
||||
AdcCommand cmd(AdcCommand::CMD_INF, getSID() == AdcCommand::HUB_SID ? AdcCommand::TYPE_INFO : AdcCommand::TYPE_BROADCAST, getSID());
|
||||
getAllFields(cmd);
|
||||
INF = cmd.getBuffer();
|
||||
}
|
||||
return INF;
|
||||
}
|
||||
|
||||
bool Entity::addSupports(uint32_t feature) {
|
||||
if(std::find(supports.begin(), supports.end(), feature) != supports.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
supports.push_back(feature);
|
||||
|
||||
SUP = BufferPtr();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
StringList Entity::getSupportList() const {
|
||||
StringList ret(supports.size());
|
||||
for(size_t i = 0; i < supports.size(); ++i) {
|
||||
ret[i] = AdcCommand::fromFourCC(supports[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Entity::removeSupports(uint32_t feature) {
|
||||
std::vector<uint32_t>::iterator i = std::find(supports.begin(), supports.end(), feature);
|
||||
if(i == supports.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
supports.erase(i);
|
||||
|
||||
SUP = BufferPtr();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const BufferPtr& Entity::getSUP() const {
|
||||
if(!SUP) {
|
||||
AdcCommand cmd(AdcCommand::CMD_SUP, getSID() == AdcCommand::HUB_SID ? AdcCommand::TYPE_INFO : AdcCommand::TYPE_BROADCAST, getSID());
|
||||
for(std::vector<uint32_t>::const_iterator i = supports.begin(), iend = supports.end(); i != iend; ++i) {
|
||||
cmd.addParam("AD", AdcCommand::fromFourCC(*i));
|
||||
}
|
||||
SUP = cmd.getBuffer();
|
||||
}
|
||||
return SUP;
|
||||
}
|
||||
|
||||
bool Entity::hasSupport(uint32_t feature) const {
|
||||
return find(supports.begin(), supports.end(), feature) != supports.end();
|
||||
}
|
||||
|
||||
void Entity::updateSupports(const AdcCommand& cmd) throw() {
|
||||
for(StringIterC i = cmd.getParameters().begin(); i != cmd.getParameters().end(); ++i) {
|
||||
const std::string& str = *i;
|
||||
if(str.size() != 6) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(str[0] == 'A' && str[1] == 'D') {
|
||||
addSupports(AdcCommand::toFourCC(str.c_str() + 2));
|
||||
} else if(str[0] == 'R' && str[1] == 'M') {
|
||||
removeSupports(AdcCommand::toFourCC(str.c_str() + 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Entity::isFiltered(const std::string& features) const {
|
||||
if(filters.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < features.size(); i += 5) {
|
||||
if(features[i] == '-') {
|
||||
if(std::find(filters.begin(), filters.end(), AdcCommand::toFourCC(features.data() + i + 1)) != filters.end()) {
|
||||
return true;
|
||||
}
|
||||
} else if(features[i] == '+') {
|
||||
if(std::find(filters.begin(), filters.end(), AdcCommand::toFourCC(features.data() + i + 1)) == filters.end()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Entity::setPluginData(const PluginDataHandle& handle, void* data) throw() {
|
||||
clearPluginData(handle);
|
||||
pluginData.insert(std::make_pair(handle, data));
|
||||
}
|
||||
|
||||
void* Entity::getPluginData(const PluginDataHandle& handle) const throw() {
|
||||
PluginDataMap::const_iterator i = pluginData.find(handle);
|
||||
return i == pluginData.end() ? 0 : i->second;
|
||||
}
|
||||
|
||||
void Entity::clearPluginData(const PluginDataHandle& handle) throw() {
|
||||
PluginDataMap::iterator i = pluginData.find(handle);
|
||||
if(i == pluginData.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
(*i->first)(i->second);
|
||||
pluginData.erase(i);
|
||||
}
|
||||
|
||||
void Entity::setFlag(size_t flag) {
|
||||
flags.setFlag(flag);
|
||||
if(flag & MASK_CLIENT_TYPE) {
|
||||
setField("CT", Util::toString(flags.getFlags() & MASK_CLIENT_TYPE));
|
||||
}
|
||||
}
|
||||
|
||||
void Entity::unsetFlag(size_t flag) {
|
||||
flags.unsetFlag(flag);
|
||||
if(flag & MASK_CLIENT_TYPE) {
|
||||
setField("CT", Util::toString(flags.getFlags() & MASK_CLIENT_TYPE));
|
||||
}
|
||||
}
|
||||
|
||||
size_t Entity::getQueuedBytes() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
time::ptime Entity::getOverflow() const {
|
||||
return time::not_a_date_time;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_ENTITY_H
|
||||
#define ADCHPP_ENTITY_H
|
||||
|
||||
#include "forward.h"
|
||||
#include "Buffer.h"
|
||||
#include "AdcCommand.h"
|
||||
#include "Plugin.h"
|
||||
#include "CID.h"
|
||||
#include "TimeUtil.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
class ADCHPP_VISIBLE Entity : private boost::noncopyable {
|
||||
public:
|
||||
enum State {
|
||||
/** Initial protocol negotiation (wait for SUP) */
|
||||
STATE_PROTOCOL,
|
||||
/** Identify the connecting client (wait for INF) */
|
||||
STATE_IDENTIFY,
|
||||
/** Verify the client (wait for PAS) */
|
||||
STATE_VERIFY,
|
||||
/** Normal operation */
|
||||
STATE_NORMAL,
|
||||
/** Binary data transfer */
|
||||
STATE_DATA
|
||||
};
|
||||
|
||||
enum Flag {
|
||||
FLAG_BOT = 0x01,
|
||||
FLAG_REGISTERED = 0x02,
|
||||
FLAG_OP = 0x04,
|
||||
FLAG_SU = 0x08,
|
||||
FLAG_OWNER = 0x10,
|
||||
FLAG_HUB = 0x20,
|
||||
FLAG_HIDDEN = 0x40,
|
||||
MASK_CLIENT_TYPE = FLAG_BOT | FLAG_REGISTERED | FLAG_OP | FLAG_SU | FLAG_OWNER | FLAG_HUB | FLAG_HIDDEN,
|
||||
|
||||
FLAG_PASSWORD = 0x100,
|
||||
|
||||
/** Extended away, no need to send msg */
|
||||
FLAG_EXT_AWAY = 0x200,
|
||||
|
||||
/** Plugins can use these flags to disable various checks */
|
||||
/** Bypass ip check */
|
||||
FLAG_OK_IP = 0x400,
|
||||
|
||||
/** This entity is now a ghost being disconnected, totally ignored by ADCH++ */
|
||||
FLAG_GHOST = 0x800
|
||||
};
|
||||
|
||||
|
||||
Entity(ClientManager &cm, uint32_t sid_) : sid(sid_), state(STATE_PROTOCOL), cm(cm) { }
|
||||
|
||||
void send(const AdcCommand& cmd) { send(cmd.getBuffer()); }
|
||||
virtual void send(const BufferPtr& cmd) = 0;
|
||||
|
||||
ADCHPP_DLL virtual void inject(AdcCommand& cmd);
|
||||
|
||||
ADCHPP_DLL const std::string& getField(const char* name) const;
|
||||
ADCHPP_DLL bool hasField(const char* name) const;
|
||||
ADCHPP_DLL void setField(const char* name, const std::string& value);
|
||||
|
||||
/** Add any flags that have been updated to the AdcCommand (type etc is not set) */
|
||||
ADCHPP_DLL bool getAllFields(AdcCommand& cmd) const throw();
|
||||
ADCHPP_DLL const BufferPtr& getINF() const;
|
||||
|
||||
ADCHPP_DLL bool addSupports(uint32_t feature);
|
||||
ADCHPP_DLL StringList getSupportList() const;
|
||||
ADCHPP_DLL bool hasSupport(uint32_t feature) const;
|
||||
ADCHPP_DLL bool removeSupports(uint32_t feature);
|
||||
|
||||
ADCHPP_DLL const BufferPtr& getSUP() const;
|
||||
|
||||
uint32_t getSID() const { return sid; }
|
||||
|
||||
ADCHPP_DLL bool isFiltered(const std::string& features) const;
|
||||
|
||||
ADCHPP_DLL void updateFields(const AdcCommand& cmd);
|
||||
ADCHPP_DLL void updateSupports(const AdcCommand& cmd) throw();
|
||||
|
||||
/**
|
||||
* Set PSD (plugin specific data). This allows a plugin to store arbitrary
|
||||
* per-client data, and retrieve it later on. The life cycle of the data follows
|
||||
* that of the client unless explicitly removed. Any data referenced by the plugin
|
||||
* will have its delete function called when the Entity is deleted.
|
||||
* @param id Id as retrieved from PluginManager::getPluginId()
|
||||
* @param data Data to store, this can be pretty much anything
|
||||
*/
|
||||
ADCHPP_DLL void setPluginData(const PluginDataHandle& handle, void* data) throw();
|
||||
|
||||
/**
|
||||
* @param handle Plugin data handle, as returned by PluginManager::registerPluginData
|
||||
* @return Value stored, NULL if none found
|
||||
*/
|
||||
ADCHPP_DLL void* getPluginData(const PluginDataHandle& handle) const throw();
|
||||
|
||||
/**
|
||||
* Clear any data referenced by the handle, calling the registered delete function.
|
||||
*/
|
||||
ADCHPP_DLL void clearPluginData(const PluginDataHandle& handle) throw();
|
||||
|
||||
const CID& getCID() const { return cid; }
|
||||
void setCID(const CID& cid_) { cid = cid_; }
|
||||
|
||||
State getState() const { return state; }
|
||||
void setState(State state_) { state = state_; }
|
||||
|
||||
bool isSet(size_t aFlag) const { return flags.isSet(aFlag); }
|
||||
bool isAnySet(size_t aFlag) const { return flags.isAnySet(aFlag); }
|
||||
ADCHPP_DLL void setFlag(size_t aFlag);
|
||||
ADCHPP_DLL void unsetFlag(size_t aFlag);
|
||||
|
||||
ADCHPP_DLL virtual void disconnect(Util::Reason reason, const std::string &info = Util::emptyString) = 0;
|
||||
|
||||
/** The number of bytes in the write buffer */
|
||||
ADCHPP_DLL virtual size_t getQueuedBytes() const;
|
||||
|
||||
/** The time that this entity's write buffer size exceeded the maximum buffer size, 0 if no overflow */
|
||||
ADCHPP_DLL virtual time::ptime getOverflow() const;
|
||||
|
||||
protected:
|
||||
virtual ~Entity();
|
||||
|
||||
typedef std::map<PluginDataHandle, void*> PluginDataMap;
|
||||
|
||||
CID cid;
|
||||
uint32_t sid;
|
||||
Flags flags;
|
||||
State state;
|
||||
|
||||
/** SUP items */
|
||||
std::vector<uint32_t> supports;
|
||||
|
||||
/** INF SU */
|
||||
std::vector<uint32_t> filters;
|
||||
|
||||
/** INF fields */
|
||||
std::map<uint16_t, std::string> fields;
|
||||
|
||||
/** Plugin data, see PluginManager::registerPluginData */
|
||||
PluginDataMap pluginData;
|
||||
|
||||
/** Latest INF cached */
|
||||
mutable BufferPtr INF;
|
||||
|
||||
/** Latest SUP cached */
|
||||
mutable BufferPtr SUP;
|
||||
|
||||
/** ClientManager that owns this entity */
|
||||
ClientManager &cm;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* ADCHPP_ENTITY_H */
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_EXCEPTION_H
|
||||
#define ADCHPP_EXCEPTION_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
class ADCHPP_VISIBLE Exception : public std::exception
|
||||
{
|
||||
public:
|
||||
Exception() { }
|
||||
Exception(const std::string& aError) throw() : error(aError) { dcdebug("Thrown: %s\n", error.c_str()); }
|
||||
virtual ~Exception() throw() { }
|
||||
const std::string& getError() const throw() { return error; }
|
||||
|
||||
virtual const char* what() const throw() { return error.c_str(); }
|
||||
protected:
|
||||
std::string error;
|
||||
};
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
#define STANDARD_EXCEPTION(name) class ADCHPP_VISIBLE name : public Exception { \
|
||||
public:\
|
||||
name() throw() : Exception(#name) { } \
|
||||
name(const std::string& aError) throw() : Exception(#name ": " + aError) { } \
|
||||
virtual ~name() throw() { } \
|
||||
}
|
||||
|
||||
#else // NDEBUG
|
||||
|
||||
#define STANDARD_EXCEPTION(name) class ADCHPP_VISIBLE name : public Exception { \
|
||||
public:\
|
||||
name() throw() : Exception() { } \
|
||||
name(const std::string& aError) throw() : Exception(aError) { } \
|
||||
virtual ~name() throw() { } \
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif // EXCEPTION_H
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_FASTALLOC_H
|
||||
#define ADCHPP_FASTALLOC_H
|
||||
|
||||
#include "Mutex.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
#ifdef NDEBUG
|
||||
struct FastAllocBase {
|
||||
ADCHPP_DLL static FastMutex mtx;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fast new/delete replacements for constant sized objects, that also give nice
|
||||
* reference locality...
|
||||
*/
|
||||
template<class T>
|
||||
struct FastAlloc : public FastAllocBase {
|
||||
// Custom new & delete that (hopefully) use the node allocator
|
||||
static void* operator new(size_t s) {
|
||||
if(s != sizeof(T))
|
||||
return ::operator new(s);
|
||||
return allocate();
|
||||
}
|
||||
|
||||
// Avoid hiding placement new that's needed by the stl containers...
|
||||
static void* operator new(size_t, void* m) {
|
||||
return m;
|
||||
}
|
||||
// ...and the warning about missing placement delete...
|
||||
static void operator delete(void*, void*) {
|
||||
// ? We didn't allocate so...
|
||||
}
|
||||
|
||||
static void operator delete(void* m, size_t s) {
|
||||
if (s != sizeof(T)) {
|
||||
::operator delete(m);
|
||||
} else if(m != NULL) {
|
||||
deallocate((uint8_t*)m);
|
||||
}
|
||||
}
|
||||
private:
|
||||
|
||||
static void* allocate() {
|
||||
FastMutex::Lock l(mtx);
|
||||
if(freeList == NULL) {
|
||||
grow();
|
||||
}
|
||||
void* tmp = freeList;
|
||||
freeList = *((void**)freeList);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static void deallocate(void* p) {
|
||||
FastMutex::Lock l(mtx);
|
||||
*(void**)p = freeList;
|
||||
freeList = p;
|
||||
}
|
||||
|
||||
static void* freeList;
|
||||
|
||||
static void grow() {
|
||||
dcassert(sizeof(T) >= sizeof(void*));
|
||||
// We want to grow by approximately 128kb at a time...
|
||||
size_t items = ((128*1024 + sizeof(T) - 1)/sizeof(T));
|
||||
freeList = new uint8_t[sizeof(T)*items];
|
||||
uint8_t* tmp = (uint8_t*)freeList;
|
||||
for(size_t i = 0; i < items - 1; i++) {
|
||||
*(void**)tmp = tmp + sizeof(T);
|
||||
tmp += sizeof(T);
|
||||
}
|
||||
*(void**)tmp = NULL;
|
||||
}
|
||||
};
|
||||
template<class T> void* FastAlloc<T>::freeList = 0;
|
||||
#else
|
||||
template<class T> struct FastAlloc { };
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif // FASTALLOC_H
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
|
||||
#include "File.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
using namespace std;
|
||||
|
||||
string File::read(uint32_t len) throw(FileException) {
|
||||
string tmp;
|
||||
tmp.resize(len);
|
||||
uint32_t x = read(&tmp[0], len);
|
||||
tmp.resize(x);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
File::File(const string& aFileName, int access, int mode) throw(FileException) {
|
||||
dcassert(access == WRITE || access == READ || access == (READ | WRITE));
|
||||
|
||||
int m = 0;
|
||||
if(mode & OPEN) {
|
||||
if(mode & CREATE) {
|
||||
m = (mode & TRUNCATE) ? CREATE_ALWAYS : OPEN_ALWAYS;
|
||||
} else {
|
||||
m = (mode & TRUNCATE) ? TRUNCATE_EXISTING : OPEN_EXISTING;
|
||||
}
|
||||
} else {
|
||||
if(mode & CREATE) {
|
||||
m = (mode & TRUNCATE) ? CREATE_ALWAYS : CREATE_NEW;
|
||||
} else {
|
||||
dcassert(0);
|
||||
}
|
||||
}
|
||||
int a = 0;
|
||||
if(access & READ)
|
||||
a |= GENERIC_READ;
|
||||
if(access & WRITE)
|
||||
a |= GENERIC_WRITE;
|
||||
|
||||
h = ::CreateFile(aFileName.c_str(), a, FILE_SHARE_READ, NULL, m, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
||||
|
||||
if(h == INVALID_HANDLE_VALUE) {
|
||||
throw FileException(Util::translateError(GetLastError()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int64_t File::getSize() {
|
||||
DWORD x;
|
||||
DWORD l = ::GetFileSize(h, &x);
|
||||
|
||||
if( (l == INVALID_FILE_SIZE) && (GetLastError() != NO_ERROR))
|
||||
return -1;
|
||||
|
||||
return (int64_t)l | ((int64_t)x)<<32;
|
||||
}
|
||||
|
||||
int64_t File::getSize(const string& aFileName) {
|
||||
WIN32_FIND_DATA fd;
|
||||
HANDLE hFind;
|
||||
|
||||
hFind = FindFirstFile(aFileName.c_str(), &fd);
|
||||
|
||||
if (hFind == INVALID_HANDLE_VALUE) {
|
||||
return -1;
|
||||
} else {
|
||||
FindClose(hFind);
|
||||
return ((int64_t)fd.nFileSizeHigh << 32 | (int64_t)fd.nFileSizeLow);
|
||||
}
|
||||
}
|
||||
|
||||
string File::getFilePath(const string& path) throw() {
|
||||
string::size_type i = path.find_last_of("\\/");
|
||||
return (i != string::npos) ? path.substr(0, i) : path;
|
||||
}
|
||||
|
||||
string File::getFileName(const string& path) throw() {
|
||||
string::size_type i = path.find_last_of("\\/");
|
||||
return (i != string::npos) ? path.substr(i + 1) : path;
|
||||
}
|
||||
|
||||
bool File::isAbsolutePath(const string& path) throw() {
|
||||
return (path.length() >= 3 && path[1] == ':' && (path[2] == '\\' || path[2] == '/')) ||
|
||||
(path.length() >= 1 && (path[0] == '\\' || path[0] == '/'));
|
||||
}
|
||||
|
||||
void File::ensureDirectory(const string& aFile) throw() {
|
||||
string::size_type start = 0;
|
||||
|
||||
while( (start = aFile.find_first_of("\\/", start)) != string::npos) {
|
||||
::CreateDirectory(aFile.substr(0, start+1).c_str(), NULL);
|
||||
start++;
|
||||
}
|
||||
}
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
File::File(const string& aFileName, int access, int mode) throw(FileException) {
|
||||
dcassert(access == WRITE || access == READ || access == (READ | WRITE));
|
||||
|
||||
int m = 0;
|
||||
if(access == READ)
|
||||
m |= O_RDONLY;
|
||||
else if(access == WRITE)
|
||||
m |= O_WRONLY;
|
||||
else
|
||||
m |= O_RDWR;
|
||||
|
||||
if(mode & CREATE) {
|
||||
m |= O_CREAT;
|
||||
}
|
||||
if(mode & TRUNCATE) {
|
||||
m |= O_TRUNC;
|
||||
}
|
||||
h = open(aFileName.c_str(), m, S_IRUSR | S_IWUSR);
|
||||
if(h == -1)
|
||||
throw FileException("Could not open file");
|
||||
}
|
||||
|
||||
int64_t File::getSize() {
|
||||
struct stat s;
|
||||
if(fstat(h, &s) == -1)
|
||||
return -1;
|
||||
|
||||
return (int64_t)s.st_size;
|
||||
}
|
||||
|
||||
int64_t File::getSize(const string& aFileName) {
|
||||
struct stat s;
|
||||
if(stat(aFileName.c_str(), &s) == -1)
|
||||
return -1;
|
||||
|
||||
return s.st_size;
|
||||
}
|
||||
|
||||
string File::getFilePath(const string& path) throw() {
|
||||
string::size_type i = path.rfind('/');
|
||||
return (i != string::npos) ? path.substr(0, i) : path;
|
||||
}
|
||||
|
||||
string File::getFileName(const string& path) throw() {
|
||||
string::size_type i = path.rfind('/');
|
||||
return (i != string::npos) ? path.substr(i + 1) : path;
|
||||
}
|
||||
|
||||
bool File::isAbsolutePath(const string& path) throw() {
|
||||
return path.length() >= 1 && path[0] == '/';
|
||||
}
|
||||
|
||||
void File::ensureDirectory(const string& aFile) throw() {
|
||||
string::size_type start = 0;
|
||||
|
||||
while( (start = aFile.find('/', start)) != string::npos) {
|
||||
::mkdir(aFile.substr(0, start+1).c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
||||
start++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string File::makeAbsolutePath(const std::string& filename) {
|
||||
return makeAbsolutePath(Util::getAppPath() + PATH_SEPARATOR, filename);
|
||||
}
|
||||
|
||||
std::string File::makeAbsolutePath(const std::string& path, const std::string& filename) {
|
||||
return isAbsolutePath(filename) ? filename : path + filename;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_FILE_H
|
||||
#define ADCHPP_FILE_H
|
||||
|
||||
#include "Exception.h"
|
||||
#include "Util.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
STANDARD_EXCEPTION(FileException);
|
||||
|
||||
class File
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
READ = 0x01,
|
||||
WRITE = 0x02
|
||||
};
|
||||
|
||||
enum {
|
||||
OPEN = 0x01,
|
||||
CREATE = 0x02,
|
||||
TRUNCATE = 0x04
|
||||
};
|
||||
|
||||
ADCHPP_DLL File(const std::string& aFileName, int access, int mode = OPEN) throw(FileException);
|
||||
|
||||
ADCHPP_DLL int64_t getSize();
|
||||
ADCHPP_DLL static int64_t getSize(const std::string& aFileName);
|
||||
|
||||
ADCHPP_DLL std::string read(uint32_t len) throw(FileException);
|
||||
|
||||
/** Returns the directory part of the full path */
|
||||
ADCHPP_DLL static std::string getFilePath(const std::string& name) throw();
|
||||
/** Returns the filename part of the full path */
|
||||
ADCHPP_DLL static std::string getFileName(const std::string& name) throw();
|
||||
ADCHPP_DLL static bool isAbsolutePath(const std::string& name) throw();
|
||||
|
||||
ADCHPP_DLL static std::string makeAbsolutePath(const std::string& filename);
|
||||
ADCHPP_DLL static std::string makeAbsolutePath(const std::string& path, const std::string& filename);
|
||||
|
||||
ADCHPP_DLL static void ensureDirectory(const std::string& aFile) throw();
|
||||
|
||||
#ifdef _WIN32
|
||||
void close() {
|
||||
if(h != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(h);
|
||||
h = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t getPos() {
|
||||
LONG x = 0;
|
||||
DWORD l = ::SetFilePointer(h, 0, &x, FILE_CURRENT);
|
||||
|
||||
return (int64_t)l | ((int64_t)x)<<32;
|
||||
}
|
||||
|
||||
void setPos(int64_t pos) {
|
||||
LONG x = (LONG) (pos>>32);
|
||||
::SetFilePointer(h, (DWORD)(pos & 0xffffffff), &x, FILE_BEGIN);
|
||||
}
|
||||
void setEndPos(int64_t pos) {
|
||||
LONG x = (LONG) (pos>>32);
|
||||
::SetFilePointer(h, (DWORD)(pos & 0xffffffff), &x, FILE_END);
|
||||
}
|
||||
|
||||
void movePos(int64_t pos) {
|
||||
LONG x = (LONG) (pos>>32);
|
||||
::SetFilePointer(h, (DWORD)(pos & 0xffffffff), &x, FILE_CURRENT);
|
||||
}
|
||||
|
||||
uint32_t read(void* buf, uint32_t len) throw(FileException) {
|
||||
DWORD x;
|
||||
if(!::ReadFile(h, buf, len, &x, NULL)) {
|
||||
throw(FileException(Util::translateError(GetLastError())));
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
void write(const void* buf, size_t len) throw(FileException) {
|
||||
DWORD x;
|
||||
if(!::WriteFile(h, buf, (DWORD)len, &x, NULL)) {
|
||||
throw FileException(Util::translateError(GetLastError()));
|
||||
}
|
||||
if(x < len) {
|
||||
throw FileException("Unable to write, disk full?");
|
||||
}
|
||||
}
|
||||
|
||||
void setEOF() throw(FileException) {
|
||||
dcassert(h != NULL);
|
||||
if(!SetEndOfFile(h)) {
|
||||
throw FileException(Util::translateError(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
static void deleteFile(const std::string& aFileName) { ::DeleteFile(aFileName.c_str()); };
|
||||
static void renameFile(const std::string& source, const std::string& target) { ::MoveFile(source.c_str(), target.c_str()); };
|
||||
|
||||
#else // WIN32
|
||||
|
||||
void close() {
|
||||
if(h != -1) {
|
||||
::close(h);
|
||||
h = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t getPos() { return (int64_t) lseek(h, 0, SEEK_CUR); }
|
||||
|
||||
void setPos(int64_t pos) { lseek(h, (off_t)pos, SEEK_SET); };
|
||||
void setEndPos(int64_t pos) { lseek(h, (off_t)pos, SEEK_END); };
|
||||
void movePos(int64_t pos) { lseek(h, (off_t)pos, SEEK_CUR); };
|
||||
|
||||
uint32_t read(void* buf, uint32_t len) throw(FileException) {
|
||||
ssize_t x = ::read(h, buf, (size_t)len);
|
||||
if(x == -1)
|
||||
throw FileException(Util::translateError(errno));
|
||||
return (uint32_t)x;
|
||||
}
|
||||
|
||||
void write(const void* buf, uint32_t len) throw(FileException) {
|
||||
ssize_t x;
|
||||
x = ::write(h, buf, len);
|
||||
if(x == -1)
|
||||
throw FileException(Util::translateError(errno));
|
||||
if(x < (ssize_t)len)
|
||||
throw FileException("Unable to write, disk full?");
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo fix for unix...
|
||||
*/
|
||||
void setEOF() throw(FileException) {
|
||||
}
|
||||
|
||||
static void deleteFile(const std::string& aFileName) { ::unlink(aFileName.c_str()); };
|
||||
static void renameFile(const std::string& source, const std::string& target) { ::rename(source.c_str(), target.c_str()); };
|
||||
|
||||
#endif // WIN32
|
||||
|
||||
~File() {
|
||||
close();
|
||||
}
|
||||
|
||||
std::string read() throw(FileException) {
|
||||
setPos(0);
|
||||
return read((uint32_t)getSize());
|
||||
}
|
||||
|
||||
void write(const std::string& aString) throw(FileException) {
|
||||
write((void*)aString.data(), aString.size());
|
||||
}
|
||||
|
||||
private:
|
||||
File(const File&);
|
||||
File& operator=(const File&);
|
||||
|
||||
#ifdef _WIN32
|
||||
HANDLE h;
|
||||
#else
|
||||
int h;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FILE_H
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
|
||||
#include "Hub.h"
|
||||
#include "AdcCommand.h"
|
||||
#include "version.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
Hub::Hub(ClientManager &cm) : Entity(cm, AdcCommand::HUB_SID) {
|
||||
setField("NI", "adchpp");
|
||||
setField("HI", "1");
|
||||
setField("DE", appName + ' ' + versionString);
|
||||
setField("AP", appName);
|
||||
setField("VE", versionString);
|
||||
setFlag(FLAG_HUB);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef HUB_H_
|
||||
#define HUB_H_
|
||||
|
||||
#include "forward.h"
|
||||
|
||||
#include "Entity.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
class ADCHPP_VISIBLE Hub : public Entity {
|
||||
public:
|
||||
ADCHPP_DLL Hub(ClientManager &cm);
|
||||
|
||||
virtual void send(const BufferPtr& cmd) { }
|
||||
virtual void disconnect(Util::Reason reason, const std::string &) throw() { }
|
||||
private:
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* HUB_H_ */
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
|
||||
#include "LogManager.h"
|
||||
|
||||
#include "File.h"
|
||||
#include "Core.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
using namespace std;
|
||||
|
||||
LogManager::LogManager(Core &core) : logFile("logs/adchpp%Y%m.log"), enabled(true), core(core) { }
|
||||
|
||||
void LogManager::log(const string& area, const string& msg) throw() {
|
||||
char buf[64];
|
||||
time_t now = std::time(NULL);
|
||||
size_t s = strftime(buf, 64, "%Y-%m-%d %H:%M:%S: ", localtime(&now));
|
||||
string tmp(buf, s);
|
||||
tmp += area;
|
||||
tmp += ": ";
|
||||
tmp += msg;
|
||||
dolog(tmp);
|
||||
}
|
||||
|
||||
void LogManager::dolog(const string& msg) throw() {
|
||||
dcdebug("Logging: %s\n", msg.c_str());
|
||||
signalLog_(msg);
|
||||
if(getEnabled()) {
|
||||
string logFile = Util::formatTime(File::makeAbsolutePath(core.getConfigPath(), getLogFile()));
|
||||
FastMutex::Lock l(mtx);
|
||||
try {
|
||||
File f(logFile, File::WRITE, File::OPEN | File::CREATE);
|
||||
f.setEndPos(0);
|
||||
f.write(msg + "\r\n");
|
||||
return;
|
||||
} catch(const FileException& e) {
|
||||
dcdebug("LogManager::log: %s\n", e.getError().c_str());
|
||||
}
|
||||
try {
|
||||
File::ensureDirectory(logFile);
|
||||
|
||||
File f(logFile, File::WRITE, File::OPEN | File::CREATE);
|
||||
f.setEndPos(0);
|
||||
f.write(msg + "\r\n");
|
||||
} catch(const FileException& ee) {
|
||||
dcdebug("LogManager::log2: %s\n", ee.getError().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_LOGMANAGER_H
|
||||
#define ADCHPP_LOGMANAGER_H
|
||||
|
||||
#include "forward.h"
|
||||
|
||||
#include "Mutex.h"
|
||||
#include "Signal.h"
|
||||
|
||||
namespace adchpp {
|
||||
/**
|
||||
* Log writing utilities.
|
||||
*/
|
||||
class LogManager
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Add a line to the log.
|
||||
* @param area Name of the module that generated the error.
|
||||
* @param msg Message to log.
|
||||
*/
|
||||
ADCHPP_DLL void log(const std::string& area, const std::string& msg) throw();
|
||||
|
||||
void setLogFile(const std::string& fileName) { logFile = fileName; }
|
||||
const std::string& getLogFile() const { return logFile; }
|
||||
|
||||
void setEnabled(bool enabled_) { enabled = enabled_; }
|
||||
bool getEnabled() const { return enabled; }
|
||||
|
||||
typedef SignalTraits<void (const std::string&)> SignalLog;
|
||||
SignalLog::Signal& signalLog() { return signalLog_; }
|
||||
|
||||
private:
|
||||
friend class Core;
|
||||
|
||||
FastMutex mtx;
|
||||
std::string logFile;
|
||||
bool enabled;
|
||||
|
||||
LogManager(Core &core);
|
||||
|
||||
SignalLog::Signal signalLog_;
|
||||
Core &core;
|
||||
|
||||
ADCHPP_DLL void dolog(const std::string& msg) throw();
|
||||
};
|
||||
|
||||
#define LOGC(core, area, msg) (core).getLogManager().log(area, msg)
|
||||
#define LOG(area, msg) LOGC(core, area, msg)
|
||||
|
||||
}
|
||||
|
||||
#endif // LOGMANAGER_H
|
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
|
||||
#include "ManagedSocket.h"
|
||||
|
||||
#include "SocketManager.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
using namespace std;
|
||||
|
||||
using namespace boost::asio;
|
||||
|
||||
ManagedSocket::ManagedSocket(SocketManager &sm, const AsyncStreamPtr &sock_) :
|
||||
sock(sock_),
|
||||
overflow(time::not_a_date_time),
|
||||
disc(time::not_a_date_time),
|
||||
lastWrite(time::not_a_date_time),
|
||||
sm(sm)
|
||||
{ }
|
||||
|
||||
ManagedSocket::~ManagedSocket() throw() {
|
||||
dcdebug("ManagedSocket deleted\n");
|
||||
}
|
||||
|
||||
static size_t sum(const BufferList& l) {
|
||||
size_t bytes = 0;
|
||||
for(BufferList::const_iterator i = l.begin(); i != l.end(); ++i) {
|
||||
bytes += (*i)->size();
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
size_t ManagedSocket::getQueuedBytes() const {
|
||||
return sum(outBuf);
|
||||
}
|
||||
|
||||
void ManagedSocket::write(const BufferPtr& buf, bool lowPrio /* = false */) throw() {
|
||||
if(buf->size() == 0 || disconnecting())
|
||||
return;
|
||||
|
||||
size_t queued = getQueuedBytes();
|
||||
|
||||
if(sm.getMaxBufferSize() > 0 && queued + buf->size() > sm.getMaxBufferSize()) {
|
||||
if(lowPrio) {
|
||||
return;
|
||||
} else if(!overflow.is_not_a_date_time() && overflow + time::millisec(sm.getOverflowTimeout()) < time::now()) {
|
||||
disconnect(Util::REASON_WRITE_OVERFLOW);
|
||||
return;
|
||||
} else {
|
||||
overflow = time::now();
|
||||
}
|
||||
}
|
||||
|
||||
sm.getStats().queueBytes += buf->size();
|
||||
sm.getStats().queueCalls++;
|
||||
|
||||
outBuf.push_back(buf);
|
||||
|
||||
prepareWrite();
|
||||
}
|
||||
|
||||
// Simplified handlers to avoid bind complexity
|
||||
namespace {
|
||||
|
||||
/** Keeper keeps a reference to the managed socket */
|
||||
struct Keeper {
|
||||
Keeper(const ManagedSocketPtr& ms_) : ms(ms_) { }
|
||||
ManagedSocketPtr ms;
|
||||
|
||||
void operator()(const boost::system::error_code& ec, size_t bytes) { }
|
||||
};
|
||||
|
||||
template<void (ManagedSocket::*F)(const boost::system::error_code&, size_t)>
|
||||
struct Handler : Keeper {
|
||||
Handler(const ManagedSocketPtr& ms) : Keeper(ms) { }
|
||||
|
||||
void operator()(const boost::system::error_code& ec, size_t bytes) {
|
||||
(ms.get()->*F)(ec, bytes);
|
||||
}
|
||||
};
|
||||
|
||||
struct Disconnector {
|
||||
Disconnector(const AsyncStreamPtr& stream_) : stream(stream_) { }
|
||||
void operator()() { stream->close(); }
|
||||
AsyncStreamPtr stream;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void ManagedSocket::prepareWrite() throw() {
|
||||
if(!writing()) { // Not writing
|
||||
if(!outBuf.empty()) {
|
||||
lastWrite = time::now();
|
||||
sock->write(outBuf, Handler<&ManagedSocket::completeWrite>(shared_from_this()));
|
||||
}
|
||||
} else if(time::now() > lastWrite + time::seconds(60)) {
|
||||
disconnect(Util::REASON_WRITE_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
void ManagedSocket::completeWrite(const boost::system::error_code& ec, size_t bytes) throw() {
|
||||
lastWrite = time::not_a_date_time;
|
||||
|
||||
if(!ec) {
|
||||
sm.getStats().sendBytes += bytes;
|
||||
sm.getStats().sendCalls++;
|
||||
|
||||
while(bytes > 0) {
|
||||
BufferPtr& p = *outBuf.begin();
|
||||
if(p->size() <= bytes) {
|
||||
bytes -= p->size();
|
||||
outBuf.erase(outBuf.begin());
|
||||
} else {
|
||||
p = make_shared<Buffer>(p->data() + bytes, p->size() - bytes);
|
||||
bytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(!overflow.is_not_a_date_time()) {
|
||||
size_t left = getQueuedBytes();
|
||||
if(left < sm.getMaxBufferSize()) {
|
||||
overflow = time::not_a_date_time;
|
||||
}
|
||||
}
|
||||
|
||||
if(disconnecting() && outBuf.empty()) {
|
||||
sock->shutdown(Keeper(shared_from_this()));
|
||||
} else {
|
||||
prepareWrite();
|
||||
}
|
||||
} else {
|
||||
fail(Util::REASON_SOCKET_ERROR, ec.message());
|
||||
}
|
||||
}
|
||||
|
||||
void ManagedSocket::prepareRead() throw() {
|
||||
// We first send in an empty buffer to get notification when there's data available
|
||||
sock->prepareRead(BufferPtr(), Handler<&ManagedSocket::prepareRead2>(shared_from_this()));
|
||||
}
|
||||
|
||||
void ManagedSocket::prepareRead2(const boost::system::error_code& ec, size_t) throw() {
|
||||
if(!ec) {
|
||||
// ADC commands are typically small - using a small buffer
|
||||
// helps with fairness
|
||||
// Calling available() on an ASIO socket seems to be terribly slow
|
||||
// Also, we might end up here if the socket has been closed, in which
|
||||
// case available would return 0 bytes...
|
||||
// We can't make a synchronous receive here because when using SSL
|
||||
// there might be data on the socket that won't translate into user data
|
||||
// and thus read_some will block
|
||||
// If there's no user data, this will effectively post a read operation
|
||||
// with a buffer and waste memory...to be continued.
|
||||
inBuf = make_shared<Buffer>(64);
|
||||
|
||||
sock->prepareRead(inBuf, Handler<&ManagedSocket::completeRead>(shared_from_this()));
|
||||
} else {
|
||||
fail(Util::REASON_SOCKET_ERROR, ec.message());
|
||||
}
|
||||
}
|
||||
|
||||
void ManagedSocket::completeRead(const boost::system::error_code& ec, size_t bytes) throw() {
|
||||
if(!ec) {
|
||||
try {
|
||||
sm.getStats().recvBytes += bytes;
|
||||
sm.getStats().recvCalls++;
|
||||
|
||||
inBuf->resize(bytes);
|
||||
|
||||
if(dataHandler) {
|
||||
dataHandler(inBuf);
|
||||
}
|
||||
|
||||
inBuf.reset();
|
||||
prepareRead();
|
||||
} catch(const boost::system::system_error& e) {
|
||||
fail(Util::REASON_SOCKET_ERROR, e.code().message());
|
||||
}
|
||||
} else {
|
||||
inBuf.reset();
|
||||
fail(Util::REASON_SOCKET_ERROR, ec.message());
|
||||
}
|
||||
}
|
||||
|
||||
void ManagedSocket::completeAccept(const boost::system::error_code& ec) throw() {
|
||||
if(!ec) {
|
||||
if(connectedHandler)
|
||||
connectedHandler();
|
||||
|
||||
sock->init(std::bind(&ManagedSocket::ready, shared_from_this()));
|
||||
|
||||
} else {
|
||||
fail(Util::REASON_SOCKET_ERROR, ec.message());
|
||||
}
|
||||
}
|
||||
|
||||
void ManagedSocket::ready() throw() {
|
||||
if(readyHandler)
|
||||
readyHandler();
|
||||
|
||||
prepareRead();
|
||||
}
|
||||
|
||||
void ManagedSocket::fail(Util::Reason reason, const std::string &info) throw() {
|
||||
if(failedHandler) {
|
||||
failedHandler(reason, info);
|
||||
|
||||
// using nullptr fails on older GCCs for which we're using nullptr.h; using 0 fails on VS...
|
||||
#ifndef FAKE_NULLPTR
|
||||
connectedHandler = nullptr;
|
||||
readyHandler = nullptr;
|
||||
dataHandler = nullptr;
|
||||
failedHandler = nullptr;
|
||||
#else
|
||||
connectedHandler = 0;
|
||||
readyHandler = 0;
|
||||
dataHandler = 0;
|
||||
failedHandler = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
struct Reporter {
|
||||
Reporter(ManagedSocketPtr ms, void (ManagedSocket::*f)(Util::Reason reason, const std::string &info), Util::Reason reason, const std::string &info) :
|
||||
ms(ms), f(f), reason(reason), info(info) { }
|
||||
|
||||
void operator()() { (ms.get()->*f)(reason, info); }
|
||||
|
||||
ManagedSocketPtr ms;
|
||||
void (ManagedSocket::*f)(Util::Reason reason, const std::string &info);
|
||||
|
||||
Util::Reason reason;
|
||||
std::string info;
|
||||
};
|
||||
|
||||
void ManagedSocket::disconnect(Util::Reason reason, const std::string &info) throw() {
|
||||
if(disconnecting()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto timeout = sm.getDisconnectTimeout();
|
||||
|
||||
disc = time::now() + time::millisec(timeout);
|
||||
|
||||
sm.addJob(Reporter(shared_from_this(), &ManagedSocket::fail, reason, info));
|
||||
|
||||
if(!writing()) {
|
||||
sock->shutdown(Keeper(shared_from_this()));
|
||||
}
|
||||
sm.addJob(timeout, Disconnector(sock));
|
||||
}
|
||||
|
||||
bool ManagedSocket::disconnecting() const {
|
||||
return !disc.is_not_a_date_time();
|
||||
}
|
||||
|
||||
bool ManagedSocket::writing() const {
|
||||
return !lastWrite.is_not_a_date_time();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_MANAGEDSOCKET_H
|
||||
#define ADCHPP_MANAGEDSOCKET_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "forward.h"
|
||||
#include "Signal.h"
|
||||
#include "Util.h"
|
||||
#include "Buffer.h"
|
||||
#include "AsyncStream.h"
|
||||
#include "TimeUtil.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
/**
|
||||
* An asynchronous socket managed by SocketManager.
|
||||
*/
|
||||
class ManagedSocket : private boost::noncopyable, public enable_shared_from_this<ManagedSocket> {
|
||||
public:
|
||||
ManagedSocket(SocketManager &sm, const AsyncStreamPtr& sock_);
|
||||
|
||||
/** Asynchronous write */
|
||||
ADCHPP_DLL void write(const BufferPtr& buf, bool lowPrio = false) throw();
|
||||
|
||||
/** Returns the number of bytes in the output buffer; buffers must be locked */
|
||||
ADCHPP_DLL size_t getQueuedBytes() const;
|
||||
|
||||
/** Asynchronous disconnect. Pending data will be written within the limits of the
|
||||
* DisconnectTimeout setting, but no more data will be read. */
|
||||
ADCHPP_DLL void disconnect(Util::Reason reason, const std::string &info = Util::emptyString) throw();
|
||||
|
||||
const std::string& getIp() const { return ip; }
|
||||
void setIp(const std::string& ip_) { ip = ip_; }
|
||||
|
||||
typedef std::function<void()> ConnectedHandler;
|
||||
void setConnectedHandler(const ConnectedHandler& handler) { connectedHandler = handler; }
|
||||
|
||||
typedef std::function<void()> ReadyHandler;
|
||||
void setReadyHandler(const ReadyHandler& handler) { readyHandler = handler; }
|
||||
|
||||
typedef std::function<void(const BufferPtr&)> DataHandler;
|
||||
void setDataHandler(const DataHandler& handler) { dataHandler = handler; }
|
||||
|
||||
typedef std::function<void(Util::Reason, const std::string &)> FailedHandler;
|
||||
void setFailedHandler(const FailedHandler& handler) { failedHandler = handler; }
|
||||
|
||||
time::ptime getOverflow() { return overflow; }
|
||||
|
||||
time::ptime getLastWrite() { return lastWrite; }
|
||||
|
||||
~ManagedSocket() throw();
|
||||
|
||||
private:
|
||||
friend class SocketManager;
|
||||
friend class SocketFactory;
|
||||
|
||||
void completeAccept(const boost::system::error_code&) throw();
|
||||
void ready() throw();
|
||||
void prepareWrite() throw();
|
||||
void completeWrite(const boost::system::error_code& ec, size_t bytes) throw();
|
||||
void prepareRead() throw();
|
||||
void prepareRead2(const boost::system::error_code& ec, size_t bytes) throw();
|
||||
void completeRead(const boost::system::error_code& ec, size_t bytes) throw();
|
||||
|
||||
void fail(Util::Reason reason, const std::string &info) throw();
|
||||
|
||||
bool disconnecting() const;
|
||||
bool writing() const;
|
||||
|
||||
AsyncStreamPtr sock;
|
||||
|
||||
/** Output buffer, for storing data that's waiting to be transmitted */
|
||||
BufferList outBuf;
|
||||
|
||||
/** Input buffer used when receiving data */
|
||||
BufferPtr inBuf;
|
||||
|
||||
/** Overflow timer, the time when the socket started to overflow */
|
||||
time::ptime overflow;
|
||||
|
||||
/** Time when this socket will be disconnected regardless of buffers */
|
||||
time::ptime disc;
|
||||
|
||||
/** Last time that a write started, 0 if no active write */
|
||||
time::ptime lastWrite;
|
||||
|
||||
std::string ip;
|
||||
|
||||
ConnectedHandler connectedHandler;
|
||||
ReadyHandler readyHandler;
|
||||
DataHandler dataHandler;
|
||||
FailedHandler failedHandler;
|
||||
|
||||
SocketManager &sm;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MANAGEDSOCKET_H
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_MUTEX_H_
|
||||
#define ADCHPP_MUTEX_H_
|
||||
|
||||
#include "Thread.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
template<typename Mutex>
|
||||
class ScopedLock {
|
||||
public:
|
||||
ScopedLock(Mutex& m_) : m(m_) { m.lock(); }
|
||||
~ScopedLock() { m.unlock(); }
|
||||
private:
|
||||
Mutex& m;
|
||||
|
||||
};
|
||||
|
||||
#if defined(_WIN32)
|
||||
class RecursiveMutex : private boost::noncopyable {
|
||||
public:
|
||||
RecursiveMutex() { InitializeCriticalSection(&cs); }
|
||||
~RecursiveMutex() { DeleteCriticalSection(&cs); }
|
||||
|
||||
void lock() { EnterCriticalSection(&cs); }
|
||||
void unlock() { LeaveCriticalSection(&cs); }
|
||||
|
||||
typedef ScopedLock<RecursiveMutex> Lock;
|
||||
private:
|
||||
CRITICAL_SECTION cs;
|
||||
};
|
||||
|
||||
class FastMutex : private boost::noncopyable {
|
||||
public:
|
||||
FastMutex() : val(0) { }
|
||||
~FastMutex() { }
|
||||
|
||||
void lock() { while(InterlockedExchange(&val, 1) == 1) Thread::yield(); }
|
||||
void unlock() { InterlockedExchange(&val, 0); }
|
||||
|
||||
typedef ScopedLock<FastMutex> Lock;
|
||||
private:
|
||||
long val;
|
||||
};
|
||||
|
||||
#elif defined(HAVE_PTHREAD)
|
||||
|
||||
class RecursiveMutex : private boost::noncopyable {
|
||||
public:
|
||||
RecursiveMutex() throw() {
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(&mtx, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
}
|
||||
~RecursiveMutex() throw() { pthread_mutex_destroy(&mtx); }
|
||||
void lock() throw() { pthread_mutex_lock(&mtx); }
|
||||
void unlock() throw() { pthread_mutex_unlock(&mtx); }
|
||||
|
||||
typedef ScopedLock<RecursiveMutex> Lock;
|
||||
private:
|
||||
pthread_mutex_t mtx;
|
||||
};
|
||||
|
||||
class FastMutex : private boost::noncopyable {
|
||||
public:
|
||||
FastMutex() throw() {
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
|
||||
pthread_mutex_init(&mtx, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
}
|
||||
~FastMutex() throw() { pthread_mutex_destroy(&mtx); }
|
||||
void lock() throw() { pthread_mutex_lock(&mtx); }
|
||||
void unlock() throw() { pthread_mutex_unlock(&mtx); }
|
||||
|
||||
typedef ScopedLock<FastMutex> Lock;
|
||||
|
||||
private:
|
||||
pthread_mutex_t mtx;
|
||||
};
|
||||
|
||||
#else
|
||||
#error No mutex found
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif /*MUTEX_H_*/
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef ADCHPP_PLUGIN_H_
|
||||
#define ADCHPP_PLUGIN_H_
|
||||
|
||||
#include "forward.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
/**
|
||||
* Public plugin interface, for plugin intercom.
|
||||
* Plugins that register a public interface must inherit from this class.
|
||||
* Plugins requesting another plugins interface will get a pointer to this
|
||||
* class and must upcast it (using dynamic_cast<> and check NULL to be safe).
|
||||
*/
|
||||
class Plugin {
|
||||
public:
|
||||
virtual ~Plugin() { }
|
||||
/** @return API version for a plugin (incremented every time API changes) */
|
||||
virtual int getVersion() = 0;
|
||||
|
||||
protected:
|
||||
Plugin() { }
|
||||
};
|
||||
|
||||
typedef std::function<void (void*)> PluginDataDeleter;
|
||||
|
||||
class PluginData {
|
||||
public:
|
||||
template<typename T>
|
||||
static void simpleDataDeleter(void* p) { delete reinterpret_cast<T*>(p); }
|
||||
private:
|
||||
friend class PluginManager;
|
||||
friend class Entity;
|
||||
|
||||
PluginData(const PluginDataDeleter& deleter_) : deleter(deleter_) { }
|
||||
|
||||
void operator()(void* p) { if(deleter) deleter(p); }
|
||||
|
||||
PluginDataDeleter deleter;
|
||||
};
|
||||
|
||||
typedef shared_ptr<PluginData> PluginDataHandle;
|
||||
|
||||
}
|
||||
|
||||
#endif /* PLUGIN_H_ */
|
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
|
||||
#include "PluginManager.h"
|
||||
|
||||
#include "SimpleXML.h"
|
||||
#include "LogManager.h"
|
||||
#include "SocketManager.h"
|
||||
#include "version.h"
|
||||
#include "File.h"
|
||||
#include "Text.h"
|
||||
#include "Core.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#define PLUGIN_EXT _T(".dll")
|
||||
|
||||
#define PM_LOAD_LIBRARY(filename) ::LoadLibrary(filename)
|
||||
#define PM_UNLOAD_LIBRARY(lib) ::FreeLibrary(lib)
|
||||
#define PM_GET_ADDRESS(lib, name) ::GetProcAddress(lib, name)
|
||||
#define PM_GET_ERROR_STRING() Util::translateError(GetLastError())
|
||||
|
||||
#else
|
||||
|
||||
#include "dlfcn.h"
|
||||
|
||||
#define PLUGIN_EXT ".so"
|
||||
|
||||
#define PM_LOAD_LIBRARY(filename) ::dlopen(filename, RTLD_LAZY | RTLD_GLOBAL)
|
||||
#define PM_UNLOAD_LIBRARY(lib) ::dlclose(lib)
|
||||
#define PM_GET_ADDRESS(lib, name) ::dlsym(lib, name)
|
||||
#define PM_GET_ERROR_STRING() ::dlerror()
|
||||
|
||||
#endif
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
using namespace std;
|
||||
using std::placeholders::_1;
|
||||
|
||||
const string PluginManager::className = "PluginManager";
|
||||
|
||||
PluginManager::PluginManager(Core &core) throw() : core(core) {
|
||||
|
||||
}
|
||||
|
||||
void PluginManager::attention(const function<void()>& f) {
|
||||
core.addJob(f);
|
||||
}
|
||||
|
||||
void PluginManager::load() {
|
||||
for(StringIter i = plugins.begin(); i != plugins.end(); ++i) {
|
||||
loadPlugin(*i + PLUGIN_EXT);
|
||||
}
|
||||
}
|
||||
|
||||
bool PluginManager::loadPlugin(const string& file) {
|
||||
if(file.length() < 3) {
|
||||
return false;
|
||||
}
|
||||
plugin_t h;
|
||||
|
||||
#ifndef _WIN32
|
||||
if(!File::isAbsolutePath(file)) {
|
||||
h = PM_LOAD_LIBRARY((pluginPath + file).c_str());
|
||||
} else {
|
||||
h = PM_LOAD_LIBRARY(file.c_str());
|
||||
}
|
||||
#else
|
||||
if(!File::isAbsolutePath(file)) {
|
||||
h = LoadLibraryEx((pluginPath + file).c_str(), NULL, DONT_RESOLVE_DLL_REFERENCES);
|
||||
} else {
|
||||
h = LoadLibraryEx(file.c_str(), NULL, DONT_RESOLVE_DLL_REFERENCES);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(h == NULL) {
|
||||
LOG(className, "Failed to load " + Text::utf8ToAcp(file) + ": " + PM_GET_ERROR_STRING());
|
||||
return false;
|
||||
}
|
||||
|
||||
PLUGIN_GET_VERSION v = (PLUGIN_GET_VERSION)PM_GET_ADDRESS(h, "pluginGetVersion");
|
||||
if(v != NULL) {
|
||||
double ver = v();
|
||||
if(ver == PLUGINVERSION) {
|
||||
#ifdef _WIN32
|
||||
// Reload plugin with references resolved...
|
||||
FreeLibrary(h);
|
||||
if(!File::isAbsolutePath(file)) {
|
||||
h = PM_LOAD_LIBRARY((pluginPath + file).c_str());
|
||||
} else {
|
||||
h = PM_LOAD_LIBRARY(file.c_str());
|
||||
}
|
||||
if(h == NULL) {
|
||||
LOG(className, "Failed to load " + Text::utf8ToAcp(file) + ": " + PM_GET_ERROR_STRING());
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
PLUGIN_LOAD l = (PLUGIN_LOAD)PM_GET_ADDRESS(h, "pluginLoad");
|
||||
PLUGIN_UNLOAD u = (PLUGIN_UNLOAD)PM_GET_ADDRESS(h, "pluginUnload");
|
||||
|
||||
if(l != NULL && u != NULL) {
|
||||
int i = l(this);
|
||||
if(i != 0) {
|
||||
LOG(className, "Failed to load plugin " + Text::utf8ToAcp(file) + " (Error " + Util::toString(i) + ")");
|
||||
} else {
|
||||
// Wonderful, we have a plugin...
|
||||
active.push_back(PluginInfo(h, v, l, u));
|
||||
LOG(className, Text::utf8ToAcp(file) + " loaded");
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
LOG(className, Text::utf8ToAcp(file) + " is not a valid ADCH++ plugin");
|
||||
}
|
||||
} else {
|
||||
LOG(className, Text::utf8ToAcp(file) + " is for another version of ADCH++ (" + Util::toString(ver) + "), please get the correct one from the author");
|
||||
}
|
||||
} else {
|
||||
LOG(className, Text::utf8ToAcp(file) + " is not a valid ADCH++ plugin");
|
||||
}
|
||||
|
||||
PM_UNLOAD_LIBRARY(h);
|
||||
return false;
|
||||
}
|
||||
|
||||
void PluginManager::shutdown() {
|
||||
registry.clear();
|
||||
|
||||
for(PluginList::reverse_iterator i = active.rbegin(); i != active.rend(); ++i)
|
||||
i->pluginUnload();
|
||||
#ifndef HAVE_BROKEN_MTALLOC
|
||||
for(PluginList::reverse_iterator i = active.rbegin(); i != active.rend(); ++i)
|
||||
PM_UNLOAD_LIBRARY(i->handle);
|
||||
#endif
|
||||
active.clear();
|
||||
}
|
||||
|
||||
PluginManager::CommandDispatch::CommandDispatch(PluginManager& pm, const std::string& name_, const PluginManager::CommandSlot& f_) :
|
||||
name('+' + name_),
|
||||
f(f_),
|
||||
pm(&pm)
|
||||
{
|
||||
}
|
||||
|
||||
void PluginManager::CommandDispatch::operator()(Entity& e, AdcCommand& cmd, bool& ok) {
|
||||
if(e.getState() != Entity::STATE_NORMAL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(cmd.getCommand() != AdcCommand::CMD_MSG) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(cmd.getParameters().size() < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
StringList l;
|
||||
Util::tokenize(l, cmd.getParameters()[0], ' ');
|
||||
if(l[0] != name) {
|
||||
return;
|
||||
}
|
||||
|
||||
l[0] = name.substr(1);
|
||||
|
||||
if(!pm->handleCommand(e, l)) {
|
||||
return;
|
||||
}
|
||||
|
||||
cmd.setPriority(AdcCommand::PRIORITY_IGNORE);
|
||||
f(e, l, ok);
|
||||
}
|
||||
|
||||
ClientManager::SignalReceive::Connection PluginManager::onCommand(const std::string& commandName, const CommandSlot& f) {
|
||||
return core.getClientManager().signalReceive().connect(CommandDispatch(*this, commandName, f));
|
||||
}
|
||||
|
||||
PluginManager::CommandSignal& PluginManager::getCommandSignal(const std::string& commandName) {
|
||||
CommandHandlers::iterator i = commandHandlers.find(commandName);
|
||||
if(i == commandHandlers.end())
|
||||
return commandHandlers.insert(make_pair(commandName, CommandSignal())).first->second;
|
||||
|
||||
return i->second;
|
||||
}
|
||||
|
||||
bool PluginManager::handleCommand(Entity& e, const StringList& l) {
|
||||
CommandHandlers::iterator i = commandHandlers.find(l[0]);
|
||||
if(i == commandHandlers.end())
|
||||
return true;
|
||||
|
||||
bool ok = true;
|
||||
i->second(e, l, ok);
|
||||
return ok;
|
||||
}
|
||||
|
||||
Core &PluginManager::getCore() { return core; }
|
||||
}
|
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page PluginAPI Plugin API Information
|
||||
* @section General General
|
||||
*
|
||||
* ADCH++ contains a rather powerful plugin API that can be used to create advanced
|
||||
* plugins that change or add to ADCH++'s behaviour. Most plugins will need
|
||||
* PluginManager.h, ClientManager.h and Client.h included to work, even though the
|
||||
* other header files are available as well (they're more likely to change in future
|
||||
* versions though). You can use any method that is declared as DLL or is inline, the
|
||||
* others are meant to be internal to ADCH++, very likely to change/disappear and will
|
||||
* generate link errors (when compiling under windows anyway). When starting a plugin
|
||||
* project I strongly recommend that you take one of the existing plugins and modify
|
||||
* it to your needs (to get all compiler settings and base code right).
|
||||
*
|
||||
* @section Versions Versions
|
||||
*
|
||||
* Due to C++ name mangling, plugins are generally valid only for a certain version
|
||||
* of the ADCH++ plugin API. This version usually follows the main ADCH++ version,
|
||||
* unless a small update is made that I judge shouldn't affect plugins in any way.
|
||||
* Most of the time, recompiling the plugin should be enough, unless any major changes
|
||||
* have been made, and your plugin doesn't rely on the nasty internals.
|
||||
*
|
||||
* @section Threads Threads
|
||||
*
|
||||
* ADCH++ has two main threads running when operating. One handles all network
|
||||
* communication while the other does all other work (handle protocol data and
|
||||
* so on). All plugins are run in the worker thread, which is the only thread
|
||||
* visible to the API. You are only allowed to interact with ADCH++ from this
|
||||
* thread, as none of the API is thread safe, unless otherwise noted. This has a
|
||||
* few important consequences. First off, you can assume that your plugin will
|
||||
* only be called by this thread, which means that you don't have to worry about
|
||||
* multithreading issues unless you start threads by yourself. Second, any work you
|
||||
* do in a plugin halts <b>all</b> of ADCH++'s processing (apart from receiving/sending
|
||||
* buffered data), in other words, don't do any lengthy processing in the on methods,
|
||||
* as the whole of ADCH++ will suffer. Third, if you indeed start another thread, make
|
||||
* sure you don't use any API functions from it apart from those explicitly marked
|
||||
* as thread safe. To indicate from a plugin that you have work to do in the main
|
||||
* worker thread, call PluginManager::attention().
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_PLUGINMANAGER_H
|
||||
#define ADCHPP_PLUGINMANAGER_H
|
||||
|
||||
#include "version.h"
|
||||
#include "Signal.h"
|
||||
#include "ClientManager.h"
|
||||
#include "Plugin.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
class SimpleXML;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifdef BUILDING_ADCHPP
|
||||
#define PLUGIN_API
|
||||
#else
|
||||
#define PLUGIN_API __declspec(dllexport)
|
||||
#endif
|
||||
|
||||
typedef HMODULE plugin_t;
|
||||
|
||||
#else // WIN32
|
||||
|
||||
#ifdef BUILDING_ADCHPP
|
||||
#define PLUGIN_API
|
||||
#else
|
||||
#define PLUGIN_API __attribute__ ((visibility("default")))
|
||||
#endif
|
||||
|
||||
typedef void* plugin_t;
|
||||
|
||||
#endif // WIN32
|
||||
|
||||
/**
|
||||
* PLUGIN_API double pluginGetVersion()
|
||||
* This function should just return the constant PLUGINVERSIONFLOAT
|
||||
* so that the pluginmanager can determine if this plugin should
|
||||
* be loaded or not
|
||||
*/
|
||||
typedef int (*PLUGIN_GET_VERSION)();
|
||||
|
||||
/**
|
||||
* PLUGIN_API void pluginLoad()
|
||||
* This function is called when the hub is starting up and loading the plugin.
|
||||
* Here you should load any data your plugin might need and connect to any
|
||||
* Managers you might be interested in. Note; you also have to connect to
|
||||
* PluginManager itself to receive its events.
|
||||
* @return 0 if the plugin was loaded ok, != 0 otherwise (the number will be logged,
|
||||
* use as error code). Plugin dll will get unloaded without calling pluginUnload if the return
|
||||
* value is not 0 here.
|
||||
* @see pluginUnload
|
||||
*/
|
||||
typedef int (*PLUGIN_LOAD)(PluginManager *);
|
||||
|
||||
/**
|
||||
* PLUGIN_API void pluginUnload()
|
||||
* Called when the hub is shutting down
|
||||
* @see pluginLoad
|
||||
*/
|
||||
typedef void (*PLUGIN_UNLOAD)();
|
||||
|
||||
class PluginManager
|
||||
{
|
||||
public:
|
||||
typedef std::unordered_map<std::string, shared_ptr<Plugin>> Registry;
|
||||
|
||||
/**
|
||||
* This is a thread-safe method to call when you need to perform some work
|
||||
* in the main ADCH++ worker thread. Your job will be executed once, when
|
||||
* time permits.
|
||||
*/
|
||||
ADCHPP_DLL void attention(const std::function<void()>& f);
|
||||
|
||||
/**
|
||||
* Get a list of currently loaded plugins
|
||||
*/
|
||||
const StringList& getPluginList() const {
|
||||
return plugins;
|
||||
}
|
||||
|
||||
void setPluginList(const StringList& pluginList) { plugins = pluginList; }
|
||||
|
||||
/**
|
||||
* Get the plugin path as set in adchpp.xml
|
||||
*/
|
||||
const std::string& getPluginPath() const {
|
||||
return pluginPath;
|
||||
}
|
||||
|
||||
void setPluginPath(const std::string& path) { pluginPath = path; }
|
||||
|
||||
/**
|
||||
* Register a plugin data type to be used with Client::setPSD and friends.
|
||||
* When data is removed, the deleter function will automatically be called
|
||||
* with the data as parameter, allowing automatic life cycle managment for
|
||||
* plugin-specific data.
|
||||
*/
|
||||
PluginDataHandle registerPluginData(const PluginDataDeleter& deleter_) { return PluginDataHandle(new PluginData(deleter_)); }
|
||||
|
||||
/**
|
||||
* Register a plugin interface under a name.
|
||||
* @return false if name was already registered and call fails
|
||||
*/
|
||||
bool registerPlugin(const std::string& name, shared_ptr<Plugin> ptr) {
|
||||
return registry.insert(std::make_pair(name, ptr)).second;
|
||||
}
|
||||
|
||||
/** @return True if the plugin existed and was thus unregistered */
|
||||
bool unregisterPlugin(const std::string& name) {
|
||||
return registry.erase(name) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Plugin interface, or an empty pointer if not found
|
||||
*/
|
||||
shared_ptr<Plugin> getPlugin(const std::string& name) {
|
||||
auto i = registry.find(name);
|
||||
return i == registry.end() ? shared_ptr<Plugin>() : i->second;
|
||||
}
|
||||
|
||||
/**
|
||||
* The full map of registered plugins.
|
||||
*/
|
||||
const Registry& getPlugins() const {
|
||||
return registry;
|
||||
}
|
||||
|
||||
typedef SignalTraits<void (Entity&, const StringList&, bool&)>::Signal CommandSignal;
|
||||
typedef CommandSignal::Slot CommandSlot;
|
||||
/**
|
||||
* Utility function to handle +-commands from clients
|
||||
* The parameters are the same as ClientManager::signalReceive, only that the parameters will
|
||||
* have been parsed already, and the function will only be called if the command name matches
|
||||
*/
|
||||
ADCHPP_DLL ClientManager::SignalReceive::Connection onCommand(const std::string& commandName, const CommandSlot& f);
|
||||
/// Handle +-commands set by another script, and possibly prevent them from being dispatched
|
||||
ADCHPP_DLL CommandSignal& getCommandSignal(const std::string& commandName);
|
||||
|
||||
/** @internal */
|
||||
void load();
|
||||
/** @internal */
|
||||
void shutdown();
|
||||
|
||||
ADCHPP_DLL Core &getCore();
|
||||
|
||||
private:
|
||||
friend class Core;
|
||||
|
||||
PluginManager(Core &core) throw();
|
||||
|
||||
class PluginInfo {
|
||||
public:
|
||||
|
||||
PluginInfo(plugin_t h, PLUGIN_GET_VERSION v, PLUGIN_LOAD l, PLUGIN_UNLOAD u) :
|
||||
handle(h), pluginGetVersion(v), pluginLoad(l), pluginUnload(u) { }
|
||||
|
||||
plugin_t handle;
|
||||
PLUGIN_GET_VERSION pluginGetVersion;
|
||||
PLUGIN_LOAD pluginLoad;
|
||||
PLUGIN_UNLOAD pluginUnload;
|
||||
};
|
||||
|
||||
struct CommandDispatch {
|
||||
CommandDispatch(PluginManager &pm, const std::string& name_, const PluginManager::CommandSlot& f_);
|
||||
|
||||
void operator()(Entity& e, AdcCommand& cmd, bool& ok);
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
PluginManager::CommandSlot f;
|
||||
PluginManager *pm;
|
||||
};
|
||||
|
||||
friend struct CommandDispatch;
|
||||
|
||||
typedef std::vector<PluginInfo> PluginList;
|
||||
typedef PluginList::iterator PluginIter;
|
||||
|
||||
PluginList active;
|
||||
Registry registry;
|
||||
|
||||
StringList plugins;
|
||||
std::string pluginPath;
|
||||
|
||||
Core &core;
|
||||
|
||||
static const std::string className;
|
||||
|
||||
bool loadPlugin(const std::string& file);
|
||||
|
||||
typedef std::unordered_map<std::string, CommandSignal> CommandHandlers;
|
||||
CommandHandlers commandHandlers;
|
||||
bool handleCommand(Entity& e, const StringList& l);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // PLUGINMANAGER_H
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_POOL_H
|
||||
#define ADCHPP_POOL_H
|
||||
|
||||
#include "Mutex.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
template<class T>
|
||||
struct PoolDummy {
|
||||
void operator()(T&) { }
|
||||
};
|
||||
|
||||
template<typename T, class Clear = PoolDummy<T> >
|
||||
class SimplePool {
|
||||
public:
|
||||
SimplePool() : busy(0) { }
|
||||
~SimplePool() { dcdebug("Busy pool objects: %d\n", (int)busy); }
|
||||
|
||||
T* get() {
|
||||
busy++;
|
||||
if(!free.empty()) {
|
||||
T* tmp = free.back();
|
||||
free.pop_back();
|
||||
return tmp;
|
||||
} else {
|
||||
return new T;
|
||||
}
|
||||
}
|
||||
void put(T* item) {
|
||||
dcassert(busy > 0);
|
||||
busy--;
|
||||
Clear()(*item);
|
||||
// Remove some objects every now and then...
|
||||
if(free.size() > (2*busy) && free.size() > 32) {
|
||||
dcdebug("Clearing pool\n");
|
||||
while(free.size() > busy / 2) {
|
||||
delete free.back();
|
||||
free.pop_back();
|
||||
}
|
||||
}
|
||||
free.push_back(item);
|
||||
}
|
||||
|
||||
private:
|
||||
size_t busy;
|
||||
std::vector<T*> free;
|
||||
};
|
||||
|
||||
|
||||
/** A thread safe object pool */
|
||||
template<class T, class Clear = PoolDummy<T> >
|
||||
class Pool {
|
||||
public:
|
||||
Pool() { }
|
||||
~Pool() { }
|
||||
|
||||
T* get() {
|
||||
FastMutex::Lock l(mtx);
|
||||
return pool.get();
|
||||
}
|
||||
void put(T* obj) {
|
||||
FastMutex::Lock l(mtx);
|
||||
pool.put(obj);
|
||||
}
|
||||
|
||||
private:
|
||||
Pool(const Pool&);
|
||||
Pool& operator=(const Pool&);
|
||||
FastMutex mtx;
|
||||
|
||||
SimplePool<T, Clear> pool;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //POOL_H_
|
|
@ -0,0 +1,68 @@
|
|||
# vim: set filetype=py
|
||||
|
||||
def getRevision(env):
|
||||
"""Attempt to get information about the repository, via the "hg log"
|
||||
command. Its output is formatted via the "-T" parameter (see "hg templates"
|
||||
for details).
|
||||
|
||||
:return: Version information string, or "[unknown]" on failure.
|
||||
:rtype: str.
|
||||
"""
|
||||
|
||||
try:
|
||||
import subprocess
|
||||
ret = subprocess.check_output(
|
||||
'hg log -r tip -T "{node | short} - {date | isodate}"',
|
||||
shell=True
|
||||
)
|
||||
if ret:
|
||||
return ret
|
||||
except:
|
||||
pass
|
||||
return '[unknown]'
|
||||
|
||||
Import('dev source_path')
|
||||
|
||||
env, target, sources = dev.prepare_build(source_path, 'adchpp', shared_precompiled_header = 'adchpp')
|
||||
|
||||
env.Append(CPPPATH = ['.'])
|
||||
|
||||
env.Append(CPPDEFINES=["BUILDING_ADCHPP=1"])
|
||||
|
||||
if env['CC'] == 'cl': # MSVC
|
||||
env.Append(LIBS = ['advapi32', 'user32'])
|
||||
|
||||
if 'HAVE_DL' in env['CPPDEFINES']:
|
||||
env.Append(LIBS = ['dl'])
|
||||
|
||||
if 'HAVE_PTHREAD' in env['CPPDEFINES']:
|
||||
env.Append(LIBS = ['pthread'])
|
||||
|
||||
if 'HAVE_OPENSSL' in env['CPPDEFINES']:
|
||||
if dev.is_win32():
|
||||
if env['CC'] == 'cl': # MSVC
|
||||
if env['mode'] == 'debug':
|
||||
env.Prepend(LIBS = ['ssleay32d', 'libeay32d'])
|
||||
else:
|
||||
env.Prepend(LIBS = ['ssleay32', 'libeay32'])
|
||||
else:
|
||||
env.Prepend(LIBS = ['ssl', 'crypto'])
|
||||
env.Append(LIBS = ['gdi32']) # something in OpenSSL uses CreateDC etc...
|
||||
env.Append(CPPPATH=['#/openssl/include'])
|
||||
openssl_lib = '#/openssl/lib/'
|
||||
if env['arch'] != 'x86':
|
||||
openssl_lib += env['arch'] + '/'
|
||||
env.Append(LIBPATH=[openssl_lib])
|
||||
else:
|
||||
env.Prepend(LIBS = ['ssl', 'crypto'])
|
||||
|
||||
for i, source in enumerate(sources):
|
||||
if source.find("version.cpp") != -1:
|
||||
rev = ['ADCHPP_REVISION=' + getRevision(env)]
|
||||
sources[i] = env.SharedObject(source, CPPDEFINES=env['CPPDEFINES'] + rev)
|
||||
|
||||
headers=dev.get_sources(source_path, "*.h")
|
||||
|
||||
ret = env.SharedLibrary(target, sources)
|
||||
|
||||
Return('ret')
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_SERVER_INFO_H
|
||||
#define ADCHPP_SERVER_INFO_H
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
struct ServerInfo {
|
||||
std::string ip;
|
||||
std::string port;
|
||||
|
||||
struct TLSInfo {
|
||||
std::string cert;
|
||||
std::string pkey;
|
||||
std::string trustedPath;
|
||||
std::string dh;
|
||||
|
||||
private:
|
||||
friend struct ServerInfo;
|
||||
bool secure() const {
|
||||
return !cert.empty() && !pkey.empty() && !trustedPath.empty() && !dh.empty();
|
||||
}
|
||||
} TLSParams;
|
||||
bool secure() const { return TLSParams.secure(); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_SIGNAL_H
|
||||
#define ADCHPP_SIGNAL_H
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
struct Connection : private boost::noncopyable {
|
||||
public:
|
||||
Connection() { }
|
||||
virtual ~Connection() { }
|
||||
|
||||
virtual void disconnect() = 0;
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<Connection> ConnectionPtr;
|
||||
|
||||
template<typename F>
|
||||
class Signal {
|
||||
public:
|
||||
typedef std::function<F> Slot;
|
||||
typedef std::list<Slot> SlotList;
|
||||
typedef F FunctionType;
|
||||
|
||||
template<typename T0>
|
||||
void operator()(T0&& t0) {
|
||||
for(auto i = slots.begin(), iend = slots.end(); i != iend;) {
|
||||
(*i++)(std::forward<T0>(t0));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T0, typename T1>
|
||||
void operator()(T0&& t0, T1&& t1) {
|
||||
for(auto i = slots.begin(), iend = slots.end(); i != iend;) {
|
||||
(*i++)(std::forward<T0>(t0), std::forward<T1>(t1));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T0, typename T1, typename T2>
|
||||
void operator()(T0&& t0, T1&& t1, T2&& t2) {
|
||||
for(auto i = slots.begin(), iend = slots.end(); i != iend;) {
|
||||
(*i++)(std::forward<T0>(t0), std::forward<T1>(t1), std::forward<T2>(t2));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ConnectionPtr connect(const T& f) { return ConnectionPtr(new SlotConnection(this, slots.insert(slots.end(), f))); }
|
||||
|
||||
~Signal() { }
|
||||
private:
|
||||
SlotList slots;
|
||||
|
||||
void disconnect(const typename SlotList::iterator& i) {
|
||||
slots.erase(i);
|
||||
}
|
||||
|
||||
struct SlotConnection : public Connection {
|
||||
SlotConnection(Signal<F>* sig_, const typename SlotList::iterator& i_) : sig(sig_), i(i_) { }
|
||||
|
||||
virtual void disconnect() { if(sig) sig->disconnect(i), sig = 0; }
|
||||
Signal<F>* sig;
|
||||
typename Signal<F>::SlotList::iterator i;
|
||||
};
|
||||
};
|
||||
|
||||
struct ManagedConnection : private boost::noncopyable {
|
||||
ManagedConnection(ConnectionPtr&& conn_) : conn(move(conn_)) {
|
||||
}
|
||||
|
||||
void disconnect() {
|
||||
if(conn.get()) {
|
||||
conn->disconnect();
|
||||
conn.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void release() {
|
||||
conn.reset();
|
||||
}
|
||||
|
||||
~ManagedConnection() {
|
||||
disconnect();
|
||||
}
|
||||
private:
|
||||
ConnectionPtr conn;
|
||||
};
|
||||
|
||||
typedef shared_ptr<ManagedConnection> ManagedConnectionPtr;
|
||||
|
||||
template<typename F1, typename F2>
|
||||
inline ManagedConnectionPtr manage(Signal<F1>* signal, const F2& f) {
|
||||
return make_shared<ManagedConnection>(signal->connect(f));
|
||||
}
|
||||
|
||||
inline ManagedConnectionPtr manage(ConnectionPtr && conn) {
|
||||
return make_shared<ManagedConnection>(move(conn));
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
struct SignalTraits {
|
||||
typedef adchpp::Signal<F> Signal;
|
||||
typedef adchpp::ConnectionPtr Connection;
|
||||
typedef adchpp::ManagedConnectionPtr ManagedConnection;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // SIGNAL_H
|
|
@ -0,0 +1,349 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
|
||||
#include "SimpleXML.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
using namespace std;
|
||||
|
||||
SimpleXML::SimpleXML(int numAttribs) : attribs(numAttribs), found(false) {
|
||||
root = current = new Tag("BOGUSROOT", Util::emptyString, NULL);
|
||||
}
|
||||
|
||||
SimpleXML::~SimpleXML() {
|
||||
delete root;
|
||||
}
|
||||
|
||||
void SimpleXML::escape(string& aString, bool aAttrib, bool aLoading /* = false */) {
|
||||
string::size_type i = 0;
|
||||
const char* chars = aAttrib ? "<&>'\"" : "<&>";
|
||||
|
||||
if(aLoading) {
|
||||
while((i = aString.find('&', i)) != string::npos) {
|
||||
if(aString.compare(i+1, 3, "lt;") == 0) {
|
||||
aString.replace(i, 4, 1, '<');
|
||||
} else if(aString.compare(i+1, 4, "amp;") == 0) {
|
||||
aString.replace(i, 5, 1, '&');
|
||||
} else if(aString.compare(i+1, 3, "gt;") == 0) {
|
||||
aString.replace(i, 4, 1, '>');
|
||||
} else if(aAttrib) {
|
||||
if(aString.compare(i+1, 5, "apos;") == 0) {
|
||||
aString.replace(i, 6, 1, '\'');
|
||||
} else if(aString.compare(i+1, 5, "quot;") == 0) {
|
||||
aString.replace(i, 6, 1, '"');
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
i = 0;
|
||||
if( (i = aString.find('\n')) != string::npos) {
|
||||
if(i > 0 && aString[i-1] != '\r') {
|
||||
// This is a unix \n thing...convert it...
|
||||
i = 0;
|
||||
while( (i = aString.find('\n', i) ) != string::npos) {
|
||||
if(aString[i-1] != '\r')
|
||||
aString.insert(i, 1, '\r');
|
||||
|
||||
i+=2;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while( (i = aString.find_first_of(chars, i)) != string::npos) {
|
||||
switch(aString[i]) {
|
||||
case '<': aString.replace(i, 1, "<"); i+=4; break;
|
||||
case '&': aString.replace(i, 1, "&"); i+=5; break;
|
||||
case '>': aString.replace(i, 1, ">"); i+=4; break;
|
||||
case '\'': aString.replace(i, 1, "'"); i+=6; break;
|
||||
case '"': aString.replace(i, 1, """); i+=6; break;
|
||||
default: dcasserta(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleXML::Tag::appendAttribString(string& tmp) {
|
||||
for(AttribIter i = attribs.begin(); i!= attribs.end(); ++i) {
|
||||
tmp.append(i->first);
|
||||
tmp.append("=\"", 2);
|
||||
if(needsEscape(i->second, true)) {
|
||||
string tmp2(i->second);
|
||||
escape(tmp2, true);
|
||||
tmp.append(tmp2);
|
||||
} else {
|
||||
tmp.append(i->second);
|
||||
}
|
||||
tmp.append("\" ", 2);
|
||||
}
|
||||
tmp.erase(tmp.size()-1);
|
||||
}
|
||||
|
||||
string SimpleXML::Tag::toXML(int indent) {
|
||||
if(children.empty() && data.empty()) {
|
||||
string tmp;
|
||||
tmp.reserve(indent + name.length() + 30);
|
||||
tmp.append(indent, '\t');
|
||||
tmp.append(1, '<');
|
||||
tmp.append(name);
|
||||
tmp.append(1, ' ');
|
||||
appendAttribString(tmp);
|
||||
tmp.append("/>\r\n", 4);
|
||||
return tmp;
|
||||
} else {
|
||||
string tmp;
|
||||
tmp.append(indent, '\t');
|
||||
tmp.append(1, '<');
|
||||
tmp.append(name);
|
||||
tmp.append(1, ' ');
|
||||
appendAttribString(tmp);
|
||||
if(children.empty()) {
|
||||
tmp.append(1, '>');
|
||||
if(needsEscape(data, false)) {
|
||||
string tmp2(data);
|
||||
escape(tmp2, false);
|
||||
tmp.append(tmp2);
|
||||
} else {
|
||||
tmp.append(data);
|
||||
}
|
||||
} else {
|
||||
tmp.append(">\r\n", 3);
|
||||
for(Iter i = children.begin(); i!=children.end(); ++i) {
|
||||
tmp.append((*i)->toXML(indent + 1));
|
||||
}
|
||||
tmp.append(indent, '\t');
|
||||
}
|
||||
tmp.append("</", 2);
|
||||
tmp.append(name);
|
||||
tmp.append(">\r\n", 3);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
bool SimpleXML::findChild(const string& aName) const throw() {
|
||||
dcassert(current != NULL);
|
||||
|
||||
if(found && currentChild != current->children.end())
|
||||
currentChild++;
|
||||
|
||||
while(currentChild!=current->children.end()) {
|
||||
if(aName.empty() || (*currentChild)->name == aName) {
|
||||
found = true;
|
||||
return true;
|
||||
} else
|
||||
currentChild++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SimpleXML::stepIn() const throw(SimpleXMLException) {
|
||||
checkChildSelected();
|
||||
current = *currentChild;
|
||||
currentChild = current->children.begin();
|
||||
found = false;
|
||||
}
|
||||
|
||||
void SimpleXML::stepOut() const throw(SimpleXMLException) {
|
||||
if(current == root)
|
||||
throw SimpleXMLException("Already at lowest level");
|
||||
|
||||
dcassert(current->parent != NULL);
|
||||
|
||||
currentChild = find(current->parent->children.begin(), current->parent->children.end(), current);
|
||||
|
||||
current = current->parent;
|
||||
found = true;
|
||||
}
|
||||
|
||||
string::size_type SimpleXML::Tag::loadAttribs(const string& tmp, string::size_type start) throw(SimpleXMLException) {
|
||||
string::size_type i = start;
|
||||
string::size_type j;
|
||||
for(;;) {
|
||||
j = tmp.find('=', i);
|
||||
if(j == string::npos) {
|
||||
throw SimpleXMLException("Missing '=' in " + name);
|
||||
}
|
||||
if(tmp[j+1] != '"' && tmp[j+1] != '\'') {
|
||||
throw SimpleXMLException("Invalid character after '=' in " + name);
|
||||
}
|
||||
string::size_type x = j + 2;
|
||||
string::size_type y = tmp.find(tmp[j+1], x);
|
||||
if(y == string::npos) {
|
||||
throw SimpleXMLException("Missing '" + string(1, tmp[j+1]) + "' in " + name);
|
||||
}
|
||||
// Ok, we have an attribute...
|
||||
attribs.push_back(make_pair(tmp.substr(i, j-i), tmp.substr(x, y-x)));
|
||||
escape(attribs.back().second, true, true);
|
||||
|
||||
i = tmp.find_first_not_of("\r\n\t ", y + 1);
|
||||
if(tmp[i] == '/' || tmp[i] == '>')
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
string::size_type SimpleXML::Tag::fromXML(const string& tmp, string::size_type start, int aa, bool isRoot /* = false */) throw(SimpleXMLException) {
|
||||
string::size_type i = start;
|
||||
string::size_type j;
|
||||
|
||||
bool hasChildren = false;
|
||||
dcassert(tmp.size() > 0);
|
||||
|
||||
for(;;) {
|
||||
j = tmp.find('<', i);
|
||||
if(j == string::npos) {
|
||||
if(isRoot) {
|
||||
throw SimpleXMLException("Invalid XML file, missing root tag");
|
||||
} else {
|
||||
throw SimpleXMLException("Missing end tag in " + name);
|
||||
}
|
||||
}
|
||||
|
||||
// Check that we have at least 3 more characters as the shortest valid xml tag is <a/>...
|
||||
if((j + 3) > tmp.size()) {
|
||||
throw SimpleXMLException("Missing end tag in " + name);
|
||||
}
|
||||
|
||||
Ptr child = NULL;
|
||||
|
||||
i = j + 1;
|
||||
|
||||
if(tmp[i] == '?') {
|
||||
// <? processing instruction ?>, ignore...
|
||||
i = tmp.find("?>", i);
|
||||
if(i == string::npos) {
|
||||
throw SimpleXMLException("Missing '?>' in " + name);
|
||||
}
|
||||
i+= 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(tmp[i] == '!' && tmp[i+1] == '-' && tmp[i+2] == '-') {
|
||||
// <!-- comment -->, ignore...
|
||||
i = tmp.find("-->", i);
|
||||
if(i == string::npos) {
|
||||
throw SimpleXMLException("Missing '-->' in " + name);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if we reached the end tag
|
||||
if(tmp[i] == '/') {
|
||||
i++;
|
||||
if( (tmp.compare(i, name.length(), name) == 0) &&
|
||||
(tmp[i + name.length()] == '>') )
|
||||
{
|
||||
if(!hasChildren) {
|
||||
data = tmp.substr(start, i - start - 2);
|
||||
escape(data, false, true);
|
||||
}
|
||||
return i + name.length() + 1;
|
||||
} else {
|
||||
throw SimpleXMLException("Missing end tag in " + name);
|
||||
}
|
||||
}
|
||||
|
||||
// Alright, we have a real tag for sure...now get the name of it.
|
||||
j = tmp.find_first_of("\r\n\t />", i);
|
||||
if(j == string::npos) {
|
||||
throw SimpleXMLException("Missing '>' in " + name);
|
||||
}
|
||||
|
||||
child = new Tag(tmp.substr(i, j-i), Util::emptyString, this, aa);
|
||||
// Put it here immideately to avoid mem leaks
|
||||
children.push_back(child);
|
||||
|
||||
if(tmp[j] == ' ')
|
||||
j = tmp.find_first_not_of("\r\n\t ", j+1);
|
||||
|
||||
if(j == string::npos) {
|
||||
throw SimpleXMLException("Missing '>' in " + name);
|
||||
}
|
||||
|
||||
if(tmp[j] != '/' && tmp[j] != '>') {
|
||||
// We have attribs...
|
||||
j = child->loadAttribs(tmp, j);
|
||||
}
|
||||
|
||||
if(tmp[j] == '>') {
|
||||
// This is a real tag with data etc...
|
||||
hasChildren = true;
|
||||
j = child->fromXML(tmp, j+1, aa);
|
||||
} else {
|
||||
// A simple tag (<xxx/>
|
||||
j++;
|
||||
}
|
||||
i = j;
|
||||
if(isRoot) {
|
||||
if(tmp.find('<', i) != string::npos) {
|
||||
throw SimpleXMLException("Invalid XML file, multiple root tags");
|
||||
}
|
||||
return tmp.length();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleXML::addTag(const string& aName, const string& aData /* = "" */) throw(SimpleXMLException) {
|
||||
if(aName.empty()) {
|
||||
throw SimpleXMLException("Empty tag names not allowed");
|
||||
}
|
||||
|
||||
if(current == root) {
|
||||
if(current->children.empty()) {
|
||||
current->children.push_back(new Tag(aName, aData, root, attribs));
|
||||
currentChild = current->children.begin();
|
||||
} else {
|
||||
throw SimpleXMLException("Only one root tag allowed");
|
||||
}
|
||||
} else {
|
||||
current->children.push_back(new Tag(aName, aData, current, attribs));
|
||||
currentChild = current->children.end() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleXML::addAttrib(const string& aName, const string& aData) throw(SimpleXMLException) {
|
||||
if(current==root)
|
||||
throw SimpleXMLException("No tag is currently selected");
|
||||
|
||||
current->attribs.push_back(make_pair(aName, aData));
|
||||
}
|
||||
|
||||
void SimpleXML::addChildAttrib(const string& aName, const string& aData) throw(SimpleXMLException) {
|
||||
checkChildSelected();
|
||||
|
||||
(*currentChild)->attribs.push_back(make_pair(aName, aData));
|
||||
}
|
||||
|
||||
void SimpleXML::fromXML(const string& aXML) throw(SimpleXMLException) {
|
||||
if(root) {
|
||||
delete root;
|
||||
}
|
||||
root = new Tag("BOGUSROOT", Util::emptyString, NULL, 0);
|
||||
|
||||
root->fromXML(aXML, 0, attribs, true);
|
||||
|
||||
if(root->children.size() != 1) {
|
||||
throw SimpleXMLException("Invalid XML file, missing or multiple root tags");
|
||||
}
|
||||
|
||||
current = root;
|
||||
resetCurrentChild();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_SIMPLEXML_H
|
||||
#define ADCHPP_SIMPLEXML_H
|
||||
|
||||
#include "Exception.h"
|
||||
#include "Util.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
STANDARD_EXCEPTION(SimpleXMLException);
|
||||
|
||||
/**
|
||||
* A simple XML class that loads an XML-ish structure into an internal tree
|
||||
* and allows easy access to each element through a "current location".
|
||||
*/
|
||||
class SimpleXML : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
ADCHPP_DLL SimpleXML(int numAttribs = 0);
|
||||
ADCHPP_DLL ~SimpleXML();
|
||||
|
||||
ADCHPP_DLL void addTag(const std::string& aName, const std::string& aData = Util::emptyString) throw(SimpleXMLException);
|
||||
void addTag(const std::string& aName, int aData) throw(SimpleXMLException) {
|
||||
addTag(aName, Util::toString(aData));
|
||||
}
|
||||
void addTag(const std::string& aName, int64_t aData) throw(SimpleXMLException) {
|
||||
addTag(aName, Util::toString(aData));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void addAttrib(const std::string& aName, const T& aData) throw(SimpleXMLException) {
|
||||
addAttrib(aName, Util::toString(aData));
|
||||
}
|
||||
|
||||
ADCHPP_DLL void addAttrib(const std::string& aName, const std::string& aData) throw(SimpleXMLException);
|
||||
|
||||
template <typename T>
|
||||
void addChildAttrib(const std::string& aName, const T& aData) throw(SimpleXMLException) {
|
||||
addChildAttrib(aName, Util::toString(aData));
|
||||
}
|
||||
ADCHPP_DLL void addChildAttrib(const std::string& aName, const std::string& aData) throw(SimpleXMLException);
|
||||
|
||||
const std::string& getData() const {
|
||||
dcassert(current != NULL);
|
||||
return current->data;
|
||||
}
|
||||
|
||||
ADCHPP_DLL void stepIn() const throw(SimpleXMLException);
|
||||
ADCHPP_DLL void stepOut() const throw(SimpleXMLException);
|
||||
|
||||
void resetCurrentChild() const throw() {
|
||||
found = false;
|
||||
dcassert(current != NULL);
|
||||
currentChild = current->children.begin();
|
||||
}
|
||||
|
||||
ADCHPP_DLL bool findChild(const std::string& aName) const throw();
|
||||
|
||||
const std::string& getChildName() const {
|
||||
checkChildSelected();
|
||||
return (*currentChild)->name;
|
||||
}
|
||||
|
||||
const std::string& getChildData() const {
|
||||
checkChildSelected();
|
||||
return (*currentChild)->data;
|
||||
}
|
||||
|
||||
const std::string& getChildAttrib(const std::string& aName, const std::string& aDefault = Util::emptyString) const {
|
||||
checkChildSelected();
|
||||
return (*currentChild)->getAttrib(aName, aDefault);
|
||||
}
|
||||
|
||||
int getIntChildAttrib(const std::string& aName) const {
|
||||
checkChildSelected();
|
||||
return Util::toInt(getChildAttrib(aName));
|
||||
}
|
||||
int64_t getLongLongChildAttrib(const std::string& aName) const {
|
||||
checkChildSelected();
|
||||
return Util::toInt64(getChildAttrib(aName));
|
||||
}
|
||||
bool getBoolChildAttrib(const std::string& aName) const {
|
||||
checkChildSelected();
|
||||
const std::string& tmp = getChildAttrib(aName);
|
||||
|
||||
return (tmp.size() > 0) && tmp[0] == '1';
|
||||
}
|
||||
|
||||
ADCHPP_DLL void fromXML(const std::string& aXML) throw(SimpleXMLException);
|
||||
std::string toXML() { return (!root->children.empty()) ? root->children[0]->toXML(0) : Util::emptyString; }
|
||||
|
||||
ADCHPP_DLL static void escape(std::string& aString, bool aAttrib, bool aLoading = false);
|
||||
/**
|
||||
* This is a heurestic for whether escape needs to be called or not. The results are
|
||||
* only guaranteed for false, i e sometimes true might be returned even though escape
|
||||
* was not needed...
|
||||
*/
|
||||
static bool needsEscape(const std::string& aString, bool aAttrib, bool aLoading = false) {
|
||||
return ((aLoading) ? aString.find('&') : aString.find_first_of(aAttrib ? "<&>'\"" : "<&>")) != std::string::npos;
|
||||
}
|
||||
private:
|
||||
class Tag {
|
||||
public:
|
||||
typedef Tag* Ptr;
|
||||
typedef std::vector<Ptr> List;
|
||||
typedef List::iterator Iter;
|
||||
typedef std::pair<std::string, std::string> StringPair;
|
||||
typedef std::vector<StringPair> AttribMap;
|
||||
typedef AttribMap::iterator AttribIter;
|
||||
|
||||
/**
|
||||
* A simple list of children. To find a tag, one must search the entire list.
|
||||
*/
|
||||
List children;
|
||||
/**
|
||||
* Attributes of this tag. According to the XML standard the names
|
||||
* must be unique (case-sensitive). (Assuming that we have few attributes here,
|
||||
* we use a vector instead of a (hash)map to save a few bytes of memory and unnecessary
|
||||
* calls to the memory allocator...)
|
||||
*/
|
||||
AttribMap attribs;
|
||||
|
||||
/** Tag name */
|
||||
std::string name;
|
||||
|
||||
/** Tag data, may be empty. */
|
||||
std::string data;
|
||||
|
||||
/** Parent tag, for easy traversal */
|
||||
Ptr parent;
|
||||
|
||||
Tag(const std::string& aName, const std::string& aData, Ptr aParent, int numAttribs = 0) : name(aName), data(aData), parent(aParent) {
|
||||
if(numAttribs > 0)
|
||||
attribs.reserve(numAttribs);
|
||||
}
|
||||
|
||||
const std::string& getAttrib(const std::string& aName, const std::string& aDefault = Util::emptyString) {
|
||||
AttribIter i = find_if(attribs.begin(), attribs.end(), CompareFirst<std::string, std::string>(aName));
|
||||
return (i == attribs.end()) ? aDefault : i->second;
|
||||
}
|
||||
ADCHPP_DLL std::string toXML(int indent);
|
||||
|
||||
std::string::size_type fromXML(const std::string& tmp, std::string::size_type start, int aa, bool isRoot = false) throw(SimpleXMLException);
|
||||
std::string::size_type loadAttribs(const std::string& tmp, std::string::size_type start) throw(SimpleXMLException);
|
||||
|
||||
void appendAttribString(std::string& tmp);
|
||||
/** Delete all children! */
|
||||
~Tag() {
|
||||
for(Iter i = children.begin(); i != children.end(); ++i) {
|
||||
delete *i;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** Bogus root tag, should be only one child! */
|
||||
Tag::Ptr root;
|
||||
|
||||
/** Current position */
|
||||
mutable Tag::Ptr current;
|
||||
|
||||
mutable Tag::Iter currentChild;
|
||||
|
||||
void checkChildSelected() const throw() {
|
||||
dcassert(current != NULL);
|
||||
dcassert(currentChild != current->children.end());
|
||||
}
|
||||
|
||||
int attribs;
|
||||
mutable bool found;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // SIMPLEXML_H
|
|
@ -0,0 +1,385 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
|
||||
#include "SocketManager.h"
|
||||
|
||||
#include "LogManager.h"
|
||||
#include "ManagedSocket.h"
|
||||
#include "ServerInfo.h"
|
||||
#include "SimpleXML.h"
|
||||
#include "Core.h"
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/date_time/posix_time/time_parsers.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ip/v6_only.hpp>
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
using namespace std;
|
||||
using namespace std::placeholders;
|
||||
using namespace boost::asio;
|
||||
using boost::system::error_code;
|
||||
using boost::system::system_error;
|
||||
|
||||
SocketManager::SocketManager(Core &core) :
|
||||
core(core),
|
||||
bufferSize(1024),
|
||||
maxBufferSize(16 * 1024),
|
||||
overflowTimeout(60 * 1000),
|
||||
disconnectTimeout(10 * 1000)
|
||||
{
|
||||
}
|
||||
|
||||
const string SocketManager::className = "SocketManager";
|
||||
|
||||
template<typename T>
|
||||
class SocketStream : public AsyncStream {
|
||||
public:
|
||||
template<typename X>
|
||||
SocketStream(X& x) : sock(x) { }
|
||||
|
||||
template<typename X, typename Y>
|
||||
SocketStream(X& x, Y& y) : sock(x, y) { }
|
||||
|
||||
~SocketStream() { dcdebug("SocketStream deleted\n"); }
|
||||
|
||||
virtual size_t available() {
|
||||
return sock.lowest_layer().available();
|
||||
}
|
||||
|
||||
virtual void setOptions(size_t bufferSize) {
|
||||
sock.lowest_layer().set_option(socket_base::receive_buffer_size(bufferSize));
|
||||
sock.lowest_layer().set_option(socket_base::send_buffer_size(bufferSize));
|
||||
}
|
||||
|
||||
virtual std::string getIp() {
|
||||
try { return sock.lowest_layer().remote_endpoint().address().to_string(); }
|
||||
catch(const system_error&) { return Util::emptyString; }
|
||||
}
|
||||
|
||||
virtual void prepareRead(const BufferPtr& buf, const Handler& handler) {
|
||||
if(buf) {
|
||||
sock.async_read_some(buffer(buf->data(), buf->size()), handler);
|
||||
} else {
|
||||
sock.async_read_some(null_buffers(), handler);
|
||||
}
|
||||
}
|
||||
|
||||
virtual size_t read(const BufferPtr& buf) {
|
||||
return sock.read_some(buffer(buf->data(), buf->size()));
|
||||
}
|
||||
|
||||
virtual void write(const BufferList& bufs, const Handler& handler) {
|
||||
if(bufs.size() == 1) {
|
||||
sock.async_write_some(buffer(bufs[0]->data(), bufs[0]->size()), handler);
|
||||
} else {
|
||||
size_t n = std::min(bufs.size(), static_cast<size_t>(64));
|
||||
std::vector<const_buffer> buffers;
|
||||
buffers.reserve(n);
|
||||
|
||||
const size_t maxBytes = 1024;
|
||||
|
||||
for(size_t i = 0, total = 0; i < n && total < maxBytes; ++i) {
|
||||
size_t left = maxBytes - total;
|
||||
size_t bytes = min(bufs[i]->size(), left);
|
||||
buffers.push_back(const_buffer(bufs[i]->data(), bytes));
|
||||
total += bytes;
|
||||
}
|
||||
|
||||
sock.async_write_some(buffers, handler);
|
||||
}
|
||||
}
|
||||
|
||||
T sock;
|
||||
};
|
||||
|
||||
class SimpleSocketStream : public SocketStream<ip::tcp::socket> {
|
||||
typedef SocketStream<ip::tcp::socket> Stream;
|
||||
|
||||
struct ShutdownHandler {
|
||||
ShutdownHandler(const Handler& h) : h(h) { }
|
||||
void operator()() { error_code ec; h(ec, 0); }
|
||||
Handler h;
|
||||
};
|
||||
|
||||
public:
|
||||
SimpleSocketStream(boost::asio::io_service& x) : Stream(x) { }
|
||||
|
||||
virtual void init(const std::function<void ()>& postInit) {
|
||||
postInit();
|
||||
}
|
||||
|
||||
virtual void shutdown(const Handler& handler) {
|
||||
sock.shutdown(ip::tcp::socket::shutdown_send);
|
||||
sock.get_io_service().post(ShutdownHandler(handler));
|
||||
}
|
||||
|
||||
virtual void close() {
|
||||
// Abortive close, just go away...
|
||||
if(sock.is_open()) {
|
||||
error_code ec;
|
||||
sock.close(ec); // Ignore errors
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
|
||||
class TLSSocketStream : public SocketStream<ssl::stream<ip::tcp::socket> > {
|
||||
typedef SocketStream<ssl::stream<ip::tcp::socket> > Stream;
|
||||
|
||||
struct ShutdownHandler {
|
||||
ShutdownHandler(const Handler& h) : h(h) { }
|
||||
void operator()(const error_code &ec) { h(ec, 0); }
|
||||
Handler h;
|
||||
};
|
||||
|
||||
public:
|
||||
TLSSocketStream(io_service& x, ssl::context& y) : Stream(x, y) { }
|
||||
|
||||
virtual void init(const std::function<void ()>& postInit) {
|
||||
sock.async_handshake(ssl::stream_base::server, std::bind(&TLSSocketStream::handleHandshake,
|
||||
this, std::placeholders::_1, postInit));
|
||||
}
|
||||
|
||||
virtual void shutdown(const Handler& handler) {
|
||||
sock.async_shutdown(ShutdownHandler(handler));
|
||||
}
|
||||
|
||||
virtual void close() {
|
||||
// Abortive close, just go away...
|
||||
if(sock.lowest_layer().is_open()) {
|
||||
error_code ec;
|
||||
sock.lowest_layer().close(ec); // Ignore errors
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void handleHandshake(const error_code& ec, const std::function<void ()>& postInit) {
|
||||
if(!ec) {
|
||||
postInit();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static string formatEndpoint(const ip::tcp::endpoint& ep) {
|
||||
return (ep.address().is_v4() ? ep.address().to_string() + ':' : '[' + ep.address().to_string() + "]:")
|
||||
+ Util::toString(ep.port());
|
||||
}
|
||||
|
||||
class SocketFactory : public enable_shared_from_this<SocketFactory>, boost::noncopyable {
|
||||
public:
|
||||
SocketFactory(SocketManager& sm, const SocketManager::IncomingHandler& handler_, const ServerInfo& info, const ip::tcp::endpoint& endpoint) :
|
||||
sm(sm),
|
||||
acceptor(sm.io),
|
||||
handler(handler_)
|
||||
{
|
||||
acceptor.open(endpoint.protocol());
|
||||
acceptor.set_option(socket_base::reuse_address(true));
|
||||
if(endpoint.protocol() == ip::tcp::v6()) {
|
||||
acceptor.set_option(ip::v6_only(true));
|
||||
}
|
||||
|
||||
acceptor.bind(endpoint);
|
||||
acceptor.listen(socket_base::max_connections);
|
||||
|
||||
LOGC(sm.getCore(), SocketManager::className,
|
||||
"Listening on " + formatEndpoint(endpoint) +
|
||||
" (Encrypted: " + (info.secure() ? "Yes)" : "No)"));
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
if(info.secure()) {
|
||||
context.reset(new ssl::context(sm.io, ssl::context::sslv23_server));
|
||||
context->set_options(ssl::context::no_sslv2 | ssl::context::no_sslv3 | ssl::context::single_dh_use);
|
||||
//context->set_password_callback(boost::bind(&server::get_password, this));
|
||||
context->use_certificate_chain_file(info.TLSParams.cert);
|
||||
context->use_private_key_file(info.TLSParams.pkey, ssl::context::pem);
|
||||
context->use_tmp_dh_file(info.TLSParams.dh);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void prepareAccept() {
|
||||
if(!sm.work.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
if(context) {
|
||||
auto s = make_shared<TLSSocketStream>(sm.io, *context);
|
||||
auto socket = make_shared<ManagedSocket>(sm, s);
|
||||
acceptor.async_accept(s->sock.lowest_layer(), std::bind(&SocketFactory::handleAccept, shared_from_this(), std::placeholders::_1, socket));
|
||||
} else {
|
||||
#endif
|
||||
auto s = make_shared<SimpleSocketStream>(sm.io);
|
||||
auto socket = make_shared<ManagedSocket>(sm, s);
|
||||
acceptor.async_accept(s->sock.lowest_layer(), std::bind(&SocketFactory::handleAccept, shared_from_this(), std::placeholders::_1, socket));
|
||||
#ifdef HAVE_OPENSSL
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void handleAccept(const error_code& ec, const ManagedSocketPtr& socket) {
|
||||
if(!ec) {
|
||||
socket->sock->setOptions(sm.getBufferSize());
|
||||
socket->setIp(socket->sock->getIp());
|
||||
}
|
||||
|
||||
completeAccept(ec, socket);
|
||||
|
||||
prepareAccept();
|
||||
}
|
||||
|
||||
void completeAccept(const error_code& ec, const ManagedSocketPtr& socket) {
|
||||
handler(socket);
|
||||
socket->completeAccept(ec);
|
||||
}
|
||||
|
||||
void close() { acceptor.close(); }
|
||||
|
||||
SocketManager &sm;
|
||||
ip::tcp::acceptor acceptor;
|
||||
SocketManager::IncomingHandler handler;
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
unique_ptr<ssl::context> context;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
int SocketManager::run() {
|
||||
LOG(SocketManager::className, "Starting");
|
||||
|
||||
work.reset(new io_service::work(io));
|
||||
|
||||
for(auto i = servers.begin(), iend = servers.end(); i != iend; ++i) {
|
||||
auto& si = *i;
|
||||
|
||||
try {
|
||||
using ip::tcp;
|
||||
tcp::resolver r(io);
|
||||
auto local = r.resolve(tcp::resolver::query(si->ip, si->port,
|
||||
tcp::resolver::query::address_configured | tcp::resolver::query::passive));
|
||||
|
||||
for(auto i = local; i != tcp::resolver::iterator(); ++i) {
|
||||
SocketFactoryPtr factory = make_shared<SocketFactory>(*this, incomingHandler, *si, *i);
|
||||
factory->prepareAccept();
|
||||
factories.push_back(factory);
|
||||
}
|
||||
} catch(const std::exception& e) {
|
||||
LOG(SocketManager::className, "Error while loading server on port " + si->port +": " + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
io.run();
|
||||
|
||||
io.reset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SocketManager::closeFactories() {
|
||||
for(auto i = factories.begin(), iend = factories.end(); i != iend; ++i) {
|
||||
(*i)->close();
|
||||
}
|
||||
factories.clear();
|
||||
}
|
||||
|
||||
void SocketManager::addJob(const Callback& callback) throw() {
|
||||
io.post(callback);
|
||||
}
|
||||
|
||||
void SocketManager::addJob(const long msec, const Callback& callback) {
|
||||
addJob(boost::posix_time::milliseconds(msec), callback);
|
||||
}
|
||||
|
||||
void SocketManager::addJob(const std::string& time, const Callback& callback) {
|
||||
addJob(boost::posix_time::duration_from_string(time), callback);
|
||||
}
|
||||
|
||||
SocketManager::Callback SocketManager::addTimedJob(const long msec, const Callback& callback) {
|
||||
return addTimedJob(boost::posix_time::milliseconds(msec), callback);
|
||||
}
|
||||
|
||||
SocketManager::Callback SocketManager::addTimedJob(const std::string& time, const Callback& callback) {
|
||||
return addTimedJob(boost::posix_time::duration_from_string(time), callback);
|
||||
}
|
||||
|
||||
void SocketManager::addJob(const deadline_timer::duration_type& duration, const Callback& callback) {
|
||||
setTimer(make_shared<timer_ptr::element_type>(io, duration), deadline_timer::duration_type(), new Callback(callback));
|
||||
}
|
||||
|
||||
SocketManager::Callback SocketManager::addTimedJob(const deadline_timer::duration_type& duration, const Callback& callback) {
|
||||
timer_ptr timer = make_shared<timer_ptr::element_type>(io, duration);
|
||||
Callback* pCallback = new Callback(callback); // create a separate callback on the heap to avoid shutdown crashes
|
||||
setTimer(timer, duration, pCallback);
|
||||
return std::bind(&SocketManager::cancelTimer, this, timer, pCallback);
|
||||
}
|
||||
|
||||
void SocketManager::setTimer(timer_ptr timer, const deadline_timer::duration_type& duration, Callback* callback) {
|
||||
timer->async_wait(std::bind(&SocketManager::handleWait, this, timer, duration, std::placeholders::_1, callback));
|
||||
}
|
||||
|
||||
void SocketManager::handleWait(timer_ptr timer, const deadline_timer::duration_type& duration, const error_code& error, Callback* callback) {
|
||||
bool run_on = duration.ticks();
|
||||
|
||||
if(!error) {
|
||||
if(run_on) {
|
||||
// re-schedule the timer
|
||||
timer->expires_at(timer->expires_at() + duration);
|
||||
setTimer(timer, duration, callback);
|
||||
}
|
||||
|
||||
addJob(*callback);
|
||||
}
|
||||
|
||||
if(!run_on) {
|
||||
// this timer was only running once, so it has no cancel function
|
||||
delete callback;
|
||||
}
|
||||
}
|
||||
|
||||
void SocketManager::cancelTimer(timer_ptr timer, Callback* callback) {
|
||||
if(timer.get()) {
|
||||
error_code ec;
|
||||
timer->cancel(ec);
|
||||
}
|
||||
|
||||
delete callback;
|
||||
}
|
||||
|
||||
void SocketManager::shutdown() {
|
||||
closeFactories();
|
||||
|
||||
work.reset();
|
||||
io.stop();
|
||||
}
|
||||
|
||||
void SocketManager::onLoad(const SimpleXML& xml) throw() {
|
||||
servers.clear();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_SOCKETMANAGER_H
|
||||
#define ADCHPP_SOCKETMANAGER_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "forward.h"
|
||||
#include "ServerInfo.h"
|
||||
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/deadline_timer.hpp>
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
struct SocketStats {
|
||||
SocketStats() : queueCalls(0), queueBytes(0), sendCalls(0), sendBytes(0), recvCalls(0), recvBytes(0) { }
|
||||
|
||||
size_t queueCalls;
|
||||
int64_t queueBytes;
|
||||
size_t sendCalls;
|
||||
int64_t sendBytes;
|
||||
int64_t recvCalls;
|
||||
int64_t recvBytes;
|
||||
};
|
||||
|
||||
class SocketManager {
|
||||
public:
|
||||
typedef std::function<void()> Callback;
|
||||
|
||||
/** execute a function asynchronously */
|
||||
ADCHPP_DLL void addJob(const Callback& callback) throw();
|
||||
/** execute a function after the specified amount of time
|
||||
* @param msec milliseconds
|
||||
*/
|
||||
ADCHPP_DLL void addJob(const long msec, const Callback& callback);
|
||||
/** execute a function after the specified amount of time
|
||||
* @param time a string that obeys to the "[-]h[h][:mm][:ss][.fff]" format
|
||||
*/
|
||||
ADCHPP_DLL void addJob(const std::string& time, const Callback& callback);
|
||||
/** execute a function at regular intervals
|
||||
* @param msec milliseconds
|
||||
* @return function one must call to cancel the timer (its callback will still be executed)
|
||||
*/
|
||||
ADCHPP_DLL Callback addTimedJob(const long msec, const Callback& callback);
|
||||
/** execute a function at regular intervals
|
||||
* @param time a string that obeys to the "[-]h[h][:mm][:ss][.fff]" format
|
||||
* @return function one must call to cancel the timer (its callback will still be executed)
|
||||
*/
|
||||
ADCHPP_DLL Callback addTimedJob(const std::string& time, const Callback& callback);
|
||||
|
||||
void shutdown();
|
||||
|
||||
void setServers(const ServerInfoList& servers_) { servers = servers_; }
|
||||
|
||||
typedef std::function<void (const ManagedSocketPtr&)> IncomingHandler;
|
||||
void setIncomingHandler(const IncomingHandler& handler) { incomingHandler = handler; }
|
||||
|
||||
int run();
|
||||
|
||||
void setBufferSize(size_t newSize) { bufferSize = newSize; }
|
||||
size_t getBufferSize() const { return bufferSize; }
|
||||
|
||||
void setMaxBufferSize(size_t newSize) { maxBufferSize = newSize; }
|
||||
size_t getMaxBufferSize() const { return maxBufferSize; }
|
||||
|
||||
void setOverflowTimeout(size_t timeout) { overflowTimeout = timeout; }
|
||||
size_t getOverflowTimeout() const { return overflowTimeout; }
|
||||
|
||||
void setDisconnectTimeout(size_t timeout) { disconnectTimeout = timeout; }
|
||||
size_t getDisconnectTimeout() const { return disconnectTimeout; }
|
||||
|
||||
SocketStats &getStats() { return stats; }
|
||||
|
||||
Core &getCore() { return core; }
|
||||
private:
|
||||
friend class Core;
|
||||
friend class ManagedSocket;
|
||||
friend class SocketFactory;
|
||||
|
||||
void closeFactories();
|
||||
|
||||
Core &core;
|
||||
|
||||
boost::asio::io_service io;
|
||||
std::unique_ptr<boost::asio::io_service::work> work;
|
||||
|
||||
SocketStats stats;
|
||||
|
||||
ServerInfoList servers;
|
||||
std::vector<SocketFactoryPtr> factories;
|
||||
|
||||
IncomingHandler incomingHandler;
|
||||
|
||||
size_t bufferSize; /// Default buffer size used for SO_RCVBUF/SO_SNDBUF
|
||||
size_t maxBufferSize; /// Max allowed write buffer size for each socket
|
||||
size_t overflowTimeout;
|
||||
size_t disconnectTimeout;
|
||||
|
||||
static const std::string className;
|
||||
|
||||
typedef shared_ptr<boost::asio::deadline_timer> timer_ptr;
|
||||
void addJob(const boost::asio::deadline_timer::duration_type& duration, const Callback& callback);
|
||||
Callback addTimedJob(const boost::asio::deadline_timer::duration_type& duration, const Callback& callback);
|
||||
void setTimer(timer_ptr timer, const boost::asio::deadline_timer::duration_type& duration, Callback* callback);
|
||||
void handleWait(timer_ptr timer, const boost::asio::deadline_timer::duration_type& duration, const boost::system::error_code& error,
|
||||
Callback* callback);
|
||||
void cancelTimer(timer_ptr timer, Callback* callback);
|
||||
|
||||
void onLoad(const SimpleXML& xml) throw();
|
||||
|
||||
SocketManager(Core &core);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // SOCKETMANAGER_H
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2014 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
|
||||
#include "Text.h"
|
||||
|
||||
#include "Util.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
int Text::utf8ToWc(const char* str, wchar_t& c) {
|
||||
const auto c0 = static_cast<uint8_t>(str[0]);
|
||||
const auto bytes = 2 + !!(c0 & 0x20) + ((c0 & 0x30) == 0x30);
|
||||
|
||||
if((c0 & 0xc0) == 0xc0) { // 11xx xxxx
|
||||
// # bytes of leading 1's; check for 0 next
|
||||
const auto check_bit = 1 << (7 - bytes);
|
||||
if (c0 & check_bit)
|
||||
return -1;
|
||||
|
||||
c = (check_bit - 1) & c0;
|
||||
|
||||
// 2-4 total, or 1-3 additional, bytes
|
||||
// Can't run off end of str so long as has sub-0x80-terminator
|
||||
for (auto i = 1; i < bytes; ++i) {
|
||||
const auto ci = static_cast<uint8_t>(str[i]);
|
||||
if ((ci & 0xc0) != 0x80)
|
||||
return -i;
|
||||
c = (c << 6) | (ci & 0x3f);
|
||||
}
|
||||
|
||||
// Invalid UTF-8 code points
|
||||
if (c > 0x10ffff || (c >= 0xd800 && c <= 0xdfff)) {
|
||||
// "REPLACEMENT CHARACTER": used to replace an incoming character
|
||||
// whose value is unknown or unrepresentable in Unicode
|
||||
c = 0xfffd;
|
||||
return -bytes;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
} else if ((c0 & 0x80) == 0) { // 0xxx xxxx
|
||||
c = static_cast<unsigned char>(str[0]);
|
||||
return 1;
|
||||
} else { // 10xx xxxx
|
||||
return -1;
|
||||
}
|
||||
dcassert(0);
|
||||
}
|
||||
|
||||
void Text::wcToUtf8(wchar_t c, string& str) {
|
||||
// https://tools.ietf.org/html/rfc3629#section-3
|
||||
if(c > 0x10ffff || (c >= 0xd800 && c <= 0xdfff)) {
|
||||
// Invalid UTF-8 code point
|
||||
// REPLACEMENT CHARACTER: http://www.fileformat.info/info/unicode/char/0fffd/index.htm
|
||||
wcToUtf8(0xfffd, str);
|
||||
} else if(c >= 0x10000) {
|
||||
str += (char)(0x80 | 0x40 | 0x20 | 0x10 | (c >> 18));
|
||||
str += (char)(0x80 | ((c >> 12) & 0x3f));
|
||||
str += (char)(0x80 | ((c >> 6) & 0x3f));
|
||||
str += (char)(0x80 | (c & 0x3f));
|
||||
} else if(c >= 0x0800) {
|
||||
str += (char)(0x80 | 0x40 | 0x20 | (c >> 12));
|
||||
str += (char)(0x80 | ((c >> 6) & 0x3f));
|
||||
str += (char)(0x80 | (c & 0x3f));
|
||||
} else if(c >= 0x0080) {
|
||||
str += (char)(0x80 | 0x40 | (c >> 6));
|
||||
str += (char)(0x80 | (c & 0x3f));
|
||||
} else {
|
||||
str += (char)c;
|
||||
}
|
||||
}
|
||||
|
||||
const string& Text::acpToUtf8(const string& str, string& tmp) throw() {
|
||||
wstring wtmp;
|
||||
return wideToUtf8(acpToWide(str, wtmp), tmp);
|
||||
}
|
||||
|
||||
const wstring& Text::acpToWide(const string& str, wstring& tmp) throw() {
|
||||
if(str.empty())
|
||||
return Util::emptyStringW;
|
||||
#ifdef _WIN32
|
||||
int n = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str.c_str(), (int)str.length(), NULL, 0);
|
||||
if(n == 0) {
|
||||
return Util::emptyStringW;
|
||||
}
|
||||
|
||||
tmp.resize(n);
|
||||
n = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str.c_str(), (int)str.length(), &tmp[0], n);
|
||||
if(n == 0) {
|
||||
return Util::emptyStringW;
|
||||
}
|
||||
return tmp;
|
||||
#else
|
||||
size_t rv;
|
||||
wchar_t wc;
|
||||
const char *src = str.c_str();
|
||||
size_t n = str.length() + 1;
|
||||
|
||||
tmp.clear();
|
||||
tmp.reserve(n);
|
||||
|
||||
while(n > 0) {
|
||||
rv = mbrtowc(&wc, src, n, NULL);
|
||||
if(rv == 0 || rv == (size_t)-2) {
|
||||
break;
|
||||
} else if(rv == (size_t)-1) {
|
||||
tmp.push_back(L'_');
|
||||
++src;
|
||||
--n;
|
||||
} else {
|
||||
tmp.push_back(wc);
|
||||
src += rv;
|
||||
n -= rv;
|
||||
}
|
||||
}
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
const string& Text::wideToUtf8(const wstring& str, string& tgt) throw() {
|
||||
if(str.empty()) {
|
||||
return Util::emptyString;
|
||||
}
|
||||
|
||||
string::size_type n = str.length();
|
||||
tgt.clear();
|
||||
for(string::size_type i = 0; i < n; ++i) {
|
||||
wcToUtf8(str[i], tgt);
|
||||
}
|
||||
return tgt;
|
||||
}
|
||||
|
||||
const string& Text::wideToAcp(const wstring& str, string& tmp) throw() {
|
||||
if(str.empty())
|
||||
return Util::emptyString;
|
||||
#ifdef _WIN32
|
||||
int n = WideCharToMultiByte(CP_ACP, 0, str.c_str(), (int)str.length(), NULL, 0, NULL, NULL);
|
||||
if(n == 0) {
|
||||
return Util::emptyString;
|
||||
}
|
||||
|
||||
tmp.resize(n);
|
||||
n = WideCharToMultiByte(CP_ACP, 0, str.c_str(), (int)str.length(), &tmp[0], n, NULL, NULL);
|
||||
if(n == 0) {
|
||||
return Util::emptyString;
|
||||
}
|
||||
return tmp;
|
||||
#else
|
||||
const wchar_t* src = str.c_str();
|
||||
int n = wcsrtombs(NULL, &src, 0, NULL);
|
||||
if(n < 1) {
|
||||
return Util::emptyString;
|
||||
}
|
||||
src = str.c_str();
|
||||
tmp.resize(n);
|
||||
n = wcsrtombs(&tmp[0], &src, n, NULL);
|
||||
if(n < 1) {
|
||||
return Util::emptyString;
|
||||
}
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Text::validateUtf8(const string& str) throw() {
|
||||
string::size_type i = 0;
|
||||
while(i < str.length()) {
|
||||
wchar_t dummy = 0;
|
||||
int j = utf8ToWc(&str[i], dummy);
|
||||
if(j < 0)
|
||||
return false;
|
||||
i += j;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const string& Text::utf8ToAcp(const string& str, string& tmp) throw() {
|
||||
wstring wtmp;
|
||||
return wideToAcp(utf8ToWide(str, wtmp), tmp);
|
||||
}
|
||||
|
||||
const wstring& Text::utf8ToWide(const string& str, wstring& tgt) throw() {
|
||||
tgt.reserve(str.length());
|
||||
string::size_type n = str.length();
|
||||
for(string::size_type i = 0; i < n; ) {
|
||||
wchar_t c = 0;
|
||||
int x = utf8ToWc(str.c_str() + i, c);
|
||||
if(x < 0) {
|
||||
tgt += '_';
|
||||
i += abs(x);
|
||||
} else {
|
||||
i += x;
|
||||
tgt += c;
|
||||
}
|
||||
}
|
||||
return tgt;
|
||||
}
|
||||
|
||||
string Text::acpToUtf8(const string& str) throw() {
|
||||
string tmp;
|
||||
return acpToUtf8(str, tmp);
|
||||
}
|
||||
|
||||
wstring Text::acpToWide(const string& str) throw() {
|
||||
wstring tmp;
|
||||
return acpToWide(str, tmp);
|
||||
}
|
||||
|
||||
string Text::utf8ToAcp(const string& str) throw() {
|
||||
string tmp;
|
||||
return utf8ToAcp(str, tmp);
|
||||
}
|
||||
|
||||
wstring Text::utf8ToWide(const string& str) throw() {
|
||||
wstring tmp;
|
||||
return utf8ToWide(str, tmp);
|
||||
}
|
||||
|
||||
string Text::wideToAcp(const wstring& str) throw() {
|
||||
string tmp;
|
||||
return wideToAcp(str, tmp);
|
||||
}
|
||||
|
||||
string Text::wideToUtf8(const wstring& str) throw() {
|
||||
string tmp;
|
||||
return wideToUtf8(str, tmp);
|
||||
}
|
||||
|
||||
} // namespace adchpp
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2015 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_TEXT_H
|
||||
#define ADCHPP_TEXT_H
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
/**
|
||||
* Text handling routines for ADCH++. ADCH++ internally uses UTF-8 for
|
||||
* (almost) all string:s, hence all foreign text must be converted
|
||||
* appropriately...
|
||||
* acp - ANSI code page used by the system
|
||||
* wide - wide unicode string
|
||||
* utf8 - UTF-8 representation of the string
|
||||
* string - UTF-8 string (most of the time)
|
||||
* wstring - Wide string
|
||||
*
|
||||
* Taken from DC++.
|
||||
*/
|
||||
class Text {
|
||||
typedef std::string string;
|
||||
typedef std::wstring wstring;
|
||||
|
||||
public:
|
||||
static const string& acpToUtf8(const string& str, string& tmp) throw();
|
||||
ADCHPP_DLL static string acpToUtf8(const string& str) throw();
|
||||
|
||||
static const wstring& acpToWide(const string& str, wstring& tmp) throw();
|
||||
ADCHPP_DLL static wstring acpToWide(const string& str) throw();
|
||||
|
||||
static const string& utf8ToAcp(const string& str, string& tmp) throw();
|
||||
ADCHPP_DLL static string utf8ToAcp(const string& str) throw();
|
||||
|
||||
static const wstring& utf8ToWide(const string& str, wstring& tmp) throw();
|
||||
ADCHPP_DLL static wstring utf8ToWide(const string& str) throw();
|
||||
|
||||
static const string& wideToAcp(const wstring& str, string& tmp) throw();
|
||||
ADCHPP_DLL static string wideToAcp(const wstring& str) throw();
|
||||
|
||||
static const string& wideToUtf8(const wstring& str, string& tmp) throw();
|
||||
ADCHPP_DLL static string wideToUtf8(const wstring& str) throw();
|
||||
|
||||
ADCHPP_DLL static bool validateUtf8(const string& str) throw();
|
||||
|
||||
private:
|
||||
static int utf8ToWc(const char* str, wchar_t& c);
|
||||
static void wcToUtf8(wchar_t c, string& str);
|
||||
};
|
||||
|
||||
} // namespace dcpp
|
||||
|
||||
#endif
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
|
||||
#include "Thread.h"
|
||||
#include "Util.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
void Thread::start() throw(ThreadException) {
|
||||
if(isRunning()) {
|
||||
throw ThreadException(_T("Already running"));
|
||||
}
|
||||
|
||||
DWORD threadId = 0;
|
||||
if( (threadHandle = ::CreateThread(NULL, 0, &starter, this, 0, &threadId)) == NULL) {
|
||||
throw ThreadException(Util::translateError(::GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
void Thread::join() throw() {
|
||||
if(!isRunning()) {
|
||||
return;
|
||||
}
|
||||
|
||||
::WaitForSingleObject(threadHandle, INFINITE);
|
||||
::CloseHandle(threadHandle);
|
||||
threadHandle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
void Thread::start() throw(ThreadException) {
|
||||
if(isRunning()) {
|
||||
throw ThreadException(_T("Already running"));
|
||||
}
|
||||
|
||||
// Not all implementations may create threads as joinable by default.
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
||||
int result = pthread_create(&t, &attr, &starter, this);
|
||||
if(result != 0) {
|
||||
throw ThreadException(Util::translateError(result));
|
||||
}
|
||||
pthread_attr_destroy(&attr);
|
||||
}
|
||||
|
||||
void Thread::join() throw() {
|
||||
if(t == 0)
|
||||
return;
|
||||
|
||||
void* x;
|
||||
pthread_join(t, &x);
|
||||
t = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_THREAD_H
|
||||
#define ADCHPP_THREAD_H
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <pthread.h>
|
||||
# include <sched.h>
|
||||
# include <sys/resource.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "Exception.h"
|
||||
#include "nullptr.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
STANDARD_EXCEPTION(ThreadException);
|
||||
|
||||
class Thread : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
ADCHPP_DLL void start() throw(ThreadException);
|
||||
ADCHPP_DLL void join() throw();
|
||||
|
||||
#ifdef _WIN32
|
||||
enum Priority {
|
||||
LOW = THREAD_PRIORITY_BELOW_NORMAL,
|
||||
NORMAL = THREAD_PRIORITY_NORMAL,
|
||||
HIGH = THREAD_PRIORITY_ABOVE_NORMAL
|
||||
};
|
||||
|
||||
Thread() throw() : threadHandle(INVALID_HANDLE_VALUE) { }
|
||||
virtual ~Thread() {
|
||||
if(threadHandle != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(threadHandle);
|
||||
}
|
||||
|
||||
void setThreadPriority(Priority p) throw() { ::SetThreadPriority(threadHandle, p); }
|
||||
|
||||
bool isRunning() throw() { return (threadHandle != INVALID_HANDLE_VALUE); }
|
||||
|
||||
static void sleep(uint32_t millis) { ::Sleep(millis); }
|
||||
static void yield() { ::Sleep(1); }
|
||||
|
||||
#elif defined(HAVE_PTHREAD)
|
||||
|
||||
enum Priority {
|
||||
LOW = 1,
|
||||
NORMAL = 0,
|
||||
HIGH = -1
|
||||
};
|
||||
Thread() throw() : t(0) { }
|
||||
virtual ~Thread() {
|
||||
if(t != 0) {
|
||||
pthread_detach(t);
|
||||
}
|
||||
}
|
||||
|
||||
void setThreadPriority(Priority p) { setpriority(PRIO_PROCESS, 0, p); }
|
||||
bool isRunning() { return (t != 0); }
|
||||
|
||||
static void sleep(uint32_t millis) { ::usleep(millis*1000); }
|
||||
static void yield() { ::sched_yield(); }
|
||||
|
||||
#else
|
||||
#error No threading support found
|
||||
#endif
|
||||
|
||||
protected:
|
||||
virtual int run() = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
HANDLE threadHandle;
|
||||
static DWORD WINAPI starter(void* p) {
|
||||
return static_cast<DWORD>(reinterpret_cast<Thread*>(p)->run());
|
||||
}
|
||||
#else
|
||||
pthread_t t;
|
||||
static void* starter(void* p) {
|
||||
// ignore the return value.
|
||||
reinterpret_cast<Thread*>(p)->run();
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // THREAD_H
|
|
@ -0,0 +1,687 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
|
||||
#include "TigerHash.h"
|
||||
#include "common.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define PASSES 3
|
||||
|
||||
#define t1 (table)
|
||||
#define t2 (table+256)
|
||||
#define t3 (table+256*2)
|
||||
#define t4 (table+256*3)
|
||||
|
||||
#define save_abc \
|
||||
aa = a; \
|
||||
bb = b; \
|
||||
cc = c;
|
||||
|
||||
#define round(a,b,c,x,mul) \
|
||||
c ^= x; \
|
||||
a -= t1[(uint8_t)(c)] ^ \
|
||||
t2[(uint8_t)(((uint32_t)(c))>>(2*8))] ^ \
|
||||
t3[(uint8_t)((c)>>(4*8))] ^ \
|
||||
t4[(uint8_t)(((uint32_t)((c)>>(4*8)))>>(2*8))] ; \
|
||||
b += t4[(uint8_t)(((uint32_t)(c))>>(1*8))] ^ \
|
||||
t3[(uint8_t)(((uint32_t)(c))>>(3*8))] ^ \
|
||||
t2[(uint8_t)(((uint32_t)((c)>>(4*8)))>>(1*8))] ^ \
|
||||
t1[(uint8_t)(((uint32_t)((c)>>(4*8)))>>(3*8))]; \
|
||||
b *= mul;
|
||||
|
||||
#define pass(a,b,c,mul) \
|
||||
round(a,b,c,x0,mul) \
|
||||
round(b,c,a,x1,mul) \
|
||||
round(c,a,b,x2,mul) \
|
||||
round(a,b,c,x3,mul) \
|
||||
round(b,c,a,x4,mul) \
|
||||
round(c,a,b,x5,mul) \
|
||||
round(a,b,c,x6,mul) \
|
||||
round(b,c,a,x7,mul)
|
||||
|
||||
#define key_schedule \
|
||||
x0 -= x7 ^ _ULL(0xA5A5A5A5A5A5A5A5); \
|
||||
x1 ^= x0; \
|
||||
x2 += x1; \
|
||||
x3 -= x2 ^ ((~x1)<<19); \
|
||||
x4 ^= x3; \
|
||||
x5 += x4; \
|
||||
x6 -= x5 ^ ((~x4)>>23); \
|
||||
x7 ^= x6; \
|
||||
x0 += x7; \
|
||||
x1 -= x0 ^ ((~x7)<<19); \
|
||||
x2 ^= x1; \
|
||||
x3 += x2; \
|
||||
x4 -= x3 ^ ((~x2)>>23); \
|
||||
x5 ^= x4; \
|
||||
x6 += x5; \
|
||||
x7 -= x6 ^ _ULL(0x0123456789ABCDEF);
|
||||
|
||||
#define feedforward \
|
||||
a ^= aa; \
|
||||
b -= bb; \
|
||||
c += cc;
|
||||
|
||||
#define compress \
|
||||
save_abc \
|
||||
for(pass_no=0; pass_no<PASSES; pass_no++) { \
|
||||
if(pass_no != 0) {key_schedule} \
|
||||
pass(a,b,c,(pass_no==0?5:pass_no==1?7:9)); \
|
||||
tmpa=a; a=c; c=b; b=tmpa;} \
|
||||
feedforward
|
||||
|
||||
#define tiger_compress_macro(str, state) \
|
||||
{ \
|
||||
register uint64_t a, b, c, tmpa; \
|
||||
uint64_t aa, bb, cc; \
|
||||
register uint64_t x0, x1, x2, x3, x4, x5, x6, x7; \
|
||||
int pass_no; \
|
||||
\
|
||||
a = state[0]; \
|
||||
b = state[1]; \
|
||||
c = state[2]; \
|
||||
\
|
||||
x0=str[0]; x1=str[1]; x2=str[2]; x3=str[3]; \
|
||||
x4=str[4]; x5=str[5]; x6=str[6]; x7=str[7]; \
|
||||
\
|
||||
compress; \
|
||||
\
|
||||
state[0] = a; \
|
||||
state[1] = b; \
|
||||
state[2] = c; \
|
||||
}
|
||||
|
||||
/* The compress function is a function. Requires smaller cache? */
|
||||
void TigerHash::tigerCompress(const uint64_t *str, uint64_t state[3]) {
|
||||
tiger_compress_macro(((const uint64_t*)str), ((uint64_t*)state));
|
||||
}
|
||||
|
||||
void TigerHash::update(const void* data, size_t length) {
|
||||
size_t tmppos = (uint32_t)(pos & (BLOCK_SIZE-1));
|
||||
const uint8_t* str = (const uint8_t*)data;
|
||||
// First empty tmp buffer if possible
|
||||
if(tmppos > 0) {
|
||||
size_t n = min(length, BLOCK_SIZE-tmppos);
|
||||
memcpy(tmp + tmppos, str, n);
|
||||
str += n;
|
||||
pos += n;
|
||||
length -= n;
|
||||
|
||||
if((tmppos + n) == BLOCK_SIZE) {
|
||||
tigerCompress((uint64_t*)tmp, res);
|
||||
tmppos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// So, now either tmp is empty or all data has been consumed...
|
||||
dcassert(length == 0 || tmppos == 0);
|
||||
|
||||
// Process the bulk of data
|
||||
while(length>=BLOCK_SIZE) {
|
||||
tigerCompress((uint64_t*)str, res);
|
||||
str += BLOCK_SIZE;
|
||||
pos += BLOCK_SIZE;
|
||||
length -= BLOCK_SIZE;
|
||||
}
|
||||
|
||||
// Copy the rest to the tmp buffer
|
||||
memcpy(tmp, str, length);
|
||||
pos += length;
|
||||
}
|
||||
|
||||
uint8_t* TigerHash::finalize() {
|
||||
size_t tmppos = (size_t)(pos & (BLOCK_SIZE-1));
|
||||
// Tmp buffer always has at least one pos, otherwise it would have
|
||||
// been processed in update()
|
||||
|
||||
tmp[tmppos++] = 0x01;
|
||||
|
||||
if(tmppos > (BLOCK_SIZE - sizeof(uint64_t))) {
|
||||
memset(tmp + tmppos, 0, BLOCK_SIZE - tmppos);
|
||||
tigerCompress(((uint64_t*)tmp), res);
|
||||
memset(tmp, 0, BLOCK_SIZE);
|
||||
} else {
|
||||
memset(tmp + tmppos, 0, BLOCK_SIZE - tmppos - sizeof(uint64_t));
|
||||
}
|
||||
|
||||
((uint64_t*)(&(tmp[56])))[0] = pos<<3;
|
||||
tigerCompress((uint64_t*)tmp, res);
|
||||
return getResult();
|
||||
}
|
||||
|
||||
uint64_t TigerHash::table[4*256] = {
|
||||
_ULL(0x02AAB17CF7E90C5E) /* 0 */, _ULL(0xAC424B03E243A8EC) /* 1 */,
|
||||
_ULL(0x72CD5BE30DD5FCD3) /* 2 */, _ULL(0x6D019B93F6F97F3A) /* 3 */,
|
||||
_ULL(0xCD9978FFD21F9193) /* 4 */, _ULL(0x7573A1C9708029E2) /* 5 */,
|
||||
_ULL(0xB164326B922A83C3) /* 6 */, _ULL(0x46883EEE04915870) /* 7 */,
|
||||
_ULL(0xEAACE3057103ECE6) /* 8 */, _ULL(0xC54169B808A3535C) /* 9 */,
|
||||
_ULL(0x4CE754918DDEC47C) /* 10 */, _ULL(0x0AA2F4DFDC0DF40C) /* 11 */,
|
||||
_ULL(0x10B76F18A74DBEFA) /* 12 */, _ULL(0xC6CCB6235AD1AB6A) /* 13 */,
|
||||
_ULL(0x13726121572FE2FF) /* 14 */, _ULL(0x1A488C6F199D921E) /* 15 */,
|
||||
_ULL(0x4BC9F9F4DA0007CA) /* 16 */, _ULL(0x26F5E6F6E85241C7) /* 17 */,
|
||||
_ULL(0x859079DBEA5947B6) /* 18 */, _ULL(0x4F1885C5C99E8C92) /* 19 */,
|
||||
_ULL(0xD78E761EA96F864B) /* 20 */, _ULL(0x8E36428C52B5C17D) /* 21 */,
|
||||
_ULL(0x69CF6827373063C1) /* 22 */, _ULL(0xB607C93D9BB4C56E) /* 23 */,
|
||||
_ULL(0x7D820E760E76B5EA) /* 24 */, _ULL(0x645C9CC6F07FDC42) /* 25 */,
|
||||
_ULL(0xBF38A078243342E0) /* 26 */, _ULL(0x5F6B343C9D2E7D04) /* 27 */,
|
||||
_ULL(0xF2C28AEB600B0EC6) /* 28 */, _ULL(0x6C0ED85F7254BCAC) /* 29 */,
|
||||
_ULL(0x71592281A4DB4FE5) /* 30 */, _ULL(0x1967FA69CE0FED9F) /* 31 */,
|
||||
_ULL(0xFD5293F8B96545DB) /* 32 */, _ULL(0xC879E9D7F2A7600B) /* 33 */,
|
||||
_ULL(0x860248920193194E) /* 34 */, _ULL(0xA4F9533B2D9CC0B3) /* 35 */,
|
||||
_ULL(0x9053836C15957613) /* 36 */, _ULL(0xDB6DCF8AFC357BF1) /* 37 */,
|
||||
_ULL(0x18BEEA7A7A370F57) /* 38 */, _ULL(0x037117CA50B99066) /* 39 */,
|
||||
_ULL(0x6AB30A9774424A35) /* 40 */, _ULL(0xF4E92F02E325249B) /* 41 */,
|
||||
_ULL(0x7739DB07061CCAE1) /* 42 */, _ULL(0xD8F3B49CECA42A05) /* 43 */,
|
||||
_ULL(0xBD56BE3F51382F73) /* 44 */, _ULL(0x45FAED5843B0BB28) /* 45 */,
|
||||
_ULL(0x1C813D5C11BF1F83) /* 46 */, _ULL(0x8AF0E4B6D75FA169) /* 47 */,
|
||||
_ULL(0x33EE18A487AD9999) /* 48 */, _ULL(0x3C26E8EAB1C94410) /* 49 */,
|
||||
_ULL(0xB510102BC0A822F9) /* 50 */, _ULL(0x141EEF310CE6123B) /* 51 */,
|
||||
_ULL(0xFC65B90059DDB154) /* 52 */, _ULL(0xE0158640C5E0E607) /* 53 */,
|
||||
_ULL(0x884E079826C3A3CF) /* 54 */, _ULL(0x930D0D9523C535FD) /* 55 */,
|
||||
_ULL(0x35638D754E9A2B00) /* 56 */, _ULL(0x4085FCCF40469DD5) /* 57 */,
|
||||
_ULL(0xC4B17AD28BE23A4C) /* 58 */, _ULL(0xCAB2F0FC6A3E6A2E) /* 59 */,
|
||||
_ULL(0x2860971A6B943FCD) /* 60 */, _ULL(0x3DDE6EE212E30446) /* 61 */,
|
||||
_ULL(0x6222F32AE01765AE) /* 62 */, _ULL(0x5D550BB5478308FE) /* 63 */,
|
||||
_ULL(0xA9EFA98DA0EDA22A) /* 64 */, _ULL(0xC351A71686C40DA7) /* 65 */,
|
||||
_ULL(0x1105586D9C867C84) /* 66 */, _ULL(0xDCFFEE85FDA22853) /* 67 */,
|
||||
_ULL(0xCCFBD0262C5EEF76) /* 68 */, _ULL(0xBAF294CB8990D201) /* 69 */,
|
||||
_ULL(0xE69464F52AFAD975) /* 70 */, _ULL(0x94B013AFDF133E14) /* 71 */,
|
||||
_ULL(0x06A7D1A32823C958) /* 72 */, _ULL(0x6F95FE5130F61119) /* 73 */,
|
||||
_ULL(0xD92AB34E462C06C0) /* 74 */, _ULL(0xED7BDE33887C71D2) /* 75 */,
|
||||
_ULL(0x79746D6E6518393E) /* 76 */, _ULL(0x5BA419385D713329) /* 77 */,
|
||||
_ULL(0x7C1BA6B948A97564) /* 78 */, _ULL(0x31987C197BFDAC67) /* 79 */,
|
||||
_ULL(0xDE6C23C44B053D02) /* 80 */, _ULL(0x581C49FED002D64D) /* 81 */,
|
||||
_ULL(0xDD474D6338261571) /* 82 */, _ULL(0xAA4546C3E473D062) /* 83 */,
|
||||
_ULL(0x928FCE349455F860) /* 84 */, _ULL(0x48161BBACAAB94D9) /* 85 */,
|
||||
_ULL(0x63912430770E6F68) /* 86 */, _ULL(0x6EC8A5E602C6641C) /* 87 */,
|
||||
_ULL(0x87282515337DDD2B) /* 88 */, _ULL(0x2CDA6B42034B701B) /* 89 */,
|
||||
_ULL(0xB03D37C181CB096D) /* 90 */, _ULL(0xE108438266C71C6F) /* 91 */,
|
||||
_ULL(0x2B3180C7EB51B255) /* 92 */, _ULL(0xDF92B82F96C08BBC) /* 93 */,
|
||||
_ULL(0x5C68C8C0A632F3BA) /* 94 */, _ULL(0x5504CC861C3D0556) /* 95 */,
|
||||
_ULL(0xABBFA4E55FB26B8F) /* 96 */, _ULL(0x41848B0AB3BACEB4) /* 97 */,
|
||||
_ULL(0xB334A273AA445D32) /* 98 */, _ULL(0xBCA696F0A85AD881) /* 99 */,
|
||||
_ULL(0x24F6EC65B528D56C) /* 100 */, _ULL(0x0CE1512E90F4524A) /* 101 */,
|
||||
_ULL(0x4E9DD79D5506D35A) /* 102 */, _ULL(0x258905FAC6CE9779) /* 103 */,
|
||||
_ULL(0x2019295B3E109B33) /* 104 */, _ULL(0xF8A9478B73A054CC) /* 105 */,
|
||||
_ULL(0x2924F2F934417EB0) /* 106 */, _ULL(0x3993357D536D1BC4) /* 107 */,
|
||||
_ULL(0x38A81AC21DB6FF8B) /* 108 */, _ULL(0x47C4FBF17D6016BF) /* 109 */,
|
||||
_ULL(0x1E0FAADD7667E3F5) /* 110 */, _ULL(0x7ABCFF62938BEB96) /* 111 */,
|
||||
_ULL(0xA78DAD948FC179C9) /* 112 */, _ULL(0x8F1F98B72911E50D) /* 113 */,
|
||||
_ULL(0x61E48EAE27121A91) /* 114 */, _ULL(0x4D62F7AD31859808) /* 115 */,
|
||||
_ULL(0xECEBA345EF5CEAEB) /* 116 */, _ULL(0xF5CEB25EBC9684CE) /* 117 */,
|
||||
_ULL(0xF633E20CB7F76221) /* 118 */, _ULL(0xA32CDF06AB8293E4) /* 119 */,
|
||||
_ULL(0x985A202CA5EE2CA4) /* 120 */, _ULL(0xCF0B8447CC8A8FB1) /* 121 */,
|
||||
_ULL(0x9F765244979859A3) /* 122 */, _ULL(0xA8D516B1A1240017) /* 123 */,
|
||||
_ULL(0x0BD7BA3EBB5DC726) /* 124 */, _ULL(0xE54BCA55B86ADB39) /* 125 */,
|
||||
_ULL(0x1D7A3AFD6C478063) /* 126 */, _ULL(0x519EC608E7669EDD) /* 127 */,
|
||||
_ULL(0x0E5715A2D149AA23) /* 128 */, _ULL(0x177D4571848FF194) /* 129 */,
|
||||
_ULL(0xEEB55F3241014C22) /* 130 */, _ULL(0x0F5E5CA13A6E2EC2) /* 131 */,
|
||||
_ULL(0x8029927B75F5C361) /* 132 */, _ULL(0xAD139FABC3D6E436) /* 133 */,
|
||||
_ULL(0x0D5DF1A94CCF402F) /* 134 */, _ULL(0x3E8BD948BEA5DFC8) /* 135 */,
|
||||
_ULL(0xA5A0D357BD3FF77E) /* 136 */, _ULL(0xA2D12E251F74F645) /* 137 */,
|
||||
_ULL(0x66FD9E525E81A082) /* 138 */, _ULL(0x2E0C90CE7F687A49) /* 139 */,
|
||||
_ULL(0xC2E8BCBEBA973BC5) /* 140 */, _ULL(0x000001BCE509745F) /* 141 */,
|
||||
_ULL(0x423777BBE6DAB3D6) /* 142 */, _ULL(0xD1661C7EAEF06EB5) /* 143 */,
|
||||
_ULL(0xA1781F354DAACFD8) /* 144 */, _ULL(0x2D11284A2B16AFFC) /* 145 */,
|
||||
_ULL(0xF1FC4F67FA891D1F) /* 146 */, _ULL(0x73ECC25DCB920ADA) /* 147 */,
|
||||
_ULL(0xAE610C22C2A12651) /* 148 */, _ULL(0x96E0A810D356B78A) /* 149 */,
|
||||
_ULL(0x5A9A381F2FE7870F) /* 150 */, _ULL(0xD5AD62EDE94E5530) /* 151 */,
|
||||
_ULL(0xD225E5E8368D1427) /* 152 */, _ULL(0x65977B70C7AF4631) /* 153 */,
|
||||
_ULL(0x99F889B2DE39D74F) /* 154 */, _ULL(0x233F30BF54E1D143) /* 155 */,
|
||||
_ULL(0x9A9675D3D9A63C97) /* 156 */, _ULL(0x5470554FF334F9A8) /* 157 */,
|
||||
_ULL(0x166ACB744A4F5688) /* 158 */, _ULL(0x70C74CAAB2E4AEAD) /* 159 */,
|
||||
_ULL(0xF0D091646F294D12) /* 160 */, _ULL(0x57B82A89684031D1) /* 161 */,
|
||||
_ULL(0xEFD95A5A61BE0B6B) /* 162 */, _ULL(0x2FBD12E969F2F29A) /* 163 */,
|
||||
_ULL(0x9BD37013FEFF9FE8) /* 164 */, _ULL(0x3F9B0404D6085A06) /* 165 */,
|
||||
_ULL(0x4940C1F3166CFE15) /* 166 */, _ULL(0x09542C4DCDF3DEFB) /* 167 */,
|
||||
_ULL(0xB4C5218385CD5CE3) /* 168 */, _ULL(0xC935B7DC4462A641) /* 169 */,
|
||||
_ULL(0x3417F8A68ED3B63F) /* 170 */, _ULL(0xB80959295B215B40) /* 171 */,
|
||||
_ULL(0xF99CDAEF3B8C8572) /* 172 */, _ULL(0x018C0614F8FCB95D) /* 173 */,
|
||||
_ULL(0x1B14ACCD1A3ACDF3) /* 174 */, _ULL(0x84D471F200BB732D) /* 175 */,
|
||||
_ULL(0xC1A3110E95E8DA16) /* 176 */, _ULL(0x430A7220BF1A82B8) /* 177 */,
|
||||
_ULL(0xB77E090D39DF210E) /* 178 */, _ULL(0x5EF4BD9F3CD05E9D) /* 179 */,
|
||||
_ULL(0x9D4FF6DA7E57A444) /* 180 */, _ULL(0xDA1D60E183D4A5F8) /* 181 */,
|
||||
_ULL(0xB287C38417998E47) /* 182 */, _ULL(0xFE3EDC121BB31886) /* 183 */,
|
||||
_ULL(0xC7FE3CCC980CCBEF) /* 184 */, _ULL(0xE46FB590189BFD03) /* 185 */,
|
||||
_ULL(0x3732FD469A4C57DC) /* 186 */, _ULL(0x7EF700A07CF1AD65) /* 187 */,
|
||||
_ULL(0x59C64468A31D8859) /* 188 */, _ULL(0x762FB0B4D45B61F6) /* 189 */,
|
||||
_ULL(0x155BAED099047718) /* 190 */, _ULL(0x68755E4C3D50BAA6) /* 191 */,
|
||||
_ULL(0xE9214E7F22D8B4DF) /* 192 */, _ULL(0x2ADDBF532EAC95F4) /* 193 */,
|
||||
_ULL(0x32AE3909B4BD0109) /* 194 */, _ULL(0x834DF537B08E3450) /* 195 */,
|
||||
_ULL(0xFA209DA84220728D) /* 196 */, _ULL(0x9E691D9B9EFE23F7) /* 197 */,
|
||||
_ULL(0x0446D288C4AE8D7F) /* 198 */, _ULL(0x7B4CC524E169785B) /* 199 */,
|
||||
_ULL(0x21D87F0135CA1385) /* 200 */, _ULL(0xCEBB400F137B8AA5) /* 201 */,
|
||||
_ULL(0x272E2B66580796BE) /* 202 */, _ULL(0x3612264125C2B0DE) /* 203 */,
|
||||
_ULL(0x057702BDAD1EFBB2) /* 204 */, _ULL(0xD4BABB8EACF84BE9) /* 205 */,
|
||||
_ULL(0x91583139641BC67B) /* 206 */, _ULL(0x8BDC2DE08036E024) /* 207 */,
|
||||
_ULL(0x603C8156F49F68ED) /* 208 */, _ULL(0xF7D236F7DBEF5111) /* 209 */,
|
||||
_ULL(0x9727C4598AD21E80) /* 210 */, _ULL(0xA08A0896670A5FD7) /* 211 */,
|
||||
_ULL(0xCB4A8F4309EBA9CB) /* 212 */, _ULL(0x81AF564B0F7036A1) /* 213 */,
|
||||
_ULL(0xC0B99AA778199ABD) /* 214 */, _ULL(0x959F1EC83FC8E952) /* 215 */,
|
||||
_ULL(0x8C505077794A81B9) /* 216 */, _ULL(0x3ACAAF8F056338F0) /* 217 */,
|
||||
_ULL(0x07B43F50627A6778) /* 218 */, _ULL(0x4A44AB49F5ECCC77) /* 219 */,
|
||||
_ULL(0x3BC3D6E4B679EE98) /* 220 */, _ULL(0x9CC0D4D1CF14108C) /* 221 */,
|
||||
_ULL(0x4406C00B206BC8A0) /* 222 */, _ULL(0x82A18854C8D72D89) /* 223 */,
|
||||
_ULL(0x67E366B35C3C432C) /* 224 */, _ULL(0xB923DD61102B37F2) /* 225 */,
|
||||
_ULL(0x56AB2779D884271D) /* 226 */, _ULL(0xBE83E1B0FF1525AF) /* 227 */,
|
||||
_ULL(0xFB7C65D4217E49A9) /* 228 */, _ULL(0x6BDBE0E76D48E7D4) /* 229 */,
|
||||
_ULL(0x08DF828745D9179E) /* 230 */, _ULL(0x22EA6A9ADD53BD34) /* 231 */,
|
||||
_ULL(0xE36E141C5622200A) /* 232 */, _ULL(0x7F805D1B8CB750EE) /* 233 */,
|
||||
_ULL(0xAFE5C7A59F58E837) /* 234 */, _ULL(0xE27F996A4FB1C23C) /* 235 */,
|
||||
_ULL(0xD3867DFB0775F0D0) /* 236 */, _ULL(0xD0E673DE6E88891A) /* 237 */,
|
||||
_ULL(0x123AEB9EAFB86C25) /* 238 */, _ULL(0x30F1D5D5C145B895) /* 239 */,
|
||||
_ULL(0xBB434A2DEE7269E7) /* 240 */, _ULL(0x78CB67ECF931FA38) /* 241 */,
|
||||
_ULL(0xF33B0372323BBF9C) /* 242 */, _ULL(0x52D66336FB279C74) /* 243 */,
|
||||
_ULL(0x505F33AC0AFB4EAA) /* 244 */, _ULL(0xE8A5CD99A2CCE187) /* 245 */,
|
||||
_ULL(0x534974801E2D30BB) /* 246 */, _ULL(0x8D2D5711D5876D90) /* 247 */,
|
||||
_ULL(0x1F1A412891BC038E) /* 248 */, _ULL(0xD6E2E71D82E56648) /* 249 */,
|
||||
_ULL(0x74036C3A497732B7) /* 250 */, _ULL(0x89B67ED96361F5AB) /* 251 */,
|
||||
_ULL(0xFFED95D8F1EA02A2) /* 252 */, _ULL(0xE72B3BD61464D43D) /* 253 */,
|
||||
_ULL(0xA6300F170BDC4820) /* 254 */, _ULL(0xEBC18760ED78A77A) /* 255 */,
|
||||
_ULL(0xE6A6BE5A05A12138) /* 256 */, _ULL(0xB5A122A5B4F87C98) /* 257 */,
|
||||
_ULL(0x563C6089140B6990) /* 258 */, _ULL(0x4C46CB2E391F5DD5) /* 259 */,
|
||||
_ULL(0xD932ADDBC9B79434) /* 260 */, _ULL(0x08EA70E42015AFF5) /* 261 */,
|
||||
_ULL(0xD765A6673E478CF1) /* 262 */, _ULL(0xC4FB757EAB278D99) /* 263 */,
|
||||
_ULL(0xDF11C6862D6E0692) /* 264 */, _ULL(0xDDEB84F10D7F3B16) /* 265 */,
|
||||
_ULL(0x6F2EF604A665EA04) /* 266 */, _ULL(0x4A8E0F0FF0E0DFB3) /* 267 */,
|
||||
_ULL(0xA5EDEEF83DBCBA51) /* 268 */, _ULL(0xFC4F0A2A0EA4371E) /* 269 */,
|
||||
_ULL(0xE83E1DA85CB38429) /* 270 */, _ULL(0xDC8FF882BA1B1CE2) /* 271 */,
|
||||
_ULL(0xCD45505E8353E80D) /* 272 */, _ULL(0x18D19A00D4DB0717) /* 273 */,
|
||||
_ULL(0x34A0CFEDA5F38101) /* 274 */, _ULL(0x0BE77E518887CAF2) /* 275 */,
|
||||
_ULL(0x1E341438B3C45136) /* 276 */, _ULL(0xE05797F49089CCF9) /* 277 */,
|
||||
_ULL(0xFFD23F9DF2591D14) /* 278 */, _ULL(0x543DDA228595C5CD) /* 279 */,
|
||||
_ULL(0x661F81FD99052A33) /* 280 */, _ULL(0x8736E641DB0F7B76) /* 281 */,
|
||||
_ULL(0x15227725418E5307) /* 282 */, _ULL(0xE25F7F46162EB2FA) /* 283 */,
|
||||
_ULL(0x48A8B2126C13D9FE) /* 284 */, _ULL(0xAFDC541792E76EEA) /* 285 */,
|
||||
_ULL(0x03D912BFC6D1898F) /* 286 */, _ULL(0x31B1AAFA1B83F51B) /* 287 */,
|
||||
_ULL(0xF1AC2796E42AB7D9) /* 288 */, _ULL(0x40A3A7D7FCD2EBAC) /* 289 */,
|
||||
_ULL(0x1056136D0AFBBCC5) /* 290 */, _ULL(0x7889E1DD9A6D0C85) /* 291 */,
|
||||
_ULL(0xD33525782A7974AA) /* 292 */, _ULL(0xA7E25D09078AC09B) /* 293 */,
|
||||
_ULL(0xBD4138B3EAC6EDD0) /* 294 */, _ULL(0x920ABFBE71EB9E70) /* 295 */,
|
||||
_ULL(0xA2A5D0F54FC2625C) /* 296 */, _ULL(0xC054E36B0B1290A3) /* 297 */,
|
||||
_ULL(0xF6DD59FF62FE932B) /* 298 */, _ULL(0x3537354511A8AC7D) /* 299 */,
|
||||
_ULL(0xCA845E9172FADCD4) /* 300 */, _ULL(0x84F82B60329D20DC) /* 301 */,
|
||||
_ULL(0x79C62CE1CD672F18) /* 302 */, _ULL(0x8B09A2ADD124642C) /* 303 */,
|
||||
_ULL(0xD0C1E96A19D9E726) /* 304 */, _ULL(0x5A786A9B4BA9500C) /* 305 */,
|
||||
_ULL(0x0E020336634C43F3) /* 306 */, _ULL(0xC17B474AEB66D822) /* 307 */,
|
||||
_ULL(0x6A731AE3EC9BAAC2) /* 308 */, _ULL(0x8226667AE0840258) /* 309 */,
|
||||
_ULL(0x67D4567691CAECA5) /* 310 */, _ULL(0x1D94155C4875ADB5) /* 311 */,
|
||||
_ULL(0x6D00FD985B813FDF) /* 312 */, _ULL(0x51286EFCB774CD06) /* 313 */,
|
||||
_ULL(0x5E8834471FA744AF) /* 314 */, _ULL(0xF72CA0AEE761AE2E) /* 315 */,
|
||||
_ULL(0xBE40E4CDAEE8E09A) /* 316 */, _ULL(0xE9970BBB5118F665) /* 317 */,
|
||||
_ULL(0x726E4BEB33DF1964) /* 318 */, _ULL(0x703B000729199762) /* 319 */,
|
||||
_ULL(0x4631D816F5EF30A7) /* 320 */, _ULL(0xB880B5B51504A6BE) /* 321 */,
|
||||
_ULL(0x641793C37ED84B6C) /* 322 */, _ULL(0x7B21ED77F6E97D96) /* 323 */,
|
||||
_ULL(0x776306312EF96B73) /* 324 */, _ULL(0xAE528948E86FF3F4) /* 325 */,
|
||||
_ULL(0x53DBD7F286A3F8F8) /* 326 */, _ULL(0x16CADCE74CFC1063) /* 327 */,
|
||||
_ULL(0x005C19BDFA52C6DD) /* 328 */, _ULL(0x68868F5D64D46AD3) /* 329 */,
|
||||
_ULL(0x3A9D512CCF1E186A) /* 330 */, _ULL(0x367E62C2385660AE) /* 331 */,
|
||||
_ULL(0xE359E7EA77DCB1D7) /* 332 */, _ULL(0x526C0773749ABE6E) /* 333 */,
|
||||
_ULL(0x735AE5F9D09F734B) /* 334 */, _ULL(0x493FC7CC8A558BA8) /* 335 */,
|
||||
_ULL(0xB0B9C1533041AB45) /* 336 */, _ULL(0x321958BA470A59BD) /* 337 */,
|
||||
_ULL(0x852DB00B5F46C393) /* 338 */, _ULL(0x91209B2BD336B0E5) /* 339 */,
|
||||
_ULL(0x6E604F7D659EF19F) /* 340 */, _ULL(0xB99A8AE2782CCB24) /* 341 */,
|
||||
_ULL(0xCCF52AB6C814C4C7) /* 342 */, _ULL(0x4727D9AFBE11727B) /* 343 */,
|
||||
_ULL(0x7E950D0C0121B34D) /* 344 */, _ULL(0x756F435670AD471F) /* 345 */,
|
||||
_ULL(0xF5ADD442615A6849) /* 346 */, _ULL(0x4E87E09980B9957A) /* 347 */,
|
||||
_ULL(0x2ACFA1DF50AEE355) /* 348 */, _ULL(0xD898263AFD2FD556) /* 349 */,
|
||||
_ULL(0xC8F4924DD80C8FD6) /* 350 */, _ULL(0xCF99CA3D754A173A) /* 351 */,
|
||||
_ULL(0xFE477BACAF91BF3C) /* 352 */, _ULL(0xED5371F6D690C12D) /* 353 */,
|
||||
_ULL(0x831A5C285E687094) /* 354 */, _ULL(0xC5D3C90A3708A0A4) /* 355 */,
|
||||
_ULL(0x0F7F903717D06580) /* 356 */, _ULL(0x19F9BB13B8FDF27F) /* 357 */,
|
||||
_ULL(0xB1BD6F1B4D502843) /* 358 */, _ULL(0x1C761BA38FFF4012) /* 359 */,
|
||||
_ULL(0x0D1530C4E2E21F3B) /* 360 */, _ULL(0x8943CE69A7372C8A) /* 361 */,
|
||||
_ULL(0xE5184E11FEB5CE66) /* 362 */, _ULL(0x618BDB80BD736621) /* 363 */,
|
||||
_ULL(0x7D29BAD68B574D0B) /* 364 */, _ULL(0x81BB613E25E6FE5B) /* 365 */,
|
||||
_ULL(0x071C9C10BC07913F) /* 366 */, _ULL(0xC7BEEB7909AC2D97) /* 367 */,
|
||||
_ULL(0xC3E58D353BC5D757) /* 368 */, _ULL(0xEB017892F38F61E8) /* 369 */,
|
||||
_ULL(0xD4EFFB9C9B1CC21A) /* 370 */, _ULL(0x99727D26F494F7AB) /* 371 */,
|
||||
_ULL(0xA3E063A2956B3E03) /* 372 */, _ULL(0x9D4A8B9A4AA09C30) /* 373 */,
|
||||
_ULL(0x3F6AB7D500090FB4) /* 374 */, _ULL(0x9CC0F2A057268AC0) /* 375 */,
|
||||
_ULL(0x3DEE9D2DEDBF42D1) /* 376 */, _ULL(0x330F49C87960A972) /* 377 */,
|
||||
_ULL(0xC6B2720287421B41) /* 378 */, _ULL(0x0AC59EC07C00369C) /* 379 */,
|
||||
_ULL(0xEF4EAC49CB353425) /* 380 */, _ULL(0xF450244EEF0129D8) /* 381 */,
|
||||
_ULL(0x8ACC46E5CAF4DEB6) /* 382 */, _ULL(0x2FFEAB63989263F7) /* 383 */,
|
||||
_ULL(0x8F7CB9FE5D7A4578) /* 384 */, _ULL(0x5BD8F7644E634635) /* 385 */,
|
||||
_ULL(0x427A7315BF2DC900) /* 386 */, _ULL(0x17D0C4AA2125261C) /* 387 */,
|
||||
_ULL(0x3992486C93518E50) /* 388 */, _ULL(0xB4CBFEE0A2D7D4C3) /* 389 */,
|
||||
_ULL(0x7C75D6202C5DDD8D) /* 390 */, _ULL(0xDBC295D8E35B6C61) /* 391 */,
|
||||
_ULL(0x60B369D302032B19) /* 392 */, _ULL(0xCE42685FDCE44132) /* 393 */,
|
||||
_ULL(0x06F3DDB9DDF65610) /* 394 */, _ULL(0x8EA4D21DB5E148F0) /* 395 */,
|
||||
_ULL(0x20B0FCE62FCD496F) /* 396 */, _ULL(0x2C1B912358B0EE31) /* 397 */,
|
||||
_ULL(0xB28317B818F5A308) /* 398 */, _ULL(0xA89C1E189CA6D2CF) /* 399 */,
|
||||
_ULL(0x0C6B18576AAADBC8) /* 400 */, _ULL(0xB65DEAA91299FAE3) /* 401 */,
|
||||
_ULL(0xFB2B794B7F1027E7) /* 402 */, _ULL(0x04E4317F443B5BEB) /* 403 */,
|
||||
_ULL(0x4B852D325939D0A6) /* 404 */, _ULL(0xD5AE6BEEFB207FFC) /* 405 */,
|
||||
_ULL(0x309682B281C7D374) /* 406 */, _ULL(0xBAE309A194C3B475) /* 407 */,
|
||||
_ULL(0x8CC3F97B13B49F05) /* 408 */, _ULL(0x98A9422FF8293967) /* 409 */,
|
||||
_ULL(0x244B16B01076FF7C) /* 410 */, _ULL(0xF8BF571C663D67EE) /* 411 */,
|
||||
_ULL(0x1F0D6758EEE30DA1) /* 412 */, _ULL(0xC9B611D97ADEB9B7) /* 413 */,
|
||||
_ULL(0xB7AFD5887B6C57A2) /* 414 */, _ULL(0x6290AE846B984FE1) /* 415 */,
|
||||
_ULL(0x94DF4CDEACC1A5FD) /* 416 */, _ULL(0x058A5BD1C5483AFF) /* 417 */,
|
||||
_ULL(0x63166CC142BA3C37) /* 418 */, _ULL(0x8DB8526EB2F76F40) /* 419 */,
|
||||
_ULL(0xE10880036F0D6D4E) /* 420 */, _ULL(0x9E0523C9971D311D) /* 421 */,
|
||||
_ULL(0x45EC2824CC7CD691) /* 422 */, _ULL(0x575B8359E62382C9) /* 423 */,
|
||||
_ULL(0xFA9E400DC4889995) /* 424 */, _ULL(0xD1823ECB45721568) /* 425 */,
|
||||
_ULL(0xDAFD983B8206082F) /* 426 */, _ULL(0xAA7D29082386A8CB) /* 427 */,
|
||||
_ULL(0x269FCD4403B87588) /* 428 */, _ULL(0x1B91F5F728BDD1E0) /* 429 */,
|
||||
_ULL(0xE4669F39040201F6) /* 430 */, _ULL(0x7A1D7C218CF04ADE) /* 431 */,
|
||||
_ULL(0x65623C29D79CE5CE) /* 432 */, _ULL(0x2368449096C00BB1) /* 433 */,
|
||||
_ULL(0xAB9BF1879DA503BA) /* 434 */, _ULL(0xBC23ECB1A458058E) /* 435 */,
|
||||
_ULL(0x9A58DF01BB401ECC) /* 436 */, _ULL(0xA070E868A85F143D) /* 437 */,
|
||||
_ULL(0x4FF188307DF2239E) /* 438 */, _ULL(0x14D565B41A641183) /* 439 */,
|
||||
_ULL(0xEE13337452701602) /* 440 */, _ULL(0x950E3DCF3F285E09) /* 441 */,
|
||||
_ULL(0x59930254B9C80953) /* 442 */, _ULL(0x3BF299408930DA6D) /* 443 */,
|
||||
_ULL(0xA955943F53691387) /* 444 */, _ULL(0xA15EDECAA9CB8784) /* 445 */,
|
||||
_ULL(0x29142127352BE9A0) /* 446 */, _ULL(0x76F0371FFF4E7AFB) /* 447 */,
|
||||
_ULL(0x0239F450274F2228) /* 448 */, _ULL(0xBB073AF01D5E868B) /* 449 */,
|
||||
_ULL(0xBFC80571C10E96C1) /* 450 */, _ULL(0xD267088568222E23) /* 451 */,
|
||||
_ULL(0x9671A3D48E80B5B0) /* 452 */, _ULL(0x55B5D38AE193BB81) /* 453 */,
|
||||
_ULL(0x693AE2D0A18B04B8) /* 454 */, _ULL(0x5C48B4ECADD5335F) /* 455 */,
|
||||
_ULL(0xFD743B194916A1CA) /* 456 */, _ULL(0x2577018134BE98C4) /* 457 */,
|
||||
_ULL(0xE77987E83C54A4AD) /* 458 */, _ULL(0x28E11014DA33E1B9) /* 459 */,
|
||||
_ULL(0x270CC59E226AA213) /* 460 */, _ULL(0x71495F756D1A5F60) /* 461 */,
|
||||
_ULL(0x9BE853FB60AFEF77) /* 462 */, _ULL(0xADC786A7F7443DBF) /* 463 */,
|
||||
_ULL(0x0904456173B29A82) /* 464 */, _ULL(0x58BC7A66C232BD5E) /* 465 */,
|
||||
_ULL(0xF306558C673AC8B2) /* 466 */, _ULL(0x41F639C6B6C9772A) /* 467 */,
|
||||
_ULL(0x216DEFE99FDA35DA) /* 468 */, _ULL(0x11640CC71C7BE615) /* 469 */,
|
||||
_ULL(0x93C43694565C5527) /* 470 */, _ULL(0xEA038E6246777839) /* 471 */,
|
||||
_ULL(0xF9ABF3CE5A3E2469) /* 472 */, _ULL(0x741E768D0FD312D2) /* 473 */,
|
||||
_ULL(0x0144B883CED652C6) /* 474 */, _ULL(0xC20B5A5BA33F8552) /* 475 */,
|
||||
_ULL(0x1AE69633C3435A9D) /* 476 */, _ULL(0x97A28CA4088CFDEC) /* 477 */,
|
||||
_ULL(0x8824A43C1E96F420) /* 478 */, _ULL(0x37612FA66EEEA746) /* 479 */,
|
||||
_ULL(0x6B4CB165F9CF0E5A) /* 480 */, _ULL(0x43AA1C06A0ABFB4A) /* 481 */,
|
||||
_ULL(0x7F4DC26FF162796B) /* 482 */, _ULL(0x6CBACC8E54ED9B0F) /* 483 */,
|
||||
_ULL(0xA6B7FFEFD2BB253E) /* 484 */, _ULL(0x2E25BC95B0A29D4F) /* 485 */,
|
||||
_ULL(0x86D6A58BDEF1388C) /* 486 */, _ULL(0xDED74AC576B6F054) /* 487 */,
|
||||
_ULL(0x8030BDBC2B45805D) /* 488 */, _ULL(0x3C81AF70E94D9289) /* 489 */,
|
||||
_ULL(0x3EFF6DDA9E3100DB) /* 490 */, _ULL(0xB38DC39FDFCC8847) /* 491 */,
|
||||
_ULL(0x123885528D17B87E) /* 492 */, _ULL(0xF2DA0ED240B1B642) /* 493 */,
|
||||
_ULL(0x44CEFADCD54BF9A9) /* 494 */, _ULL(0x1312200E433C7EE6) /* 495 */,
|
||||
_ULL(0x9FFCC84F3A78C748) /* 496 */, _ULL(0xF0CD1F72248576BB) /* 497 */,
|
||||
_ULL(0xEC6974053638CFE4) /* 498 */, _ULL(0x2BA7B67C0CEC4E4C) /* 499 */,
|
||||
_ULL(0xAC2F4DF3E5CE32ED) /* 500 */, _ULL(0xCB33D14326EA4C11) /* 501 */,
|
||||
_ULL(0xA4E9044CC77E58BC) /* 502 */, _ULL(0x5F513293D934FCEF) /* 503 */,
|
||||
_ULL(0x5DC9645506E55444) /* 504 */, _ULL(0x50DE418F317DE40A) /* 505 */,
|
||||
_ULL(0x388CB31A69DDE259) /* 506 */, _ULL(0x2DB4A83455820A86) /* 507 */,
|
||||
_ULL(0x9010A91E84711AE9) /* 508 */, _ULL(0x4DF7F0B7B1498371) /* 509 */,
|
||||
_ULL(0xD62A2EABC0977179) /* 510 */, _ULL(0x22FAC097AA8D5C0E) /* 511 */,
|
||||
_ULL(0xF49FCC2FF1DAF39B) /* 512 */, _ULL(0x487FD5C66FF29281) /* 513 */,
|
||||
_ULL(0xE8A30667FCDCA83F) /* 514 */, _ULL(0x2C9B4BE3D2FCCE63) /* 515 */,
|
||||
_ULL(0xDA3FF74B93FBBBC2) /* 516 */, _ULL(0x2FA165D2FE70BA66) /* 517 */,
|
||||
_ULL(0xA103E279970E93D4) /* 518 */, _ULL(0xBECDEC77B0E45E71) /* 519 */,
|
||||
_ULL(0xCFB41E723985E497) /* 520 */, _ULL(0xB70AAA025EF75017) /* 521 */,
|
||||
_ULL(0xD42309F03840B8E0) /* 522 */, _ULL(0x8EFC1AD035898579) /* 523 */,
|
||||
_ULL(0x96C6920BE2B2ABC5) /* 524 */, _ULL(0x66AF4163375A9172) /* 525 */,
|
||||
_ULL(0x2174ABDCCA7127FB) /* 526 */, _ULL(0xB33CCEA64A72FF41) /* 527 */,
|
||||
_ULL(0xF04A4933083066A5) /* 528 */, _ULL(0x8D970ACDD7289AF5) /* 529 */,
|
||||
_ULL(0x8F96E8E031C8C25E) /* 530 */, _ULL(0xF3FEC02276875D47) /* 531 */,
|
||||
_ULL(0xEC7BF310056190DD) /* 532 */, _ULL(0xF5ADB0AEBB0F1491) /* 533 */,
|
||||
_ULL(0x9B50F8850FD58892) /* 534 */, _ULL(0x4975488358B74DE8) /* 535 */,
|
||||
_ULL(0xA3354FF691531C61) /* 536 */, _ULL(0x0702BBE481D2C6EE) /* 537 */,
|
||||
_ULL(0x89FB24057DEDED98) /* 538 */, _ULL(0xAC3075138596E902) /* 539 */,
|
||||
_ULL(0x1D2D3580172772ED) /* 540 */, _ULL(0xEB738FC28E6BC30D) /* 541 */,
|
||||
_ULL(0x5854EF8F63044326) /* 542 */, _ULL(0x9E5C52325ADD3BBE) /* 543 */,
|
||||
_ULL(0x90AA53CF325C4623) /* 544 */, _ULL(0xC1D24D51349DD067) /* 545 */,
|
||||
_ULL(0x2051CFEEA69EA624) /* 546 */, _ULL(0x13220F0A862E7E4F) /* 547 */,
|
||||
_ULL(0xCE39399404E04864) /* 548 */, _ULL(0xD9C42CA47086FCB7) /* 549 */,
|
||||
_ULL(0x685AD2238A03E7CC) /* 550 */, _ULL(0x066484B2AB2FF1DB) /* 551 */,
|
||||
_ULL(0xFE9D5D70EFBF79EC) /* 552 */, _ULL(0x5B13B9DD9C481854) /* 553 */,
|
||||
_ULL(0x15F0D475ED1509AD) /* 554 */, _ULL(0x0BEBCD060EC79851) /* 555 */,
|
||||
_ULL(0xD58C6791183AB7F8) /* 556 */, _ULL(0xD1187C5052F3EEE4) /* 557 */,
|
||||
_ULL(0xC95D1192E54E82FF) /* 558 */, _ULL(0x86EEA14CB9AC6CA2) /* 559 */,
|
||||
_ULL(0x3485BEB153677D5D) /* 560 */, _ULL(0xDD191D781F8C492A) /* 561 */,
|
||||
_ULL(0xF60866BAA784EBF9) /* 562 */, _ULL(0x518F643BA2D08C74) /* 563 */,
|
||||
_ULL(0x8852E956E1087C22) /* 564 */, _ULL(0xA768CB8DC410AE8D) /* 565 */,
|
||||
_ULL(0x38047726BFEC8E1A) /* 566 */, _ULL(0xA67738B4CD3B45AA) /* 567 */,
|
||||
_ULL(0xAD16691CEC0DDE19) /* 568 */, _ULL(0xC6D4319380462E07) /* 569 */,
|
||||
_ULL(0xC5A5876D0BA61938) /* 570 */, _ULL(0x16B9FA1FA58FD840) /* 571 */,
|
||||
_ULL(0x188AB1173CA74F18) /* 572 */, _ULL(0xABDA2F98C99C021F) /* 573 */,
|
||||
_ULL(0x3E0580AB134AE816) /* 574 */, _ULL(0x5F3B05B773645ABB) /* 575 */,
|
||||
_ULL(0x2501A2BE5575F2F6) /* 576 */, _ULL(0x1B2F74004E7E8BA9) /* 577 */,
|
||||
_ULL(0x1CD7580371E8D953) /* 578 */, _ULL(0x7F6ED89562764E30) /* 579 */,
|
||||
_ULL(0xB15926FF596F003D) /* 580 */, _ULL(0x9F65293DA8C5D6B9) /* 581 */,
|
||||
_ULL(0x6ECEF04DD690F84C) /* 582 */, _ULL(0x4782275FFF33AF88) /* 583 */,
|
||||
_ULL(0xE41433083F820801) /* 584 */, _ULL(0xFD0DFE409A1AF9B5) /* 585 */,
|
||||
_ULL(0x4325A3342CDB396B) /* 586 */, _ULL(0x8AE77E62B301B252) /* 587 */,
|
||||
_ULL(0xC36F9E9F6655615A) /* 588 */, _ULL(0x85455A2D92D32C09) /* 589 */,
|
||||
_ULL(0xF2C7DEA949477485) /* 590 */, _ULL(0x63CFB4C133A39EBA) /* 591 */,
|
||||
_ULL(0x83B040CC6EBC5462) /* 592 */, _ULL(0x3B9454C8FDB326B0) /* 593 */,
|
||||
_ULL(0x56F56A9E87FFD78C) /* 594 */, _ULL(0x2DC2940D99F42BC6) /* 595 */,
|
||||
_ULL(0x98F7DF096B096E2D) /* 596 */, _ULL(0x19A6E01E3AD852BF) /* 597 */,
|
||||
_ULL(0x42A99CCBDBD4B40B) /* 598 */, _ULL(0xA59998AF45E9C559) /* 599 */,
|
||||
_ULL(0x366295E807D93186) /* 600 */, _ULL(0x6B48181BFAA1F773) /* 601 */,
|
||||
_ULL(0x1FEC57E2157A0A1D) /* 602 */, _ULL(0x4667446AF6201AD5) /* 603 */,
|
||||
_ULL(0xE615EBCACFB0F075) /* 604 */, _ULL(0xB8F31F4F68290778) /* 605 */,
|
||||
_ULL(0x22713ED6CE22D11E) /* 606 */, _ULL(0x3057C1A72EC3C93B) /* 607 */,
|
||||
_ULL(0xCB46ACC37C3F1F2F) /* 608 */, _ULL(0xDBB893FD02AAF50E) /* 609 */,
|
||||
_ULL(0x331FD92E600B9FCF) /* 610 */, _ULL(0xA498F96148EA3AD6) /* 611 */,
|
||||
_ULL(0xA8D8426E8B6A83EA) /* 612 */, _ULL(0xA089B274B7735CDC) /* 613 */,
|
||||
_ULL(0x87F6B3731E524A11) /* 614 */, _ULL(0x118808E5CBC96749) /* 615 */,
|
||||
_ULL(0x9906E4C7B19BD394) /* 616 */, _ULL(0xAFED7F7E9B24A20C) /* 617 */,
|
||||
_ULL(0x6509EADEEB3644A7) /* 618 */, _ULL(0x6C1EF1D3E8EF0EDE) /* 619 */,
|
||||
_ULL(0xB9C97D43E9798FB4) /* 620 */, _ULL(0xA2F2D784740C28A3) /* 621 */,
|
||||
_ULL(0x7B8496476197566F) /* 622 */, _ULL(0x7A5BE3E6B65F069D) /* 623 */,
|
||||
_ULL(0xF96330ED78BE6F10) /* 624 */, _ULL(0xEEE60DE77A076A15) /* 625 */,
|
||||
_ULL(0x2B4BEE4AA08B9BD0) /* 626 */, _ULL(0x6A56A63EC7B8894E) /* 627 */,
|
||||
_ULL(0x02121359BA34FEF4) /* 628 */, _ULL(0x4CBF99F8283703FC) /* 629 */,
|
||||
_ULL(0x398071350CAF30C8) /* 630 */, _ULL(0xD0A77A89F017687A) /* 631 */,
|
||||
_ULL(0xF1C1A9EB9E423569) /* 632 */, _ULL(0x8C7976282DEE8199) /* 633 */,
|
||||
_ULL(0x5D1737A5DD1F7ABD) /* 634 */, _ULL(0x4F53433C09A9FA80) /* 635 */,
|
||||
_ULL(0xFA8B0C53DF7CA1D9) /* 636 */, _ULL(0x3FD9DCBC886CCB77) /* 637 */,
|
||||
_ULL(0xC040917CA91B4720) /* 638 */, _ULL(0x7DD00142F9D1DCDF) /* 639 */,
|
||||
_ULL(0x8476FC1D4F387B58) /* 640 */, _ULL(0x23F8E7C5F3316503) /* 641 */,
|
||||
_ULL(0x032A2244E7E37339) /* 642 */, _ULL(0x5C87A5D750F5A74B) /* 643 */,
|
||||
_ULL(0x082B4CC43698992E) /* 644 */, _ULL(0xDF917BECB858F63C) /* 645 */,
|
||||
_ULL(0x3270B8FC5BF86DDA) /* 646 */, _ULL(0x10AE72BB29B5DD76) /* 647 */,
|
||||
_ULL(0x576AC94E7700362B) /* 648 */, _ULL(0x1AD112DAC61EFB8F) /* 649 */,
|
||||
_ULL(0x691BC30EC5FAA427) /* 650 */, _ULL(0xFF246311CC327143) /* 651 */,
|
||||
_ULL(0x3142368E30E53206) /* 652 */, _ULL(0x71380E31E02CA396) /* 653 */,
|
||||
_ULL(0x958D5C960AAD76F1) /* 654 */, _ULL(0xF8D6F430C16DA536) /* 655 */,
|
||||
_ULL(0xC8FFD13F1BE7E1D2) /* 656 */, _ULL(0x7578AE66004DDBE1) /* 657 */,
|
||||
_ULL(0x05833F01067BE646) /* 658 */, _ULL(0xBB34B5AD3BFE586D) /* 659 */,
|
||||
_ULL(0x095F34C9A12B97F0) /* 660 */, _ULL(0x247AB64525D60CA8) /* 661 */,
|
||||
_ULL(0xDCDBC6F3017477D1) /* 662 */, _ULL(0x4A2E14D4DECAD24D) /* 663 */,
|
||||
_ULL(0xBDB5E6D9BE0A1EEB) /* 664 */, _ULL(0x2A7E70F7794301AB) /* 665 */,
|
||||
_ULL(0xDEF42D8A270540FD) /* 666 */, _ULL(0x01078EC0A34C22C1) /* 667 */,
|
||||
_ULL(0xE5DE511AF4C16387) /* 668 */, _ULL(0x7EBB3A52BD9A330A) /* 669 */,
|
||||
_ULL(0x77697857AA7D6435) /* 670 */, _ULL(0x004E831603AE4C32) /* 671 */,
|
||||
_ULL(0xE7A21020AD78E312) /* 672 */, _ULL(0x9D41A70C6AB420F2) /* 673 */,
|
||||
_ULL(0x28E06C18EA1141E6) /* 674 */, _ULL(0xD2B28CBD984F6B28) /* 675 */,
|
||||
_ULL(0x26B75F6C446E9D83) /* 676 */, _ULL(0xBA47568C4D418D7F) /* 677 */,
|
||||
_ULL(0xD80BADBFE6183D8E) /* 678 */, _ULL(0x0E206D7F5F166044) /* 679 */,
|
||||
_ULL(0xE258A43911CBCA3E) /* 680 */, _ULL(0x723A1746B21DC0BC) /* 681 */,
|
||||
_ULL(0xC7CAA854F5D7CDD3) /* 682 */, _ULL(0x7CAC32883D261D9C) /* 683 */,
|
||||
_ULL(0x7690C26423BA942C) /* 684 */, _ULL(0x17E55524478042B8) /* 685 */,
|
||||
_ULL(0xE0BE477656A2389F) /* 686 */, _ULL(0x4D289B5E67AB2DA0) /* 687 */,
|
||||
_ULL(0x44862B9C8FBBFD31) /* 688 */, _ULL(0xB47CC8049D141365) /* 689 */,
|
||||
_ULL(0x822C1B362B91C793) /* 690 */, _ULL(0x4EB14655FB13DFD8) /* 691 */,
|
||||
_ULL(0x1ECBBA0714E2A97B) /* 692 */, _ULL(0x6143459D5CDE5F14) /* 693 */,
|
||||
_ULL(0x53A8FBF1D5F0AC89) /* 694 */, _ULL(0x97EA04D81C5E5B00) /* 695 */,
|
||||
_ULL(0x622181A8D4FDB3F3) /* 696 */, _ULL(0xE9BCD341572A1208) /* 697 */,
|
||||
_ULL(0x1411258643CCE58A) /* 698 */, _ULL(0x9144C5FEA4C6E0A4) /* 699 */,
|
||||
_ULL(0x0D33D06565CF620F) /* 700 */, _ULL(0x54A48D489F219CA1) /* 701 */,
|
||||
_ULL(0xC43E5EAC6D63C821) /* 702 */, _ULL(0xA9728B3A72770DAF) /* 703 */,
|
||||
_ULL(0xD7934E7B20DF87EF) /* 704 */, _ULL(0xE35503B61A3E86E5) /* 705 */,
|
||||
_ULL(0xCAE321FBC819D504) /* 706 */, _ULL(0x129A50B3AC60BFA6) /* 707 */,
|
||||
_ULL(0xCD5E68EA7E9FB6C3) /* 708 */, _ULL(0xB01C90199483B1C7) /* 709 */,
|
||||
_ULL(0x3DE93CD5C295376C) /* 710 */, _ULL(0xAED52EDF2AB9AD13) /* 711 */,
|
||||
_ULL(0x2E60F512C0A07884) /* 712 */, _ULL(0xBC3D86A3E36210C9) /* 713 */,
|
||||
_ULL(0x35269D9B163951CE) /* 714 */, _ULL(0x0C7D6E2AD0CDB5FA) /* 715 */,
|
||||
_ULL(0x59E86297D87F5733) /* 716 */, _ULL(0x298EF221898DB0E7) /* 717 */,
|
||||
_ULL(0x55000029D1A5AA7E) /* 718 */, _ULL(0x8BC08AE1B5061B45) /* 719 */,
|
||||
_ULL(0xC2C31C2B6C92703A) /* 720 */, _ULL(0x94CC596BAF25EF42) /* 721 */,
|
||||
_ULL(0x0A1D73DB22540456) /* 722 */, _ULL(0x04B6A0F9D9C4179A) /* 723 */,
|
||||
_ULL(0xEFFDAFA2AE3D3C60) /* 724 */, _ULL(0xF7C8075BB49496C4) /* 725 */,
|
||||
_ULL(0x9CC5C7141D1CD4E3) /* 726 */, _ULL(0x78BD1638218E5534) /* 727 */,
|
||||
_ULL(0xB2F11568F850246A) /* 728 */, _ULL(0xEDFABCFA9502BC29) /* 729 */,
|
||||
_ULL(0x796CE5F2DA23051B) /* 730 */, _ULL(0xAAE128B0DC93537C) /* 731 */,
|
||||
_ULL(0x3A493DA0EE4B29AE) /* 732 */, _ULL(0xB5DF6B2C416895D7) /* 733 */,
|
||||
_ULL(0xFCABBD25122D7F37) /* 734 */, _ULL(0x70810B58105DC4B1) /* 735 */,
|
||||
_ULL(0xE10FDD37F7882A90) /* 736 */, _ULL(0x524DCAB5518A3F5C) /* 737 */,
|
||||
_ULL(0x3C9E85878451255B) /* 738 */, _ULL(0x4029828119BD34E2) /* 739 */,
|
||||
_ULL(0x74A05B6F5D3CECCB) /* 740 */, _ULL(0xB610021542E13ECA) /* 741 */,
|
||||
_ULL(0x0FF979D12F59E2AC) /* 742 */, _ULL(0x6037DA27E4F9CC50) /* 743 */,
|
||||
_ULL(0x5E92975A0DF1847D) /* 744 */, _ULL(0xD66DE190D3E623FE) /* 745 */,
|
||||
_ULL(0x5032D6B87B568048) /* 746 */, _ULL(0x9A36B7CE8235216E) /* 747 */,
|
||||
_ULL(0x80272A7A24F64B4A) /* 748 */, _ULL(0x93EFED8B8C6916F7) /* 749 */,
|
||||
_ULL(0x37DDBFF44CCE1555) /* 750 */, _ULL(0x4B95DB5D4B99BD25) /* 751 */,
|
||||
_ULL(0x92D3FDA169812FC0) /* 752 */, _ULL(0xFB1A4A9A90660BB6) /* 753 */,
|
||||
_ULL(0x730C196946A4B9B2) /* 754 */, _ULL(0x81E289AA7F49DA68) /* 755 */,
|
||||
_ULL(0x64669A0F83B1A05F) /* 756 */, _ULL(0x27B3FF7D9644F48B) /* 757 */,
|
||||
_ULL(0xCC6B615C8DB675B3) /* 758 */, _ULL(0x674F20B9BCEBBE95) /* 759 */,
|
||||
_ULL(0x6F31238275655982) /* 760 */, _ULL(0x5AE488713E45CF05) /* 761 */,
|
||||
_ULL(0xBF619F9954C21157) /* 762 */, _ULL(0xEABAC46040A8EAE9) /* 763 */,
|
||||
_ULL(0x454C6FE9F2C0C1CD) /* 764 */, _ULL(0x419CF6496412691C) /* 765 */,
|
||||
_ULL(0xD3DC3BEF265B0F70) /* 766 */, _ULL(0x6D0E60F5C3578A9E) /* 767 */,
|
||||
_ULL(0x5B0E608526323C55) /* 768 */, _ULL(0x1A46C1A9FA1B59F5) /* 769 */,
|
||||
_ULL(0xA9E245A17C4C8FFA) /* 770 */, _ULL(0x65CA5159DB2955D7) /* 771 */,
|
||||
_ULL(0x05DB0A76CE35AFC2) /* 772 */, _ULL(0x81EAC77EA9113D45) /* 773 */,
|
||||
_ULL(0x528EF88AB6AC0A0D) /* 774 */, _ULL(0xA09EA253597BE3FF) /* 775 */,
|
||||
_ULL(0x430DDFB3AC48CD56) /* 776 */, _ULL(0xC4B3A67AF45CE46F) /* 777 */,
|
||||
_ULL(0x4ECECFD8FBE2D05E) /* 778 */, _ULL(0x3EF56F10B39935F0) /* 779 */,
|
||||
_ULL(0x0B22D6829CD619C6) /* 780 */, _ULL(0x17FD460A74DF2069) /* 781 */,
|
||||
_ULL(0x6CF8CC8E8510ED40) /* 782 */, _ULL(0xD6C824BF3A6ECAA7) /* 783 */,
|
||||
_ULL(0x61243D581A817049) /* 784 */, _ULL(0x048BACB6BBC163A2) /* 785 */,
|
||||
_ULL(0xD9A38AC27D44CC32) /* 786 */, _ULL(0x7FDDFF5BAAF410AB) /* 787 */,
|
||||
_ULL(0xAD6D495AA804824B) /* 788 */, _ULL(0xE1A6A74F2D8C9F94) /* 789 */,
|
||||
_ULL(0xD4F7851235DEE8E3) /* 790 */, _ULL(0xFD4B7F886540D893) /* 791 */,
|
||||
_ULL(0x247C20042AA4BFDA) /* 792 */, _ULL(0x096EA1C517D1327C) /* 793 */,
|
||||
_ULL(0xD56966B4361A6685) /* 794 */, _ULL(0x277DA5C31221057D) /* 795 */,
|
||||
_ULL(0x94D59893A43ACFF7) /* 796 */, _ULL(0x64F0C51CCDC02281) /* 797 */,
|
||||
_ULL(0x3D33BCC4FF6189DB) /* 798 */, _ULL(0xE005CB184CE66AF1) /* 799 */,
|
||||
_ULL(0xFF5CCD1D1DB99BEA) /* 800 */, _ULL(0xB0B854A7FE42980F) /* 801 */,
|
||||
_ULL(0x7BD46A6A718D4B9F) /* 802 */, _ULL(0xD10FA8CC22A5FD8C) /* 803 */,
|
||||
_ULL(0xD31484952BE4BD31) /* 804 */, _ULL(0xC7FA975FCB243847) /* 805 */,
|
||||
_ULL(0x4886ED1E5846C407) /* 806 */, _ULL(0x28CDDB791EB70B04) /* 807 */,
|
||||
_ULL(0xC2B00BE2F573417F) /* 808 */, _ULL(0x5C9590452180F877) /* 809 */,
|
||||
_ULL(0x7A6BDDFFF370EB00) /* 810 */, _ULL(0xCE509E38D6D9D6A4) /* 811 */,
|
||||
_ULL(0xEBEB0F00647FA702) /* 812 */, _ULL(0x1DCC06CF76606F06) /* 813 */,
|
||||
_ULL(0xE4D9F28BA286FF0A) /* 814 */, _ULL(0xD85A305DC918C262) /* 815 */,
|
||||
_ULL(0x475B1D8732225F54) /* 816 */, _ULL(0x2D4FB51668CCB5FE) /* 817 */,
|
||||
_ULL(0xA679B9D9D72BBA20) /* 818 */, _ULL(0x53841C0D912D43A5) /* 819 */,
|
||||
_ULL(0x3B7EAA48BF12A4E8) /* 820 */, _ULL(0x781E0E47F22F1DDF) /* 821 */,
|
||||
_ULL(0xEFF20CE60AB50973) /* 822 */, _ULL(0x20D261D19DFFB742) /* 823 */,
|
||||
_ULL(0x16A12B03062A2E39) /* 824 */, _ULL(0x1960EB2239650495) /* 825 */,
|
||||
_ULL(0x251C16FED50EB8B8) /* 826 */, _ULL(0x9AC0C330F826016E) /* 827 */,
|
||||
_ULL(0xED152665953E7671) /* 828 */, _ULL(0x02D63194A6369570) /* 829 */,
|
||||
_ULL(0x5074F08394B1C987) /* 830 */, _ULL(0x70BA598C90B25CE1) /* 831 */,
|
||||
_ULL(0x794A15810B9742F6) /* 832 */, _ULL(0x0D5925E9FCAF8C6C) /* 833 */,
|
||||
_ULL(0x3067716CD868744E) /* 834 */, _ULL(0x910AB077E8D7731B) /* 835 */,
|
||||
_ULL(0x6A61BBDB5AC42F61) /* 836 */, _ULL(0x93513EFBF0851567) /* 837 */,
|
||||
_ULL(0xF494724B9E83E9D5) /* 838 */, _ULL(0xE887E1985C09648D) /* 839 */,
|
||||
_ULL(0x34B1D3C675370CFD) /* 840 */, _ULL(0xDC35E433BC0D255D) /* 841 */,
|
||||
_ULL(0xD0AAB84234131BE0) /* 842 */, _ULL(0x08042A50B48B7EAF) /* 843 */,
|
||||
_ULL(0x9997C4EE44A3AB35) /* 844 */, _ULL(0x829A7B49201799D0) /* 845 */,
|
||||
_ULL(0x263B8307B7C54441) /* 846 */, _ULL(0x752F95F4FD6A6CA6) /* 847 */,
|
||||
_ULL(0x927217402C08C6E5) /* 848 */, _ULL(0x2A8AB754A795D9EE) /* 849 */,
|
||||
_ULL(0xA442F7552F72943D) /* 850 */, _ULL(0x2C31334E19781208) /* 851 */,
|
||||
_ULL(0x4FA98D7CEAEE6291) /* 852 */, _ULL(0x55C3862F665DB309) /* 853 */,
|
||||
_ULL(0xBD0610175D53B1F3) /* 854 */, _ULL(0x46FE6CB840413F27) /* 855 */,
|
||||
_ULL(0x3FE03792DF0CFA59) /* 856 */, _ULL(0xCFE700372EB85E8F) /* 857 */,
|
||||
_ULL(0xA7BE29E7ADBCE118) /* 858 */, _ULL(0xE544EE5CDE8431DD) /* 859 */,
|
||||
_ULL(0x8A781B1B41F1873E) /* 860 */, _ULL(0xA5C94C78A0D2F0E7) /* 861 */,
|
||||
_ULL(0x39412E2877B60728) /* 862 */, _ULL(0xA1265EF3AFC9A62C) /* 863 */,
|
||||
_ULL(0xBCC2770C6A2506C5) /* 864 */, _ULL(0x3AB66DD5DCE1CE12) /* 865 */,
|
||||
_ULL(0xE65499D04A675B37) /* 866 */, _ULL(0x7D8F523481BFD216) /* 867 */,
|
||||
_ULL(0x0F6F64FCEC15F389) /* 868 */, _ULL(0x74EFBE618B5B13C8) /* 869 */,
|
||||
_ULL(0xACDC82B714273E1D) /* 870 */, _ULL(0xDD40BFE003199D17) /* 871 */,
|
||||
_ULL(0x37E99257E7E061F8) /* 872 */, _ULL(0xFA52626904775AAA) /* 873 */,
|
||||
_ULL(0x8BBBF63A463D56F9) /* 874 */, _ULL(0xF0013F1543A26E64) /* 875 */,
|
||||
_ULL(0xA8307E9F879EC898) /* 876 */, _ULL(0xCC4C27A4150177CC) /* 877 */,
|
||||
_ULL(0x1B432F2CCA1D3348) /* 878 */, _ULL(0xDE1D1F8F9F6FA013) /* 879 */,
|
||||
_ULL(0x606602A047A7DDD6) /* 880 */, _ULL(0xD237AB64CC1CB2C7) /* 881 */,
|
||||
_ULL(0x9B938E7225FCD1D3) /* 882 */, _ULL(0xEC4E03708E0FF476) /* 883 */,
|
||||
_ULL(0xFEB2FBDA3D03C12D) /* 884 */, _ULL(0xAE0BCED2EE43889A) /* 885 */,
|
||||
_ULL(0x22CB8923EBFB4F43) /* 886 */, _ULL(0x69360D013CF7396D) /* 887 */,
|
||||
_ULL(0x855E3602D2D4E022) /* 888 */, _ULL(0x073805BAD01F784C) /* 889 */,
|
||||
_ULL(0x33E17A133852F546) /* 890 */, _ULL(0xDF4874058AC7B638) /* 891 */,
|
||||
_ULL(0xBA92B29C678AA14A) /* 892 */, _ULL(0x0CE89FC76CFAADCD) /* 893 */,
|
||||
_ULL(0x5F9D4E0908339E34) /* 894 */, _ULL(0xF1AFE9291F5923B9) /* 895 */,
|
||||
_ULL(0x6E3480F60F4A265F) /* 896 */, _ULL(0xEEBF3A2AB29B841C) /* 897 */,
|
||||
_ULL(0xE21938A88F91B4AD) /* 898 */, _ULL(0x57DFEFF845C6D3C3) /* 899 */,
|
||||
_ULL(0x2F006B0BF62CAAF2) /* 900 */, _ULL(0x62F479EF6F75EE78) /* 901 */,
|
||||
_ULL(0x11A55AD41C8916A9) /* 902 */, _ULL(0xF229D29084FED453) /* 903 */,
|
||||
_ULL(0x42F1C27B16B000E6) /* 904 */, _ULL(0x2B1F76749823C074) /* 905 */,
|
||||
_ULL(0x4B76ECA3C2745360) /* 906 */, _ULL(0x8C98F463B91691BD) /* 907 */,
|
||||
_ULL(0x14BCC93CF1ADE66A) /* 908 */, _ULL(0x8885213E6D458397) /* 909 */,
|
||||
_ULL(0x8E177DF0274D4711) /* 910 */, _ULL(0xB49B73B5503F2951) /* 911 */,
|
||||
_ULL(0x10168168C3F96B6B) /* 912 */, _ULL(0x0E3D963B63CAB0AE) /* 913 */,
|
||||
_ULL(0x8DFC4B5655A1DB14) /* 914 */, _ULL(0xF789F1356E14DE5C) /* 915 */,
|
||||
_ULL(0x683E68AF4E51DAC1) /* 916 */, _ULL(0xC9A84F9D8D4B0FD9) /* 917 */,
|
||||
_ULL(0x3691E03F52A0F9D1) /* 918 */, _ULL(0x5ED86E46E1878E80) /* 919 */,
|
||||
_ULL(0x3C711A0E99D07150) /* 920 */, _ULL(0x5A0865B20C4E9310) /* 921 */,
|
||||
_ULL(0x56FBFC1FE4F0682E) /* 922 */, _ULL(0xEA8D5DE3105EDF9B) /* 923 */,
|
||||
_ULL(0x71ABFDB12379187A) /* 924 */, _ULL(0x2EB99DE1BEE77B9C) /* 925 */,
|
||||
_ULL(0x21ECC0EA33CF4523) /* 926 */, _ULL(0x59A4D7521805C7A1) /* 927 */,
|
||||
_ULL(0x3896F5EB56AE7C72) /* 928 */, _ULL(0xAA638F3DB18F75DC) /* 929 */,
|
||||
_ULL(0x9F39358DABE9808E) /* 930 */, _ULL(0xB7DEFA91C00B72AC) /* 931 */,
|
||||
_ULL(0x6B5541FD62492D92) /* 932 */, _ULL(0x6DC6DEE8F92E4D5B) /* 933 */,
|
||||
_ULL(0x353F57ABC4BEEA7E) /* 934 */, _ULL(0x735769D6DA5690CE) /* 935 */,
|
||||
_ULL(0x0A234AA642391484) /* 936 */, _ULL(0xF6F9508028F80D9D) /* 937 */,
|
||||
_ULL(0xB8E319A27AB3F215) /* 938 */, _ULL(0x31AD9C1151341A4D) /* 939 */,
|
||||
_ULL(0x773C22A57BEF5805) /* 940 */, _ULL(0x45C7561A07968633) /* 941 */,
|
||||
_ULL(0xF913DA9E249DBE36) /* 942 */, _ULL(0xDA652D9B78A64C68) /* 943 */,
|
||||
_ULL(0x4C27A97F3BC334EF) /* 944 */, _ULL(0x76621220E66B17F4) /* 945 */,
|
||||
_ULL(0x967743899ACD7D0B) /* 946 */, _ULL(0xF3EE5BCAE0ED6782) /* 947 */,
|
||||
_ULL(0x409F753600C879FC) /* 948 */, _ULL(0x06D09A39B5926DB6) /* 949 */,
|
||||
_ULL(0x6F83AEB0317AC588) /* 950 */, _ULL(0x01E6CA4A86381F21) /* 951 */,
|
||||
_ULL(0x66FF3462D19F3025) /* 952 */, _ULL(0x72207C24DDFD3BFB) /* 953 */,
|
||||
_ULL(0x4AF6B6D3E2ECE2EB) /* 954 */, _ULL(0x9C994DBEC7EA08DE) /* 955 */,
|
||||
_ULL(0x49ACE597B09A8BC4) /* 956 */, _ULL(0xB38C4766CF0797BA) /* 957 */,
|
||||
_ULL(0x131B9373C57C2A75) /* 958 */, _ULL(0xB1822CCE61931E58) /* 959 */,
|
||||
_ULL(0x9D7555B909BA1C0C) /* 960 */, _ULL(0x127FAFDD937D11D2) /* 961 */,
|
||||
_ULL(0x29DA3BADC66D92E4) /* 962 */, _ULL(0xA2C1D57154C2ECBC) /* 963 */,
|
||||
_ULL(0x58C5134D82F6FE24) /* 964 */, _ULL(0x1C3AE3515B62274F) /* 965 */,
|
||||
_ULL(0xE907C82E01CB8126) /* 966 */, _ULL(0xF8ED091913E37FCB) /* 967 */,
|
||||
_ULL(0x3249D8F9C80046C9) /* 968 */, _ULL(0x80CF9BEDE388FB63) /* 969 */,
|
||||
_ULL(0x1881539A116CF19E) /* 970 */, _ULL(0x5103F3F76BD52457) /* 971 */,
|
||||
_ULL(0x15B7E6F5AE47F7A8) /* 972 */, _ULL(0xDBD7C6DED47E9CCF) /* 973 */,
|
||||
_ULL(0x44E55C410228BB1A) /* 974 */, _ULL(0xB647D4255EDB4E99) /* 975 */,
|
||||
_ULL(0x5D11882BB8AAFC30) /* 976 */, _ULL(0xF5098BBB29D3212A) /* 977 */,
|
||||
_ULL(0x8FB5EA14E90296B3) /* 978 */, _ULL(0x677B942157DD025A) /* 979 */,
|
||||
_ULL(0xFB58E7C0A390ACB5) /* 980 */, _ULL(0x89D3674C83BD4A01) /* 981 */,
|
||||
_ULL(0x9E2DA4DF4BF3B93B) /* 982 */, _ULL(0xFCC41E328CAB4829) /* 983 */,
|
||||
_ULL(0x03F38C96BA582C52) /* 984 */, _ULL(0xCAD1BDBD7FD85DB2) /* 985 */,
|
||||
_ULL(0xBBB442C16082AE83) /* 986 */, _ULL(0xB95FE86BA5DA9AB0) /* 987 */,
|
||||
_ULL(0xB22E04673771A93F) /* 988 */, _ULL(0x845358C9493152D8) /* 989 */,
|
||||
_ULL(0xBE2A488697B4541E) /* 990 */, _ULL(0x95A2DC2DD38E6966) /* 991 */,
|
||||
_ULL(0xC02C11AC923C852B) /* 992 */, _ULL(0x2388B1990DF2A87B) /* 993 */,
|
||||
_ULL(0x7C8008FA1B4F37BE) /* 994 */, _ULL(0x1F70D0C84D54E503) /* 995 */,
|
||||
_ULL(0x5490ADEC7ECE57D4) /* 996 */, _ULL(0x002B3C27D9063A3A) /* 997 */,
|
||||
_ULL(0x7EAEA3848030A2BF) /* 998 */, _ULL(0xC602326DED2003C0) /* 999 */,
|
||||
_ULL(0x83A7287D69A94086) /* 1000 */, _ULL(0xC57A5FCB30F57A8A) /* 1001 */,
|
||||
_ULL(0xB56844E479EBE779) /* 1002 */, _ULL(0xA373B40F05DCBCE9) /* 1003 */,
|
||||
_ULL(0xD71A786E88570EE2) /* 1004 */, _ULL(0x879CBACDBDE8F6A0) /* 1005 */,
|
||||
_ULL(0x976AD1BCC164A32F) /* 1006 */, _ULL(0xAB21E25E9666D78B) /* 1007 */,
|
||||
_ULL(0x901063AAE5E5C33C) /* 1008 */, _ULL(0x9818B34448698D90) /* 1009 */,
|
||||
_ULL(0xE36487AE3E1E8ABB) /* 1010 */, _ULL(0xAFBDF931893BDCB4) /* 1011 */,
|
||||
_ULL(0x6345A0DC5FBBD519) /* 1012 */, _ULL(0x8628FE269B9465CA) /* 1013 */,
|
||||
_ULL(0x1E5D01603F9C51EC) /* 1014 */, _ULL(0x4DE44006A15049B7) /* 1015 */,
|
||||
_ULL(0xBF6C70E5F776CBB1) /* 1016 */, _ULL(0x411218F2EF552BED) /* 1017 */,
|
||||
_ULL(0xCB0C0708705A36A3) /* 1018 */, _ULL(0xE74D14754F986044) /* 1019 */,
|
||||
_ULL(0xCD56D9430EA8280E) /* 1020 */, _ULL(0xC12591D7535F5065) /* 1021 */,
|
||||
_ULL(0xC83223F1720AEF96) /* 1022 */, _ULL(0xC3A0396F7363A51F) /* 1023 */
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_TIGER_HASH_H
|
||||
#define ADCHPP_TIGER_HASH_H
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
class TigerHash : private boost::noncopyable {
|
||||
public:
|
||||
/** Hash size */
|
||||
static const size_t BITS = 192;
|
||||
static const size_t BYTES = BITS / 8;
|
||||
|
||||
TigerHash() : pos(0) {
|
||||
res[0]=_ULL(0x0123456789ABCDEF);
|
||||
res[1]=_ULL(0xFEDCBA9876543210);
|
||||
res[2]=_ULL(0xF096A5B4C3B2E187);
|
||||
}
|
||||
|
||||
TigerHash(uint64_t pos, uint64_t initial_res[3]) : pos(pos) {
|
||||
res[0] = initial_res[0];
|
||||
res[1] = initial_res[1];
|
||||
res[2] = initial_res[2];
|
||||
}
|
||||
|
||||
~TigerHash() { }
|
||||
|
||||
/** Calculates the Tiger hash of the data. */
|
||||
ADCHPP_DLL void update(const void* data, size_t len);
|
||||
/** Call once all data has been processed. */
|
||||
ADCHPP_DLL uint8_t* finalize();
|
||||
|
||||
uint8_t* getResult() { return (uint8_t*) res; }
|
||||
private:
|
||||
enum { BLOCK_SIZE = 512/8 };
|
||||
/** 512 bit blocks for the compress function */
|
||||
uint8_t tmp[512/8];
|
||||
/** State / final hash value */
|
||||
uint64_t res[3];
|
||||
/** Total number of bytes compressed */
|
||||
uint64_t pos;
|
||||
/** S boxes */
|
||||
static uint64_t table[];
|
||||
|
||||
void tigerCompress(const uint64_t* data, uint64_t state[3]);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _TIGER_HASH
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef ADCHPP_ADCHPP_TIME_H_
|
||||
#define ADCHPP_ADCHPP_TIME_H_
|
||||
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
|
||||
namespace adchpp {
|
||||
namespace time {
|
||||
using namespace boost::posix_time;
|
||||
|
||||
inline ptime now() { return microsec_clock::local_time(); }
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* TIME_H_ */
|
|
@ -0,0 +1,365 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
|
||||
#include <random>
|
||||
|
||||
#include "Util.h"
|
||||
#include "FastAlloc.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include "TimeUtil.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef NDEBUG
|
||||
FastMutex FastAllocBase::mtx;
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
string Util::appName;
|
||||
string Util::appPath;
|
||||
#endif
|
||||
|
||||
string Util::emptyString;
|
||||
wstring Util::emptyStringW;
|
||||
|
||||
/**
|
||||
* Decodes a URL the best it can...
|
||||
* Default ports:
|
||||
* http:// -> port 80
|
||||
* dchub:// -> port 411
|
||||
*/
|
||||
void Util::decodeUrl(const string& url, string& aServer, short& aPort, string& aFile) {
|
||||
// First, check for a protocol: xxxx://
|
||||
string::size_type i = 0, j, k;
|
||||
|
||||
aServer.clear();
|
||||
aFile.clear();
|
||||
|
||||
if( (j=url.find("://", i)) != string::npos) {
|
||||
// Protocol found
|
||||
string protocol = url.substr(0, j);
|
||||
i = j + 3;
|
||||
|
||||
if(protocol == "http") {
|
||||
aPort = 80;
|
||||
} else if(protocol == "dchub") {
|
||||
aPort = 411;
|
||||
}
|
||||
}
|
||||
|
||||
if( (j=url.find('/', i)) != string::npos) {
|
||||
// We have a filename...
|
||||
aFile = url.substr(j);
|
||||
}
|
||||
|
||||
if( (k=url.find(':', i)) != string::npos) {
|
||||
// Port
|
||||
if(k < j)
|
||||
aPort = (short)Util::toInt(url.substr(k+1, j-k-1));
|
||||
} else {
|
||||
k = j;
|
||||
}
|
||||
|
||||
// Only the server should be left now...
|
||||
aServer = url.substr(i, k-i);
|
||||
}
|
||||
|
||||
|
||||
void Util::tokenize(StringList& lst, const string& str, char sep, string::size_type j) {
|
||||
string::size_type i = 0;
|
||||
while( (i=str.find_first_of(sep, j)) != string::npos ) {
|
||||
lst.push_back(str.substr(j, i-j));
|
||||
j = i + 1;
|
||||
}
|
||||
if(j <= str.size())
|
||||
lst.push_back(str.substr(j, str.size()-j));
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
string Util::getAppPath() {
|
||||
string tmp = getAppName();
|
||||
string::size_type i = tmp.rfind('\\');
|
||||
if(i != string::npos)
|
||||
tmp.erase(i+1);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
string Util::getAppName() {
|
||||
string tmp(MAX_PATH + 1, '\0');
|
||||
tmp.resize(::GetModuleFileNameA(NULL, &tmp[0], MAX_PATH));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#else // WIN32
|
||||
|
||||
void Util::setApp(const string& app) {
|
||||
string::size_type i = app.rfind('/');
|
||||
if(i != string::npos) {
|
||||
appPath = app.substr(0, i+1);
|
||||
appName = app;
|
||||
}
|
||||
}
|
||||
string Util::getAppPath() {
|
||||
return appPath;
|
||||
}
|
||||
string Util::getAppName() {
|
||||
return appName;
|
||||
}
|
||||
#endif // WIN32
|
||||
|
||||
string Util::getLocalIp() {
|
||||
string tmp;
|
||||
|
||||
char buf[256];
|
||||
gethostname(buf, 255);
|
||||
hostent* he = gethostbyname(buf);
|
||||
if(he == NULL || he->h_addr_list[0] == 0)
|
||||
return Util::emptyString;
|
||||
sockaddr_in dest;
|
||||
int i = 0;
|
||||
|
||||
// We take the first ip as default, but if we can find a better one, use it instead...
|
||||
memcpy(&(dest.sin_addr), he->h_addr_list[i++], he->h_length);
|
||||
tmp = inet_ntoa(dest.sin_addr);
|
||||
if( strncmp(tmp.c_str(), "192", 3) == 0 ||
|
||||
strncmp(tmp.c_str(), "169", 3) == 0 ||
|
||||
strncmp(tmp.c_str(), "127", 3) == 0 ||
|
||||
strncmp(tmp.c_str(), "10", 2) == 0 ) {
|
||||
|
||||
while(he->h_addr_list[i]) {
|
||||
memcpy(&(dest.sin_addr), he->h_addr_list[i], he->h_length);
|
||||
string tmp2 = inet_ntoa(dest.sin_addr);
|
||||
if( strncmp(tmp2.c_str(), "192", 3) != 0 &&
|
||||
strncmp(tmp2.c_str(), "169", 3) != 0 &&
|
||||
strncmp(tmp2.c_str(), "127", 3) != 0 &&
|
||||
strncmp(tmp2.c_str(), "10", 2) != 0) {
|
||||
|
||||
tmp = tmp2;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
string Util::formatBytes(int64_t aBytes) {
|
||||
char buf[64];
|
||||
if(aBytes < 1024) {
|
||||
sprintf(buf, "%d B", (int)(aBytes&0xffffffff));
|
||||
} else if(aBytes < 1024*1024) {
|
||||
sprintf(buf, "%.02f KiB", (double)aBytes/(1024.0));
|
||||
} else if(aBytes < 1024*1024*1024) {
|
||||
sprintf(buf, "%.02f MiB", (double)aBytes/(1024.0*1024.0));
|
||||
} else if(aBytes < (int64_t)1024*1024*1024*1024) {
|
||||
sprintf(buf, "%.02f GiB", (double)aBytes/(1024.0*1024.0*1024.0));
|
||||
} else {
|
||||
sprintf(buf, "%.02f TiB", (double)aBytes/(1024.0*1024.0*1024.0*1024.0));
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
string Util::getShortTimeString() {
|
||||
char buf[8];
|
||||
time_t _tt;
|
||||
std::time(&_tt);
|
||||
tm* _tm = localtime(&_tt);
|
||||
strftime(buf, 8, "%H:%M", _tm);
|
||||
return buf;
|
||||
}
|
||||
|
||||
string Util::getTimeString() {
|
||||
char buf[64];
|
||||
time_t _tt;
|
||||
std::time(&_tt);
|
||||
tm* _tm = localtime(&_tt);
|
||||
if(_tm == NULL) {
|
||||
strcpy(buf, "xx:xx:xx");
|
||||
} else {
|
||||
strftime(buf, 64, "%X", _tm);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
string Util::formatTime(const string& msg, time_t t /* = time(NULL) */) {
|
||||
size_t bufsize = msg.size() + 64;
|
||||
|
||||
char* buf = new char[bufsize];
|
||||
|
||||
while(!strftime(buf, bufsize-1, msg.c_str(), localtime(&t))) {
|
||||
delete buf;
|
||||
bufsize+=64;
|
||||
buf = new char[bufsize];
|
||||
}
|
||||
|
||||
string result = buf;
|
||||
delete[] buf;
|
||||
return result;
|
||||
}
|
||||
|
||||
string Util::translateError(int aError) {
|
||||
#ifdef _WIN32
|
||||
LPVOID lpMsgBuf;
|
||||
::FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
aError,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
|
||||
#ifdef _UNICODE
|
||||
string tmp = Util::toAcp((LPCTSTR)lpMsgBuf);
|
||||
#else
|
||||
string tmp = (LPCTSTR)lpMsgBuf;
|
||||
#endif
|
||||
// Free the buffer.
|
||||
LocalFree( lpMsgBuf );
|
||||
#else // WIN32
|
||||
string tmp = strerror(aError);
|
||||
#endif // WIN32
|
||||
string::size_type i = 0;
|
||||
|
||||
while( (i = tmp.find_first_of("\r\n", i)) != string::npos) {
|
||||
tmp.erase(i, 1);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
string Util::getOsVersion() {
|
||||
#ifdef _WIN32
|
||||
string os;
|
||||
|
||||
OSVERSIONINFOEX ver;
|
||||
memset(&ver, 0, sizeof(OSVERSIONINFOEX));
|
||||
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||||
|
||||
if(!GetVersionEx((OSVERSIONINFO*)&ver)) {
|
||||
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
if(!GetVersionEx((OSVERSIONINFO*)&ver)) {
|
||||
os = "Windows (version unknown)";
|
||||
}
|
||||
}
|
||||
|
||||
if(os.empty()) {
|
||||
if(ver.dwPlatformId != VER_PLATFORM_WIN32_NT) {
|
||||
os = "Win9x/ME/Junk";
|
||||
} else if(ver.dwMajorVersion == 4) {
|
||||
os = "WinNT4";
|
||||
} else if(ver.dwMajorVersion == 5) {
|
||||
if(ver.dwMinorVersion == 0) {
|
||||
os = "Win2000";
|
||||
} else if(ver.dwMinorVersion == 1) {
|
||||
os = "WinXP";
|
||||
} else if(ver.dwMinorVersion == 2) {
|
||||
os = "Win2003";
|
||||
} else {
|
||||
os = "WinUnknown";
|
||||
}
|
||||
|
||||
if(ver.wProductType == VER_NT_WORKSTATION)
|
||||
os += " Pro";
|
||||
else if(ver.wProductType == VER_NT_SERVER)
|
||||
os += " Server";
|
||||
else if(ver.wProductType == VER_NT_DOMAIN_CONTROLLER)
|
||||
os += " DC";
|
||||
}
|
||||
|
||||
if(ver.wServicePackMajor > 0) {
|
||||
os += " SP" + Util::toString(ver.wServicePackMajor);
|
||||
}
|
||||
}
|
||||
|
||||
return os;
|
||||
|
||||
#else // WIN32
|
||||
utsname n;
|
||||
|
||||
if(uname(&n) != 0) {
|
||||
return "unix (unknown version)";
|
||||
}
|
||||
|
||||
return string(n.sysname) + " " + string(n.release) + " (" + string(n.machine) + ")";
|
||||
|
||||
#endif // WIN32
|
||||
}
|
||||
|
||||
#ifdef __MINGW32__
|
||||
// creating a random_device throws an exception in MinGW with GCC 4.6; simpler alternative...
|
||||
uint32_t Util::rand() {
|
||||
static bool init = false;
|
||||
if(!init) {
|
||||
::srand(::time(0));
|
||||
init = true;
|
||||
}
|
||||
|
||||
return ::rand();
|
||||
}
|
||||
|
||||
#else
|
||||
uint32_t Util::rand() {
|
||||
static std::random_device rd;
|
||||
static std::default_random_engine dre(rd());
|
||||
|
||||
return dre();
|
||||
}
|
||||
#endif
|
||||
|
||||
bool Util::isPrivateIp(std::string const& ip) {
|
||||
struct in_addr addr;
|
||||
|
||||
addr.s_addr = inet_addr(ip.c_str());
|
||||
|
||||
if (addr.s_addr != INADDR_NONE) {
|
||||
unsigned long haddr = ntohl(addr.s_addr);
|
||||
return ((haddr & 0xff000000) == 0x0a000000 || // 10.0.0.0/8
|
||||
(haddr & 0xff000000) == 0x7f000000 || // 127.0.0.0/8
|
||||
(haddr & 0xfff00000) == 0xac100000 || // 172.16.0.0/12
|
||||
(haddr & 0xffff0000) == 0xc0a80000); // 192.168.0.0/16
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Util::validateCharset(std::string const& field, int p) {
|
||||
for(string::size_type i = 0; i < field.length(); ++i) {
|
||||
if((uint8_t) field[i] < p) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_UTIL_H
|
||||
#define ADCHPP_UTIL_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
/** Evaluates op(pair<T1, T2>.first, compareTo) */
|
||||
template<class T1, class T2, class op = std::equal_to<T1> >
|
||||
class CompareFirst {
|
||||
public:
|
||||
CompareFirst(const T1& compareTo) : a(compareTo) { }
|
||||
bool operator()(const std::pair<T1, T2>& p) { return op()(p.first, a); }
|
||||
private:
|
||||
CompareFirst& operator=(const CompareFirst&);
|
||||
const T1& a;
|
||||
};
|
||||
|
||||
/** Evaluates op(pair<T1, T2>.second, compareTo) */
|
||||
template<class T1, class T2, class op = std::equal_to<T2> >
|
||||
class CompareSecond {
|
||||
public:
|
||||
CompareSecond(const T2& compareTo) : a(compareTo) { }
|
||||
bool operator()(const std::pair<T1, T2>& p) { return op()(p.second, a); }
|
||||
private:
|
||||
CompareSecond& operator=(const CompareSecond&);
|
||||
const T2& a;
|
||||
};
|
||||
|
||||
struct DeleteFunction {
|
||||
template<typename T>
|
||||
void operator()(T* ptr) { delete ptr; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Compares two values
|
||||
* @return -1 if v1 < v2, 0 if v1 == v2 and 1 if v1 > v2
|
||||
*/
|
||||
template<typename T1>
|
||||
inline int compare(const T1& v1, const T1& v2) { return (v1 < v2) ? -1 : ((v1 == v2) ? 0 : 1); }
|
||||
|
||||
class Flags {
|
||||
public:
|
||||
typedef size_t MaskType;
|
||||
|
||||
Flags() : flags(0) { }
|
||||
Flags(const Flags& rhs) : flags(rhs.flags) { }
|
||||
Flags(MaskType f) : flags(f) { }
|
||||
MaskType getFlags() const { return flags; }
|
||||
bool isSet(MaskType aFlag) const { return (flags & aFlag) == aFlag; }
|
||||
bool isAnySet(MaskType aFlag) const { return (flags & aFlag) != 0; }
|
||||
void setFlag(MaskType aFlag) { flags |= aFlag; }
|
||||
void unsetFlag(MaskType aFlag) { flags &= ~aFlag; }
|
||||
Flags& operator=(const Flags& rhs) { flags = rhs.flags; return *this; }
|
||||
private:
|
||||
MaskType flags;
|
||||
};
|
||||
|
||||
class Util
|
||||
{
|
||||
public:
|
||||
enum Reason {
|
||||
REASON_BAD_STATE,
|
||||
REASON_CID_CHANGE,
|
||||
REASON_CID_TAKEN,
|
||||
REASON_FLOODING,
|
||||
REASON_HUB_FULL,
|
||||
REASON_INVALID_COMMAND_TYPE,
|
||||
REASON_INVALID_IP,
|
||||
REASON_INVALID_SID,
|
||||
REASON_LOGIN_TIMEOUT,
|
||||
REASON_MAX_COMMAND_SIZE,
|
||||
REASON_NICK_INVALID,
|
||||
REASON_NICK_TAKEN,
|
||||
REASON_NO_BASE_SUPPORT,
|
||||
REASON_NO_TIGR_SUPPORT,
|
||||
REASON_PID_MISSING,
|
||||
REASON_PID_CID_LENGTH,
|
||||
REASON_PID_CID_MISMATCH,
|
||||
REASON_PID_WITHOUT_CID,
|
||||
REASON_PLUGIN,
|
||||
REASON_WRITE_OVERFLOW,
|
||||
REASON_NO_BANDWIDTH,
|
||||
REASON_INVALID_DESCRIPTION,
|
||||
REASON_WRITE_TIMEOUT,
|
||||
REASON_SOCKET_ERROR,
|
||||
REASON_LAST,
|
||||
};
|
||||
|
||||
ADCHPP_DLL static std::string emptyString;
|
||||
static std::wstring emptyStringW;
|
||||
|
||||
ADCHPP_DLL static std::string getOsVersion();
|
||||
ADCHPP_DLL static void decodeUrl(const std::string& aUrl, std::string& aServer, short& aPort, std::string& aFile);
|
||||
ADCHPP_DLL static std::string formatTime(const std::string& msg, time_t t = std::time(NULL));
|
||||
|
||||
ADCHPP_DLL static std::string getAppPath();
|
||||
ADCHPP_DLL static std::string getAppName();
|
||||
|
||||
#ifndef _WIN32
|
||||
ADCHPP_DLL static void setApp(const std::string& app);
|
||||
static std::string appPath;
|
||||
static std::string appName;
|
||||
|
||||
#endif
|
||||
|
||||
ADCHPP_DLL static std::string translateError(int aError);
|
||||
|
||||
static std::string formatBytes(const std::string& aString) { return formatBytes(toInt64(aString)); }
|
||||
|
||||
ADCHPP_DLL static std::string getShortTimeString();
|
||||
ADCHPP_DLL static std::string getTimeString();
|
||||
|
||||
ADCHPP_DLL static std::string formatBytes(int64_t aBytes);
|
||||
|
||||
ADCHPP_DLL static void tokenize(StringList& lst, const std::string& str, char sep, std::string::size_type j = 0);
|
||||
|
||||
static std::string formatSeconds(int64_t aSec) {
|
||||
char buf[64];
|
||||
sprintf(buf, "%01d:%02d:%02d:%02d", (int)(aSec / (24*60*60)), (int)((aSec / (60*60)) % 24), (int)((aSec / 60) % 60), (int)(aSec % 60));
|
||||
return buf;
|
||||
}
|
||||
|
||||
static bool toBool(const std::string& aString) { return toBool(aString.c_str()); }
|
||||
static int toInt(const std::string& aString) { return toInt(aString.c_str()); }
|
||||
static double toDouble(const std::string& aString) { return toDouble(aString.c_str()); }
|
||||
static float toFloat(const std::string& aString) { return toFloat(aString.c_str()); }
|
||||
static int64_t toInt64(const std::string& aString) { return toInt64(aString.c_str()); }
|
||||
|
||||
static bool toBool(const char* aString) { return toInt(aString) > 0; }
|
||||
static int toInt(const char* aString) { return ::atoi(aString); }
|
||||
static double toDouble(const char* aString) { return ::atof(aString); }
|
||||
static float toFloat(const char* aString) { return (float)::atof(aString); }
|
||||
static int64_t toInt64(const char* aString) {
|
||||
#ifdef _MSC_VER
|
||||
return _atoi64(aString);
|
||||
#else
|
||||
return atoll(aString);
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::string toString(bool val) {
|
||||
return val ? "1" : "0";
|
||||
}
|
||||
|
||||
static std::string toString(short val) {
|
||||
char buf[8];
|
||||
sprintf(buf, "%d", (int)val);
|
||||
return buf;
|
||||
}
|
||||
static std::string toString(unsigned short val) {
|
||||
char buf[8];
|
||||
sprintf(buf, "%u", (unsigned int)val);
|
||||
return buf;
|
||||
}
|
||||
static std::string toString(int val) {
|
||||
char buf[16];
|
||||
sprintf(buf, "%d", val);
|
||||
return buf;
|
||||
}
|
||||
static std::string toString(unsigned int val) {
|
||||
char buf[16];
|
||||
sprintf(buf, "%u", val);
|
||||
return buf;
|
||||
}
|
||||
static std::string toString(long val) {
|
||||
char buf[32];
|
||||
sprintf(buf, "%ld", val);
|
||||
return buf;
|
||||
}
|
||||
static std::string toString(unsigned long val) {
|
||||
char buf[32];
|
||||
sprintf(buf, "%lu", val);
|
||||
return buf;
|
||||
}
|
||||
static std::string toString(long long val) {
|
||||
char buf[32];
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
sprintf(buf, "%I64d", val);
|
||||
#else
|
||||
sprintf(buf, "%lld", val);
|
||||
#endif
|
||||
return buf;
|
||||
}
|
||||
static std::string toString(unsigned long long val) {
|
||||
char buf[32];
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
sprintf(buf, "%I64u", val);
|
||||
#else
|
||||
sprintf(buf, "%llu", val);
|
||||
#endif
|
||||
return buf;
|
||||
}
|
||||
|
||||
static std::string toString(double val, int maxDec = 2) {
|
||||
char buf[32];
|
||||
sprintf(buf, "%.*f", maxDec, val);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const std::string& toString(const std::string& aString) {
|
||||
return aString;
|
||||
}
|
||||
|
||||
/** Avoid this! Use the one of a connected socket instead... */
|
||||
ADCHPP_DLL static std::string getLocalIp();
|
||||
|
||||
ADCHPP_DLL static uint32_t rand();
|
||||
static uint32_t rand(uint32_t high) { return rand() % high; }
|
||||
static uint32_t rand(uint32_t low, uint32_t high) { return rand(high-low) + low; }
|
||||
static double randd() { return ((double)rand()) / ((double)0xffffffff); }
|
||||
|
||||
ADCHPP_DLL static bool isPrivateIp(std::string const& ip);
|
||||
ADCHPP_DLL static bool validateCharset(std::string const& field, int p);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // UTIL_H
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_ADCHPP_H
|
||||
#define ADCHPP_ADCHPP_H
|
||||
|
||||
#include "compiler.h"
|
||||
#include "config.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdarg>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "shared_ptr.h"
|
||||
|
||||
#include "nullptr.h"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#ifdef _UNICODE
|
||||
# ifndef _T
|
||||
# define _T(s) L##s
|
||||
# endif
|
||||
#else
|
||||
# ifndef _T
|
||||
# define _T(s) s
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(max) || defined(min)
|
||||
#error min/max defined
|
||||
#endif
|
||||
|
||||
#endif // STDINC_H
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
|
||||
#include "File.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
using namespace std;
|
||||
|
||||
const char compileTime[] = __DATE__ " " __TIME__;
|
||||
|
||||
//#ifdef _DEBUG
|
||||
void logAssert(const char* file, int line, const char* exp) {
|
||||
try {
|
||||
//File f(Util::getCfgPath() + _T("exceptioninfo.txt"), File::WRITE, File::OPEN | File::CREATE);
|
||||
//f.setEndPos(0);
|
||||
|
||||
//f.write(string(file) + "(" + Util::toString(line) + "): " + string(exp) + "\r\n");
|
||||
} catch (const FileException& e) {
|
||||
dcdebug("logAssert: %s\n", e.getError().c_str());
|
||||
}
|
||||
}
|
||||
//#endif // _DEBUG
|
||||
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @mainpage
|
||||
*
|
||||
* ADCH++ is a server application meant to be used in the Direct Connect network,
|
||||
* released under the GPL-2 license.
|
||||
*
|
||||
* There's a plugin API about which you can find some general
|
||||
* information on the @ref PluginAPI page.
|
||||
*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Please see License.txt for full details regarding licensing.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_COMMON_H
|
||||
#define ADCHPP_COMMON_H
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
extern ADCHPP_DLL const char compileTime[];
|
||||
extern ADCHPP_DLL void logAssert(const char* file, int line, const char* exp);
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
inline void debugTrace(const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
char buf[512];
|
||||
|
||||
_vsnprintf(buf, sizeof(buf), format, args);
|
||||
OutputDebugStringA(buf);
|
||||
fputs(buf, stderr);
|
||||
#else // _MSC_VER
|
||||
vfprintf(stdout, format, args);
|
||||
#endif // _MSC_VER
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
#define dcdebug debugTrace
|
||||
#define dcassert(exp) do { if(!(exp)) logAssert(__FILE__, __LINE__, #exp); } while(false)
|
||||
//#define dcassert(exp) do { if(!(exp)) __asm { int 3}; } while(0)
|
||||
|
||||
#define dcasserta(exp) dcassert(exp)
|
||||
#define dcdrun(exp) exp
|
||||
#else //NDEBUG
|
||||
#define dcdebug if(false) printf
|
||||
//#define dcassert(exp) do { if(!(exp)) logAssert(__FILE__, __LINE__, #exp); } while(0)
|
||||
#define dcassert(exp)
|
||||
#ifdef _MSC_VER
|
||||
#define dcasserta(exp) __assume(exp)
|
||||
#else
|
||||
#define dcasserta(exp)
|
||||
#endif // WIN32
|
||||
#define dcdrun(exp)
|
||||
#endif //NDEBUG
|
||||
|
||||
typedef std::vector<std::string> StringList;
|
||||
typedef StringList::iterator StringIter;
|
||||
typedef StringList::const_iterator StringIterC;
|
||||
|
||||
typedef std::vector<uint8_t> ByteVector;
|
||||
typedef ByteVector::iterator ByteIter;
|
||||
|
||||
}
|
||||
|
||||
#endif // COMMON_H
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)
|
||||
#error GCC 4.4 is required
|
||||
#endif
|
||||
|
||||
#if __GNUC_MINOR__ == 4
|
||||
// GCC 4.4 is missing this type
|
||||
#define default_random_engine minstd_rand0
|
||||
#endif
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
#if _MSC_VER < 1600
|
||||
#error MSVC 10 (2010) is required
|
||||
#endif
|
||||
|
||||
#else
|
||||
#error No supported compiler found
|
||||
|
||||
#endif
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_ADCHPP_CONFIG_H_
|
||||
#define ADCHPP_ADCHPP_CONFIG_H_
|
||||
|
||||
#ifndef _REENTRANT
|
||||
# define _REENTRANT 1
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
//disable the deprecated warnings for the CRT functions.
|
||||
# define _CRT_SECURE_NO_DEPRECATE 1
|
||||
# define _ATL_SECURE_NO_DEPRECATE 1
|
||||
# define _CRT_NON_CONFORMING_SWPRINTFS 1
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
# define _LL(x) x##ll
|
||||
# define _ULL(x) x##ull
|
||||
# define I64_FMT "%I64d"
|
||||
#elif defined(SIZEOF_LONG) && SIZEOF_LONG == 8
|
||||
# define _LL(x) x##l
|
||||
# define _ULL(x) x##ul
|
||||
# define I64_FMT "%ld"
|
||||
#else
|
||||
# define _LL(x) x##ll
|
||||
# define _ULL(x) x##ull
|
||||
# define I64_FMT "%lld"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PATH_SEPARATOR '\\'
|
||||
#define PATH_SEPARATOR_STR "\\"
|
||||
#else
|
||||
#define PATH_SEPARATOR '/'
|
||||
#define PATH_SEPARATOR_STR "/"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
# ifndef _WIN32_WINNT
|
||||
# define _WIN32_WINNT 0x0501
|
||||
# endif
|
||||
# ifndef _WIN32_IE
|
||||
# define _WIN32_IE 0x0501
|
||||
# endif
|
||||
# ifndef WINVER
|
||||
# define WINVER 0x0501
|
||||
# endif
|
||||
# ifndef STRICT
|
||||
# define STRICT 1
|
||||
# endif
|
||||
# ifndef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN 1
|
||||
# endif
|
||||
# ifndef NOMINMAX
|
||||
# define NOMINMAX
|
||||
# endif
|
||||
|
||||
# define ADCHPP_VISIBLE
|
||||
# ifdef BUILDING_ADCHPP
|
||||
# define ADCHPP_DLL __declspec(dllexport)
|
||||
# else
|
||||
# define ADCHPP_DLL __declspec(dllimport)
|
||||
# endif // DLLEXPORT
|
||||
|
||||
#else
|
||||
|
||||
# define ADCHPP_DLL __attribute__ ((visibility("default")))
|
||||
# define ADCHPP_VISIBLE __attribute__ ((visibility("default")))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* CONFIG_H_ */
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_ADCHPP_FORWARD_H_
|
||||
#define ADCHPP_ADCHPP_FORWARD_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "shared_ptr.h"
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
class Client;
|
||||
|
||||
class ClientManager;
|
||||
|
||||
class Core;
|
||||
|
||||
class Entity;
|
||||
|
||||
class LogManager;
|
||||
|
||||
class ManagedSocket;
|
||||
typedef shared_ptr<ManagedSocket> ManagedSocketPtr;
|
||||
|
||||
class PluginManager;
|
||||
|
||||
struct ServerInfo;
|
||||
typedef shared_ptr<ServerInfo> ServerInfoPtr;
|
||||
typedef std::vector<ServerInfoPtr> ServerInfoList;
|
||||
|
||||
class SimpleXML;
|
||||
|
||||
class SocketFactory;
|
||||
typedef shared_ptr<SocketFactory> SocketFactoryPtr;
|
||||
|
||||
class SocketManager;
|
||||
|
||||
}
|
||||
|
||||
#endif /*FORWARD_H_*/
|
|
@ -0,0 +1,27 @@
|
|||
// for compilers that don't support nullptr, use the workaround in section 1.1 of the proposal.
|
||||
|
||||
#ifndef ADCHPP_NULLPTR_H
|
||||
#define ADCHPP_NULLPTR_H
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6) // GCC 4.6 is the first GCC to implement nullptr.
|
||||
|
||||
#define FAKE_NULLPTR
|
||||
|
||||
const // this is a const object...
|
||||
class {
|
||||
public:
|
||||
template<class T> // convertible to any type
|
||||
operator T*() const // of null non-member
|
||||
{ return 0; } // pointer...
|
||||
template<class C, class T> // or any type of null
|
||||
operator T C::*() const // member pointer...
|
||||
{ return 0; }
|
||||
private:
|
||||
void operator&() const; // whose address can't be taken
|
||||
} nullptr = {}; // and whose name is nullptr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // ADCHPP_NULLPTR_H
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_ADCHPP_SHARED_PTR_H_
|
||||
#define ADCHPP_ADCHPP_SHARED_PTR_H_
|
||||
|
||||
#ifdef __MINGW32__
|
||||
|
||||
/* the shared_ptr implementation provided by MinGW / GCC 4.5's libstdc++ consumes too many
|
||||
semaphores, so we prefer boost's one. see <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46455>. */
|
||||
|
||||
// enabling this on newer GCC versions as well as handle leaks still appear when running scripts.
|
||||
/// @todo hopefully remove this someday...
|
||||
|
||||
#define BOOST_ASIO_DISABLE_STD_SHARED_PTR 1
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
|
||||
#define SHARED_PTR_NS boost
|
||||
|
||||
#else
|
||||
|
||||
#include <memory>
|
||||
|
||||
#define SHARED_PTR_NS std
|
||||
|
||||
#endif
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
using SHARED_PTR_NS::shared_ptr;
|
||||
using SHARED_PTR_NS::make_shared;
|
||||
using SHARED_PTR_NS::enable_shared_from_this;
|
||||
using SHARED_PTR_NS::static_pointer_cast;
|
||||
using SHARED_PTR_NS::dynamic_pointer_cast;
|
||||
|
||||
}
|
||||
|
||||
#undef SHARED_PTR_NS
|
||||
|
||||
#endif /* SHARED_PTR_H_ */
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "adchpp.h"
|
||||
#include "version.h"
|
||||
|
||||
#ifndef ADCHPP_REVISION
|
||||
#define ADCHPP_REVISION 0
|
||||
#endif
|
||||
|
||||
#define xstrver(s) strver(s)
|
||||
#define strver(s) #s
|
||||
|
||||
// don't forget to also update the .rc file of adchppd!
|
||||
#define APPNAME "ADCH++"
|
||||
#define VERSIONSTRING "2.12.1 (r\"" xstrver(ADCHPP_REVISION) "\")"
|
||||
#define VERSIONFLOAT 2.96
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define BUILDSTRING "Debug"
|
||||
#else
|
||||
#define BUILDSTRING "Release"
|
||||
#endif
|
||||
|
||||
#define FULLVERSIONSTRING VERSIONSTRING " " BUILDSTRING
|
||||
|
||||
namespace adchpp {
|
||||
|
||||
using namespace std;
|
||||
|
||||
string appName = APPNAME;
|
||||
string versionString = FULLVERSIONSTRING;
|
||||
float versionFloat = VERSIONFLOAT;
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ADCHPP_VERSION_H
|
||||
#define ADCHPP_VERSION_H
|
||||
|
||||
namespace adchpp {
|
||||
ADCHPP_DLL extern std::string appName;
|
||||
ADCHPP_DLL extern std::string versionString;
|
||||
ADCHPP_DLL extern float versionFloat;
|
||||
}
|
||||
|
||||
// This should be updated whenever the plugin API changes
|
||||
#define PLUGINVERSION 1
|
||||
|
||||
#endif // VERSION_H
|
|
@ -0,0 +1,28 @@
|
|||
# vim: set filetype=py
|
||||
|
||||
Import('dev source_path')
|
||||
|
||||
env, target, sources = dev.prepare_build(source_path, 'adchppd', 'adchppd.cpp')
|
||||
|
||||
if dev.is_win32():
|
||||
sources += [dev.get_build_path(source_path) + 'adchppdw.cpp', env.RES(dev.get_sources(source_path, 'res/*.rc'))]
|
||||
else:
|
||||
sources += [dev.get_build_path(source_path) + 'adchppdu.cpp']
|
||||
|
||||
env.Append(CPPPATH = ['.', '#'])
|
||||
env.Append(LIBS=['adchpp'])
|
||||
|
||||
if env['CC'] == 'cl': # MSVC
|
||||
|
||||
from build_util import array_remove
|
||||
array_remove(env['CCFLAGS'], '/LD')
|
||||
array_remove(env['CCFLAGS'], '/LDd')
|
||||
|
||||
env.Append(LIBS = ['advapi32'])
|
||||
|
||||
#if env['nls']:
|
||||
# headers=dev.get_sources(source_path, "*.h")
|
||||
# dev.i18n(source_path, env, [sources,headers], 'adchppd')
|
||||
|
||||
ret = env.Program(target, sources)
|
||||
Return('ret')
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <adchpp/adchpp.h>
|
||||
#include <adchpp/common.h>
|
||||
|
||||
#include "adchppd.h"
|
||||
|
||||
#include <adchpp/Util.h>
|
||||
#include <adchpp/ClientManager.h>
|
||||
#include <adchpp/LogManager.h>
|
||||
#include <adchpp/SocketManager.h>
|
||||
#include <adchpp/PluginManager.h>
|
||||
#include <adchpp/Entity.h>
|
||||
#include <adchpp/File.h>
|
||||
#include <adchpp/SimpleXML.h>
|
||||
#include <adchpp/Core.h>
|
||||
|
||||
using namespace adchpp;
|
||||
using namespace std;
|
||||
|
||||
void loadXML(Core &core, const string& aFileName)
|
||||
{
|
||||
try {
|
||||
SimpleXML xml;
|
||||
|
||||
xml.fromXML(File(aFileName, File::READ, File::OPEN).read());
|
||||
|
||||
xml.resetCurrentChild();
|
||||
|
||||
xml.stepIn();
|
||||
|
||||
while(xml.findChild(Util::emptyString)) {
|
||||
if(xml.getChildName() == "Settings") {
|
||||
xml.stepIn();
|
||||
|
||||
while(xml.findChild(Util::emptyString)) {
|
||||
|
||||
printf("Processing %s\n", xml.getChildName().c_str());
|
||||
if(xml.getChildName() == "HubName") {
|
||||
core.getClientManager().getEntity(AdcCommand::HUB_SID)->setField("NI", xml.getChildData());
|
||||
} else if(xml.getChildName() == "Description") {
|
||||
core.getClientManager().getEntity(AdcCommand::HUB_SID)->setField("DE", xml.getChildData());
|
||||
} else if(xml.getChildName() == "Log") {
|
||||
core.getLogManager().setEnabled(xml.getChildData() == "1");
|
||||
} else if(xml.getChildName() == "LogFile") {
|
||||
core.getLogManager().setLogFile(xml.getChildData());
|
||||
} else if(xml.getChildName() == "MaxCommandSize") {
|
||||
core.getClientManager().setMaxCommandSize(Util::toInt(xml.getChildData()));
|
||||
} else if(xml.getChildName() == "BufferSize") {
|
||||
core.getSocketManager().setBufferSize(Util::toInt(xml.getChildData()));
|
||||
} else if(xml.getChildName() == "MaxBufferSize") {
|
||||
core.getSocketManager().setMaxBufferSize(Util::toInt(xml.getChildData()));
|
||||
} else if(xml.getChildName() == "OverflowTimeout") {
|
||||
core.getSocketManager().setOverflowTimeout(Util::toInt(xml.getChildData()));
|
||||
} else if(xml.getChildName() == "DisconnectTimeout") {
|
||||
core.getSocketManager().setDisconnectTimeout(Util::toInt(xml.getChildData()));
|
||||
} else if(xml.getChildName() == "LogTimeout") {
|
||||
core.getClientManager().setLogTimeout(Util::toInt(xml.getChildData()));
|
||||
}
|
||||
}
|
||||
|
||||
xml.stepOut();
|
||||
} else if(xml.getChildName() == "Servers") {
|
||||
xml.stepIn();
|
||||
|
||||
ServerInfoList servers;
|
||||
|
||||
while(xml.findChild("Server")) {
|
||||
ServerInfoPtr server = make_shared<ServerInfo>();
|
||||
server->port = xml.getChildAttrib("Port", Util::emptyString);
|
||||
|
||||
if(xml.getBoolChildAttrib("TLS")) {
|
||||
server->TLSParams.cert = File::makeAbsolutePath(xml.getChildAttrib("Certificate"));
|
||||
server->TLSParams.pkey = File::makeAbsolutePath(xml.getChildAttrib("PrivateKey"));
|
||||
server->TLSParams.trustedPath = File::makeAbsolutePath(xml.getChildAttrib("TrustedPath"));
|
||||
server->TLSParams.dh = File::makeAbsolutePath(xml.getChildAttrib("DHParams"));
|
||||
}
|
||||
|
||||
#ifndef HAVE_OPENSSL
|
||||
if(server->secure())
|
||||
fprintf(stderr, "Error listening on port %s: This ADCH++ hasn't been compiled with support for secure connections\n", server->port.c_str());
|
||||
else
|
||||
#endif
|
||||
servers.push_back(server);
|
||||
}
|
||||
|
||||
core.getSocketManager().setServers(servers);
|
||||
|
||||
xml.stepOut();
|
||||
} else if(xml.getChildName() == "Plugins") {
|
||||
core.getPluginManager().setPluginPath(xml.getChildAttrib("Path"));
|
||||
xml.stepIn();
|
||||
StringList plugins;
|
||||
while(xml.findChild("Plugin")) {
|
||||
plugins.push_back(xml.getChildData());
|
||||
}
|
||||
|
||||
core.getPluginManager().setPluginList(plugins);
|
||||
xml.stepOut();
|
||||
}
|
||||
}
|
||||
|
||||
xml.stepOut();
|
||||
} catch(const Exception& e) {
|
||||
printf("Unable to load adchpp.xml, using defaults: %s\n", e.getError().c_str());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <adchpp/Core.h>
|
||||
|
||||
void loadXML(adchpp::Core &core, const std::string& fileName);
|
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <adchpp/adchpp.h>
|
||||
#include <adchpp/common.h>
|
||||
|
||||
#include <adchpp/Util.h>
|
||||
#include <adchpp/version.h>
|
||||
#include <adchpp/File.h>
|
||||
#include <adchpp/Core.h>
|
||||
#include <adchpp/shared_ptr.h>
|
||||
|
||||
#include <signal.h>
|
||||
#include <limits.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include "adchppd.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace adchpp;
|
||||
|
||||
static FILE* pidFile;
|
||||
static string pidFileName;
|
||||
static bool asdaemon = false;
|
||||
static shared_ptr<Core> core;
|
||||
|
||||
static void installHandler();
|
||||
|
||||
void breakHandler(int) {
|
||||
if(core) {
|
||||
core->shutdown();
|
||||
}
|
||||
|
||||
installHandler();
|
||||
}
|
||||
|
||||
static void init() {
|
||||
// Ignore SIGPIPE...
|
||||
struct sigaction sa = { 0 };
|
||||
|
||||
sa.sa_handler = SIG_IGN;
|
||||
|
||||
sigaction(SIGPIPE, &sa, NULL);
|
||||
sigaction(SIGHUP, &sa, NULL);
|
||||
|
||||
sigset_t mask;
|
||||
|
||||
sigfillset(&mask); /* Mask all allowed signals, the other threads should inherit
|
||||
this... */
|
||||
sigdelset(&mask, SIGCONT);
|
||||
sigdelset(&mask, SIGFPE);
|
||||
sigdelset(&mask, SIGILL);
|
||||
sigdelset(&mask, SIGSEGV);
|
||||
sigdelset(&mask, SIGBUS);
|
||||
sigdelset(&mask, SIGINT);
|
||||
sigdelset(&mask, SIGTRAP);
|
||||
pthread_sigmask(SIG_SETMASK, &mask, NULL);
|
||||
|
||||
installHandler();
|
||||
|
||||
if(pidFile != NULL) {
|
||||
fprintf(pidFile, "%d", (int)getpid());
|
||||
fflush(pidFile);
|
||||
}
|
||||
|
||||
loadXML(*core, File::makeAbsolutePath(core->getConfigPath(), "adchpp.xml"));
|
||||
}
|
||||
|
||||
static void installHandler() {
|
||||
struct sigaction sa = { 0 };
|
||||
|
||||
sa.sa_handler = breakHandler;
|
||||
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
}
|
||||
|
||||
static void uninit() {
|
||||
if(!asdaemon)
|
||||
printf("Shut down");
|
||||
|
||||
if(pidFile != NULL)
|
||||
fclose(pidFile);
|
||||
pidFile = NULL;
|
||||
|
||||
if(!pidFileName.empty())
|
||||
unlink(pidFileName.c_str());
|
||||
}
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
static void daemonize() {
|
||||
switch(fork()) {
|
||||
case -1:
|
||||
fprintf(stderr, "First fork failed: %s\n", strerror(errno));
|
||||
exit(5);
|
||||
case 0: break;
|
||||
default: _exit(0);
|
||||
}
|
||||
|
||||
if(setsid() < 0) {
|
||||
fprintf(stderr, "setsid failed: %s\n", strerror(errno));
|
||||
exit(6);
|
||||
}
|
||||
|
||||
switch(fork()) {
|
||||
case -1:
|
||||
fprintf(stderr, "Second fork failed: %s\n", strerror(errno));
|
||||
exit(7);
|
||||
case 0: break;
|
||||
default: exit(0);
|
||||
}
|
||||
|
||||
chdir("/");
|
||||
close(0);
|
||||
close(1);
|
||||
close(2);
|
||||
open("/dev/null", O_RDWR);
|
||||
dup(0); dup(0);
|
||||
}
|
||||
|
||||
#include <sys/wait.h>
|
||||
|
||||
static void runDaemon(const string& configPath) {
|
||||
daemonize();
|
||||
|
||||
try {
|
||||
core = Core::create(configPath);
|
||||
|
||||
init();
|
||||
|
||||
core->run();
|
||||
|
||||
core.reset();
|
||||
} catch(const adchpp::Exception& e) {
|
||||
fprintf(stderr, "Failed to start: %s\n", e.what());
|
||||
}
|
||||
|
||||
uninit();
|
||||
}
|
||||
|
||||
static void runConsole(const string& configPath) {
|
||||
printf("Starting."); fflush(stdout);
|
||||
|
||||
try {
|
||||
core = Core::create(configPath);
|
||||
|
||||
printf("."); fflush(stdout);
|
||||
init();
|
||||
|
||||
printf(".\n%s running, press ctrl-c to exit...\n", versionString.c_str());
|
||||
core->run();
|
||||
|
||||
core.reset();
|
||||
} catch(const Exception& e) {
|
||||
fprintf(stderr, "\nFATAL: Can't start ADCH++: %s\n", e.what());
|
||||
}
|
||||
|
||||
uninit();
|
||||
}
|
||||
|
||||
static void printUsage() {
|
||||
printf("Usage: adchpp [[-c <configdir>] [-d]] | [-v] | [-h]\n");
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
char buf[PATH_MAX + 1] = { 0 };
|
||||
char* path = buf;
|
||||
if (readlink("/proc/self/exe", buf, sizeof (buf)) == -1) {
|
||||
path = getenv("_");
|
||||
}
|
||||
|
||||
Util::setApp(path == NULL ? argv[0] : path);
|
||||
string configPath = "/etc/adchpp/";
|
||||
|
||||
for(int i = 1; i < argc; i++) {
|
||||
if(strcmp(argv[i], "-d") == 0) {
|
||||
asdaemon = true;
|
||||
} else if(strcmp(argv[i], "-v") == 0) {
|
||||
printf("%s\n", versionString.c_str());
|
||||
return 0;
|
||||
} else if(strcmp(argv[i], "-c") == 0) {
|
||||
if((i + 1) == argc) {
|
||||
fprintf(stderr, "-c <directory>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
i++;
|
||||
string cfg = argv[i];
|
||||
if(cfg[0] != '/') {
|
||||
fprintf(stderr, "Config dir must be an absolute path\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
if(cfg[cfg.length() - 1] != '/') {
|
||||
cfg+='/';
|
||||
}
|
||||
|
||||
configPath = cfg;
|
||||
} else if(strcmp(argv[i], "-p") == 0) {
|
||||
if((i+1) == argc) {
|
||||
fprintf(stderr, "-p <pid-file>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
i++;
|
||||
pidFileName = argv[i];
|
||||
} else if(strcmp(argv[i], "-h") == 0) {
|
||||
printUsage();
|
||||
return 0;
|
||||
} else {
|
||||
fprintf(stderr, "Unknown parameter: %s\n", argv[i]);
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
if(!pidFileName.empty()) {
|
||||
pidFileName = File::makeAbsolutePath(configPath, pidFileName);
|
||||
pidFile = fopen(pidFileName.c_str(), "w");
|
||||
if(pidFile == NULL) {
|
||||
fprintf(stderr, "Can't open %s for writing\n", pidFileName.c_str());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(asdaemon) {
|
||||
runDaemon(configPath);
|
||||
} else {
|
||||
runConsole(configPath);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,309 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <adchpp/adchpp.h>
|
||||
#include <adchpp/common.h>
|
||||
|
||||
#include <adchpp/LogManager.h>
|
||||
#include <adchpp/Util.h>
|
||||
#include <adchpp/version.h>
|
||||
#include <adchpp/File.h>
|
||||
#include <adchpp/shared_ptr.h>
|
||||
|
||||
#include "adchppd.h"
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
using namespace adchpp;
|
||||
using namespace std;
|
||||
|
||||
static const string modName = "adchpp";
|
||||
|
||||
#define LOGERROR(func) LOG(modName, func " failed: " + Util::translateError(GetLastError()))
|
||||
#define PRINTERROR(func) fprintf(stderr, func " failed: code %lu: %s\n", GetLastError(), Util::translateError(GetLastError()).c_str())
|
||||
|
||||
bool asService = true;
|
||||
static const TCHAR* serviceName = _T("adchpp");
|
||||
static adchpp::shared_ptr<Core> core;
|
||||
static string configPath;
|
||||
|
||||
static void installService() {
|
||||
SC_HANDLE scm = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
|
||||
if(scm == NULL) {
|
||||
PRINTERROR("OpenSCManager");
|
||||
return;
|
||||
}
|
||||
|
||||
string cmdLine = '"' + Util::getAppName() + "\" -c \"" + configPath + "\\\" -d \"" + string(serviceName) + "\"";
|
||||
SC_HANDLE service = CreateService(scm, serviceName, serviceName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
|
||||
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, cmdLine.c_str(),
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
if(service == NULL) {
|
||||
PRINTERROR("CreateService");
|
||||
CloseServiceHandle(scm);
|
||||
return;
|
||||
}
|
||||
|
||||
SERVICE_DESCRIPTION description = { const_cast<LPTSTR>(cmdLine.c_str()) };
|
||||
ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &description);
|
||||
|
||||
fprintf(stdout, "ADCH++ service \"%s\" successfully installed; command line:\n%s\n", serviceName, cmdLine.c_str());
|
||||
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(scm);
|
||||
}
|
||||
|
||||
static void removeService() {
|
||||
SC_HANDLE scm = OpenSCManager(NULL, NULL, STANDARD_RIGHTS_WRITE);
|
||||
if(scm == NULL) {
|
||||
PRINTERROR("OpenSCManager");
|
||||
return;
|
||||
}
|
||||
|
||||
SC_HANDLE service = OpenService(scm, serviceName, DELETE);
|
||||
|
||||
if(service == NULL) {
|
||||
PRINTERROR("OpenService");
|
||||
CloseServiceHandle(scm);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!DeleteService(service)) {
|
||||
PRINTERROR("DeleteService");
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(scm);
|
||||
}
|
||||
|
||||
fprintf(stdout, "ADCH++ service \"%s\" successfully removed\n", serviceName);
|
||||
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(scm);
|
||||
}
|
||||
|
||||
static void init() {
|
||||
//if(asService)
|
||||
//LOG(modName, versionString + " started as a service");
|
||||
//else
|
||||
//LOG(modName, versionString + " started from console");
|
||||
|
||||
loadXML(*core, File::makeAbsolutePath(core->getConfigPath(), "adchpp.xml"));
|
||||
}
|
||||
|
||||
static void uninit() {
|
||||
//LOG(modName, versionString + " shut down");
|
||||
}
|
||||
|
||||
static SERVICE_STATUS_HANDLE ssh = 0;
|
||||
static SERVICE_STATUS ss;
|
||||
|
||||
void WINAPI handler(DWORD code) {
|
||||
switch(code) {
|
||||
case SERVICE_CONTROL_SHUTDOWN: // Fallthrough
|
||||
case SERVICE_CONTROL_STOP:
|
||||
if(core) {
|
||||
ss.dwCurrentState = SERVICE_STOP_PENDING;
|
||||
core->shutdown();
|
||||
} else {
|
||||
ss.dwCurrentState = SERVICE_STOPPED;
|
||||
}
|
||||
break;
|
||||
case SERVICE_CONTROL_INTERROGATE: break;
|
||||
default: ; //LOG(modName, "Unknown service handler code " + Util::toString(code));
|
||||
}
|
||||
|
||||
if(!SetServiceStatus(ssh, &ss)) {
|
||||
//LOGERROR("handler::SetServiceStatus");
|
||||
}
|
||||
}
|
||||
|
||||
static void WINAPI serviceStart(DWORD, TCHAR* argv[]) {
|
||||
ssh = ::RegisterServiceCtrlHandler(argv[0], handler);
|
||||
|
||||
if(ssh == 0) {
|
||||
//LOGERROR("RegisterServiceCtrlHandler");
|
||||
uninit();
|
||||
return;
|
||||
}
|
||||
|
||||
ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
||||
ss.dwCurrentState = SERVICE_START_PENDING;
|
||||
ss.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP;
|
||||
ss.dwWin32ExitCode = NO_ERROR;
|
||||
ss.dwCheckPoint = 0;
|
||||
ss.dwWaitHint = 10 * 1000;
|
||||
|
||||
if(!SetServiceStatus(ssh, &ss)) {
|
||||
//LOGERROR("SetServiceStatus");
|
||||
uninit();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
core = Core::create(configPath);
|
||||
|
||||
init();
|
||||
} catch(const adchpp::Exception& e) {
|
||||
//LOG(modName, "Failed to start: " + e.getError());
|
||||
}
|
||||
|
||||
ss.dwCurrentState = SERVICE_RUNNING;
|
||||
SetServiceStatus(ssh, &ss);
|
||||
|
||||
try {
|
||||
core->run();
|
||||
} catch(const Exception& e) {
|
||||
//LOG(modName, "ADCH++ startup failed because: " + e.getError());
|
||||
}
|
||||
|
||||
ss.dwCurrentState = SERVICE_STOPPED;
|
||||
|
||||
if(!SetServiceStatus(ssh, &ss)) {
|
||||
//LOGERROR("SetServiceStatus");
|
||||
uninit();
|
||||
return;
|
||||
}
|
||||
|
||||
uninit();
|
||||
}
|
||||
|
||||
static void runService() {
|
||||
SERVICE_TABLE_ENTRY DispatchTable[] = {
|
||||
{ (LPTSTR)serviceName, &serviceStart },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
if (!StartServiceCtrlDispatcher(DispatchTable)) {
|
||||
//LOGERROR("StartServiceCtrlDispatcher");
|
||||
}
|
||||
}
|
||||
|
||||
BOOL WINAPI HandlerRoutine(DWORD dwCtrlType) {
|
||||
if(core && dwCtrlType == CTRL_C_EVENT) {
|
||||
core->shutdown();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void runConsole() {
|
||||
SetConsoleCtrlHandler(&HandlerRoutine, TRUE);
|
||||
|
||||
printf("Starting."); fflush(stdout);
|
||||
|
||||
try {
|
||||
core = Core::create(configPath);
|
||||
|
||||
printf("."); fflush(stdout);
|
||||
init();
|
||||
|
||||
// LOG(modName, versionString + " starting from console");
|
||||
printf(".\n%s running, press ctrl-c to exit...\n", versionString.c_str());
|
||||
core->run();
|
||||
|
||||
core.reset();
|
||||
} catch(const Exception& e) {
|
||||
printf("\n\nFATAL: Can't start ADCH++: %s\n", e.getError().c_str());
|
||||
}
|
||||
|
||||
uninit();
|
||||
}
|
||||
|
||||
static void printUsage() {
|
||||
const char* text =
|
||||
"Usage: adchpp [[-c <configdir>] [-i <servicename> | -u <servicename>]] | [-v] | [-h]\n\n"
|
||||
"-c Specify the path of the configuration directory (default: .\\config)\n"
|
||||
"-i <service name> Install a service instance (name defaults to 'adchpp')\n"
|
||||
"-u <service name> Uninstall a service instance\n"
|
||||
"-v Print version number\n"
|
||||
"-h Show this help message\n";
|
||||
|
||||
printf(text);
|
||||
}
|
||||
|
||||
int CDECL main(int argc, char* argv[]) {
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
configPath = Util::getAppPath() + "config\\";
|
||||
|
||||
int task = 0;
|
||||
|
||||
for(int i = 1; i < argc; ++i) {
|
||||
if(_tcscmp(argv[i], _T("-d")) == 0) {
|
||||
if(i+1 == argc) {
|
||||
// Not much to do...
|
||||
return 1;
|
||||
}
|
||||
|
||||
i++;
|
||||
serviceName = argv[i];
|
||||
task = 1;
|
||||
} else if(_tcscmp(argv[i],_T("-c")) == 0) {
|
||||
if((i + 1) == argc) {
|
||||
printf("-c <directory>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
i++;
|
||||
string cfg = argv[i];
|
||||
if(cfg.empty()) {
|
||||
printf("-c <directory>\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
if(!File::isAbsolutePath(cfg)) {
|
||||
printf("Config dir must be an absolute path\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
if(cfg[cfg.length() - 1] != '\\') {
|
||||
cfg += '\\';
|
||||
}
|
||||
|
||||
configPath = cfg;
|
||||
} else if(_tcscmp(argv[i], _T("-i")) == 0) {
|
||||
i++;
|
||||
serviceName = (i >= argc) ? serviceName : argv[i];
|
||||
task = 2;
|
||||
} else if(_tcscmp(argv[i], _T("-u")) == 0) {
|
||||
i++;
|
||||
serviceName = (i >= argc) ? serviceName : argv[i];
|
||||
task = 3;
|
||||
} else if(_tcscmp(argv[i], _T("-v")) == 0) {
|
||||
printf("%s compiled on " __DATE__ " " __TIME__ "\n", versionString.c_str());
|
||||
return 0;
|
||||
} else if(_tcscmp(argv[i], _T("-h")) == 0) {
|
||||
printUsage();
|
||||
return 0;
|
||||
} else {
|
||||
printf("Invalid parameter: %s\n", argv[i]);
|
||||
printUsage();
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
switch(task) {
|
||||
case 0: runConsole(); break;
|
||||
case 1: runService(); break;
|
||||
case 2: installService(); break;
|
||||
case 3: removeService(); break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 180 KiB |
|
@ -0,0 +1,34 @@
|
|||
0 ICON "adchppd.ico"
|
||||
|
||||
1 VERSIONINFO
|
||||
FILEVERSION 2,12,1,0
|
||||
PRODUCTVERSION 2,12,1,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x1L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "http://adchpp.sourceforge.net"
|
||||
VALUE "FileDescription", "ADCH++"
|
||||
VALUE "FileVersion", "2, 12, 1, 0"
|
||||
VALUE "InternalName", "ADCH++"
|
||||
VALUE "LegalCopyright", "Copyright 2006-2014 Jacek Sieka"
|
||||
VALUE "OriginalFilename", "adchppd.exe"
|
||||
VALUE "ProductName", "ADCH++"
|
||||
VALUE "ProductVersion", "2, 12, 1, 0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
|
@ -0,0 +1,23 @@
|
|||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,27 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// \file accumulators.hpp
|
||||
/// Includes all of the Accumulators Framework
|
||||
//
|
||||
// Copyright 2005 Eric Niebler. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_ACCUMULATORS_ACCUMULATORS_HPP_EAN_28_10_2005
|
||||
#define BOOST_ACCUMULATORS_ACCUMULATORS_HPP_EAN_28_10_2005
|
||||
|
||||
#include <boost/accumulators/framework/accumulator_set.hpp>
|
||||
#include <boost/accumulators/framework/accumulator_concept.hpp>
|
||||
#include <boost/accumulators/framework/accumulator_base.hpp>
|
||||
#include <boost/accumulators/framework/extractor.hpp>
|
||||
#include <boost/accumulators/framework/external.hpp>
|
||||
#include <boost/accumulators/framework/features.hpp>
|
||||
#include <boost/accumulators/framework/parameters/accumulator.hpp>
|
||||
#include <boost/accumulators/framework/parameters/sample.hpp>
|
||||
#include <boost/accumulators/framework/parameters/weight.hpp>
|
||||
#include <boost/accumulators/framework/parameters/weights.hpp>
|
||||
#include <boost/accumulators/framework/accumulators/external_accumulator.hpp>
|
||||
#include <boost/accumulators/framework/accumulators/droppable_accumulator.hpp>
|
||||
#include <boost/accumulators/framework/accumulators/reference_accumulator.hpp>
|
||||
#include <boost/accumulators/framework/accumulators/value_accumulator.hpp>
|
||||
|
||||
#endif
|
|
@ -0,0 +1,219 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// accumulators_fwd.hpp
|
||||
//
|
||||
// Copyright 2005 Eric Niebler. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_ACCUMULATORS_ACCUMULATORS_FWD_HPP_EAN_28_10_2005
|
||||
#define BOOST_ACCUMULATORS_ACCUMULATORS_FWD_HPP_EAN_28_10_2005
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/mpl/apply_fwd.hpp> // for mpl::na
|
||||
#include <boost/mpl/limits/vector.hpp>
|
||||
#include <boost/preprocessor/arithmetic/inc.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
#include <boost/accumulators/numeric/functional_fwd.hpp>
|
||||
|
||||
#ifndef BOOST_ACCUMULATORS_MAX_FEATURES
|
||||
/// The maximum number of accumulators that may be put in an accumulator_set.
|
||||
/// Defaults to BOOST_MPL_LIMIT_VECTOR_SIZE (which defaults to 20).
|
||||
# define BOOST_ACCUMULATORS_MAX_FEATURES BOOST_MPL_LIMIT_VECTOR_SIZE
|
||||
#endif
|
||||
|
||||
#if BOOST_ACCUMULATORS_MAX_FEATURES > BOOST_MPL_LIMIT_VECTOR_SIZE
|
||||
# error BOOST_ACCUMULATORS_MAX_FEATURES cannot be larger than BOOST_MPL_LIMIT_VECTOR_SIZE
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_ACCUMULATORS_MAX_ARGS
|
||||
/// The maximum number of arguments that may be specified to an accumulator_set's
|
||||
/// accumulation function. Defaults to 15.
|
||||
# define BOOST_ACCUMULATORS_MAX_ARGS 15
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(__GNUC__, == 3) \
|
||||
|| BOOST_WORKAROUND(__EDG_VERSION__, BOOST_TESTED_AT(306))
|
||||
# define BOOST_ACCUMULATORS_BROKEN_CONST_OVERLOADS
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_ACCUMULATORS_BROKEN_CONST_OVERLOADS
|
||||
# include <boost/utility/enable_if.hpp>
|
||||
# include <boost/type_traits/is_const.hpp>
|
||||
# define BOOST_ACCUMULATORS_PROTO_DISABLE_IF_IS_CONST(T)\
|
||||
, typename boost::disable_if<boost::is_const<T> >::type * = 0
|
||||
#else
|
||||
# define BOOST_ACCUMULATORS_PROTO_DISABLE_IF_IS_CONST(T)
|
||||
#endif
|
||||
|
||||
#define BOOST_ACCUMULATORS_GCC_VERSION \
|
||||
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
||||
|
||||
namespace boost { namespace accumulators
|
||||
{
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Named parameters tags
|
||||
//
|
||||
namespace tag
|
||||
{
|
||||
struct sample;
|
||||
struct weight;
|
||||
struct accumulator;
|
||||
struct weights;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// User-level features
|
||||
//
|
||||
namespace tag
|
||||
{
|
||||
template<typename ValueType, typename Tag>
|
||||
struct value;
|
||||
|
||||
template<typename Tag>
|
||||
struct value_tag;
|
||||
|
||||
template<typename Referent, typename Tag>
|
||||
struct reference;
|
||||
|
||||
template<typename Tag>
|
||||
struct reference_tag;
|
||||
|
||||
template<typename Type, typename Tag = void, typename AccumulatorSet = void>
|
||||
struct external;
|
||||
|
||||
template<typename Feature>
|
||||
struct droppable;
|
||||
}
|
||||
|
||||
template<typename Accumulator>
|
||||
struct droppable_accumulator_base;
|
||||
|
||||
template<typename Accumulator>
|
||||
struct droppable_accumulator;
|
||||
|
||||
template<typename Accumulator>
|
||||
struct with_cached_result;
|
||||
|
||||
template<typename Sample, typename Features, typename Weight = void>
|
||||
struct accumulator_set;
|
||||
|
||||
template<typename Feature>
|
||||
struct extractor;
|
||||
|
||||
template<typename Feature>
|
||||
struct feature_of;
|
||||
|
||||
template<typename Feature>
|
||||
struct as_feature;
|
||||
|
||||
template<typename Feature>
|
||||
struct as_weighted_feature;
|
||||
|
||||
template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_ACCUMULATORS_MAX_FEATURES, typename Feature, mpl::na)>
|
||||
struct depends_on;
|
||||
|
||||
template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_ACCUMULATORS_MAX_FEATURES, typename Feature, mpl::na)>
|
||||
struct features;
|
||||
|
||||
template<typename Feature, typename AccumulatorSet>
|
||||
typename mpl::apply<AccumulatorSet, Feature>::type const &
|
||||
find_accumulator(AccumulatorSet const &acc);
|
||||
|
||||
template<typename Feature, typename AccumulatorSet>
|
||||
typename mpl::apply<AccumulatorSet, Feature>::type::result_type
|
||||
extract_result(AccumulatorSet const &acc);
|
||||
|
||||
template<typename Feature, typename AccumulatorSet, typename A1>
|
||||
typename mpl::apply<AccumulatorSet, Feature>::type::result_type
|
||||
extract_result(AccumulatorSet const &acc, A1 const &a1);
|
||||
|
||||
// ... other overloads generated by Boost.Preprocessor:
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
#define BOOST_ACCUMULATORS_EXTRACT_RESULT_FWD(z, n, _) \
|
||||
template< \
|
||||
typename Feature \
|
||||
, typename AccumulatorSet \
|
||||
BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \
|
||||
> \
|
||||
typename mpl::apply<AccumulatorSet, Feature>::type::result_type \
|
||||
extract_result( \
|
||||
AccumulatorSet const &acc \
|
||||
BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \
|
||||
);
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
BOOST_PP_REPEAT_FROM_TO(
|
||||
2
|
||||
, BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
|
||||
, BOOST_ACCUMULATORS_EXTRACT_RESULT_FWD
|
||||
, _
|
||||
)
|
||||
|
||||
#ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
|
||||
template<typename Feature, typename AccumulatorSet, typename A1, typename A2 ...>
|
||||
typename mpl::apply<AccumulatorSet, Feature>::type::result_type
|
||||
extract_result(AccumulatorSet const &acc, A1 const &a1, A2 const &a2 ...);
|
||||
#endif
|
||||
|
||||
namespace impl
|
||||
{
|
||||
using namespace numeric::operators;
|
||||
|
||||
template<typename Accumulator, typename Tag>
|
||||
struct external_impl;
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<typename Accumulator>
|
||||
struct feature_tag;
|
||||
|
||||
template<typename Feature, typename Sample, typename Weight>
|
||||
struct to_accumulator;
|
||||
|
||||
struct accumulator_set_base;
|
||||
|
||||
template<typename T>
|
||||
struct is_accumulator_set;
|
||||
|
||||
inline void ignore_variable(void const *) {}
|
||||
|
||||
#define BOOST_ACCUMULATORS_IGNORE_GLOBAL(X)\
|
||||
namespace detail { inline void BOOST_PP_CAT(ignore_, X)() { boost::accumulators::detail::ignore_variable(&X); } }
|
||||
}
|
||||
|
||||
}} // namespace boost::accumulators
|
||||
|
||||
// For defining boost::parameter keywords that can be inherited from to
|
||||
// get a nested, class-scoped keyword with the requested alias
|
||||
#define BOOST_PARAMETER_NESTED_KEYWORD(tag_namespace, name, alias) \
|
||||
namespace tag_namespace \
|
||||
{ \
|
||||
template<int Dummy = 0> \
|
||||
struct name ## _ \
|
||||
{ \
|
||||
static char const* keyword_name() \
|
||||
{ \
|
||||
return #name; \
|
||||
} \
|
||||
static ::boost::parameter::keyword<name ## _<Dummy> > &alias; \
|
||||
}; \
|
||||
template<int Dummy> \
|
||||
::boost::parameter::keyword<name ## _<Dummy> > &name ## _<Dummy>::alias = \
|
||||
::boost::parameter::keyword<name ## _<Dummy> >::get(); \
|
||||
typedef name ## _ <> name; \
|
||||
} \
|
||||
namespace \
|
||||
{ \
|
||||
::boost::parameter::keyword<tag_namespace::name> &name = \
|
||||
::boost::parameter::keyword<tag_namespace::name>::get(); \
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,65 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// accumulator_base.hpp
|
||||
//
|
||||
// Copyright 2005 Eric Niebler. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_BASE_HPP_EAN_28_10_2005
|
||||
#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_BASE_HPP_EAN_28_10_2005
|
||||
|
||||
#include <boost/mpl/placeholders.hpp>
|
||||
#include <boost/mpl/joint_view.hpp>
|
||||
#include <boost/mpl/single_view.hpp>
|
||||
#include <boost/mpl/fold.hpp>
|
||||
#include <boost/mpl/contains.hpp>
|
||||
#include <boost/mpl/empty_sequence.hpp>
|
||||
#include <boost/accumulators/framework/accumulator_concept.hpp>
|
||||
|
||||
namespace boost { namespace accumulators
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
typedef void void_;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// dont_care
|
||||
//
|
||||
struct dont_care
|
||||
{
|
||||
template<typename Args>
|
||||
dont_care(Args const &)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// accumulator_base
|
||||
//
|
||||
struct accumulator_base
|
||||
{
|
||||
// hidden if defined in derived classes
|
||||
detail::void_ operator ()(dont_care)
|
||||
{
|
||||
}
|
||||
|
||||
typedef mpl::false_ is_droppable;
|
||||
|
||||
detail::void_ add_ref(dont_care)
|
||||
{
|
||||
}
|
||||
|
||||
detail::void_ drop(dont_care)
|
||||
{
|
||||
}
|
||||
|
||||
detail::void_ on_drop(dont_care)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace boost::accumulators
|
||||
|
||||
#endif
|
|
@ -0,0 +1,29 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// accumulator_concept.hpp
|
||||
//
|
||||
// Copyright 2005 Eric Niebler. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_CONCEPT_HPP_EAN_28_10_2005
|
||||
#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_CONCEPT_HPP_EAN_28_10_2005
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
|
||||
namespace boost { namespace accumulators
|
||||
{
|
||||
|
||||
template<typename Stat>
|
||||
struct accumulator_concept
|
||||
{
|
||||
void constraints()
|
||||
{
|
||||
// TODO: define the stat concept
|
||||
}
|
||||
|
||||
Stat stat;
|
||||
};
|
||||
|
||||
}} // namespace boost::accumulators
|
||||
|
||||
#endif
|
|
@ -0,0 +1,401 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// accumulator_set.hpp
|
||||
//
|
||||
// Copyright 2005 Eric Niebler. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_SET_HPP_EAN_28_10_2005
|
||||
#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_SET_HPP_EAN_28_10_2005
|
||||
|
||||
#include <boost/version.hpp>
|
||||
#include <boost/mpl/apply.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/mpl/protect.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/is_sequence.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/is_base_and_derived.hpp>
|
||||
#include <boost/parameter/parameters.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/accumulators/accumulators_fwd.hpp>
|
||||
#include <boost/accumulators/framework/depends_on.hpp>
|
||||
#include <boost/accumulators/framework/accumulator_concept.hpp>
|
||||
#include <boost/accumulators/framework/parameters/accumulator.hpp>
|
||||
#include <boost/accumulators/framework/parameters/sample.hpp>
|
||||
#include <boost/accumulators/framework/accumulators/external_accumulator.hpp>
|
||||
#include <boost/accumulators/framework/accumulators/droppable_accumulator.hpp>
|
||||
#include <boost/fusion/include/any.hpp>
|
||||
#include <boost/fusion/include/find_if.hpp>
|
||||
#include <boost/fusion/include/for_each.hpp>
|
||||
#include <boost/fusion/include/filter_view.hpp>
|
||||
|
||||
namespace boost { namespace accumulators
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// accumulator_visitor
|
||||
// wrap a boost::parameter argument pack in a Fusion extractor object
|
||||
template<typename Args>
|
||||
struct accumulator_visitor
|
||||
{
|
||||
explicit accumulator_visitor(Args const &a)
|
||||
: args(a)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Accumulator>
|
||||
void operator ()(Accumulator &accumulator) const
|
||||
{
|
||||
accumulator(this->args);
|
||||
}
|
||||
|
||||
private:
|
||||
accumulator_visitor &operator =(accumulator_visitor const &);
|
||||
Args const &args;
|
||||
};
|
||||
|
||||
template<typename Args>
|
||||
inline accumulator_visitor<Args> const make_accumulator_visitor(Args const &args)
|
||||
{
|
||||
return accumulator_visitor<Args>(args);
|
||||
}
|
||||
|
||||
typedef
|
||||
parameter::parameters<
|
||||
parameter::required<tag::accumulator>
|
||||
, parameter::optional<tag::sample>
|
||||
// ... and others which are not specified here...
|
||||
>
|
||||
accumulator_params;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// accumulator_set_base
|
||||
struct accumulator_set_base
|
||||
{
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// is_accumulator_set
|
||||
template<typename T>
|
||||
struct is_accumulator_set
|
||||
: is_base_and_derived<accumulator_set_base, T>
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4355) // warning C4355: 'this' : used in base member initializer list
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief A set of accumulators.
|
||||
///
|
||||
/// accumulator_set resolves the dependencies between features and ensures that
|
||||
/// the accumulators in the set are updated in the proper order.
|
||||
///
|
||||
/// acccumulator_set provides a general mechanism to visit the accumulators
|
||||
/// in the set in order, with or without a filter. You can also fetch a reference
|
||||
/// to an accumulator that corresponds to a feature.
|
||||
///
|
||||
template<typename Sample, typename Features, typename Weight>
|
||||
struct accumulator_set
|
||||
: detail::accumulator_set_base
|
||||
{
|
||||
typedef Sample sample_type; ///< The type of the samples that will be accumulated
|
||||
typedef Features features_type; ///< An MPL sequence of the features that should be accumulated.
|
||||
typedef Weight weight_type; ///< The type of the weight parameter. Must be a scalar. Defaults to void.
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
typedef
|
||||
typename detail::make_accumulator_tuple<
|
||||
Features
|
||||
, Sample
|
||||
, Weight
|
||||
>::type
|
||||
accumulators_mpl_vector;
|
||||
|
||||
// generate a fusion::list of accumulators
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
typedef
|
||||
typename detail::meta::make_acc_list<
|
||||
accumulators_mpl_vector
|
||||
>::type
|
||||
accumulators_type;
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
//BOOST_MPL_ASSERT((mpl::is_sequence<accumulators_type>));
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// default-construct all contained accumulators
|
||||
accumulator_set()
|
||||
: accumulators(
|
||||
detail::make_acc_list(
|
||||
accumulators_mpl_vector()
|
||||
, detail::accumulator_params()(*this)
|
||||
)
|
||||
)
|
||||
{
|
||||
// Add-ref the Features that the user has specified
|
||||
this->template visit_if<detail::contains_feature_of_<Features> >(
|
||||
detail::make_add_ref_visitor(detail::accumulator_params()(*this))
|
||||
);
|
||||
}
|
||||
|
||||
/// \overload
|
||||
///
|
||||
/// \param a1 Optional named parameter to be passed to all the accumulators
|
||||
template<typename A1>
|
||||
explicit accumulator_set(A1 const &a1)
|
||||
: accumulators(
|
||||
detail::make_acc_list(
|
||||
accumulators_mpl_vector()
|
||||
, detail::accumulator_params()(*this, a1)
|
||||
)
|
||||
)
|
||||
{
|
||||
// Add-ref the Features that the user has specified
|
||||
this->template visit_if<detail::contains_feature_of_<Features> >(
|
||||
detail::make_add_ref_visitor(detail::accumulator_params()(*this))
|
||||
);
|
||||
}
|
||||
|
||||
// ... other overloads generated by Boost.Preprocessor:
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
#define BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR(z, n, _) \
|
||||
template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
|
||||
accumulator_set(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a)) \
|
||||
: accumulators( \
|
||||
detail::make_acc_list( \
|
||||
accumulators_mpl_vector() \
|
||||
, detail::accumulator_params()( \
|
||||
*this BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \
|
||||
) \
|
||||
) \
|
||||
) \
|
||||
{ \
|
||||
/* Add-ref the Features that the user has specified */ \
|
||||
this->template visit_if<detail::contains_feature_of_<Features> >( \
|
||||
detail::make_add_ref_visitor(detail::accumulator_params()(*this)) \
|
||||
); \
|
||||
}
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
BOOST_PP_REPEAT_FROM_TO(
|
||||
2
|
||||
, BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
|
||||
, BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR
|
||||
, _
|
||||
)
|
||||
|
||||
#ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
|
||||
/// \overload
|
||||
///
|
||||
template<typename A1, typename A2, ...>
|
||||
accumulator_set(A1 const &a1, A2 const &a2, ...);
|
||||
#endif
|
||||
|
||||
// ... other overloads generated by Boost.Preprocessor below ...
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Visitation
|
||||
/// \param func UnaryFunction which is invoked with each accumulator in turn.
|
||||
template<typename UnaryFunction>
|
||||
void visit(UnaryFunction const &func)
|
||||
{
|
||||
fusion::for_each(this->accumulators, func);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Conditional visitation
|
||||
/// \param func UnaryFunction which is invoked with each accumulator in turn,
|
||||
/// provided the accumulator satisfies the MPL predicate FilterPred.
|
||||
template<typename FilterPred, typename UnaryFunction>
|
||||
void visit_if(UnaryFunction const &func)
|
||||
{
|
||||
fusion::filter_view<accumulators_type, FilterPred> filtered_accs(this->accumulators);
|
||||
fusion::for_each(filtered_accs, func);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// The return type of the operator() overloads is void.
|
||||
typedef void result_type;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Accumulation
|
||||
/// \param a1 Optional named parameter to be passed to all the accumulators
|
||||
void operator ()()
|
||||
{
|
||||
this->visit(
|
||||
detail::make_accumulator_visitor(
|
||||
detail::accumulator_params()(*this)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename A1>
|
||||
void operator ()(A1 const &a1)
|
||||
{
|
||||
this->visit(
|
||||
detail::make_accumulator_visitor(
|
||||
detail::accumulator_params()(*this, a1)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// ... other overloads generated by Boost.Preprocessor:
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
#define BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP(z, n, _) \
|
||||
template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
|
||||
void operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a)) \
|
||||
{ \
|
||||
this->visit( \
|
||||
detail::make_accumulator_visitor( \
|
||||
detail::accumulator_params()( \
|
||||
*this BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \
|
||||
) \
|
||||
) \
|
||||
); \
|
||||
}
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
BOOST_PP_REPEAT_FROM_TO(
|
||||
2
|
||||
, BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
|
||||
, BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP
|
||||
, _
|
||||
)
|
||||
|
||||
#ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
|
||||
/// \overload
|
||||
///
|
||||
template<typename A1, typename A2, ...>
|
||||
void operator ()(A1 const &a1, A2 const &a2, ...);
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Extraction
|
||||
template<typename Feature>
|
||||
struct apply
|
||||
: fusion::result_of::value_of<
|
||||
typename fusion::result_of::find_if<
|
||||
accumulators_type
|
||||
, detail::matches_feature<Feature>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Extraction
|
||||
template<typename Feature>
|
||||
typename apply<Feature>::type &extract()
|
||||
{
|
||||
return *fusion::find_if<detail::matches_feature<Feature> >(this->accumulators);
|
||||
}
|
||||
|
||||
/// \overload
|
||||
template<typename Feature>
|
||||
typename apply<Feature>::type const &extract() const
|
||||
{
|
||||
return *fusion::find_if<detail::matches_feature<Feature> >(this->accumulators);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Drop
|
||||
template<typename Feature>
|
||||
void drop()
|
||||
{
|
||||
// You can only drop the features that you have specified explicitly
|
||||
typedef typename apply<Feature>::type the_accumulator;
|
||||
BOOST_MPL_ASSERT((detail::contains_feature_of<Features, the_accumulator>));
|
||||
|
||||
typedef
|
||||
typename feature_of<typename as_feature<Feature>::type>::type
|
||||
the_feature;
|
||||
|
||||
(*fusion::find_if<detail::matches_feature<Feature> >(this->accumulators))
|
||||
.drop(detail::accumulator_params()(*this));
|
||||
|
||||
// Also drop accumulators that this feature depends on
|
||||
typedef typename the_feature::dependencies dependencies;
|
||||
this->template visit_if<detail::contains_feature_of_<dependencies> >(
|
||||
detail::make_drop_visitor(detail::accumulator_params()(*this))
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
accumulators_type accumulators;
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// find_accumulator
|
||||
// find an accumulator in an accumulator_set corresponding to a feature
|
||||
template<typename Feature, typename AccumulatorSet>
|
||||
typename mpl::apply<AccumulatorSet, Feature>::type &
|
||||
find_accumulator(AccumulatorSet &acc BOOST_ACCUMULATORS_PROTO_DISABLE_IF_IS_CONST(AccumulatorSet))
|
||||
{
|
||||
return acc.template extract<Feature>();
|
||||
}
|
||||
|
||||
/// \overload
|
||||
template<typename Feature, typename AccumulatorSet>
|
||||
typename mpl::apply<AccumulatorSet, Feature>::type const &
|
||||
find_accumulator(AccumulatorSet const &acc)
|
||||
{
|
||||
return acc.template extract<Feature>();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// extract_result
|
||||
// extract a result from an accumulator set
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
#define BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN(z, n, _) \
|
||||
template< \
|
||||
typename Feature \
|
||||
, typename AccumulatorSet \
|
||||
BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \
|
||||
> \
|
||||
typename mpl::apply<AccumulatorSet, Feature>::type::result_type \
|
||||
extract_result( \
|
||||
AccumulatorSet const &acc \
|
||||
BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \
|
||||
) \
|
||||
{ \
|
||||
return find_accumulator<Feature>(acc).result( \
|
||||
detail::accumulator_params()( \
|
||||
acc \
|
||||
BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \
|
||||
) \
|
||||
); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT(
|
||||
BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
|
||||
, BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN
|
||||
, _
|
||||
)
|
||||
|
||||
}} // namespace boost::accumulators
|
||||
|
||||
#endif
|
|
@ -0,0 +1,328 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// droppable_accumulator.hpp
|
||||
//
|
||||
// Copyright 2005 Eric Niebler. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_DROPPABLE_ACCUMULATOR_HPP_EAN_13_12_2005
|
||||
#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_DROPPABLE_ACCUMULATOR_HPP_EAN_13_12_2005
|
||||
|
||||
#include <new>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/mpl/apply.hpp>
|
||||
#include <boost/aligned_storage.hpp>
|
||||
#include <boost/accumulators/framework/depends_on.hpp> // for feature_of
|
||||
#include <boost/accumulators/framework/parameters/accumulator.hpp> // for accumulator
|
||||
|
||||
namespace boost { namespace accumulators
|
||||
{
|
||||
|
||||
template<typename Accumulator>
|
||||
struct droppable_accumulator;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// add_ref_visitor
|
||||
// a fusion function object for add_ref'ing accumulators
|
||||
template<typename Args>
|
||||
struct add_ref_visitor
|
||||
{
|
||||
explicit add_ref_visitor(Args const &args)
|
||||
: args_(args)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Accumulator>
|
||||
void operator ()(Accumulator &acc) const
|
||||
{
|
||||
typedef typename Accumulator::feature_tag::dependencies dependencies;
|
||||
|
||||
acc.add_ref(this->args_);
|
||||
|
||||
// Also add_ref accumulators that this feature depends on
|
||||
this->args_[accumulator].template
|
||||
visit_if<detail::contains_feature_of_<dependencies> >(
|
||||
*this
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
add_ref_visitor &operator =(add_ref_visitor const &);
|
||||
Args const &args_;
|
||||
};
|
||||
|
||||
template<typename Args>
|
||||
add_ref_visitor<Args> make_add_ref_visitor(Args const &args)
|
||||
{
|
||||
return add_ref_visitor<Args>(args);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// drop_visitor
|
||||
// a fusion function object for dropping accumulators
|
||||
template<typename Args>
|
||||
struct drop_visitor
|
||||
{
|
||||
explicit drop_visitor(Args const &args)
|
||||
: args_(args)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Accumulator>
|
||||
void operator ()(Accumulator &acc) const
|
||||
{
|
||||
if(typename Accumulator::is_droppable())
|
||||
{
|
||||
typedef typename Accumulator::feature_tag::dependencies dependencies;
|
||||
|
||||
acc.drop(this->args_);
|
||||
// Also drop accumulators that this feature depends on
|
||||
this->args_[accumulator].template
|
||||
visit_if<detail::contains_feature_of_<dependencies> >(
|
||||
*this
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
drop_visitor &operator =(drop_visitor const &);
|
||||
Args const &args_;
|
||||
};
|
||||
|
||||
template<typename Args>
|
||||
drop_visitor<Args> make_drop_visitor(Args const &args)
|
||||
{
|
||||
return drop_visitor<Args>(args);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// droppable_accumulator_base
|
||||
template<typename Accumulator>
|
||||
struct droppable_accumulator_base
|
||||
: Accumulator
|
||||
{
|
||||
typedef droppable_accumulator_base base;
|
||||
typedef mpl::true_ is_droppable;
|
||||
typedef typename Accumulator::result_type result_type;
|
||||
|
||||
template<typename Args>
|
||||
droppable_accumulator_base(Args const &args)
|
||||
: Accumulator(args)
|
||||
, ref_count_(0)
|
||||
{
|
||||
}
|
||||
|
||||
droppable_accumulator_base(droppable_accumulator_base const &that)
|
||||
: Accumulator(*static_cast<Accumulator const *>(&that))
|
||||
, ref_count_(that.ref_count_)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Args>
|
||||
void operator ()(Args const &args)
|
||||
{
|
||||
if(!this->is_dropped())
|
||||
{
|
||||
this->Accumulator::operator ()(args);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Args>
|
||||
void add_ref(Args const &)
|
||||
{
|
||||
++this->ref_count_;
|
||||
}
|
||||
|
||||
template<typename Args>
|
||||
void drop(Args const &args)
|
||||
{
|
||||
BOOST_ASSERT(0 < this->ref_count_);
|
||||
if(1 == this->ref_count_)
|
||||
{
|
||||
static_cast<droppable_accumulator<Accumulator> *>(this)->on_drop(args);
|
||||
}
|
||||
--this->ref_count_;
|
||||
}
|
||||
|
||||
bool is_dropped() const
|
||||
{
|
||||
return 0 == this->ref_count_;
|
||||
}
|
||||
|
||||
private:
|
||||
int ref_count_;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// droppable_accumulator
|
||||
// this can be specialized for any type that needs special handling
|
||||
template<typename Accumulator>
|
||||
struct droppable_accumulator
|
||||
: droppable_accumulator_base<Accumulator>
|
||||
{
|
||||
template<typename Args>
|
||||
droppable_accumulator(Args const &args)
|
||||
: droppable_accumulator::base(args)
|
||||
{
|
||||
}
|
||||
|
||||
droppable_accumulator(droppable_accumulator const &that)
|
||||
: droppable_accumulator::base(*static_cast<typename droppable_accumulator::base const *>(&that))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// with_cached_result
|
||||
template<typename Accumulator>
|
||||
struct with_cached_result
|
||||
: Accumulator
|
||||
{
|
||||
typedef typename Accumulator::result_type result_type;
|
||||
|
||||
template<typename Args>
|
||||
with_cached_result(Args const &args)
|
||||
: Accumulator(args)
|
||||
, cache()
|
||||
{
|
||||
}
|
||||
|
||||
with_cached_result(with_cached_result const &that)
|
||||
: Accumulator(*static_cast<Accumulator const *>(&that))
|
||||
, cache()
|
||||
{
|
||||
if(that.has_result())
|
||||
{
|
||||
this->set(that.get());
|
||||
}
|
||||
}
|
||||
|
||||
~with_cached_result()
|
||||
{
|
||||
// Since this is a base class of droppable_accumulator_base,
|
||||
// this destructor is called before any of droppable_accumulator_base's
|
||||
// members get cleaned up, including is_dropped, so the following
|
||||
// call to has_result() is valid.
|
||||
if(this->has_result())
|
||||
{
|
||||
this->get().~result_type();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Args>
|
||||
void on_drop(Args const &args)
|
||||
{
|
||||
// cache the result at the point this calcuation was dropped
|
||||
BOOST_ASSERT(!this->has_result());
|
||||
this->set(this->Accumulator::result(args));
|
||||
}
|
||||
|
||||
template<typename Args>
|
||||
result_type result(Args const &args) const
|
||||
{
|
||||
return this->has_result() ? this->get() : this->Accumulator::result(args);
|
||||
}
|
||||
|
||||
private:
|
||||
with_cached_result &operator =(with_cached_result const &);
|
||||
|
||||
void set(result_type const &r)
|
||||
{
|
||||
::new(this->cache.address()) result_type(r);
|
||||
}
|
||||
|
||||
result_type const &get() const
|
||||
{
|
||||
return *static_cast<result_type const *>(this->cache.address());
|
||||
}
|
||||
|
||||
bool has_result() const
|
||||
{
|
||||
typedef with_cached_result<Accumulator> this_type;
|
||||
typedef droppable_accumulator_base<this_type> derived_type;
|
||||
return static_cast<derived_type const *>(this)->is_dropped();
|
||||
}
|
||||
|
||||
aligned_storage<sizeof(result_type)> cache;
|
||||
};
|
||||
|
||||
namespace tag
|
||||
{
|
||||
template<typename Feature>
|
||||
struct as_droppable
|
||||
{
|
||||
typedef droppable<Feature> type;
|
||||
};
|
||||
|
||||
template<typename Feature>
|
||||
struct as_droppable<droppable<Feature> >
|
||||
{
|
||||
typedef droppable<Feature> type;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// droppable
|
||||
template<typename Feature>
|
||||
struct droppable
|
||||
: as_feature<Feature>::type
|
||||
{
|
||||
typedef typename as_feature<Feature>::type feature_type;
|
||||
typedef typename feature_type::dependencies tmp_dependencies_;
|
||||
|
||||
typedef
|
||||
typename mpl::transform<
|
||||
typename feature_type::dependencies
|
||||
, as_droppable<mpl::_1>
|
||||
>::type
|
||||
dependencies;
|
||||
|
||||
struct impl
|
||||
{
|
||||
template<typename Sample, typename Weight>
|
||||
struct apply
|
||||
{
|
||||
typedef
|
||||
droppable_accumulator<
|
||||
typename mpl::apply2<typename feature_type::impl, Sample, Weight>::type
|
||||
>
|
||||
type;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// make droppable<tag::feature(modifier)> work
|
||||
template<typename Feature>
|
||||
struct as_feature<tag::droppable<Feature> >
|
||||
{
|
||||
typedef tag::droppable<typename as_feature<Feature>::type> type;
|
||||
};
|
||||
|
||||
// make droppable<tag::mean> work with non-void weights (should become
|
||||
// droppable<tag::weighted_mean>
|
||||
template<typename Feature>
|
||||
struct as_weighted_feature<tag::droppable<Feature> >
|
||||
{
|
||||
typedef tag::droppable<typename as_weighted_feature<Feature>::type> type;
|
||||
};
|
||||
|
||||
// for the purposes of feature-based dependency resolution,
|
||||
// droppable<Foo> provides the same feature as Foo
|
||||
template<typename Feature>
|
||||
struct feature_of<tag::droppable<Feature> >
|
||||
: feature_of<Feature>
|
||||
{
|
||||
};
|
||||
|
||||
// Note: Usually, the extractor is pulled into the accumulators namespace with
|
||||
// a using directive, not the tag. But the droppable<> feature doesn't have an
|
||||
// extractor, so we can put the droppable tag in the accumulators namespace
|
||||
// without fear of a name conflict.
|
||||
using tag::droppable;
|
||||
|
||||
}} // namespace boost::accumulators
|
||||
|
||||
#endif
|
|
@ -0,0 +1,108 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// external_accumulator.hpp
|
||||
//
|
||||
// Copyright 2005 Eric Niebler. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_EXTERNAL_ACCUMULATOR_HPP_EAN_01_12_2005
|
||||
#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_EXTERNAL_ACCUMULATOR_HPP_EAN_01_12_2005
|
||||
|
||||
#include <boost/mpl/placeholders.hpp>
|
||||
#include <boost/parameter/keyword.hpp>
|
||||
#include <boost/accumulators/framework/extractor.hpp>
|
||||
#include <boost/accumulators/framework/depends_on.hpp> // for feature_tag
|
||||
#include <boost/accumulators/framework/accumulator_base.hpp>
|
||||
#include <boost/accumulators/framework/accumulators/reference_accumulator.hpp>
|
||||
|
||||
namespace boost { namespace accumulators { namespace impl
|
||||
{
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// external_impl
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
template<typename Accumulator, typename Tag>
|
||||
struct external_impl
|
||||
: accumulator_base
|
||||
{
|
||||
typedef typename Accumulator::result_type result_type;
|
||||
typedef typename detail::feature_tag<Accumulator>::type feature_tag;
|
||||
|
||||
external_impl(dont_care) {}
|
||||
|
||||
template<typename Args>
|
||||
result_type result(Args const &args) const
|
||||
{
|
||||
return this->extract_(args, args[parameter::keyword<Tag>::get() | 0]);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template<typename Args>
|
||||
static result_type extract_(Args const &args, int)
|
||||
{
|
||||
// No named parameter passed to the extractor. Maybe the external
|
||||
// feature is held by reference<>.
|
||||
extractor<feature_tag> extract;
|
||||
return extract(accumulators::reference_tag<Tag>(args));
|
||||
}
|
||||
|
||||
template<typename Args, typename AccumulatorSet>
|
||||
static result_type extract_(Args const &, AccumulatorSet const &acc)
|
||||
{
|
||||
// OK, a named parameter for this external feature was passed to the
|
||||
// extractor, so use that.
|
||||
extractor<feature_tag> extract;
|
||||
return extract(acc);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
|
||||
namespace tag
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// external
|
||||
template<typename Feature, typename Tag, typename AccumulatorSet>
|
||||
struct external
|
||||
: depends_on<reference<AccumulatorSet, Tag> >
|
||||
{
|
||||
typedef
|
||||
accumulators::impl::external_impl<
|
||||
detail::to_accumulator<Feature, mpl::_1, mpl::_2>
|
||||
, Tag
|
||||
>
|
||||
impl;
|
||||
};
|
||||
|
||||
template<typename Feature, typename Tag>
|
||||
struct external<Feature, Tag, void>
|
||||
: depends_on<>
|
||||
{
|
||||
typedef
|
||||
accumulators::impl::external_impl<
|
||||
detail::to_accumulator<Feature, mpl::_1, mpl::_2>
|
||||
, Tag
|
||||
>
|
||||
impl;
|
||||
};
|
||||
}
|
||||
|
||||
// for the purposes of feature-based dependency resolution,
|
||||
// external_accumulator<Feature, Tag> provides the same feature as Feature
|
||||
template<typename Feature, typename Tag, typename AccumulatorSet>
|
||||
struct feature_of<tag::external<Feature, Tag, AccumulatorSet> >
|
||||
: feature_of<Feature>
|
||||
{
|
||||
};
|
||||
|
||||
// Note: Usually, the extractor is pulled into the accumulators namespace with
|
||||
// a using directive, not the tag. But the external<> feature doesn't have an
|
||||
// extractor, so we can put the external tag in the accumulators namespace
|
||||
// without fear of a name conflict.
|
||||
using tag::external;
|
||||
|
||||
}} // namespace boost::accumulators
|
||||
|
||||
#endif
|
|
@ -0,0 +1,89 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// reference_accumulator.hpp
|
||||
//
|
||||
// Copyright 2005 Eric Niebler. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_REFERENCE_ACCUMULATOR_HPP_EAN_03_23_2006
|
||||
#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_REFERENCE_ACCUMULATOR_HPP_EAN_03_23_2006
|
||||
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/mpl/always.hpp>
|
||||
#include <boost/parameter/keyword.hpp>
|
||||
#include <boost/accumulators/framework/depends_on.hpp> // for feature_tag
|
||||
#include <boost/accumulators/framework/accumulator_base.hpp>
|
||||
#include <boost/accumulators/framework/extractor.hpp>
|
||||
|
||||
namespace boost { namespace accumulators
|
||||
{
|
||||
|
||||
namespace impl
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// reference_accumulator_impl
|
||||
//
|
||||
template<typename Referent, typename Tag>
|
||||
struct reference_accumulator_impl
|
||||
: accumulator_base
|
||||
{
|
||||
typedef Referent &result_type;
|
||||
|
||||
template<typename Args>
|
||||
reference_accumulator_impl(Args const &args)
|
||||
: ref(args[parameter::keyword<Tag>::get()])
|
||||
{
|
||||
}
|
||||
|
||||
result_type result(dont_care) const
|
||||
{
|
||||
return this->ref;
|
||||
}
|
||||
|
||||
private:
|
||||
reference_wrapper<Referent> ref;
|
||||
};
|
||||
} // namespace impl
|
||||
|
||||
namespace tag
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// reference_tag
|
||||
template<typename Tag>
|
||||
struct reference_tag
|
||||
{
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// reference
|
||||
template<typename Referent, typename Tag>
|
||||
struct reference
|
||||
: depends_on<>
|
||||
{
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
typedef mpl::always<accumulators::impl::reference_accumulator_impl<Referent, Tag> > impl;
|
||||
};
|
||||
}
|
||||
|
||||
namespace extract
|
||||
{
|
||||
BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, reference, (typename)(typename))
|
||||
BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, reference_tag, (typename))
|
||||
}
|
||||
|
||||
using extract::reference;
|
||||
using extract::reference_tag;
|
||||
|
||||
// Map all reference<V,T> features to reference_tag<T> so
|
||||
// that references can be extracted using reference_tag<T>
|
||||
// without specifying the referent type.
|
||||
template<typename ValueType, typename Tag>
|
||||
struct feature_of<tag::reference<ValueType, Tag> >
|
||||
: feature_of<tag::reference_tag<Tag> >
|
||||
{
|
||||
};
|
||||
|
||||
}} // namespace boost::accumulators
|
||||
|
||||
#endif
|
|
@ -0,0 +1,89 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// value_accumulator.hpp
|
||||
//
|
||||
// Copyright 2005 Eric Niebler, Daniel Egloff. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_VALUE_ACCUMULATOR_HPP_EAN_03_23_2006
|
||||
#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_VALUE_ACCUMULATOR_HPP_EAN_03_23_2006
|
||||
|
||||
#include <boost/mpl/always.hpp>
|
||||
#include <boost/parameter/keyword.hpp>
|
||||
#include <boost/accumulators/framework/depends_on.hpp> // for feature_tag
|
||||
#include <boost/accumulators/framework/accumulator_base.hpp>
|
||||
#include <boost/accumulators/framework/extractor.hpp>
|
||||
|
||||
namespace boost { namespace accumulators
|
||||
{
|
||||
|
||||
namespace impl
|
||||
{
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// value_accumulator_impl
|
||||
template<typename ValueType, typename Tag>
|
||||
struct value_accumulator_impl
|
||||
: accumulator_base
|
||||
{
|
||||
typedef ValueType result_type;
|
||||
|
||||
template<typename Args>
|
||||
value_accumulator_impl(Args const &args)
|
||||
: val(args[parameter::keyword<Tag>::get()])
|
||||
{
|
||||
}
|
||||
|
||||
result_type result(dont_care) const
|
||||
{
|
||||
return this->val;
|
||||
}
|
||||
|
||||
private:
|
||||
ValueType val;
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
|
||||
namespace tag
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// value_tag
|
||||
template<typename Tag>
|
||||
struct value_tag
|
||||
{
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// value
|
||||
template<typename ValueType, typename Tag>
|
||||
struct value
|
||||
: depends_on<>
|
||||
{
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
typedef mpl::always<accumulators::impl::value_accumulator_impl<ValueType, Tag> > impl;
|
||||
};
|
||||
}
|
||||
|
||||
namespace extract
|
||||
{
|
||||
BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, value, (typename)(typename))
|
||||
BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, value_tag, (typename))
|
||||
}
|
||||
|
||||
using extract::value;
|
||||
using extract::value_tag;
|
||||
|
||||
// Map all value<V,T> features to value_tag<T> so
|
||||
// that values can be extracted using value_tag<T>
|
||||
// without specifying the value type.
|
||||
template<typename ValueType, typename Tag>
|
||||
struct feature_of<tag::value<ValueType, Tag> >
|
||||
: feature_of<tag::value_tag<Tag> >
|
||||
{
|
||||
};
|
||||
|
||||
}} // namespace boost::accumulators
|
||||
|
||||
#endif
|
|
@ -0,0 +1,448 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// depends_on.hpp
|
||||
//
|
||||
// Copyright 2005 Eric Niebler. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_ACCUMULATORS_FRAMEWORK_DEPENDS_ON_HPP_EAN_28_10_2005
|
||||
#define BOOST_ACCUMULATORS_FRAMEWORK_DEPENDS_ON_HPP_EAN_28_10_2005
|
||||
|
||||
#include <boost/version.hpp>
|
||||
#include <boost/mpl/end.hpp>
|
||||
#include <boost/mpl/map.hpp>
|
||||
#include <boost/mpl/set.hpp>
|
||||
#include <boost/mpl/copy.hpp>
|
||||
#include <boost/mpl/fold.hpp>
|
||||
#include <boost/mpl/size.hpp>
|
||||
#include <boost/mpl/sort.hpp>
|
||||
#include <boost/mpl/insert.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/mpl/remove.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/inherit.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/equal_to.hpp>
|
||||
#include <boost/mpl/contains.hpp>
|
||||
#include <boost/mpl/transform.hpp>
|
||||
#include <boost/mpl/is_sequence.hpp>
|
||||
#include <boost/mpl/placeholders.hpp>
|
||||
#include <boost/mpl/insert_range.hpp>
|
||||
#include <boost/mpl/back_inserter.hpp>
|
||||
#include <boost/mpl/transform_view.hpp>
|
||||
#include <boost/mpl/inherit_linearly.hpp>
|
||||
#include <boost/type_traits/is_base_and_derived.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/facilities/intercept.hpp>
|
||||
#include <boost/accumulators/accumulators_fwd.hpp>
|
||||
#include <boost/fusion/include/next.hpp>
|
||||
#include <boost/fusion/include/equal_to.hpp>
|
||||
#include <boost/fusion/include/value_of.hpp>
|
||||
#include <boost/fusion/include/mpl.hpp>
|
||||
#include <boost/fusion/include/end.hpp>
|
||||
#include <boost/fusion/include/begin.hpp>
|
||||
#include <boost/fusion/include/cons.hpp>
|
||||
|
||||
namespace boost { namespace accumulators
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// as_feature
|
||||
template<typename Feature>
|
||||
struct as_feature
|
||||
{
|
||||
typedef Feature type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// weighted_feature
|
||||
template<typename Feature>
|
||||
struct as_weighted_feature
|
||||
{
|
||||
typedef Feature type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// feature_of
|
||||
template<typename Feature>
|
||||
struct feature_of
|
||||
{
|
||||
typedef Feature type;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// feature_tag
|
||||
template<typename Accumulator>
|
||||
struct feature_tag
|
||||
{
|
||||
typedef typename Accumulator::feature_tag type;
|
||||
};
|
||||
|
||||
template<typename Feature>
|
||||
struct undroppable
|
||||
{
|
||||
typedef Feature type;
|
||||
};
|
||||
|
||||
template<typename Feature>
|
||||
struct undroppable<tag::droppable<Feature> >
|
||||
{
|
||||
typedef Feature type;
|
||||
};
|
||||
|
||||
// For the purpose of determining whether one feature depends on another,
|
||||
// disregard whether the feature is droppable or not.
|
||||
template<typename A, typename B>
|
||||
struct is_dependent_on
|
||||
: is_base_and_derived<
|
||||
typename feature_of<typename undroppable<B>::type>::type
|
||||
, typename undroppable<A>::type
|
||||
>
|
||||
{};
|
||||
|
||||
template<typename Feature>
|
||||
struct dependencies_of
|
||||
{
|
||||
typedef typename Feature::dependencies type;
|
||||
};
|
||||
|
||||
// Should use mpl::insert_range, but doesn't seem to work with mpl sets
|
||||
template<typename Set, typename Range>
|
||||
struct set_insert_range
|
||||
: mpl::fold<
|
||||
Range
|
||||
, Set
|
||||
, mpl::insert<mpl::_1, mpl::_2>
|
||||
>
|
||||
{};
|
||||
|
||||
template<typename Features>
|
||||
struct collect_abstract_features
|
||||
: mpl::fold<
|
||||
Features
|
||||
, mpl::set0<>
|
||||
, set_insert_range<
|
||||
mpl::insert<mpl::_1, feature_of<mpl::_2> >
|
||||
, collect_abstract_features<dependencies_of<mpl::_2> >
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
template<typename Features>
|
||||
struct depends_on_base
|
||||
: mpl::inherit_linearly<
|
||||
typename mpl::sort<
|
||||
typename mpl::copy<
|
||||
typename collect_abstract_features<Features>::type
|
||||
, mpl::back_inserter<mpl::vector0<> >
|
||||
>::type
|
||||
, is_dependent_on<mpl::_1, mpl::_2>
|
||||
>::type
|
||||
// Don't inherit multiply from a feature
|
||||
, mpl::if_<
|
||||
is_dependent_on<mpl::_1, mpl::_2>
|
||||
, mpl::_1
|
||||
, mpl::inherit<mpl::_1, mpl::_2>
|
||||
>
|
||||
>::type
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/// depends_on
|
||||
template<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, typename Feature)>
|
||||
struct depends_on
|
||||
: detail::depends_on_base<
|
||||
typename mpl::transform<
|
||||
mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, Feature)>
|
||||
, as_feature<mpl::_1>
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef mpl::false_ is_weight_accumulator;
|
||||
typedef
|
||||
typename mpl::transform<
|
||||
mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, Feature)>
|
||||
, as_feature<mpl::_1>
|
||||
>::type
|
||||
dependencies;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<typename Feature>
|
||||
struct matches_feature
|
||||
{
|
||||
template<typename Accumulator>
|
||||
struct apply
|
||||
: is_same<
|
||||
typename feature_of<typename as_feature<Feature>::type>::type
|
||||
, typename feature_of<typename as_feature<typename feature_tag<Accumulator>::type>::type>::type
|
||||
>
|
||||
{};
|
||||
};
|
||||
|
||||
template<typename Features, typename Accumulator>
|
||||
struct contains_feature_of
|
||||
{
|
||||
typedef
|
||||
mpl::transform_view<Features, feature_of<as_feature<mpl::_> > >
|
||||
features_list;
|
||||
|
||||
typedef
|
||||
typename feature_of<typename feature_tag<Accumulator>::type>::type
|
||||
the_feature;
|
||||
|
||||
typedef
|
||||
typename mpl::contains<features_list, the_feature>::type
|
||||
type;
|
||||
};
|
||||
|
||||
// This is to work around a bug in early versions of Fusion which caused
|
||||
// a compile error if contains_feature_of<List, mpl::_> is used as a
|
||||
// predicate to fusion::find_if
|
||||
template<typename Features>
|
||||
struct contains_feature_of_
|
||||
{
|
||||
template<typename Accumulator>
|
||||
struct apply
|
||||
: contains_feature_of<Features, Accumulator>
|
||||
{};
|
||||
};
|
||||
|
||||
template<
|
||||
typename First
|
||||
, typename Last
|
||||
, bool is_empty = fusion::result_of::equal_to<First, Last>::value
|
||||
>
|
||||
struct build_acc_list;
|
||||
|
||||
template<typename First, typename Last>
|
||||
struct build_acc_list<First, Last, true>
|
||||
{
|
||||
typedef fusion::nil type;
|
||||
|
||||
template<typename Args>
|
||||
static fusion::nil
|
||||
call(Args const &, First const&, Last const&)
|
||||
{
|
||||
return fusion::nil();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename First, typename Last>
|
||||
struct build_acc_list<First, Last, false>
|
||||
{
|
||||
typedef
|
||||
build_acc_list<typename fusion::result_of::next<First>::type, Last>
|
||||
next_build_acc_list;
|
||||
|
||||
typedef fusion::cons<
|
||||
typename fusion::result_of::value_of<First>::type
|
||||
, typename next_build_acc_list::type>
|
||||
type;
|
||||
|
||||
template<typename Args>
|
||||
static type
|
||||
call(Args const &args, First const& f, Last const& l)
|
||||
{
|
||||
return type(args, next_build_acc_list::call(args, fusion::next(f), l));
|
||||
}
|
||||
};
|
||||
|
||||
namespace meta
|
||||
{
|
||||
template<typename Sequence>
|
||||
struct make_acc_list
|
||||
: build_acc_list<
|
||||
typename fusion::result_of::begin<Sequence>::type
|
||||
, typename fusion::result_of::end<Sequence>::type
|
||||
>
|
||||
{};
|
||||
}
|
||||
|
||||
template<typename Sequence, typename Args>
|
||||
typename meta::make_acc_list<Sequence>::type
|
||||
make_acc_list(Sequence const &seq, Args const &args)
|
||||
{
|
||||
return meta::make_acc_list<Sequence>::call(args, fusion::begin(seq), fusion::end(seq));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// checked_as_weighted_feature
|
||||
template<typename Feature>
|
||||
struct checked_as_weighted_feature
|
||||
{
|
||||
typedef typename as_feature<Feature>::type feature_type;
|
||||
typedef typename as_weighted_feature<feature_type>::type type;
|
||||
// weighted and non-weighted flavors should provide the same feature.
|
||||
BOOST_MPL_ASSERT((
|
||||
is_same<
|
||||
typename feature_of<feature_type>::type
|
||||
, typename feature_of<type>::type
|
||||
>
|
||||
));
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// as_feature_list
|
||||
template<typename Features, typename Weight>
|
||||
struct as_feature_list
|
||||
: mpl::transform_view<Features, checked_as_weighted_feature<mpl::_1> >
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Features>
|
||||
struct as_feature_list<Features, void>
|
||||
: mpl::transform_view<Features, as_feature<mpl::_1> >
|
||||
{
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// accumulator_wrapper
|
||||
template<typename Accumulator, typename Feature>
|
||||
struct accumulator_wrapper
|
||||
: Accumulator
|
||||
{
|
||||
typedef Feature feature_tag;
|
||||
|
||||
accumulator_wrapper(accumulator_wrapper const &that)
|
||||
: Accumulator(*static_cast<Accumulator const *>(&that))
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Args>
|
||||
accumulator_wrapper(Args const &args)
|
||||
: Accumulator(args)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// to_accumulator
|
||||
template<typename Feature, typename Sample, typename Weight>
|
||||
struct to_accumulator
|
||||
{
|
||||
typedef
|
||||
accumulator_wrapper<
|
||||
typename mpl::apply2<typename Feature::impl, Sample, Weight>::type
|
||||
, Feature
|
||||
>
|
||||
type;
|
||||
};
|
||||
|
||||
template<typename Feature, typename Sample, typename Weight, typename Tag, typename AccumulatorSet>
|
||||
struct to_accumulator<Feature, Sample, tag::external<Weight, Tag, AccumulatorSet> >
|
||||
{
|
||||
BOOST_MPL_ASSERT((is_same<Tag, void>));
|
||||
BOOST_MPL_ASSERT((is_same<AccumulatorSet, void>));
|
||||
|
||||
typedef
|
||||
accumulator_wrapper<
|
||||
typename mpl::apply2<typename Feature::impl, Sample, Weight>::type
|
||||
, Feature
|
||||
>
|
||||
accumulator_type;
|
||||
|
||||
typedef
|
||||
typename mpl::if_<
|
||||
typename Feature::is_weight_accumulator
|
||||
, accumulator_wrapper<impl::external_impl<accumulator_type, tag::weights>, Feature>
|
||||
, accumulator_type
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
|
||||
// BUGBUG work around an MPL bug wrt map insertion
|
||||
template<typename FeatureMap, typename Feature>
|
||||
struct insert_feature
|
||||
: mpl::eval_if<
|
||||
mpl::has_key<FeatureMap, typename feature_of<Feature>::type>
|
||||
, mpl::identity<FeatureMap>
|
||||
, mpl::insert<FeatureMap, mpl::pair<typename feature_of<Feature>::type, Feature> >
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename FeatureMap, typename Feature, typename Weight>
|
||||
struct insert_dependencies
|
||||
: mpl::fold<
|
||||
as_feature_list<typename Feature::dependencies, Weight>
|
||||
, FeatureMap
|
||||
, insert_dependencies<
|
||||
insert_feature<mpl::_1, mpl::_2>
|
||||
, mpl::_2
|
||||
, Weight
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename FeatureMap, typename Features, typename Weight>
|
||||
struct insert_sequence
|
||||
: mpl::fold< // BUGBUG should use insert_range, but doesn't seem to work for maps
|
||||
as_feature_list<Features, Weight>
|
||||
, FeatureMap
|
||||
, insert_feature<mpl::_1, mpl::_2>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Features, typename Sample, typename Weight>
|
||||
struct make_accumulator_tuple
|
||||
{
|
||||
typedef
|
||||
typename mpl::fold<
|
||||
as_feature_list<Features, Weight>
|
||||
, mpl::map0<>
|
||||
, mpl::if_<
|
||||
mpl::is_sequence<mpl::_2>
|
||||
, insert_sequence<mpl::_1, mpl::_2, Weight>
|
||||
, insert_feature<mpl::_1, mpl::_2>
|
||||
>
|
||||
>::type
|
||||
feature_map;
|
||||
|
||||
// for each element in the map, add its dependencies also
|
||||
typedef
|
||||
typename mpl::fold<
|
||||
feature_map
|
||||
, feature_map
|
||||
, insert_dependencies<mpl::_1, mpl::second<mpl::_2>, Weight>
|
||||
>::type
|
||||
feature_map_with_dependencies;
|
||||
|
||||
// turn the map into a vector so we can sort it
|
||||
typedef
|
||||
typename mpl::insert_range<
|
||||
mpl::vector<>
|
||||
, mpl::end<mpl::vector<> >::type
|
||||
, mpl::transform_view<feature_map_with_dependencies, mpl::second<mpl::_1> >
|
||||
>::type
|
||||
feature_vector_with_dependencies;
|
||||
|
||||
// sort the features according to which is derived from which
|
||||
typedef
|
||||
typename mpl::sort<
|
||||
feature_vector_with_dependencies
|
||||
, is_dependent_on<mpl::_2, mpl::_1>
|
||||
>::type
|
||||
sorted_feature_vector;
|
||||
|
||||
// From the vector of features, construct a vector of accumulators
|
||||
typedef
|
||||
typename mpl::transform<
|
||||
sorted_feature_vector
|
||||
, to_accumulator<mpl::_1, Sample, Weight>
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
}} // namespace boost::accumulators
|
||||
|
||||
#endif
|
|
@ -0,0 +1,27 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// external.hpp
|
||||
//
|
||||
// Copyright 2005 Eric Niebler. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_ACCUMULATORS_FRAMEWORK_EXTERNAL_HPP_EAN_01_12_2005
|
||||
#define BOOST_ACCUMULATORS_FRAMEWORK_EXTERNAL_HPP_EAN_01_12_2005
|
||||
|
||||
#include <boost/mpl/apply.hpp>
|
||||
#include <boost/accumulators/framework/accumulators/external_accumulator.hpp>
|
||||
|
||||
//namespace boost { namespace accumulators
|
||||
//{
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//// external
|
||||
////
|
||||
//template<typename Type>
|
||||
//struct external
|
||||
//{
|
||||
//};
|
||||
//
|
||||
//}} // namespace boost::accumulators
|
||||
|
||||
#endif
|
|
@ -0,0 +1,229 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// extractor.hpp
|
||||
//
|
||||
// Copyright 2005 Eric Niebler. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_ACCUMULATORS_FRAMEWORK_EXTRACTOR_HPP_EAN_28_10_2005
|
||||
#define BOOST_ACCUMULATORS_FRAMEWORK_EXTRACTOR_HPP_EAN_28_10_2005
|
||||
|
||||
#include <boost/preprocessor/tuple/rem.hpp>
|
||||
#include <boost/preprocessor/array/size.hpp>
|
||||
#include <boost/preprocessor/array/data.hpp>
|
||||
#include <boost/preprocessor/array/elem.hpp>
|
||||
#include <boost/preprocessor/seq/to_array.hpp>
|
||||
#include <boost/preprocessor/seq/transform.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
|
||||
#include <boost/parameter/binding.hpp>
|
||||
#include <boost/mpl/apply.hpp>
|
||||
#include <boost/mpl/eval_if.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/accumulators/accumulators_fwd.hpp>
|
||||
#include <boost/accumulators/framework/parameters/accumulator.hpp>
|
||||
|
||||
namespace boost { namespace accumulators
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<typename AccumulatorSet, typename Feature>
|
||||
struct accumulator_set_result
|
||||
{
|
||||
typedef typename as_feature<Feature>::type feature_type;
|
||||
typedef typename mpl::apply<AccumulatorSet, feature_type>::type::result_type type;
|
||||
};
|
||||
|
||||
template<typename Args, typename Feature>
|
||||
struct argument_pack_result
|
||||
: accumulator_set_result<
|
||||
typename remove_reference<
|
||||
typename parameter::binding<Args, tag::accumulator>::type
|
||||
>::type
|
||||
, Feature
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename A, typename Feature>
|
||||
struct extractor_result
|
||||
: mpl::eval_if<
|
||||
detail::is_accumulator_set<A>
|
||||
, accumulator_set_result<A, Feature>
|
||||
, argument_pack_result<A, Feature>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Feature, typename AccumulatorSet>
|
||||
typename extractor_result<AccumulatorSet, Feature>::type
|
||||
do_extract(AccumulatorSet const &acc, mpl::true_)
|
||||
{
|
||||
typedef typename as_feature<Feature>::type feature_type;
|
||||
return extract_result<feature_type>(acc);
|
||||
}
|
||||
|
||||
template<typename Feature, typename Args>
|
||||
typename extractor_result<Args, Feature>::type
|
||||
do_extract(Args const &args, mpl::false_)
|
||||
{
|
||||
typedef typename as_feature<Feature>::type feature_type;
|
||||
return find_accumulator<feature_type>(args[accumulator]).result(args);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Extracts the result associated with Feature from the specified accumulator_set.
|
||||
template<typename Feature>
|
||||
struct extractor
|
||||
{
|
||||
typedef extractor<Feature> this_type;
|
||||
|
||||
/// The result meta-function for determining the return type of the extractor
|
||||
template<typename F>
|
||||
struct result;
|
||||
|
||||
template<typename A1>
|
||||
struct result<this_type(A1)>
|
||||
: detail::extractor_result<A1, Feature>
|
||||
{
|
||||
};
|
||||
|
||||
/// Extract the result associated with Feature from the accumulator set
|
||||
/// \param acc The accumulator set object from which to extract the result
|
||||
template<typename Arg1>
|
||||
typename detail::extractor_result<Arg1, Feature>::type
|
||||
operator ()(Arg1 const &arg1) const
|
||||
{
|
||||
// Arg1 could be an accumulator_set or an argument pack containing
|
||||
// an accumulator_set. Dispatch accordingly.
|
||||
return detail::do_extract<Feature>(arg1, detail::is_accumulator_set<Arg1>());
|
||||
}
|
||||
|
||||
/// \overload
|
||||
///
|
||||
/// \param a1 Optional named parameter to be passed to the accumulator's result() function.
|
||||
template<typename AccumulatorSet, typename A1>
|
||||
typename detail::extractor_result<AccumulatorSet, Feature>::type
|
||||
operator ()(AccumulatorSet const &acc, A1 const &a1) const
|
||||
{
|
||||
BOOST_MPL_ASSERT((detail::is_accumulator_set<AccumulatorSet>));
|
||||
typedef typename as_feature<Feature>::type feature_type;
|
||||
return extract_result<feature_type>(acc, a1);
|
||||
}
|
||||
|
||||
// ... other overloads generated by Boost.Preprocessor:
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
#define BOOST_ACCUMULATORS_EXTRACTOR_FUN_OP(z, n, _) \
|
||||
template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
|
||||
struct result<this_type(BOOST_PP_ENUM_PARAMS_Z(z, n, A))> \
|
||||
: detail::extractor_result<A1, Feature> \
|
||||
{}; \
|
||||
template< \
|
||||
typename AccumulatorSet \
|
||||
BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \
|
||||
> \
|
||||
typename detail::extractor_result<AccumulatorSet, Feature>::type \
|
||||
operator ()( \
|
||||
AccumulatorSet const &acc \
|
||||
BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \
|
||||
) const \
|
||||
{ \
|
||||
BOOST_MPL_ASSERT((detail::is_accumulator_set<AccumulatorSet>)); \
|
||||
typedef typename as_feature<Feature>::type feature_type; \
|
||||
return extract_result<feature_type>(acc BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a));\
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(
|
||||
2
|
||||
, BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
|
||||
, BOOST_ACCUMULATORS_EXTRACTOR_FUN_OP
|
||||
, _
|
||||
)
|
||||
|
||||
#ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
|
||||
/// \overload
|
||||
///
|
||||
template<typename AccumulatorSet, typename A1, typename A2, ...>
|
||||
typename detail::extractor_result<AccumulatorSet, Feature>::type
|
||||
operator ()(AccumulatorSet const &acc, A1 const &a1, A2 const &a2, ...);
|
||||
#endif
|
||||
};
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
#define BOOST_ACCUMULATORS_ARRAY_REM(Array) \
|
||||
BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_ARRAY_SIZE(Array), BOOST_PP_ARRAY_DATA(Array))
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
#define BOOST_ACCUMULATORS_SEQ_REM(Seq) \
|
||||
BOOST_ACCUMULATORS_ARRAY_REM(BOOST_PP_SEQ_TO_ARRAY(Seq))
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
#define BOOST_ACCUMULATORS_ARGS_OP(s, data, elem) \
|
||||
T ## s
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
#define BOOST_ACCUMULATORS_PARAMS_OP(s, data, elem) \
|
||||
elem T ## s
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
#define BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq) \
|
||||
Tag::Feature< \
|
||||
BOOST_ACCUMULATORS_SEQ_REM( \
|
||||
BOOST_PP_SEQ_TRANSFORM(BOOST_ACCUMULATORS_ARGS_OP, ~, ParamsSeq) \
|
||||
) \
|
||||
>
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
#define BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN_IMPL(z, n, Tag, Feature, ParamsSeq) \
|
||||
template< \
|
||||
BOOST_ACCUMULATORS_SEQ_REM( \
|
||||
BOOST_PP_SEQ_TRANSFORM(BOOST_ACCUMULATORS_PARAMS_OP, ~, ParamsSeq) \
|
||||
) \
|
||||
, typename Arg1 \
|
||||
BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \
|
||||
> \
|
||||
typename boost::accumulators::detail::extractor_result< \
|
||||
Arg1 \
|
||||
, BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq) \
|
||||
>::type \
|
||||
Feature(Arg1 const &arg1 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) ) \
|
||||
{ \
|
||||
typedef BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq) feature_type; \
|
||||
return boost::accumulators::extractor<feature_type>()( \
|
||||
arg1 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a)); \
|
||||
}
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
#define BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN(z, n, _) \
|
||||
BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN_IMPL( \
|
||||
z \
|
||||
, n \
|
||||
, BOOST_PP_ARRAY_ELEM(0, _) \
|
||||
, BOOST_PP_ARRAY_ELEM(1, _) \
|
||||
, BOOST_PP_ARRAY_ELEM(2, _) \
|
||||
)
|
||||
|
||||
#define BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(Tag, Feature, ParamSeq) \
|
||||
BOOST_PP_REPEAT( \
|
||||
BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) \
|
||||
, BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN \
|
||||
, (3, (Tag, Feature, ParamSeq)) \
|
||||
)
|
||||
|
||||
}} // namespace boost::accumulators
|
||||
|
||||
#endif
|
|
@ -0,0 +1,29 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// features.hpp
|
||||
//
|
||||
// Copyright 2005 Eric Niebler. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_ACCUMULATORS_STATISTICS_STATS_HPP_EAN_08_12_2005
|
||||
#define BOOST_ACCUMULATORS_STATISTICS_STATS_HPP_EAN_08_12_2005
|
||||
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/accumulators/accumulators_fwd.hpp>
|
||||
|
||||
namespace boost { namespace accumulators
|
||||
{
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// features
|
||||
//
|
||||
template<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, typename Feature)>
|
||||
struct features
|
||||
: mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, Feature)>
|
||||
{
|
||||
};
|
||||
|
||||
}} // namespace boost::accumulators
|
||||
|
||||
#endif
|
|
@ -0,0 +1,20 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// accumulator.hpp
|
||||
//
|
||||
// Copyright 2005 Eric Niebler. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_ACCUMULATOR_HPP_EAN_31_10_2005
|
||||
#define BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_ACCUMULATOR_HPP_EAN_31_10_2005
|
||||
|
||||
#include <boost/parameter/keyword.hpp>
|
||||
|
||||
namespace boost { namespace accumulators
|
||||
{
|
||||
|
||||
BOOST_PARAMETER_KEYWORD(tag, accumulator)
|
||||
|
||||
}} // namespace boost::accumulators
|
||||
|
||||
#endif
|
|
@ -0,0 +1,20 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// sample.hpp
|
||||
//
|
||||
// Copyright 2005 Eric Niebler. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_SAMPLE_HPP_EAN_31_10_2005
|
||||
#define BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_SAMPLE_HPP_EAN_31_10_2005
|
||||
|
||||
#include <boost/parameter/keyword.hpp>
|
||||
|
||||
namespace boost { namespace accumulators
|
||||
{
|
||||
|
||||
BOOST_PARAMETER_KEYWORD(tag, sample)
|
||||
|
||||
}} // namespace boost::accumulators
|
||||
|
||||
#endif
|
|
@ -0,0 +1,21 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// weight.hpp
|
||||
//
|
||||
// Copyright 2005 Eric Niebler. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_WEIGHT_HPP_EAN_31_10_2005
|
||||
#define BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_WEIGHT_HPP_EAN_31_10_2005
|
||||
|
||||
#include <boost/parameter/keyword.hpp>
|
||||
|
||||
namespace boost { namespace accumulators
|
||||
{
|
||||
|
||||
// The weight of a single sample
|
||||
BOOST_PARAMETER_KEYWORD(tag, weight)
|
||||
|
||||
}} // namespace boost::accumulators
|
||||
|
||||
#endif
|
|
@ -0,0 +1,21 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// weights.hpp
|
||||
//
|
||||
// Copyright 2005 Eric Niebler. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_WEIGHTS_HPP_EAN_28_10_2005
|
||||
#define BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_WEIGHTS_HPP_EAN_28_10_2005
|
||||
|
||||
#include <boost/parameter/keyword.hpp>
|
||||
|
||||
namespace boost { namespace accumulators
|
||||
{
|
||||
|
||||
// The weight accumulator
|
||||
BOOST_PARAMETER_KEYWORD(tag, weights)
|
||||
|
||||
}} // namespace boost::accumulators
|
||||
|
||||
#endif
|
|
@ -0,0 +1,75 @@
|
|||
// Copyright David Abrahams 2006. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_DETAIL_FUNCTION1_DWA200655_HPP
|
||||
# define BOOST_DETAIL_FUNCTION1_DWA200655_HPP
|
||||
|
||||
# include <boost/concept_check.hpp>
|
||||
# include <boost/type_traits/remove_reference.hpp>
|
||||
# include <boost/type_traits/add_const.hpp>
|
||||
# include <boost/mpl/apply.hpp>
|
||||
|
||||
namespace boost { namespace detail {
|
||||
|
||||
// A utility for creating unary function objects that play nicely with
|
||||
// boost::result_of and that handle the forwarding problem.
|
||||
//
|
||||
// mpl::apply<F, A0>::type is expected to be a stateless function
|
||||
// object that accepts an argument of type A0&. It is also expected
|
||||
// to have a nested ::result_type identical to its return type.
|
||||
template<typename F>
|
||||
struct function1
|
||||
{
|
||||
template<typename Signature>
|
||||
struct result
|
||||
{};
|
||||
|
||||
template<typename This, typename A0>
|
||||
struct result<This(A0)>
|
||||
{
|
||||
// How adding const to arguments handles rvalues.
|
||||
//
|
||||
// if A0 is arg0 is represents actual argument
|
||||
// -------- ------- --------------------------
|
||||
// T const & T const const T lvalue
|
||||
// T & T non-const T lvalue
|
||||
// T const T const const T rvalue
|
||||
// T T const non-const T rvalue
|
||||
typedef typename remove_reference<
|
||||
typename add_const< A0 >::type
|
||||
>::type arg0;
|
||||
|
||||
typedef typename mpl::apply1<F, arg0>::type impl;
|
||||
typedef typename impl::result_type type;
|
||||
};
|
||||
|
||||
// Handles mutable lvalues
|
||||
template<typename A0>
|
||||
typename result<function1(A0 &)>::type
|
||||
operator ()(A0 &a0) const
|
||||
{
|
||||
typedef typename result<function1(A0 &)>::impl impl;
|
||||
typedef typename result<function1(A0 &)>::type type;
|
||||
typedef A0 &arg0;
|
||||
BOOST_CONCEPT_ASSERT((UnaryFunction<impl, type, arg0>));
|
||||
//boost::function_requires<UnaryFunctionConcept<impl, type, arg0> >();
|
||||
return impl()(a0);
|
||||
}
|
||||
|
||||
// Handles const lvalues and all rvalues
|
||||
template<typename A0>
|
||||
typename result<function1(A0 const &)>::type
|
||||
operator ()(A0 const &a0) const
|
||||
{
|
||||
typedef typename result<function1(A0 const &)>::impl impl;
|
||||
typedef typename result<function1(A0 const &)>::type type;
|
||||
typedef A0 const &arg0;
|
||||
BOOST_CONCEPT_ASSERT((UnaryFunction<impl, type, arg0>));
|
||||
//boost::function_requires<UnaryFunctionConcept<impl, type, arg0> >();
|
||||
return impl()(a0);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace boost::detail
|
||||
|
||||
#endif // BOOST_DETAIL_FUNCTION1_DWA200655_HPP
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright David Abrahams 2006. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_DETAIL_FUNCTION2_DWA200655_HPP
|
||||
# define BOOST_DETAIL_FUNCTION2_DWA200655_HPP
|
||||
|
||||
# define args (2)
|
||||
# include <boost/accumulators/numeric/detail/function_n.hpp>
|
||||
|
||||
#endif // BOOST_DETAIL_FUNCTION2_DWA200655_HPP
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright David Abrahams 2006. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_DETAIL_FUNCTION3_DWA2006514_HPP
|
||||
# define BOOST_DETAIL_FUNCTION3_DWA2006514_HPP
|
||||
|
||||
# define args (3)
|
||||
# include <boost/accumulators/numeric/detail/function_n.hpp>
|
||||
|
||||
#endif // BOOST_DETAIL_FUNCTION3_DWA2006514_HPP
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright David Abrahams 2006. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_DETAIL_FUNCTION4_DWA2006514_HPP
|
||||
# define BOOST_DETAIL_FUNCTION4_DWA2006514_HPP
|
||||
|
||||
# define args (4)
|
||||
# include <boost/accumulators/numeric/detail/function_n.hpp>
|
||||
|
||||
#endif // BOOST_DETAIL_FUNCTION4_DWA2006514_HPP
|
|
@ -0,0 +1,148 @@
|
|||
// Copyright David Abrahams 2006. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// #include guards intentionally disabled.
|
||||
// #ifndef BOOST_DETAIL_FUNCTION_N_DWA2006514_HPP
|
||||
// # define BOOST_DETAIL_FUNCTION_N_DWA2006514_HPP
|
||||
|
||||
#include <boost/mpl/void.hpp>
|
||||
#include <boost/mpl/apply.hpp>
|
||||
|
||||
#include <boost/preprocessor/control/if.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/punctuation/comma_if.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat.hpp>
|
||||
#include <boost/preprocessor/seq/fold_left.hpp>
|
||||
#include <boost/preprocessor/seq/seq.hpp>
|
||||
#include <boost/preprocessor/seq/for_each.hpp>
|
||||
#include <boost/preprocessor/seq/for_each_i.hpp>
|
||||
#include <boost/preprocessor/seq/for_each_product.hpp>
|
||||
#include <boost/preprocessor/seq/size.hpp>
|
||||
#include <boost/type_traits/add_const.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
|
||||
namespace boost { namespace detail {
|
||||
|
||||
# define BOOST_DETAIL_default_arg(z, n, _) \
|
||||
typedef mpl::void_ BOOST_PP_CAT(arg, n);
|
||||
|
||||
# define BOOST_DETAIL_function_arg(z, n, _) \
|
||||
typedef typename remove_reference< \
|
||||
typename add_const< BOOST_PP_CAT(A, n) >::type \
|
||||
>::type BOOST_PP_CAT(arg, n);
|
||||
|
||||
#define BOOST_DETAIL_cat_arg_counts(s, state, n) \
|
||||
BOOST_PP_IF( \
|
||||
n \
|
||||
, BOOST_PP_CAT(state, BOOST_PP_CAT(_, n)) \
|
||||
, state \
|
||||
) \
|
||||
/**/
|
||||
|
||||
#define function_name \
|
||||
BOOST_PP_SEQ_FOLD_LEFT( \
|
||||
BOOST_DETAIL_cat_arg_counts \
|
||||
, BOOST_PP_CAT(function, BOOST_PP_SEQ_HEAD(args)) \
|
||||
, BOOST_PP_SEQ_TAIL(args)(0) \
|
||||
) \
|
||||
/**/
|
||||
|
||||
template<typename F>
|
||||
struct function_name
|
||||
{
|
||||
BOOST_PP_REPEAT(
|
||||
BOOST_MPL_LIMIT_METAFUNCTION_ARITY
|
||||
, BOOST_DETAIL_default_arg
|
||||
, ~
|
||||
)
|
||||
|
||||
template<typename Signature>
|
||||
struct result {};
|
||||
|
||||
#define BOOST_DETAIL_function_result(r, _, n) \
|
||||
template<typename This BOOST_PP_ENUM_TRAILING_PARAMS(n, typename A)> \
|
||||
struct result<This(BOOST_PP_ENUM_PARAMS(n, A))> \
|
||||
{ \
|
||||
BOOST_PP_REPEAT(n, BOOST_DETAIL_function_arg, ~) \
|
||||
typedef \
|
||||
typename BOOST_PP_CAT(mpl::apply, BOOST_MPL_LIMIT_METAFUNCTION_ARITY)<\
|
||||
F \
|
||||
BOOST_PP_ENUM_TRAILING_PARAMS( \
|
||||
BOOST_MPL_LIMIT_METAFUNCTION_ARITY \
|
||||
, arg \
|
||||
) \
|
||||
>::type \
|
||||
impl; \
|
||||
typedef typename impl::result_type type; \
|
||||
}; \
|
||||
/**/
|
||||
|
||||
BOOST_PP_SEQ_FOR_EACH(BOOST_DETAIL_function_result, _, args)
|
||||
|
||||
# define arg_type(r, _, i, is_const) \
|
||||
BOOST_PP_COMMA_IF(i) BOOST_PP_CAT(A, i) BOOST_PP_CAT(const_if, is_const) &
|
||||
|
||||
# define result_(r, n, constness) \
|
||||
typename result< \
|
||||
function_name( \
|
||||
BOOST_PP_SEQ_FOR_EACH_I_R(r, arg_type, ~, constness) \
|
||||
) \
|
||||
> \
|
||||
/**/
|
||||
|
||||
# define param(r, _, i, is_const) BOOST_PP_COMMA_IF(i) \
|
||||
BOOST_PP_CAT(A, i) BOOST_PP_CAT(const_if, is_const) & BOOST_PP_CAT(x, i)
|
||||
|
||||
# define param_list(r, n, constness) \
|
||||
BOOST_PP_SEQ_FOR_EACH_I_R(r, param, ~, constness)
|
||||
|
||||
# define call_operator(r, constness) \
|
||||
template<BOOST_PP_ENUM_PARAMS(BOOST_PP_SEQ_SIZE(constness), typename A)> \
|
||||
result_(r, BOOST_PP_SEQ_SIZE(constness), constness)::type \
|
||||
operator ()( param_list(r, BOOST_PP_SEQ_SIZE(constness), constness) ) const \
|
||||
{ \
|
||||
typedef result_(r, BOOST_PP_SEQ_SIZE(constness), constness)::impl impl; \
|
||||
return impl()(BOOST_PP_ENUM_PARAMS(BOOST_PP_SEQ_SIZE(constness), x)); \
|
||||
} \
|
||||
/**/
|
||||
|
||||
# define const_if0
|
||||
# define const_if1 const
|
||||
|
||||
# define bits(z, n, _) ((0)(1))
|
||||
|
||||
# define gen_operator(r, _, n) \
|
||||
BOOST_PP_SEQ_FOR_EACH_PRODUCT_R( \
|
||||
r \
|
||||
, call_operator \
|
||||
, BOOST_PP_REPEAT(n, bits, ~) \
|
||||
) \
|
||||
/**/
|
||||
|
||||
BOOST_PP_SEQ_FOR_EACH(
|
||||
gen_operator
|
||||
, ~
|
||||
, args
|
||||
)
|
||||
|
||||
# undef bits
|
||||
# undef const_if1
|
||||
# undef const_if0
|
||||
# undef call_operator
|
||||
# undef param_list
|
||||
# undef param
|
||||
# undef result_
|
||||
# undef default_
|
||||
# undef arg_type
|
||||
# undef gen_operator
|
||||
# undef function_name
|
||||
|
||||
# undef args
|
||||
};
|
||||
|
||||
}} // namespace boost::detail
|
||||
|
||||
//#endif // BOOST_DETAIL_FUNCTION_N_DWA2006514_HPP
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright David Abrahams 2006. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_DETAIL_POD_SINGLETON_DWA200655_HPP
|
||||
# define BOOST_DETAIL_POD_SINGLETON_DWA200655_HPP
|
||||
|
||||
namespace boost { namespace detail {
|
||||
|
||||
template<typename T>
|
||||
struct pod_singleton
|
||||
{
|
||||
static T instance;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
T pod_singleton<T>::instance;
|
||||
|
||||
}} // namespace boost::detail
|
||||
|
||||
#endif // BOOST_DETAIL_POD_SINGLETON_DWA200655_HPP
|
|
@ -0,0 +1,497 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// \file functional.hpp
|
||||
///
|
||||
// Copyright 2005 Eric Niebler. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_NUMERIC_FUNCTIONAL_HPP_EAN_08_12_2005
|
||||
#define BOOST_NUMERIC_FUNCTIONAL_HPP_EAN_08_12_2005
|
||||
|
||||
#include <limits>
|
||||
#include <functional>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/type_traits/add_reference.hpp>
|
||||
#include <boost/type_traits/is_empty.hpp>
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
#include <boost/type_traits/is_floating_point.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/typeof/typeof.hpp>
|
||||
#include <boost/accumulators/numeric/functional_fwd.hpp>
|
||||
#include <boost/accumulators/numeric/detail/function1.hpp>
|
||||
#include <boost/accumulators/numeric/detail/function2.hpp>
|
||||
#include <boost/accumulators/numeric/detail/pod_singleton.hpp>
|
||||
|
||||
#ifdef BOOST_NUMERIC_FUNCTIONAL_STD_VECTOR_SUPPORT
|
||||
# include <boost/accumulators/numeric/functional/vector.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_NUMERIC_FUNCTIONAL_STD_VALARRAY_SUPPORT
|
||||
# include <boost/accumulators/numeric/functional/valarray.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_NUMERIC_FUNCTIONAL_STD_COMPLEX_SUPPORT
|
||||
# include <boost/accumulators/numeric/functional/complex.hpp>
|
||||
#endif
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
#define BOOST_NUMERIC_FUNCTIONAL_HPP_INCLUDED
|
||||
|
||||
#ifdef BOOST_NUMERIC_FUNCTIONAL_DOXYGEN_INVOKED
|
||||
// Hack to make Doxygen show the inheritance relationships
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
namespace std
|
||||
{
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
template<class Arg, class Ret> struct unary_function {};
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
template<class Left, class Right, class Ret> struct binary_function {};
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace boost { namespace numeric
|
||||
{
|
||||
namespace functional
|
||||
{
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
template<typename A0, typename A1>
|
||||
struct are_integral
|
||||
: mpl::and_<is_integral<A0>, is_integral<A1> >
|
||||
{};
|
||||
|
||||
template<typename Left, typename Right>
|
||||
struct left_ref
|
||||
{
|
||||
typedef Left &type;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<typename T>
|
||||
T &lvalue_of();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: handle complex weight, valarray, MTL vectors
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
#define BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(Name, Op) \
|
||||
namespace functional \
|
||||
{ \
|
||||
template<typename Arg> \
|
||||
struct result_of_ ## Name \
|
||||
{ \
|
||||
BOOST_TYPEOF_NESTED_TYPEDEF_TPL( \
|
||||
nested \
|
||||
, Op boost::numeric::functional::detail::lvalue_of<Arg>() \
|
||||
) \
|
||||
typedef typename nested::type type; \
|
||||
}; \
|
||||
template<typename Arg, typename EnableIf> \
|
||||
struct Name ## _base \
|
||||
: std::unary_function< \
|
||||
typename remove_const<Arg>::type \
|
||||
, typename result_of_ ## Name<Arg>::type \
|
||||
> \
|
||||
{ \
|
||||
typename result_of_ ## Name<Arg>::type operator ()(Arg &arg) const \
|
||||
{ \
|
||||
return Op arg; \
|
||||
} \
|
||||
}; \
|
||||
template<typename Arg, typename ArgTag> \
|
||||
struct Name \
|
||||
: Name ## _base<Arg, void> \
|
||||
{}; \
|
||||
} \
|
||||
namespace op \
|
||||
{ \
|
||||
struct Name \
|
||||
: boost::detail::function1<functional::Name<_, functional::tag<_> > > \
|
||||
{}; \
|
||||
} \
|
||||
namespace \
|
||||
{ \
|
||||
op::Name const &Name = boost::detail::pod_singleton<op::Name>::instance; \
|
||||
} \
|
||||
/**/
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
#define BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(Name, Op, RetType) \
|
||||
namespace functional \
|
||||
{ \
|
||||
template<typename Left, typename Right, typename EnableIf> \
|
||||
struct result_of_ ## Name \
|
||||
{ \
|
||||
RetType(Left, Op, Right) \
|
||||
}; \
|
||||
template<typename Left, typename Right, typename EnableIf> \
|
||||
struct Name ## _base \
|
||||
: std::binary_function< \
|
||||
typename remove_const<Left>::type \
|
||||
, typename remove_const<Right>::type \
|
||||
, typename result_of_ ## Name<Left, Right>::type \
|
||||
> \
|
||||
{ \
|
||||
typename result_of_ ## Name<Left, Right>::type \
|
||||
operator ()(Left &left, Right &right) const \
|
||||
{ \
|
||||
return left Op right; \
|
||||
} \
|
||||
}; \
|
||||
template<typename Left, typename Right, typename LeftTag, typename RightTag> \
|
||||
struct Name \
|
||||
: Name ## _base<Left, Right, void> \
|
||||
{}; \
|
||||
} \
|
||||
namespace op \
|
||||
{ \
|
||||
struct Name \
|
||||
: boost::detail::function2< \
|
||||
functional::Name<_1, _2, functional::tag<_1>, functional::tag<_2> > \
|
||||
> \
|
||||
{}; \
|
||||
} \
|
||||
namespace \
|
||||
{ \
|
||||
op::Name const &Name = boost::detail::pod_singleton<op::Name>::instance; \
|
||||
} \
|
||||
/**/
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
#define BOOST_NUMERIC_FUNCTIONAL_DEDUCED(Left, Op, Right) \
|
||||
BOOST_TYPEOF_NESTED_TYPEDEF_TPL( \
|
||||
nested \
|
||||
, boost::numeric::functional::detail::lvalue_of<Left>() Op \
|
||||
boost::numeric::functional::detail::lvalue_of<Right>() \
|
||||
) \
|
||||
typedef typename nested::type type; \
|
||||
/**/
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
#define BOOST_NUMERIC_FUNCTIONAL_LEFT(Left, Op, Right) \
|
||||
typedef Left &type; \
|
||||
/**/
|
||||
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(plus, +, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(minus, -, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(multiplies, *, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(divides, /, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(modulus, %, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(greater, >, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(greater_equal, >=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(less, <, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(less_equal, <=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(equal_to, ==, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(not_equal_to, !=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
|
||||
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(assign, =, BOOST_NUMERIC_FUNCTIONAL_LEFT)
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(plus_assign, +=, BOOST_NUMERIC_FUNCTIONAL_LEFT)
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(minus_assign, -=, BOOST_NUMERIC_FUNCTIONAL_LEFT)
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(multiplies_assign, *=, BOOST_NUMERIC_FUNCTIONAL_LEFT)
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(divides_assign, /=, BOOST_NUMERIC_FUNCTIONAL_LEFT)
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(modulus_assign, %=, BOOST_NUMERIC_FUNCTIONAL_LEFT)
|
||||
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(unary_plus, +)
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(unary_minus, -)
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(complement, ~)
|
||||
BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(logical_not, !)
|
||||
|
||||
#undef BOOST_NUMERIC_FUNCTIONAL_LEFT
|
||||
#undef BOOST_NUMERIC_FUNCTIONAL_DEDUCED
|
||||
#undef BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP
|
||||
#undef BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP
|
||||
|
||||
namespace functional
|
||||
{
|
||||
template<typename Left, typename Right, typename EnableIf>
|
||||
struct min_assign_base
|
||||
: std::binary_function<Left, Right, void>
|
||||
{
|
||||
void operator ()(Left &left, Right &right) const
|
||||
{
|
||||
if(numeric::less(right, left))
|
||||
{
|
||||
left = right;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Left, typename Right, typename EnableIf>
|
||||
struct max_assign_base
|
||||
: std::binary_function<Left, Right, void>
|
||||
{
|
||||
void operator ()(Left &left, Right &right) const
|
||||
{
|
||||
if(numeric::greater(right, left))
|
||||
{
|
||||
left = right;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Left, typename Right, typename EnableIf>
|
||||
struct average_base
|
||||
: functional::divides<Left, Right>
|
||||
{};
|
||||
|
||||
// partial specialization that promotes the arguments to double for
|
||||
// integral division.
|
||||
template<typename Left, typename Right>
|
||||
struct average_base<Left, Right, typename enable_if<are_integral<Left, Right> >::type>
|
||||
: functional::divides<double const, double const>
|
||||
{};
|
||||
|
||||
template<typename To, typename From, typename EnableIf>
|
||||
struct promote_base
|
||||
: std::unary_function<From, To>
|
||||
{
|
||||
To operator ()(From &from) const
|
||||
{
|
||||
return from;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ToFrom>
|
||||
struct promote_base<ToFrom, ToFrom, void>
|
||||
: std::unary_function<ToFrom, ToFrom>
|
||||
{
|
||||
ToFrom &operator ()(ToFrom &tofrom)
|
||||
{
|
||||
return tofrom;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Arg, typename EnableIf>
|
||||
struct as_min_base
|
||||
: std::unary_function<Arg, typename remove_const<Arg>::type>
|
||||
{
|
||||
BOOST_STATIC_ASSERT(std::numeric_limits<typename remove_const<Arg>::type>::is_specialized);
|
||||
|
||||
typename remove_const<Arg>::type operator ()(Arg &) const
|
||||
{
|
||||
return (std::numeric_limits<typename remove_const<Arg>::type>::min)();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Arg>
|
||||
struct as_min_base<Arg, typename enable_if<is_floating_point<Arg> >::type>
|
||||
: std::unary_function<Arg, typename remove_const<Arg>::type>
|
||||
{
|
||||
BOOST_STATIC_ASSERT(std::numeric_limits<typename remove_const<Arg>::type>::is_specialized);
|
||||
|
||||
typename remove_const<Arg>::type operator ()(Arg &) const
|
||||
{
|
||||
return -(std::numeric_limits<typename remove_const<Arg>::type>::max)();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Arg, typename EnableIf>
|
||||
struct as_max_base
|
||||
: std::unary_function<Arg, typename remove_const<Arg>::type>
|
||||
{
|
||||
BOOST_STATIC_ASSERT(std::numeric_limits<typename remove_const<Arg>::type>::is_specialized);
|
||||
|
||||
typename remove_const<Arg>::type operator ()(Arg &) const
|
||||
{
|
||||
return (std::numeric_limits<typename remove_const<Arg>::type>::max)();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Arg, typename EnableIf>
|
||||
struct as_zero_base
|
||||
: std::unary_function<Arg, typename remove_const<Arg>::type>
|
||||
{
|
||||
typename remove_const<Arg>::type operator ()(Arg &) const
|
||||
{
|
||||
return numeric::zero<typename remove_const<Arg>::type>::value;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Arg, typename EnableIf>
|
||||
struct as_one_base
|
||||
: std::unary_function<Arg, typename remove_const<Arg>::type>
|
||||
{
|
||||
typename remove_const<Arg>::type operator ()(Arg &) const
|
||||
{
|
||||
return numeric::one<typename remove_const<Arg>::type>::value;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename To, typename From, typename ToTag, typename FromTag>
|
||||
struct promote
|
||||
: promote_base<To, From, void>
|
||||
{};
|
||||
|
||||
template<typename Left, typename Right, typename LeftTag, typename RightTag>
|
||||
struct min_assign
|
||||
: min_assign_base<Left, Right, void>
|
||||
{};
|
||||
|
||||
template<typename Left, typename Right, typename LeftTag, typename RightTag>
|
||||
struct max_assign
|
||||
: max_assign_base<Left, Right, void>
|
||||
{};
|
||||
|
||||
template<typename Left, typename Right, typename LeftTag, typename RightTag>
|
||||
struct average
|
||||
: average_base<Left, Right, void>
|
||||
{};
|
||||
|
||||
template<typename Arg, typename Tag>
|
||||
struct as_min
|
||||
: as_min_base<Arg, void>
|
||||
{};
|
||||
|
||||
template<typename Arg, typename Tag>
|
||||
struct as_max
|
||||
: as_max_base<Arg, void>
|
||||
{};
|
||||
|
||||
template<typename Arg, typename Tag>
|
||||
struct as_zero
|
||||
: as_zero_base<Arg, void>
|
||||
{};
|
||||
|
||||
template<typename Arg, typename Tag>
|
||||
struct as_one
|
||||
: as_one_base<Arg, void>
|
||||
{};
|
||||
}
|
||||
|
||||
namespace op
|
||||
{
|
||||
template<typename To>
|
||||
struct promote
|
||||
: boost::detail::function1<functional::promote<To, _, typename functional::tag<To>::type, functional::tag<_> > >
|
||||
{};
|
||||
|
||||
struct min_assign
|
||||
: boost::detail::function2<functional::min_assign<_1, _2, functional::tag<_1>, functional::tag<_2> > >
|
||||
{};
|
||||
|
||||
struct max_assign
|
||||
: boost::detail::function2<functional::max_assign<_1, _2, functional::tag<_1>, functional::tag<_2> > >
|
||||
{};
|
||||
|
||||
struct average
|
||||
: boost::detail::function2<functional::average<_1, _2, functional::tag<_1>, functional::tag<_2> > >
|
||||
{};
|
||||
|
||||
struct as_min
|
||||
: boost::detail::function1<functional::as_min<_, functional::tag<_> > >
|
||||
{};
|
||||
|
||||
struct as_max
|
||||
: boost::detail::function1<functional::as_max<_, functional::tag<_> > >
|
||||
{};
|
||||
|
||||
struct as_zero
|
||||
: boost::detail::function1<functional::as_zero<_, functional::tag<_> > >
|
||||
{};
|
||||
|
||||
struct as_one
|
||||
: boost::detail::function1<functional::as_one<_, functional::tag<_> > >
|
||||
{};
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
op::min_assign const &min_assign = boost::detail::pod_singleton<op::min_assign>::instance;
|
||||
op::max_assign const &max_assign = boost::detail::pod_singleton<op::max_assign>::instance;
|
||||
op::average const &average = boost::detail::pod_singleton<op::average>::instance;
|
||||
op::as_min const &as_min = boost::detail::pod_singleton<op::as_min>::instance;
|
||||
op::as_max const &as_max = boost::detail::pod_singleton<op::as_max>::instance;
|
||||
op::as_zero const &as_zero = boost::detail::pod_singleton<op::as_zero>::instance;
|
||||
op::as_one const &as_one = boost::detail::pod_singleton<op::as_one>::instance;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// promote
|
||||
template<typename To, typename From>
|
||||
typename lazy_disable_if<is_const<From>, mpl::if_<is_same<To, From>, To &, To> >::type
|
||||
promote(From &from)
|
||||
{
|
||||
return functional::promote<To, From>()(from);
|
||||
}
|
||||
|
||||
template<typename To, typename From>
|
||||
typename mpl::if_<is_same<To const, From const>, To const &, To const>::type
|
||||
promote(From const &from)
|
||||
{
|
||||
return functional::promote<To const, From const>()(from);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct default_
|
||||
{
|
||||
typedef default_ type;
|
||||
typedef T value_type;
|
||||
static T const value;
|
||||
|
||||
operator T const & () const
|
||||
{
|
||||
return default_::value;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
T const default_<T>::value = T();
|
||||
|
||||
template<typename T>
|
||||
struct one
|
||||
{
|
||||
typedef one type;
|
||||
typedef T value_type;
|
||||
static T const value;
|
||||
|
||||
operator T const & () const
|
||||
{
|
||||
return one::value;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
T const one<T>::value = T(1);
|
||||
|
||||
template<typename T>
|
||||
struct zero
|
||||
{
|
||||
typedef zero type;
|
||||
typedef T value_type;
|
||||
static T const value;
|
||||
|
||||
operator T const & () const
|
||||
{
|
||||
return zero::value;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
T const zero<T>::value = T();
|
||||
|
||||
template<typename T>
|
||||
struct one_or_default
|
||||
: mpl::if_<is_empty<T>, default_<T>, one<T> >::type
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
struct zero_or_default
|
||||
: mpl::if_<is_empty<T>, default_<T>, zero<T> >::type
|
||||
{};
|
||||
|
||||
}} // namespace boost::numeric
|
||||
|
||||
#endif
|
|
@ -0,0 +1,82 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// \file complex.hpp
|
||||
///
|
||||
// Copyright 2005 Eric Niebler. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_NUMERIC_FUNCTIONAL_COMPLEX_HPP_EAN_01_17_2006
|
||||
#define BOOST_NUMERIC_FUNCTIONAL_COMPLEX_HPP_EAN_01_17_2006
|
||||
|
||||
#ifdef BOOST_NUMERIC_FUNCTIONAL_HPP_INCLUDED
|
||||
# error Include this file before boost/accumulators/numeric/functional.hpp
|
||||
#endif
|
||||
|
||||
#include <complex>
|
||||
#include <boost/mpl/or.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/typeof/std/complex.hpp>
|
||||
#include <boost/accumulators/numeric/functional_fwd.hpp>
|
||||
|
||||
namespace boost { namespace numeric { namespace operators
|
||||
{
|
||||
// So that the stats compile when Sample type is std::complex
|
||||
template<typename T, typename U>
|
||||
typename
|
||||
disable_if<
|
||||
mpl::or_<is_same<T, U>, is_same<std::complex<T>, U> >
|
||||
, std::complex<T>
|
||||
>::type
|
||||
operator *(std::complex<T> ri, U const &u)
|
||||
{
|
||||
// BUGBUG promote result to typeof(T()*u) ?
|
||||
return ri *= static_cast<T>(u);
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
typename
|
||||
disable_if<
|
||||
mpl::or_<is_same<T, U>, is_same<std::complex<T>, U> >
|
||||
, std::complex<T>
|
||||
>::type
|
||||
operator /(std::complex<T> ri, U const &u)
|
||||
{
|
||||
// BUGBUG promote result to typeof(T()*u) ?
|
||||
return ri /= static_cast<T>(u);
|
||||
}
|
||||
|
||||
}}} // namespace boost::numeric::operators
|
||||
|
||||
namespace boost { namespace numeric
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename T>
|
||||
struct one_complex
|
||||
{
|
||||
static std::complex<T> const value;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
std::complex<T> const one_complex<T>::value
|
||||
= std::complex<T>(numeric::one<T>::value, numeric::one<T>::value);
|
||||
}
|
||||
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
template<typename T>
|
||||
struct one<std::complex<T> >
|
||||
: detail::one_complex<T>
|
||||
{
|
||||
typedef one type;
|
||||
typedef std::complex<T> value_type;
|
||||
operator value_type const & () const
|
||||
{
|
||||
return detail::one_complex<T>::value;
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace boost::numeric
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue