├── .gitmodules ├── CMakeLists.txt ├── CheckAtomic.cmake ├── LICENSE.md ├── README.md ├── UseMultiArch.cmake ├── debian ├── changelog.in ├── compat ├── control ├── copyright ├── libp8-platform-dev.install ├── libp8-platform2.install ├── rules └── source │ └── format ├── p8-platform-config.cmake.in ├── p8-platform.pc.in ├── src ├── os.h ├── posix │ ├── os-socket.h │ ├── os-threads.h │ └── os-types.h ├── sockets │ ├── cdevsocket.h │ ├── socket.h │ └── tcp.h ├── threads │ ├── atomics.h │ ├── mutex.h │ └── threads.h ├── util │ ├── StdString.h │ ├── StringUtils.cpp │ ├── StringUtils.h │ ├── atomic.h │ ├── buffer.h │ ├── timeutils.h │ └── util.h └── windows │ ├── dlfcn-win32.cpp │ ├── dlfcn-win32.h │ ├── inttypes.h │ ├── os-socket.h │ ├── os-threads.cpp │ ├── os-threads.h │ ├── os-types.h │ └── stdint.h └── windows ├── build-lib.cmd └── build.cmd /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "support"] 2 | path = support 3 | url = https://github.com/Pulse-Eight/libcec-support.git 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12.0) 2 | project(p8-platform) 3 | 4 | enable_language(CXX) 5 | 6 | set(CMAKE_CXX_STANDARD 11) 7 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 8 | set(CMAKE_CXX_EXTENSIONS NO) 9 | 10 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}) 11 | 12 | find_package(Threads REQUIRED) 13 | include(UseMultiArch.cmake) 14 | include(CheckAtomic.cmake) 15 | 16 | set(p8-platform_NAME p8-platform) 17 | set(p8-platform_DESCRIPTION "Pulse-Eight platform support library") 18 | set(p8-platform_VERSION_MAJOR 2) 19 | set(p8-platform_VERSION_MINOR 1) 20 | set(p8-platform_VERSION_PATCH 1) 21 | 22 | set(CMAKE_POSITION_INDEPENDENT_CODE on) 23 | 24 | if(WIN32) 25 | set(PLAT_SOURCES src/windows/dlfcn-win32.cpp 26 | src/windows/os-threads.cpp) 27 | endif() 28 | 29 | set(p8-platform_INCLUDE_DIRS "${CMAKE_INSTALL_PREFIX}/include/p8-platform") 30 | if(WIN32) 31 | LIST(APPEND p8-platform_INCLUDE_DIRS "${CMAKE_INSTALL_PREFIX}/include/p8-platform/windows") 32 | endif(WIN32) 33 | set(p8-platform_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) 34 | 35 | if(NOT ${CORE_SYSTEM_NAME} STREQUAL "") 36 | if(${CORE_SYSTEM_NAME} STREQUAL "osx" OR ${CORE_SYSTEM_NAME} STREQUAL "ios") 37 | list(APPEND p8-platform_LIBRARIES "-framework CoreVideo") 38 | endif() 39 | endif() 40 | 41 | set(SOURCES src/util/StringUtils.cpp) 42 | 43 | add_library(p8-platform ${SOURCES} ${PLAT_SOURCES}) 44 | target_link_libraries(p8-platform ${p8-platform_LIBRARIES}) 45 | set_target_properties(p8-platform 46 | PROPERTIES 47 | VERSION ${p8-platform_VERSION_MAJOR}.${p8-platform_VERSION_MINOR}.${p8-platform_VERSION_PATCH} 48 | SOVERSION ${p8-platform_VERSION_MAJOR}) 49 | 50 | if(WIN32) 51 | if (MSVC) 52 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_HAS_ITERATOR_DEBUGGING=1 /D_SECURE_SCL=1") 53 | add_compile_definitions($<$:_ITERATOR_DEBUG_LEVEL=2>) 54 | add_compile_definitions($<$:_HAS_ITERATOR_DEBUGGING=1>) 55 | # generate pdb in release mode too 56 | set_target_properties(p8-platform 57 | PROPERTIES 58 | COMPILE_PDB_NAME_DEBUG p8-platform${CMAKE_DEBUG_POSTFIX} 59 | COMPILE_PDB_NAME_RELEASE p8-platform 60 | COMPILE_PDB_NAME_MINSIZEREL p8-platform 61 | COMPILE_PDB_NAME_RELWITHDEBINFO p8-platform) 62 | 63 | if (${WIN64}) 64 | # default setting that got removed in recent vs versions, generates a warning if set 65 | string(REPLACE "/arch:SSE2" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) 66 | endif(${WIN64}) 67 | 68 | endif(MSVC) 69 | 70 | if ((NOT ${WIN64}) AND (NOT ${_M_ARM64})) 71 | add_definitions(-D_USE_32BIT_TIME_T) 72 | endif((NOT ${WIN64}) AND (NOT ${_M_ARM64})) 73 | endif(WIN32) 74 | 75 | install(TARGETS p8-platform DESTINATION ${CMAKE_INSTALL_LIBDIR}) 76 | install(FILES src/os.h DESTINATION include/p8-platform) 77 | if(WIN32) 78 | install(FILES src/windows/dlfcn-win32.h 79 | src/windows/os-socket.h 80 | src/windows/os-threads.h 81 | src/windows/os-types.h 82 | DESTINATION include/p8-platform/windows) 83 | else(WIN32) 84 | install(FILES src/posix/os-socket.h 85 | src/posix/os-threads.h 86 | src/posix/os-types.h 87 | DESTINATION include/p8-platform/posix) 88 | endif(WIN32) 89 | install(FILES src/sockets/cdevsocket.h 90 | src/sockets/socket.h 91 | src/sockets/tcp.h 92 | DESTINATION include/p8-platform/sockets) 93 | install(FILES src/threads/atomics.h 94 | src/threads/mutex.h 95 | src/threads/threads.h 96 | DESTINATION include/p8-platform/threads) 97 | install(FILES src/util/atomic.h 98 | src/util/buffer.h 99 | src/util/StringUtils.h 100 | src/util/StdString.h 101 | src/util/timeutils.h 102 | src/util/util.h 103 | DESTINATION include/p8-platform/util) 104 | 105 | if(MSVC) 106 | # install generated pdb 107 | install(FILES $/p8-platform.pdb 108 | DESTINATION "${CMAKE_INSTALL_LIBDIR}") 109 | endif(MSVC) 110 | 111 | if(NOT WIN32) 112 | configure_file(p8-platform.pc.in p8-platform.pc @ONLY) 113 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/p8-platform.pc 114 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) 115 | endif(NOT WIN32) 116 | 117 | # config mode 118 | configure_file (p8-platform-config.cmake.in 119 | p8-platform-config.cmake @ONLY) 120 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/p8-platform-config.cmake 121 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/p8-platform) 122 | 123 | -------------------------------------------------------------------------------- /CheckAtomic.cmake: -------------------------------------------------------------------------------- 1 | include(CheckCXXSourceCompiles) 2 | 3 | check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC) 4 | if (HAVE_LIBATOMIC) 5 | list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") 6 | endif() 7 | 8 | CHECK_CXX_SOURCE_COMPILES("int main() { long* temp=0; long ret=__sync_add_and_fetch(temp, 1); return 0; }" HAS_BUILTIN_SYNC_ADD_AND_FETCH) 9 | CHECK_CXX_SOURCE_COMPILES("int main() { long* temp=0; long ret=__sync_sub_and_fetch(temp, 1); return 0; }" HAS_BUILTIN_SYNC_SUB_AND_FETCH) 10 | CHECK_CXX_SOURCE_COMPILES("int main() { long *temp = 0; long ret=__sync_val_compare_and_swap(temp, 1, 1); return 0; }" HAS_BUILTIN_SYNC_VAL_COMPARE_AND_SWAP) -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | This file is part of the libCEC(R) library. 2 | 3 | libCEC(R) is Copyright (C) 2011-2020 Pulse-Eight Limited. All rights reserved. 4 | libCEC(R) is a original work, containing original code. 5 | 6 | libCEC(R) is a trademark of Pulse-Eight Limited. 7 | 8 | This program is dual-licensed; you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation; either version 2 of the License, or 11 | (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | Alternatively, you can license this library under a commercial license, 23 | please contact Pulse-Eight Licensing for more information. 24 | 25 | For more information contact: 26 | Pulse-Eight Licensing 27 | http://www.pulse-eight.com/ 28 | http://www.pulse-eight.net/ 29 | 30 | 31 | 32 | GNU GENERAL PUBLIC LICENSE 33 | Version 2, June 1991 34 | 35 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 36 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 37 | Everyone is permitted to copy and distribute verbatim copies 38 | of this license document, but changing it is not allowed. 39 | 40 | Preamble 41 | 42 | The licenses for most software are designed to take away your 43 | freedom to share and change it. By contrast, the GNU General Public 44 | License is intended to guarantee your freedom to share and change free 45 | software--to make sure the software is free for all its users. This 46 | General Public License applies to most of the Free Software 47 | Foundation's software and to any other program whose authors commit to 48 | using it. (Some other Free Software Foundation software is covered by 49 | the GNU Lesser General Public License instead.) You can apply it to 50 | your programs, too. 51 | 52 | When we speak of free software, we are referring to freedom, not 53 | price. Our General Public Licenses are designed to make sure that you 54 | have the freedom to distribute copies of free software (and charge for 55 | this service if you wish), that you receive source code or can get it 56 | if you want it, that you can change the software or use pieces of it 57 | in new free programs; and that you know you can do these things. 58 | 59 | To protect your rights, we need to make restrictions that forbid 60 | anyone to deny you these rights or to ask you to surrender the rights. 61 | These restrictions translate to certain responsibilities for you if you 62 | distribute copies of the software, or if you modify it. 63 | 64 | For example, if you distribute copies of such a program, whether 65 | gratis or for a fee, you must give the recipients all the rights that 66 | you have. You must make sure that they, too, receive or can get the 67 | source code. And you must show them these terms so they know their 68 | rights. 69 | 70 | We protect your rights with two steps: (1) copyright the software, and 71 | (2) offer you this license which gives you legal permission to copy, 72 | distribute and/or modify the software. 73 | 74 | Also, for each author's protection and ours, we want to make certain 75 | that everyone understands that there is no warranty for this free 76 | software. If the software is modified by someone else and passed on, we 77 | want its recipients to know that what they have is not the original, so 78 | that any problems introduced by others will not reflect on the original 79 | authors' reputations. 80 | 81 | Finally, any free program is threatened constantly by software 82 | patents. We wish to avoid the danger that redistributors of a free 83 | program will individually obtain patent licenses, in effect making the 84 | program proprietary. To prevent this, we have made it clear that any 85 | patent must be licensed for everyone's free use or not licensed at all. 86 | 87 | The precise terms and conditions for copying, distribution and 88 | modification follow. 89 | 90 | GNU GENERAL PUBLIC LICENSE 91 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 92 | 93 | 0. This License applies to any program or other work which contains 94 | a notice placed by the copyright holder saying it may be distributed 95 | under the terms of this General Public License. The "Program", below, 96 | refers to any such program or work, and a "work based on the Program" 97 | means either the Program or any derivative work under copyright law: 98 | that is to say, a work containing the Program or a portion of it, 99 | either verbatim or with modifications and/or translated into another 100 | language. (Hereinafter, translation is included without limitation in 101 | the term "modification".) Each licensee is addressed as "you". 102 | 103 | Activities other than copying, distribution and modification are not 104 | covered by this License; they are outside its scope. The act of 105 | running the Program is not restricted, and the output from the Program 106 | is covered only if its contents constitute a work based on the 107 | Program (independent of having been made by running the Program). 108 | Whether that is true depends on what the Program does. 109 | 110 | 1. You may copy and distribute verbatim copies of the Program's 111 | source code as you receive it, in any medium, provided that you 112 | conspicuously and appropriately publish on each copy an appropriate 113 | copyright notice and disclaimer of warranty; keep intact all the 114 | notices that refer to this License and to the absence of any warranty; 115 | and give any other recipients of the Program a copy of this License 116 | along with the Program. 117 | 118 | You may charge a fee for the physical act of transferring a copy, and 119 | you may at your option offer warranty protection in exchange for a fee. 120 | 121 | 2. You may modify your copy or copies of the Program or any portion 122 | of it, thus forming a work based on the Program, and copy and 123 | distribute such modifications or work under the terms of Section 1 124 | above, provided that you also meet all of these conditions: 125 | 126 | a) You must cause the modified files to carry prominent notices 127 | stating that you changed the files and the date of any change. 128 | 129 | b) You must cause any work that you distribute or publish, that in 130 | whole or in part contains or is derived from the Program or any 131 | part thereof, to be licensed as a whole at no charge to all third 132 | parties under the terms of this License. 133 | 134 | c) If the modified program normally reads commands interactively 135 | when run, you must cause it, when started running for such 136 | interactive use in the most ordinary way, to print or display an 137 | announcement including an appropriate copyright notice and a 138 | notice that there is no warranty (or else, saying that you provide 139 | a warranty) and that users may redistribute the program under 140 | these conditions, and telling the user how to view a copy of this 141 | License. (Exception: if the Program itself is interactive but 142 | does not normally print such an announcement, your work based on 143 | the Program is not required to print an announcement.) 144 | 145 | These requirements apply to the modified work as a whole. If 146 | identifiable sections of that work are not derived from the Program, 147 | and can be reasonably considered independent and separate works in 148 | themselves, then this License, and its terms, do not apply to those 149 | sections when you distribute them as separate works. But when you 150 | distribute the same sections as part of a whole which is a work based 151 | on the Program, the distribution of the whole must be on the terms of 152 | this License, whose permissions for other licensees extend to the 153 | entire whole, and thus to each and every part regardless of who wrote it. 154 | 155 | Thus, it is not the intent of this section to claim rights or contest 156 | your rights to work written entirely by you; rather, the intent is to 157 | exercise the right to control the distribution of derivative or 158 | collective works based on the Program. 159 | 160 | In addition, mere aggregation of another work not based on the Program 161 | with the Program (or with a work based on the Program) on a volume of 162 | a storage or distribution medium does not bring the other work under 163 | the scope of this License. 164 | 165 | 3. You may copy and distribute the Program (or a work based on it, 166 | under Section 2) in object code or executable form under the terms of 167 | Sections 1 and 2 above provided that you also do one of the following: 168 | 169 | a) Accompany it with the complete corresponding machine-readable 170 | source code, which must be distributed under the terms of Sections 171 | 1 and 2 above on a medium customarily used for software interchange; or, 172 | 173 | b) Accompany it with a written offer, valid for at least three 174 | years, to give any third party, for a charge no more than your 175 | cost of physically performing source distribution, a complete 176 | machine-readable copy of the corresponding source code, to be 177 | distributed under the terms of Sections 1 and 2 above on a medium 178 | customarily used for software interchange; or, 179 | 180 | c) Accompany it with the information you received as to the offer 181 | to distribute corresponding source code. (This alternative is 182 | allowed only for noncommercial distribution and only if you 183 | received the program in object code or executable form with such 184 | an offer, in accord with Subsection b above.) 185 | 186 | The source code for a work means the preferred form of the work for 187 | making modifications to it. For an executable work, complete source 188 | code means all the source code for all modules it contains, plus any 189 | associated interface definition files, plus the scripts used to 190 | control compilation and installation of the executable. However, as a 191 | special exception, the source code distributed need not include 192 | anything that is normally distributed (in either source or binary 193 | form) with the major components (compiler, kernel, and so on) of the 194 | operating system on which the executable runs, unless that component 195 | itself accompanies the executable. 196 | 197 | If distribution of executable or object code is made by offering 198 | access to copy from a designated place, then offering equivalent 199 | access to copy the source code from the same place counts as 200 | distribution of the source code, even though third parties are not 201 | compelled to copy the source along with the object code. 202 | 203 | 4. You may not copy, modify, sublicense, or distribute the Program 204 | except as expressly provided under this License. Any attempt 205 | otherwise to copy, modify, sublicense or distribute the Program is 206 | void, and will automatically terminate your rights under this License. 207 | However, parties who have received copies, or rights, from you under 208 | this License will not have their licenses terminated so long as such 209 | parties remain in full compliance. 210 | 211 | 5. You are not required to accept this License, since you have not 212 | signed it. However, nothing else grants you permission to modify or 213 | distribute the Program or its derivative works. These actions are 214 | prohibited by law if you do not accept this License. Therefore, by 215 | modifying or distributing the Program (or any work based on the 216 | Program), you indicate your acceptance of this License to do so, and 217 | all its terms and conditions for copying, distributing or modifying 218 | the Program or works based on it. 219 | 220 | 6. Each time you redistribute the Program (or any work based on the 221 | Program), the recipient automatically receives a license from the 222 | original licensor to copy, distribute or modify the Program subject to 223 | these terms and conditions. You may not impose any further 224 | restrictions on the recipients' exercise of the rights granted herein. 225 | You are not responsible for enforcing compliance by third parties to 226 | this License. 227 | 228 | 7. If, as a consequence of a court judgment or allegation of patent 229 | infringement or for any other reason (not limited to patent issues), 230 | conditions are imposed on you (whether by court order, agreement or 231 | otherwise) that contradict the conditions of this License, they do not 232 | excuse you from the conditions of this License. If you cannot 233 | distribute so as to satisfy simultaneously your obligations under this 234 | License and any other pertinent obligations, then as a consequence you 235 | may not distribute the Program at all. For example, if a patent 236 | license would not permit royalty-free redistribution of the Program by 237 | all those who receive copies directly or indirectly through you, then 238 | the only way you could satisfy both it and this License would be to 239 | refrain entirely from distribution of the Program. 240 | 241 | If any portion of this section is held invalid or unenforceable under 242 | any particular circumstance, the balance of the section is intended to 243 | apply and the section as a whole is intended to apply in other 244 | circumstances. 245 | 246 | It is not the purpose of this section to induce you to infringe any 247 | patents or other property right claims or to contest validity of any 248 | such claims; this section has the sole purpose of protecting the 249 | integrity of the free software distribution system, which is 250 | implemented by public license practices. Many people have made 251 | generous contributions to the wide range of software distributed 252 | through that system in reliance on consistent application of that 253 | system; it is up to the author/donor to decide if he or she is willing 254 | to distribute software through any other system and a licensee cannot 255 | impose that choice. 256 | 257 | This section is intended to make thoroughly clear what is believed to 258 | be a consequence of the rest of this License. 259 | 260 | 8. If the distribution and/or use of the Program is restricted in 261 | certain countries either by patents or by copyrighted interfaces, the 262 | original copyright holder who places the Program under this License 263 | may add an explicit geographical distribution limitation excluding 264 | those countries, so that distribution is permitted only in or among 265 | countries not thus excluded. In such case, this License incorporates 266 | the limitation as if written in the body of this License. 267 | 268 | 9. The Free Software Foundation may publish revised and/or new versions 269 | of the General Public License from time to time. Such new versions will 270 | be similar in spirit to the present version, but may differ in detail to 271 | address new problems or concerns. 272 | 273 | Each version is given a distinguishing version number. If the Program 274 | specifies a version number of this License which applies to it and "any 275 | later version", you have the option of following the terms and conditions 276 | either of that version or of any later version published by the Free 277 | Software Foundation. If the Program does not specify a version number of 278 | this License, you may choose any version ever published by the Free Software 279 | Foundation. 280 | 281 | 10. If you wish to incorporate parts of the Program into other free 282 | programs whose distribution conditions are different, write to the author 283 | to ask for permission. For software which is copyrighted by the Free 284 | Software Foundation, write to the Free Software Foundation; we sometimes 285 | make exceptions for this. Our decision will be guided by the two goals 286 | of preserving the free status of all derivatives of our free software and 287 | of promoting the sharing and reuse of software generally. 288 | 289 | NO WARRANTY 290 | 291 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 292 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 293 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 294 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 295 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 296 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 297 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 298 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 299 | REPAIR OR CORRECTION. 300 | 301 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 302 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 303 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 304 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 305 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 306 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 307 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 308 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 309 | POSSIBILITY OF SUCH DAMAGES. 310 | 311 | END OF TERMS AND CONDITIONS 312 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Pulse-Eight logo](https://pulseeight.files.wordpress.com/2016/02/pulse-eight-logo-white-on-green.png?w=200) 2 | 3 | # About 4 | This library provides platform specific support for other libraries, and is used by libCEC and binary add-ons for Kodi 5 | 6 | # Supported platforms 7 | 8 | ## Linux, BSD & Apple OS X 9 | To compile this library on Linux, you'll need the following dependencies: 10 | * [cmake 2.6 or better] (http://www.cmake.org/) 11 | * a supported C++ 11 compiler 12 | 13 | Follow these instructions to compile and install the library: 14 | ``` 15 | apt-get update 16 | apt-get install cmake build-essential 17 | git clone https://github.com/Pulse-Eight/platform.git 18 | mkdir platform/build 19 | cd platform/build 20 | cmake .. 21 | make -j4 22 | sudo make install 23 | sudo ldconfig 24 | ``` 25 | 26 | ## Microsoft Windows 27 | To compile this library on Windows, you'll need the following dependencies: 28 | * [cmake 2.6 or better] (http://www.cmake.org/) 29 | * [Visual Studio 2013 (v120) or 2015 (v140)] (https://www.visualstudio.com/) 30 | 31 | Follow these instructions to compile and install the library: 32 | ``` 33 | git clone https://github.com/Pulse-Eight/platform.git 34 | cd platform 35 | git submodule update --init --recursive 36 | cd 37 | build.cmd 38 | ``` 39 | -------------------------------------------------------------------------------- /UseMultiArch.cmake: -------------------------------------------------------------------------------- 1 | # - Multiarch support in object code library directories 2 | # 3 | # This module sets the following variable 4 | # CMAKE_INSTALL_LIBDIR to lib, lib64 or lib/x86_64-linux-gnu 5 | # depending on the platform; use this path 6 | # for platform-specific binaries. 7 | # 8 | # CMAKE_INSTALL_LIBDIR_NOARCH to lib or lib64 depending on the platform; 9 | # use this path for architecture-independent 10 | # files. 11 | # 12 | # Note that it will override the results of GNUInstallDirs if included after 13 | # that module. 14 | 15 | # Fedora uses lib64/ for 64-bit systems, Debian uses lib/x86_64-linux-gnu; 16 | # Fedora put module files in lib64/ too, but Debian uses lib/ for that 17 | if ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux" AND 18 | "${CMAKE_INSTALL_PREFIX}" STREQUAL "/usr") 19 | # Debian or Ubuntu? 20 | if (EXISTS "/etc/debian_version") 21 | set (_libdir_def "lib/${CMAKE_LIBRARY_ARCHITECTURE}") 22 | set (_libdir_noarch "lib") 23 | elseif (EXISTS "/etc/fedora-release" OR 24 | EXISTS "/etc/redhat-release" OR 25 | EXISTS "/etc/slackware-version" OR 26 | EXISTS "/etc/gentoo-release") 27 | # 64-bit system? 28 | if (CMAKE_SIZEOF_VOID_P EQUAL 8) 29 | set (_libdir_noarch "lib64") 30 | else (CMAKE_SIZEOF_VOID_P EQUAL 8) 31 | set (_libdir_noarch "lib") 32 | endif (CMAKE_SIZEOF_VOID_P EQUAL 8) 33 | set (_libdir_def "${_libdir_noarch}") 34 | else () 35 | set (_libdir_def "lib") 36 | set (_libdir_noarch "lib") 37 | endif () 38 | else () 39 | set (_libdir_def "lib") 40 | set (_libdir_noarch "lib") 41 | endif () 42 | 43 | # let the user override if somewhere else is desirable 44 | set (CMAKE_INSTALL_LIBDIR "${_libdir_def}" CACHE PATH "Object code libraries") 45 | set (CMAKE_INSTALL_LIBDIR_NOARCH "${_libdir_noarch}" CACHE PATH "Architecture-independent library files") 46 | mark_as_advanced ( 47 | CMAKE_INSTALL_LIBDIR 48 | CMAKE_INSTALL_LIBDIR_NOARCH 49 | ) 50 | -------------------------------------------------------------------------------- /debian/changelog.in: -------------------------------------------------------------------------------- 1 | p8-platform (2.1.0.1~#DIST#) #DIST#; urgency=medium 2 | 3 | * [tvos] remove IOKit linkage. credits @Memphiz 4 | * [posix] use standard SO versioning. credits @rbalint 5 | * [posix] install pkg-config and .cmake files in arch-specific libdirs. 6 | credits @rbalint 7 | * [posix] fixed: wrong timeout in SocketRead(). closes #27. credits @SeppSTA 8 | * [windows] added support files for building 9 | 10 | -- Pulse-Eight Packaging Mon, 24 Oct 2016 10:56:12 +0100 11 | 12 | p8-platform (2.0.1-1~#DIST#) #DIST#; urgency=medium 13 | 14 | * Avoid that cmake removes variables from pkg-config file 15 | 16 | -- Pulse-Eight Packaging Tue, 19 Jan 2016 20:48:37 +0100 17 | 18 | p8-platform (2.0.0-1~#DIST#) #DIST#; urgency=medium 19 | 20 | * renamed to p8-platform 21 | 22 | -- Pulse-Eight Packaging Tue, 01 Dec 2015 03:22:00 +0100 23 | 24 | platform (2.0.0-1~#DIST#) #DIST#; urgency=medium 25 | 26 | * removed: fstrcmp and StringUtils::CompareFuzzy() + 27 | StringUtils::FindBestMatch() because of an incompatible license 28 | 29 | -- Pulse-Eight Packaging Tue, 01 Dec 2015 02:48:06 +0100 30 | 31 | platform (1.0.10-1~#DIST#) #DIST#; urgency=medium 32 | 33 | * fixed: posix socket return value for connect 34 | 35 | -- Pulse-Eight Packaging Tue, 30 Jun 2015 10:53:06 +0100 36 | 37 | platform (1.0.9-1~#DIST#) #DIST#; urgency=medium 38 | 39 | * fixed: add missing stdio.h include in windows/os-socket.h 40 | 41 | -- Pulse-Eight Packaging Wed, 13 May 2015 10:01:43 +0100 42 | 43 | platform (1.0.8-1~#DIST#) #DIST#; urgency=medium 44 | 45 | * added: cdevsocket.h character device socket 46 | * fixed: guards for #defines on OS X and iOS for values already defined in 47 | CFPlugInCOM.h 48 | 49 | -- Pulse-Eight Packaging Mon, 11 May 2015 09:33:17 +0100 50 | 51 | platform (1.0.7-1~#DIST#) #DIST#; urgency=medium 52 | 53 | * fixed: include on OS X 54 | 55 | -- Pulse-Eight Packaging Fri, 08 May 2015 22:15:23 +0100 56 | 57 | platform (1.0.6-1~#DIST#) #DIST#; urgency=medium 58 | 59 | * fixed: add include path and link the threads lib 60 | * (re-)added: public Reset() function in CEvent 61 | * sync UseMultiArch.cmake 62 | 63 | -- Pulse-Eight Packaging Thu, 07 May 2015 21:20:00 +0100 64 | 65 | platform (1.0.5-1~#DIST#) #DIST#; urgency=medium 66 | 67 | * fixed: missing #include in socket.h 68 | 69 | -- Pulse-Eight Packaging Mon, 04 May 2015 01:29:00 +0100 70 | 71 | platform (1.0.4-1~#DIST#) #DIST#; urgency=medium 72 | 73 | * proper platform.pc.in fix 74 | 75 | -- Pulse-Eight Packaging Sun, 03 May 2015 21:56:00 +0100 76 | 77 | platform (1.0.3-1~#DIST#) #DIST#; urgency=medium 78 | 79 | * platform.pc.in fix 80 | 81 | -- Pulse-Eight Packaging Fri, 01 May 2015 14:38:00 +0100 82 | 83 | platform (1.0.2-1~#DIST#) #DIST#; urgency=medium 84 | 85 | * Build fixes 86 | 87 | -- Pulse-Eight Packaging Fri, 01 May 2015 01:38:00 +0100 88 | 89 | platform (1.0.0-1~#DIST#) #DIST#; urgency=medium 90 | 91 | * Initial release 92 | 93 | -- Pulse-Eight Packaging Thu, 12 Mar 2015 13:35:07 +0100 94 | 95 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 8 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: p8-platform 2 | Priority: extra 3 | Maintainer: Lars Op den Kamp 4 | Build-Depends: debhelper (>= 8.0.0), cmake (>= 2.8.9) 5 | Standards-Version: 3.9.2 6 | Section: libs 7 | 8 | Package: libp8-platform-dev 9 | Section: libdevel 10 | Architecture: any 11 | Multi-Arch: same 12 | Depends: libp8-platform2 (= ${binary:Version}) 13 | Provides: libp8-platform-dev 14 | Description: Pulse-Eight platform support library -- development files 15 | Pulse-Eight platform support library 16 | 17 | Package: libp8-platform2 18 | Section: libs 19 | Architecture: any 20 | Multi-Arch: same 21 | Depends: ${shlibs:Depends}, ${misc:Depends} 22 | Provides: libp8-platform 23 | Description: Pulse-Eight platform support library 24 | Pulse-Eight platform support library 25 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: http://dep.debian.net/deps/dep5 2 | Upstream-Name: platform 3 | Source: https://github.com/Pulse-Eight/platform.git 4 | 5 | Files: * 6 | Copyright: 2011-2012 Pulse-Eight Limited 7 | 2005-2015 Team XBMC 8 | License: 9 | This program is dual-licensed; you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation; either version 2 of the License, or 12 | (at your option) any later version. 13 | . 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | . 19 | You should have received a copy of the GNU General Public License 20 | along with this program; if not, write to the Free Software 21 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 | . 23 | . 24 | Alternatively, you can license this library under a commercial license, 25 | please contact Pulse-Eight Licensing for more information. 26 | . 27 | For more information contact: 28 | Pulse-Eight Licensing 29 | 30 | Files: debian/* 31 | Copyright: 2013 Arne Morten Kvarving 32 | License: GPL-2+ 33 | This package is free software; you can redistribute it and/or modify 34 | it under the terms of the GNU General Public License as published by 35 | the Free Software Foundation; either version 2 of the License, or 36 | (at your option) any later version. 37 | . 38 | This package is distributed in the hope that it will be useful, 39 | but WITHOUT ANY WARRANTY; without even the implied warranty of 40 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 41 | GNU General Public License for more details. 42 | . 43 | You should have received a copy of the GNU General Public License 44 | along with this program. If not, see 45 | . 46 | On Debian systems, the complete text of the GNU General 47 | Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". 48 | 49 | # Please also look if there are files or directories which have a 50 | # different copyright/license attached and list them here. 51 | -------------------------------------------------------------------------------- /debian/libp8-platform-dev.install: -------------------------------------------------------------------------------- 1 | usr/include/* 2 | usr/lib/*/*.so 3 | usr/lib/*/pkgconfig 4 | usr/lib/*/p8-platform/* 5 | -------------------------------------------------------------------------------- /debian/libp8-platform2.install: -------------------------------------------------------------------------------- 1 | usr/lib/*/*.so.* 2 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # -*- makefile -*- 3 | # Sample debian/rules that uses debhelper. 4 | # This file was originally written by Joey Hess and Craig Small. 5 | # As a special exception, when this file is copied by dh-make into a 6 | # dh-make output file, you may use that output file without restriction. 7 | # This special exception was added by Craig Small in version 0.37 of dh-make. 8 | 9 | # Uncomment this to turn on verbose mode. 10 | #export DH_VERBOSE=1 11 | 12 | %: 13 | dh $@ 14 | 15 | override_dh_auto_configure: 16 | cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=1 -DCMAKE_INSTALL_PREFIX=/usr 17 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (native) 2 | -------------------------------------------------------------------------------- /p8-platform-config.cmake.in: -------------------------------------------------------------------------------- 1 | # - p8-platform config mode 2 | # 3 | # Defines the following variables: 4 | # p8-platform_FOUND - true 5 | # p8-platform_VERSION - version of the platform library found, e.g. 0.2 6 | # p8-platform_INCLUDE_DIRS - header directories with which to compile 7 | # p8-platform_LINKER_FLAGS - flags that must be passed to the linker 8 | # p8-platform_LIBRARIES - names of the libraries with which to link 9 | # p8-platform_LIBRARY_DIRS - directories in which the libraries are situated 10 | # 11 | # propagate these properties from one build system to the other 12 | set (p8-platform_VERSION "@p8-platform_VERSION_MAJOR@.@p8-platform_VERSION_MINOR@") 13 | find_path (p8-platform_INCLUDE_DIRS p8-platform/os.h) 14 | set (p8-platform_LIBRARY_DIRS "@CMAKE_LIBRARY_OUTPUT_DIRECTORY@") 15 | set (p8-platform_LINKER_FLAGS "@p8-platform_LINKER_FLAGS@") 16 | set (p8-platform_CONFIG_VARS "@p8-platform_CONFIG_VARS@") 17 | 18 | # libraries come from the build tree where this file was generated 19 | if(WIN32) 20 | set (p8-platform_LIBRARY "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/p8-platform.lib") 21 | else(WIN32) 22 | find_library (p8-platform_LIBRARY p8-platform) 23 | endif(WIN32) 24 | set (p8-platform_LIBRARIES ${p8-platform_LIBRARY} "@p8-platform_LIBRARIES@") 25 | mark_as_advanced (p8-platform_LIBRARY) 26 | 27 | # add the library as a target, so that other things in the project including 28 | # this file may depend on it and get rebuild if this library changes. 29 | add_library (p8-platform UNKNOWN IMPORTED) 30 | set_property (TARGET p8-platform PROPERTY IMPORTED_LOCATION "${p8-platform_LIBRARY}") 31 | -------------------------------------------------------------------------------- /p8-platform.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | libdir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@ 3 | includedir=@CMAKE_INSTALL_PREFIX@/include 4 | DEPENDENCIES=@p8-platform_LIBRARIES@ 5 | 6 | Name: @p8-platform_NAME@ 7 | Description: @p8-platform_DESCRIPTION@ @p8-platform_VERSION_MAJOR@.@p8-platform_VERSION_MINOR@ 8 | Version: @p8-platform_VERSION_MAJOR@.@p8-platform_VERSION_MINOR@.@p8-platform_VERSION_PATCH@ 9 | Libs: -L${libdir} -lp8-platform 10 | Cflags: -I${includedir} 11 | -------------------------------------------------------------------------------- /src/os.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | * This file is part of the libCEC(R) library. 4 | * 5 | * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. 6 | * libCEC(R) is an original work, containing original code. 7 | * 8 | * libCEC(R) is a trademark of Pulse-Eight Limited. 9 | * 10 | * This program is dual-licensed; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 | * 24 | * 25 | * Alternatively, you can license this library under a commercial license, 26 | * please contact Pulse-Eight Licensing for more information. 27 | * 28 | * For more information contact: 29 | * Pulse-Eight Licensing 30 | * http://www.pulse-eight.com/ 31 | * http://www.pulse-eight.net/ 32 | */ 33 | 34 | #if (defined(_WIN32) || defined(_WIN64) || defined(_M_ARM64)) 35 | #include "windows/os-types.h" 36 | #else 37 | #include "posix/os-types.h" 38 | #endif 39 | -------------------------------------------------------------------------------- /src/posix/os-socket.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | * This file is part of the libCEC(R) library. 4 | * 5 | * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. 6 | * libCEC(R) is an original work, containing original code. 7 | * 8 | * libCEC(R) is a trademark of Pulse-Eight Limited. 9 | * 10 | * This program is dual-licensed; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 | * 24 | * 25 | * Alternatively, you can license this library under a commercial license, 26 | * please contact Pulse-Eight Licensing for more information. 27 | * 28 | * For more information contact: 29 | * Pulse-Eight Licensing 30 | * http://www.pulse-eight.com/ 31 | * http://www.pulse-eight.net/ 32 | */ 33 | 34 | 35 | #include "../os.h" 36 | #include "../util/timeutils.h" 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | /* Needed on Mac OS/X */ 48 | #ifndef SOL_TCP 49 | #define SOL_TCP IPPROTO_TCP 50 | #endif 51 | 52 | namespace P8PLATFORM 53 | { 54 | // Standard sockets 55 | //@{ 56 | inline void SocketClose(socket_t socket) 57 | { 58 | if (socket != INVALID_SOCKET_VALUE) 59 | close(socket); 60 | } 61 | 62 | inline void SocketSetBlocking(socket_t socket, bool bSetTo) 63 | { 64 | if (socket != INVALID_SOCKET_VALUE) 65 | { 66 | if (bSetTo) 67 | fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) & ~O_NONBLOCK); 68 | else 69 | fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) | O_NONBLOCK); 70 | } 71 | } 72 | 73 | inline ssize_t SocketWrite(socket_t socket, int *iError, void* data, size_t len) 74 | { 75 | fd_set port; 76 | 77 | if (socket == INVALID_SOCKET_VALUE) 78 | { 79 | *iError = EINVAL; 80 | return -EINVAL; 81 | } 82 | 83 | ssize_t iBytesWritten(0); 84 | struct timeval *tv(NULL); 85 | 86 | while (iBytesWritten < (ssize_t)len) 87 | { 88 | FD_ZERO(&port); 89 | FD_SET(socket, &port); 90 | int returnv = select(socket + 1, NULL, &port, NULL, tv); 91 | if (returnv < 0) 92 | { 93 | *iError = errno; 94 | return -errno; 95 | } 96 | else if (returnv == 0) 97 | { 98 | *iError = ETIMEDOUT; 99 | return -ETIMEDOUT; 100 | } 101 | 102 | returnv = write(socket, (char*)data + iBytesWritten, len - iBytesWritten); 103 | if (returnv == -1) 104 | { 105 | *iError = errno; 106 | return -errno; 107 | } 108 | iBytesWritten += returnv; 109 | } 110 | 111 | return iBytesWritten; 112 | } 113 | 114 | inline ssize_t SocketRead(socket_t socket, int *iError, void* data, size_t len, uint64_t iTimeoutMs /*= 0*/) 115 | { 116 | fd_set port; 117 | struct timeval timeout, *tv; 118 | ssize_t iBytesRead(0); 119 | *iError = 0; 120 | CTimeout readTimeout(iTimeoutMs); 121 | 122 | if (socket == INVALID_SOCKET_VALUE) 123 | { 124 | *iError = EINVAL; 125 | return -EINVAL; 126 | } 127 | 128 | while (iBytesRead >= 0 && iBytesRead < (ssize_t)len && (iTimeoutMs == 0 || readTimeout.TimeLeft() > 0)) 129 | { 130 | if (iTimeoutMs == 0) 131 | { 132 | tv = NULL; 133 | } 134 | else 135 | { 136 | long iTimeLeft = (long)readTimeout.TimeLeft(); 137 | timeout.tv_sec = iTimeLeft / (long int)1000.; 138 | timeout.tv_usec = (iTimeLeft % (long int)1000.) * (long int)1000.; 139 | tv = &timeout; 140 | } 141 | 142 | FD_ZERO(&port); 143 | FD_SET(socket, &port); 144 | int32_t returnv = select(socket + 1, &port, NULL, NULL, tv); 145 | 146 | if (returnv == -1) 147 | { 148 | *iError = errno; 149 | return -errno; 150 | } 151 | else if (returnv == 0) 152 | { 153 | break; //nothing to read 154 | } 155 | 156 | returnv = read(socket, (char*)data + iBytesRead, len - iBytesRead); 157 | if (returnv == -1) 158 | { 159 | *iError = errno; 160 | return -errno; 161 | } 162 | 163 | iBytesRead += returnv; 164 | } 165 | 166 | return iBytesRead; 167 | } 168 | 169 | inline int SocketIoctl(socket_t socket, int *iError, int request, void* data) 170 | { 171 | if (socket == INVALID_SOCKET_VALUE) 172 | { 173 | *iError = EINVAL; 174 | return -1; 175 | } 176 | 177 | int iReturn = ioctl(socket, request, data); 178 | if (iReturn < 0) 179 | *iError = errno; 180 | return iReturn; 181 | } 182 | //@} 183 | 184 | 185 | // TCP 186 | //@{ 187 | inline void TcpSocketClose(tcp_socket_t socket) 188 | { 189 | SocketClose(socket); 190 | } 191 | 192 | inline void TcpSocketShutdown(tcp_socket_t socket) 193 | { 194 | if (socket != INVALID_SOCKET_VALUE) 195 | shutdown(socket, SHUT_RDWR); 196 | } 197 | 198 | inline ssize_t TcpSocketWrite(tcp_socket_t socket, int *iError, void* data, size_t len) 199 | { 200 | if (socket == INVALID_SOCKET_VALUE) 201 | { 202 | *iError = EINVAL; 203 | return -1; 204 | } 205 | 206 | ssize_t iReturn = send(socket, data, len, 0); 207 | if (iReturn < (ssize_t)len) 208 | *iError = errno; 209 | return iReturn; 210 | } 211 | 212 | inline ssize_t TcpSocketRead(tcp_socket_t socket, int *iError, void* data, size_t len, uint64_t iTimeoutMs /*= 0*/) 213 | { 214 | int64_t iNow(0), iTarget(0); 215 | ssize_t iBytesRead(0); 216 | *iError = 0; 217 | 218 | if (socket == INVALID_SOCKET_VALUE) 219 | { 220 | *iError = EINVAL; 221 | return -EINVAL; 222 | } 223 | 224 | if (iTimeoutMs > 0) 225 | { 226 | iNow = GetTimeMs(); 227 | iTarget = iNow + (int64_t) iTimeoutMs; 228 | } 229 | 230 | struct pollfd fds; 231 | fds.fd = socket; 232 | fds.events = POLLIN; 233 | fds.revents = 0; 234 | 235 | while (iBytesRead >= 0 && 236 | iBytesRead < (ssize_t)len && 237 | (iTimeoutMs == 0 || iTarget > iNow) && 238 | *iError == 0) 239 | { 240 | if (iTimeoutMs > 0) 241 | { 242 | int iPollResult = poll(&fds, 1, iTarget - iNow); 243 | if (iPollResult == 0) 244 | *iError = ETIMEDOUT; 245 | } 246 | 247 | ssize_t iReadResult = (iTimeoutMs > 0) ? 248 | recv(socket, (char*)data + iBytesRead, len - iBytesRead, MSG_DONTWAIT) : 249 | recv(socket, data, len, MSG_WAITALL); 250 | if (iReadResult < 0) 251 | { 252 | if (errno == EAGAIN && iTimeoutMs > 0) 253 | continue; 254 | *iError = errno; 255 | return (iBytesRead > 0) ? iBytesRead : -errno; 256 | } 257 | else if (iReadResult == 0 || (iReadResult != (ssize_t)len && iTimeoutMs == 0)) 258 | { 259 | *iError = ECONNRESET; 260 | } 261 | 262 | iBytesRead += iReadResult; 263 | 264 | if (iTimeoutMs > 0) 265 | iNow = GetTimeMs(); 266 | } 267 | 268 | if (iBytesRead < (ssize_t)len && iError == 0) 269 | *iError = ETIMEDOUT; 270 | return iBytesRead; 271 | } 272 | 273 | inline bool TcpResolveAddress(const char *strHost, uint16_t iPort, int *iError, struct addrinfo **info) 274 | { 275 | struct addrinfo hints; 276 | char service[33]; 277 | memset(&hints, 0, sizeof(hints)); 278 | hints.ai_family = AF_UNSPEC; 279 | hints.ai_socktype = SOCK_STREAM; 280 | hints.ai_protocol = IPPROTO_TCP; 281 | sprintf(service, "%d", iPort); 282 | 283 | *iError = getaddrinfo(strHost, service, &hints, info); 284 | return !(*iError); 285 | } 286 | 287 | inline int TcpGetSocketError(tcp_socket_t socket) 288 | { 289 | int iReturn(0); 290 | socklen_t optLen = sizeof(socket_t); 291 | getsockopt(socket, SOL_SOCKET, SO_ERROR, (void *)&iReturn, &optLen); 292 | return iReturn; 293 | } 294 | 295 | inline bool TcpSetNoDelay(tcp_socket_t socket) 296 | { 297 | int iSetTo(1); 298 | setsockopt(socket, SOL_TCP, TCP_NODELAY, &iSetTo, sizeof(iSetTo)); 299 | return true; 300 | } 301 | 302 | inline bool TcpConnectSocket(tcp_socket_t socket, struct addrinfo* addr, int *iError, uint64_t iTimeout = 0) 303 | { 304 | *iError = 0; 305 | SocketSetBlocking(socket, false); 306 | int iConnectResult = connect(socket, addr->ai_addr, addr->ai_addrlen); 307 | SocketSetBlocking(socket, true); 308 | if (iConnectResult == -1) 309 | { 310 | if (errno == EINPROGRESS) 311 | { 312 | struct pollfd pfd; 313 | pfd.fd = socket; 314 | pfd.events = POLLOUT; 315 | pfd.revents = 0; 316 | 317 | int iPollResult = poll(&pfd, 1, iTimeout); 318 | if (iPollResult == 0) 319 | *iError = ETIMEDOUT; 320 | else if (iPollResult == -1) 321 | *iError = errno; 322 | 323 | if (*iError == 0) 324 | { 325 | socklen_t errlen = sizeof(int); 326 | getsockopt(socket, SOL_SOCKET, SO_ERROR, (void *)iError, &errlen); 327 | } 328 | } 329 | else 330 | { 331 | *iError = errno; 332 | } 333 | } 334 | 335 | return *iError == 0; 336 | } 337 | //@} 338 | } 339 | -------------------------------------------------------------------------------- /src/posix/os-threads.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | * This file is part of the libCEC(R) library. 4 | * 5 | * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. 6 | * libCEC(R) is an original work, containing original code. 7 | * 8 | * libCEC(R) is a trademark of Pulse-Eight Limited. 9 | * 10 | * This program is dual-licensed; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 | * 24 | * 25 | * Alternatively, you can license this library under a commercial license, 26 | * please contact Pulse-Eight Licensing for more information. 27 | * 28 | * For more information contact: 29 | * Pulse-Eight Licensing 30 | * http://www.pulse-eight.com/ 31 | * http://www.pulse-eight.net/ 32 | */ 33 | 34 | #if defined(TARGET_DARWIN) 35 | # ifndef PTHREAD_MUTEX_RECURSIVE_NP 36 | # define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE 37 | # endif 38 | #endif 39 | 40 | namespace P8PLATFORM 41 | { 42 | inline pthread_mutexattr_t *GetRecursiveMutexAttribute(void) 43 | { 44 | static pthread_mutexattr_t g_mutexAttr; 45 | static bool bAttributeInitialised = false; 46 | if (!bAttributeInitialised) 47 | { 48 | pthread_mutexattr_init(&g_mutexAttr); 49 | pthread_mutexattr_settype(&g_mutexAttr, PTHREAD_MUTEX_RECURSIVE); 50 | bAttributeInitialised = true; 51 | } 52 | return &g_mutexAttr; 53 | } 54 | 55 | inline struct timespec GetAbsTime(uint64_t iIncreaseBy = 0) 56 | { 57 | struct timespec now; 58 | #ifdef __APPLE__ 59 | struct timeval tv; 60 | gettimeofday(&tv, NULL); 61 | now.tv_sec = tv.tv_sec; 62 | now.tv_nsec = tv.tv_usec * 1000; 63 | #else 64 | clock_gettime(CLOCK_REALTIME, &now); 65 | #endif 66 | now.tv_nsec += iIncreaseBy % 1000 * 1000000; 67 | now.tv_sec += iIncreaseBy / 1000 + now.tv_nsec / 1000000000; 68 | now.tv_nsec %= 1000000000; 69 | return now; 70 | } 71 | 72 | typedef pthread_t thread_t; 73 | 74 | inline pthread_attr_t *GetDetachedThreadAttribute(void) 75 | { 76 | static pthread_attr_t g_threadAttr; 77 | static bool bAttributeInitialised = false; 78 | if (!bAttributeInitialised) 79 | { 80 | pthread_attr_init(&g_threadAttr); 81 | pthread_attr_setdetachstate(&g_threadAttr, PTHREAD_CREATE_DETACHED); 82 | bAttributeInitialised = true; 83 | } 84 | return &g_threadAttr; 85 | } 86 | 87 | #define ThreadsCreate(thread, func, arg) (pthread_create(&thread, GetDetachedThreadAttribute(), (void *(*) (void *))func, (void *)arg) == 0) 88 | #define ThreadsWait(thread, retval) (pthread_join(thread, retval) == 0) 89 | 90 | typedef pthread_mutex_t mutex_t; 91 | #define MutexCreate(mutex) pthread_mutex_init(&mutex, GetRecursiveMutexAttribute()); 92 | #define MutexDelete(mutex) pthread_mutex_destroy(&mutex); 93 | #define MutexLock(mutex) (pthread_mutex_lock(&mutex) == 0) 94 | #define MutexTryLock(mutex) (pthread_mutex_trylock(&mutex) == 0) 95 | #define MutexUnlock(mutex) pthread_mutex_unlock(&mutex) 96 | 97 | class CConditionImpl 98 | { 99 | public: 100 | CConditionImpl(void) 101 | { 102 | pthread_cond_init(&m_condition, NULL); 103 | } 104 | 105 | virtual ~CConditionImpl(void) 106 | { 107 | pthread_cond_destroy(&m_condition); 108 | } 109 | 110 | void Signal(void) 111 | { 112 | pthread_cond_signal(&m_condition); 113 | } 114 | 115 | void Broadcast(void) 116 | { 117 | pthread_cond_broadcast(&m_condition); 118 | } 119 | 120 | bool Wait(mutex_t &mutex) 121 | { 122 | sched_yield(); 123 | return (pthread_cond_wait(&m_condition, &mutex) == 0); 124 | } 125 | 126 | bool Wait(mutex_t &mutex, uint32_t iTimeoutMs) 127 | { 128 | if (iTimeoutMs == 0) 129 | return Wait(mutex); 130 | 131 | sched_yield(); 132 | struct timespec timeout = GetAbsTime(iTimeoutMs); 133 | return (pthread_cond_timedwait(&m_condition, &mutex, &timeout) == 0); 134 | } 135 | 136 | pthread_cond_t m_condition; 137 | }; 138 | } 139 | -------------------------------------------------------------------------------- /src/posix/os-types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | * This file is part of the libCEC(R) library. 4 | * 5 | * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. 6 | * libCEC(R) is an original work, containing original code. 7 | * 8 | * libCEC(R) is a trademark of Pulse-Eight Limited. 9 | * 10 | * This program is dual-licensed; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 | * 24 | * 25 | * Alternatively, you can license this library under a commercial license, 26 | * please contact Pulse-Eight Licensing for more information. 27 | * 28 | * For more information contact: 29 | * Pulse-Eight Licensing 30 | * http://www.pulse-eight.com/ 31 | * http://www.pulse-eight.net/ 32 | */ 33 | 34 | #define _FILE_OFFSET_BITS 64 35 | #include 36 | #include 37 | #include 38 | #include 39 | #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__) 40 | #include 41 | #endif 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | #include 48 | #include 49 | #include 50 | #include 51 | #if defined(__APPLE__) 52 | // for HRESULT 53 | #include 54 | #endif 55 | 56 | #define LIBTYPE 57 | #define DECLSPEC 58 | 59 | typedef int socket_t; 60 | typedef socket_t tcp_socket_t; 61 | #define INVALID_SOCKET_VALUE (-1) 62 | typedef socket_t serial_socket_t; 63 | #define INVALID_SERIAL_SOCKET_VALUE (-1) 64 | typedef socket_t chardev_socket_t; 65 | #define INVALID_CHARDEV_SOCKET_VALUE (-1) 66 | 67 | typedef long LONG; 68 | #if !defined(__APPLE__) 69 | typedef LONG HRESULT; 70 | #endif 71 | 72 | #define _FILE_OFFSET_BITS 64 73 | #define FILE_BEGIN 0 74 | #define FILE_CURRENT 1 75 | #define FILE_END 2 76 | 77 | // Success codes 78 | #ifndef S_OK 79 | #define S_OK 0L 80 | #endif 81 | 82 | #ifndef S_FALSE 83 | #define S_FALSE 1L 84 | #endif 85 | 86 | #ifndef FAILED 87 | #define FAILED(Status) ((HRESULT)(Status)<0) 88 | #endif 89 | 90 | #ifndef SUCCEEDED 91 | #define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0) 92 | #endif 93 | 94 | // Error codes 95 | #define ERROR_FILENAME_EXCED_RANGE 206L 96 | #define ERROR_INVALID_NAME 123L 97 | 98 | #ifndef E_OUTOFMEMORY 99 | #define E_OUTOFMEMORY 0x8007000EL 100 | #endif 101 | 102 | #ifndef E_FAIL 103 | #define E_FAIL 0x8004005EL 104 | #endif 105 | 106 | #ifdef TARGET_LINUX 107 | #include 108 | #define MAX_PATH PATH_MAX 109 | #elif defined TARGET_DARWIN || defined __FreeBSD__ 110 | #include 111 | #define MAX_PATH PATH_MAX 112 | #else 113 | #define MAX_PATH 256 114 | #endif 115 | 116 | #if defined(__APPLE__) 117 | #include // for fpos_t 118 | #include 119 | #include 120 | typedef int64_t off64_t; 121 | typedef off_t __off_t; 122 | typedef off64_t __off64_t; 123 | typedef fpos_t fpos64_t; 124 | #define __stat64 stat 125 | #define stat64 stat 126 | #if defined(TARGET_DARWIN_IOS) 127 | #define statfs64 statfs 128 | #endif 129 | #define fstat64 fstat 130 | #elif defined(__FreeBSD__) 131 | #include // for fpos_t 132 | typedef int64_t off64_t; 133 | typedef off_t __off_t; 134 | typedef off64_t __off64_t; 135 | typedef fpos_t fpos64_t; 136 | #define __stat64 stat 137 | #define stat64 stat 138 | #define statfs64 statfs 139 | #define fstat64 fstat 140 | #else 141 | #define __stat64 stat64 142 | #endif 143 | 144 | #include 145 | #define strnicmp(X,Y,N) strncasecmp(X,Y,N) 146 | 147 | typedef unsigned char byte; 148 | 149 | /* Platform dependent path separator */ 150 | #ifndef PATH_SEPARATOR_CHAR 151 | #define PATH_SEPARATOR_CHAR '/' 152 | #define PATH_SEPARATOR_STRING "/" 153 | #endif 154 | 155 | #ifdef TARGET_LINUX 156 | // Retrieve the number of milliseconds that have elapsed since the system was started 157 | #include 158 | inline unsigned long GetTickCount(void) 159 | { 160 | struct timespec ts; 161 | if(clock_gettime(CLOCK_MONOTONIC, &ts) != 0) 162 | { 163 | return 0; 164 | } 165 | return (unsigned long)( (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000) ); 166 | }; 167 | #else 168 | #include 169 | inline unsigned long GetTickCount(void) 170 | { 171 | struct timeval tv; 172 | gettimeofday(&tv, NULL); 173 | return (unsigned long)( (tv.tv_sec * 1000) + (tv.tv_usec / 1000) ); 174 | }; 175 | #endif /* TARGET_LINUX || TARGET_DARWIN */ 176 | 177 | /* Handling of 2-byte Windows wchar strings on non-Windows targets 178 | * Used by The MediaPortal and ForTheRecord pvr addons 179 | */ 180 | typedef uint16_t Wchar_t; /* sizeof(wchar_t) = 4 bytes on Linux, but the MediaPortal buffer files have 2-byte wchars */ 181 | 182 | /* This is a replacement of the Windows wcslen() function which assumes that 183 | * wchar_t is a 2-byte character. 184 | * It is used for processing Windows wchar strings 185 | */ 186 | inline size_t WcsLen(const Wchar_t *str) 187 | { 188 | const unsigned short *eos = (const unsigned short*)str; 189 | while( *eos++ ) ; 190 | return( (size_t)(eos - (const unsigned short*)str) -1); 191 | }; 192 | 193 | /* This is a replacement of the Windows wcstombs() function which assumes that 194 | * wchar_t is a 2-byte character. 195 | * It is used for processing Windows wchar strings 196 | */ 197 | inline size_t WcsToMbs(char *s, const Wchar_t *w, size_t n) 198 | { 199 | size_t i = 0; 200 | const unsigned short *wc = (const unsigned short*) w; 201 | while(wc[i] && (i < n)) 202 | { 203 | s[i] = wc[i]; 204 | ++i; 205 | } 206 | if (i < n) s[i] = '\0'; 207 | 208 | return (i); 209 | }; 210 | -------------------------------------------------------------------------------- /src/sockets/cdevsocket.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | * This file is part of the libCEC(R) library. 4 | * 5 | * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved. 6 | * libCEC(R) is an original work, containing original code. 7 | * 8 | * libCEC(R) is a trademark of Pulse-Eight Limited. 9 | * 10 | * This program is dual-licensed; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 | * 24 | * 25 | * Alternatively, you can license this library under a commercial license, 26 | * please contact Pulse-Eight Licensing for more information. 27 | * 28 | * For more information contact: 29 | * Pulse-Eight Licensing 30 | * http://www.pulse-eight.com/ 31 | * http://www.pulse-eight.net/ 32 | */ 33 | 34 | #include "../os.h" 35 | #include "../util/buffer.h" 36 | 37 | #include 38 | #include 39 | 40 | #if !defined(__WINDOWS__) 41 | #include 42 | #endif 43 | 44 | #include "socket.h" 45 | 46 | namespace P8PLATFORM 47 | { 48 | class CCDevSocket : public CCommonSocket 49 | { 50 | public: 51 | CCDevSocket(const std::string &strName ) : 52 | CCommonSocket(INVALID_CHARDEV_SOCKET_VALUE, strName) 53 | #ifdef __WINDOWS__ 54 | ,m_iCurrentReadTimeout(MAXDWORD) 55 | #endif 56 | {} 57 | 58 | virtual ~CCDevSocket(void) 59 | { 60 | Close(); 61 | } 62 | 63 | virtual bool Open(uint64_t iTimeoutMs = 0) 64 | { 65 | (void)iTimeoutMs; 66 | 67 | if (IsOpen()) 68 | return false; 69 | 70 | m_socket = open(m_strName.c_str(), O_RDWR ); 71 | 72 | if (m_socket == INVALID_CHARDEV_SOCKET_VALUE) 73 | { 74 | m_strError = strerror(errno); 75 | return false; 76 | } 77 | 78 | return true; 79 | } 80 | 81 | virtual void Close(void) 82 | { 83 | if (IsOpen()) 84 | { 85 | SocketClose(m_socket); 86 | m_socket = INVALID_CHARDEV_SOCKET_VALUE; 87 | } 88 | } 89 | 90 | virtual void Shutdown(void) 91 | { 92 | SocketClose(m_socket); 93 | } 94 | 95 | virtual int Ioctl(int request, void* data) 96 | { 97 | return IsOpen() ? SocketIoctl(m_socket, &m_iError, request, data) : -1; 98 | } 99 | 100 | virtual ssize_t Write(void* data, size_t len) 101 | { 102 | return IsOpen() ? SocketWrite(m_socket, &m_iError, data, len) : -1; 103 | } 104 | 105 | virtual ssize_t Read(void* data, size_t len, uint64_t iTimeoutMs = 0) 106 | { 107 | return IsOpen() ? SocketRead(m_socket, &m_iError, data, len, iTimeoutMs) : -1; 108 | } 109 | 110 | virtual bool IsOpen(void) 111 | { 112 | return m_socket != INVALID_CHARDEV_SOCKET_VALUE; 113 | } 114 | }; 115 | 116 | }; 117 | 118 | -------------------------------------------------------------------------------- /src/sockets/socket.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | * This file is part of the libCEC(R) library. 4 | * 5 | * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. 6 | * libCEC(R) is an original work, containing original code. 7 | * 8 | * libCEC(R) is a trademark of Pulse-Eight Limited. 9 | * 10 | * This program is dual-licensed; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 | * 24 | * 25 | * Alternatively, you can license this library under a commercial license, 26 | * please contact Pulse-Eight Licensing for more information. 27 | * 28 | * For more information contact: 29 | * Pulse-Eight Licensing 30 | * http://www.pulse-eight.com/ 31 | * http://www.pulse-eight.net/ 32 | */ 33 | 34 | #include "../threads/mutex.h" 35 | 36 | #if defined(__WINDOWS__) 37 | #include "../windows/os-socket.h" 38 | #else 39 | #include "../posix/os-socket.h" 40 | #endif 41 | #include 42 | 43 | // Common socket operations 44 | 45 | namespace P8PLATFORM 46 | { 47 | class ISocket : public PreventCopy 48 | { 49 | public: 50 | ISocket(void) {}; 51 | virtual ~ISocket(void) {} 52 | 53 | virtual bool Open(uint64_t iTimeoutMs = 0) = 0; 54 | virtual void Close(void) = 0; 55 | virtual void Shutdown(void) = 0; 56 | virtual bool IsOpen(void) = 0; 57 | virtual ssize_t Write(void* data, size_t len) = 0; 58 | virtual ssize_t Read(void* data, size_t len, uint64_t iTimeoutMs = 0) = 0; 59 | virtual std::string GetError(void) = 0; 60 | virtual int GetErrorNumber(void) = 0; 61 | virtual std::string GetName(void) = 0; 62 | }; 63 | 64 | template 65 | class CCommonSocket : public ISocket 66 | { 67 | public: 68 | CCommonSocket(_SType initialSocketValue, const std::string &strName) : 69 | m_socket(initialSocketValue), 70 | m_strName(strName), 71 | m_iError(0) {} 72 | 73 | virtual ~CCommonSocket(void) {} 74 | 75 | virtual std::string GetError(void) 76 | { 77 | std::string strError; 78 | strError = m_strError.empty() && m_iError != 0 ? strerror(m_iError) : m_strError; 79 | return strError; 80 | } 81 | 82 | virtual int GetErrorNumber(void) 83 | { 84 | return m_iError; 85 | } 86 | 87 | virtual std::string GetName(void) 88 | { 89 | return m_strName; 90 | } 91 | 92 | protected: 93 | _SType m_socket; 94 | std::string m_strError; 95 | std::string m_strName; 96 | int m_iError; 97 | CMutex m_mutex; 98 | }; 99 | 100 | template 101 | class CProtectedSocket : public ISocket 102 | { 103 | public: 104 | CProtectedSocket(_Socket *socket) : 105 | m_socket(socket), 106 | m_bIsIdle(true) {} 107 | 108 | virtual ~CProtectedSocket(void) 109 | { 110 | delete m_socket; 111 | } 112 | 113 | virtual bool Open(uint64_t iTimeoutMs = 0) 114 | { 115 | bool bReturn(false); 116 | if (m_socket && WaitReady()) 117 | { 118 | bReturn = m_socket->Open(iTimeoutMs); 119 | MarkReady(); 120 | } 121 | return bReturn; 122 | } 123 | 124 | virtual void Close(void) 125 | { 126 | if (m_socket && WaitReady()) 127 | { 128 | m_socket->Close(); 129 | MarkReady(); 130 | } 131 | } 132 | 133 | virtual void Shutdown(void) 134 | { 135 | CLockObject lock(m_mutex); 136 | if (m_socket) 137 | { 138 | m_socket->Shutdown(); 139 | } 140 | } 141 | 142 | virtual bool IsOpen(void) 143 | { 144 | CLockObject lock(m_mutex); 145 | return m_socket && m_socket->IsOpen(); 146 | } 147 | 148 | virtual bool IsBusy(void) 149 | { 150 | CLockObject lock(m_mutex); 151 | return m_socket && !m_bIsIdle; 152 | } 153 | 154 | virtual bool IsIdle(void) 155 | { 156 | CLockObject lock(m_mutex); 157 | return m_socket && m_bIsIdle; 158 | } 159 | 160 | virtual ssize_t Write(void* data, size_t len) 161 | { 162 | if (!m_socket || !WaitReady()) 163 | return -EINVAL; 164 | 165 | ssize_t iReturn = m_socket->Write(data, len); 166 | MarkReady(); 167 | 168 | return iReturn; 169 | } 170 | 171 | virtual ssize_t Read(void* data, size_t len, uint64_t iTimeoutMs = 0) 172 | { 173 | if (!m_socket || !WaitReady()) 174 | return -EINVAL; 175 | 176 | ssize_t iReturn = m_socket->Read(data, len, iTimeoutMs); 177 | MarkReady(); 178 | 179 | return iReturn; 180 | } 181 | 182 | virtual std::string GetError(void) 183 | { 184 | std::string strError; 185 | CLockObject lock(m_mutex); 186 | strError = m_socket ? m_socket->GetError() : ""; 187 | return strError; 188 | } 189 | 190 | virtual int GetErrorNumber(void) 191 | { 192 | CLockObject lock(m_mutex); 193 | return m_socket ? m_socket->GetErrorNumber() : -EINVAL; 194 | } 195 | 196 | virtual std::string GetName(void) 197 | { 198 | std::string strName; 199 | CLockObject lock(m_mutex); 200 | strName = m_socket ? m_socket->GetName() : ""; 201 | return strName; 202 | } 203 | 204 | private: 205 | bool WaitReady(void) 206 | { 207 | CLockObject lock(m_mutex); 208 | m_condition.Wait(m_mutex, m_bIsIdle); 209 | m_bIsIdle = false; 210 | return true; 211 | } 212 | 213 | void MarkReady(void) 214 | { 215 | CLockObject lock(m_mutex); 216 | m_bIsIdle = true; 217 | m_condition.Signal(); 218 | } 219 | 220 | _Socket * m_socket; 221 | CMutex m_mutex; 222 | CCondition m_condition; 223 | bool m_bIsIdle; 224 | }; 225 | }; 226 | -------------------------------------------------------------------------------- /src/sockets/tcp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | * This file is part of the libCEC(R) library. 4 | * 5 | * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. 6 | * libCEC(R) is an original work, containing original code. 7 | * 8 | * libCEC(R) is a trademark of Pulse-Eight Limited. 9 | * 10 | * This program is dual-licensed; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 | * 24 | * 25 | * Alternatively, you can license this library under a commercial license, 26 | * please contact Pulse-Eight Licensing for more information. 27 | * 28 | * For more information contact: 29 | * Pulse-Eight Licensing 30 | * http://www.pulse-eight.com/ 31 | * http://www.pulse-eight.net/ 32 | */ 33 | 34 | #include "socket.h" 35 | 36 | 37 | namespace P8PLATFORM 38 | { 39 | class CTcpSocket : public CCommonSocket 40 | { 41 | public: 42 | CTcpSocket(const std::string &strHostname, uint16_t iPort) : 43 | CCommonSocket(INVALID_SOCKET_VALUE, strHostname), 44 | m_iPort(iPort) {} 45 | 46 | virtual ~CTcpSocket(void) { Close(); } 47 | 48 | virtual bool Open(uint64_t iTimeoutMs = 0) 49 | { 50 | bool bReturn(false); 51 | struct addrinfo *address(NULL), *addr(NULL); 52 | m_strError.clear(); 53 | m_iError = 0; 54 | if (!TcpResolveAddress(m_strName.c_str(), m_iPort, &m_iError, &address)) 55 | { 56 | m_strError = strerror(m_iError); 57 | return bReturn; 58 | } 59 | 60 | for(addr = address; !bReturn && addr; addr = addr->ai_next) 61 | { 62 | m_socket = TcpCreateSocket(addr, &m_iError); 63 | if (m_socket != INVALID_SOCKET_VALUE) 64 | { 65 | if (!TcpConnectSocket(m_socket, addr, &m_iError, iTimeoutMs)) 66 | { 67 | TcpSocketClose(m_socket); 68 | m_strError = strerror(m_iError); 69 | m_socket = INVALID_SOCKET_VALUE; 70 | } 71 | else 72 | { 73 | TcpSetNoDelay(m_socket); 74 | bReturn = true; 75 | } 76 | } 77 | else 78 | m_strError = strerror(m_iError); 79 | } 80 | 81 | freeaddrinfo(address); 82 | return bReturn; 83 | } 84 | 85 | virtual void Close(void) 86 | { 87 | TcpSocketClose(m_socket); 88 | m_socket = INVALID_SOCKET_VALUE; 89 | } 90 | 91 | virtual void Shutdown(void) 92 | { 93 | TcpSocketShutdown(m_socket); 94 | TcpSocketClose(m_socket); 95 | m_socket = INVALID_SOCKET_VALUE; 96 | } 97 | 98 | virtual ssize_t Write(void* data, size_t len) 99 | { 100 | return TcpSocketWrite(m_socket, &m_iError, data, len); 101 | } 102 | 103 | virtual ssize_t Read(void* data, size_t len, uint64_t iTimeoutMs = 0) 104 | { 105 | return TcpSocketRead(m_socket, &m_iError, data, len, iTimeoutMs); 106 | } 107 | 108 | virtual bool IsOpen(void) 109 | { 110 | return m_socket != INVALID_SOCKET_VALUE; 111 | } 112 | 113 | protected: 114 | virtual tcp_socket_t TcpCreateSocket(struct addrinfo* addr, int* iError) 115 | { 116 | tcp_socket_t fdSock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); 117 | if (fdSock == INVALID_SOCKET_VALUE) 118 | { 119 | *iError = errno; 120 | return (tcp_socket_t)INVALID_SOCKET_VALUE; 121 | } 122 | 123 | return fdSock; 124 | } 125 | 126 | uint16_t m_iPort; 127 | }; 128 | 129 | class CTcpConnection : public CProtectedSocket 130 | { 131 | public: 132 | CTcpConnection(const std::string &strHostname, uint16_t iPort) : 133 | CProtectedSocket (new CTcpSocket(strHostname, iPort)) {} 134 | virtual ~CTcpConnection(void) {} 135 | }; 136 | }; 137 | -------------------------------------------------------------------------------- /src/threads/atomics.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | * Copyright (C) 2015 Team XBMC 4 | * http://kodi.tv 5 | * 6 | * This Program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2, or (at your option) 9 | * any later version. 10 | * 11 | * This Program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with XBMC; see the file COPYING. If not, see 18 | * . 19 | * 20 | */ 21 | 22 | #include "../os.h" 23 | 24 | namespace P8PLATFORM 25 | { 26 | /////////////////////////////////////////////////////////////////////////// 27 | // 32-bit atomic compare-and-swap 28 | // Returns previous value of *pAddr 29 | /////////////////////////////////////////////////////////////////////////// 30 | static inline long cas(volatile long *pAddr, long expectedVal, long swapVal) 31 | { 32 | #if defined(HAS_BUILTIN_SYNC_VAL_COMPARE_AND_SWAP) 33 | return(__sync_val_compare_and_swap(pAddr, expectedVal, swapVal)); 34 | #elif defined(__ppc__) || defined(__powerpc__) // PowerPC 35 | unsigned int prev; 36 | __asm__ __volatile__ ( 37 | " 1: lwarx %0,0,%2 \n" /* Load the current value of *pAddr(%2) into prev (%0) and lock pAddr, */ 38 | " cmpw 0,%0,%3 \n" /* Verify that the current value (%2) == old value (%3) */ 39 | " bne- 2f \n" /* Bail if the two values are not equal [not as expected] */ 40 | " stwcx. %4,0,%2 \n" /* Attempt to store swapVal (%4) value into *pAddr (%2) [p must still be reserved] */ 41 | " bne- 1b \n" /* Loop if p was no longer reserved */ 42 | " isync \n" /* Reconcile multiple processors [if present] */ 43 | " 2: \n" 44 | : "=&r" (prev), "+m" (*pAddr) /* Outputs [prev, *pAddr] */ 45 | : "r" (pAddr), "r" (expectedVal), "r" (swapVal) /* Inputs [pAddr, expectedVal, swapVal] */ 46 | : "cc", "memory"); /* Clobbers */ 47 | return prev; 48 | 49 | #elif defined(__arm__) 50 | register long prev; 51 | asm volatile ( 52 | "dmb ish \n" // Memory barrier. Make sure all memory accesses appearing before this complete before any that appear after 53 | "1: \n" 54 | "ldrex %0, [%1] \n" // Load the current value of *pAddr(%1) into prev (%0) and lock pAddr, 55 | "cmp %0, %2 \n" // Verify that the current value (%0) == old value (%2) 56 | "bne 2f \n" // Bail if the two values are not equal [not as expected] 57 | "strex r1, %3, [%1] \n" 58 | "cmp r1, #0 \n" 59 | "bne 1b \n" 60 | "dmb ish \n" // Memory barrier. 61 | "2: \n" 62 | : "=&r" (prev) 63 | : "r"(pAddr), "r"(expectedVal),"r"(swapVal) 64 | : "r1" 65 | ); 66 | return prev; 67 | 68 | #elif defined(__mips__) 69 | // TODO: 70 | unsigned int prev; 71 | #error atomic cas undefined for mips 72 | return prev; 73 | 74 | #elif defined(__WINDOWS__) 75 | long prev; 76 | __asm 77 | { 78 | // Load parameters 79 | mov eax, expectedVal ; 80 | mov ebx, pAddr ; 81 | mov ecx, swapVal ; 82 | 83 | // Do Swap 84 | lock cmpxchg dword ptr [ebx], ecx ; 85 | 86 | // Store the return value 87 | mov prev, eax; 88 | } 89 | return prev; 90 | 91 | #else // Linux / OSX86 (GCC) 92 | long prev; 93 | __asm__ __volatile__ ( 94 | "lock/cmpxchg %1, %2" 95 | : "=a" (prev) 96 | : "r" (swapVal), "m" (*pAddr), "0" (expectedVal) 97 | : "memory" ); 98 | return prev; 99 | 100 | #endif 101 | } 102 | 103 | #if !defined(__ppc__) && !defined(__powerpc__) && !defined(__arm__) 104 | /////////////////////////////////////////////////////////////////////////// 105 | // 64-bit atomic compare-and-swap 106 | // Returns previous value of *pAddr 107 | /////////////////////////////////////////////////////////////////////////// 108 | static inline long long cas2(volatile long long* pAddr, long long expectedVal, long long swapVal) 109 | { 110 | #if defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || defined(__mips__) // PowerPC, ARM, and MIPS 111 | // Not available/required 112 | // Hack to allow compilation 113 | throw "cas2 is not implemented"; 114 | 115 | #elif defined(__WINDOWS__) 116 | long long prev; 117 | __asm 118 | { 119 | mov esi, pAddr ; 120 | mov eax, dword ptr [expectedVal] ; 121 | mov edx, dword ptr expectedVal[4] ; 122 | mov ebx, dword ptr [swapVal] ; 123 | mov ecx, dword ptr swapVal[4] ; 124 | lock cmpxchg8b qword ptr [esi] ; 125 | mov dword ptr [prev], eax ; 126 | mov dword ptr prev[4], edx ; 127 | } 128 | return prev; 129 | 130 | #else // Linux / OSX86 (GCC) 131 | #if !defined (__x86_64) 132 | long long prev; 133 | __asm__ volatile ( 134 | " push %%ebx \n" // We have to manually handle ebx, because PIC uses it and the compiler refuses to build anything that touches it 135 | " mov %4, %%ebx \n" 136 | " lock/cmpxchg8b (%%esi) \n" 137 | " pop %%ebx" 138 | : "=A" (prev) 139 | : "c" ((unsigned long)(swapVal >> 32)), "0" (expectedVal), "S" (pAddr), "m" (swapVal) 140 | : "memory"); 141 | return prev; 142 | #else 143 | // Hack to allow compilation on x86_64 144 | throw "cas2 is not implemented on x86_64!"; 145 | #endif 146 | #endif 147 | } 148 | #endif 149 | 150 | /////////////////////////////////////////////////////////////////////////// 151 | // 32-bit atomic increment 152 | // Returns new value of *pAddr 153 | /////////////////////////////////////////////////////////////////////////// 154 | static inline long atomic_inc(volatile long* pAddr) 155 | { 156 | #if defined(HAS_BUILTIN_SYNC_ADD_AND_FETCH) 157 | return __sync_add_and_fetch(pAddr, 1); 158 | 159 | #elif defined(__ppc__) || defined(__powerpc__) // PowerPC 160 | long val; 161 | __asm__ __volatile__ ( 162 | "sync \n" 163 | "1: lwarx %0, 0, %1 \n" 164 | "addic %0, %0, 1 \n" 165 | "stwcx. %0, 0, %1 \n" 166 | "bne- 1b \n" 167 | "isync" 168 | : "=&r" (val) 169 | : "r" (pAddr) 170 | : "cc", "xer", "memory"); 171 | return val; 172 | 173 | #elif defined(__arm__) && !defined(__ARM_ARCH_5__) 174 | register long val; 175 | asm volatile ( 176 | "dmb ish \n" // Memory barrier. Make sure all memory accesses appearing before this complete before any that appear after 177 | "1: \n" 178 | "ldrex %0, [%1] \n" // (val = *pAddr) 179 | "add %0, #1 \n" // (val += 1) 180 | "strex r1, %0, [%1] \n" 181 | "cmp r1, #0 \n" 182 | "bne 1b \n" 183 | "dmb ish \n" // Memory barrier. 184 | : "=&r" (val) 185 | : "r"(pAddr) 186 | : "r1" 187 | ); 188 | return val; 189 | 190 | #elif defined(__mips__) 191 | // TODO: 192 | long val; 193 | #error AtomicIncrement undefined for mips 194 | return val; 195 | 196 | #elif defined(__WINDOWS__) 197 | long val; 198 | __asm 199 | { 200 | mov eax, pAddr ; 201 | lock inc dword ptr [eax] ; 202 | mov eax, [eax] ; 203 | mov val, eax ; 204 | } 205 | return val; 206 | 207 | #elif defined(__x86_64__) 208 | register long result; 209 | __asm__ __volatile__ ( 210 | "lock/xaddq %q0, %1" 211 | : "=r" (result), "=m" (*pAddr) 212 | : "0" ((long) (1)), "m" (*pAddr)); 213 | return *pAddr; 214 | 215 | #else // Linux / OSX86 (GCC) 216 | register long reg __asm__ ("eax") = 1; 217 | __asm__ __volatile__ ( 218 | "lock/xadd %0, %1 \n" 219 | "inc %%eax" 220 | : "+r" (reg) 221 | : "m" (*pAddr) 222 | : "memory" ); 223 | return reg; 224 | 225 | #endif 226 | } 227 | 228 | /////////////////////////////////////////////////////////////////////////// 229 | // 32-bit atomic decrement 230 | // Returns new value of *pAddr 231 | /////////////////////////////////////////////////////////////////////////// 232 | static inline long atomic_dec(volatile long* pAddr) 233 | { 234 | #if defined(HAS_BUILTIN_SYNC_SUB_AND_FETCH) 235 | return __sync_sub_and_fetch(pAddr, 1); 236 | 237 | #elif defined(__ppc__) || defined(__powerpc__) // PowerPC 238 | long val; 239 | __asm__ __volatile__ ( 240 | "sync \n" 241 | "1: lwarx %0, 0, %1 \n" 242 | "addic %0, %0, -1 \n" 243 | "stwcx. %0, 0, %1 \n" 244 | "bne- 1b \n" 245 | "isync" 246 | : "=&r" (val) 247 | : "r" (pAddr) 248 | : "cc", "xer", "memory"); 249 | return val; 250 | 251 | #elif defined(__arm__) 252 | register long val; 253 | asm volatile ( 254 | "dmb ish \n" // Memory barrier. Make sure all memory accesses appearing before this complete before any that appear after 255 | "1: \n" 256 | "ldrex %0, [%1] \n" // (val = *pAddr) 257 | "sub %0, #1 \n" // (val -= 1) 258 | "strex r1, %0, [%1] \n" 259 | "cmp r1, #0 \n" 260 | "bne 1b \n" 261 | "dmb ish \n" // Memory barrier. 262 | : "=&r" (val) 263 | : "r"(pAddr) 264 | : "r1" 265 | ); 266 | return val; 267 | 268 | #elif defined(__mips__) 269 | // TODO: 270 | long val; 271 | #error AtomicDecrement undefined for mips 272 | return val; 273 | 274 | #elif defined(__WINDOWS__) 275 | long val; 276 | __asm 277 | { 278 | mov eax, pAddr ; 279 | lock dec dword ptr [eax] ; 280 | mov eax, [eax] ; 281 | mov val, eax ; 282 | } 283 | return val; 284 | 285 | #elif defined(__x86_64__) 286 | register long result; 287 | __asm__ __volatile__ ( 288 | "lock/xaddq %q0, %1" 289 | : "=r" (result), "=m" (*pAddr) 290 | : "0" ((long) (-1)), "m" (*pAddr)); 291 | return *pAddr; 292 | 293 | #else // Linux / OSX86 (GCC) 294 | register long reg __asm__ ("eax") = -1; 295 | __asm__ __volatile__ ( 296 | "lock/xadd %0, %1 \n" 297 | "dec %%eax" 298 | : "+r" (reg) 299 | : "m" (*pAddr) 300 | : "memory" ); 301 | return reg; 302 | 303 | #endif 304 | } 305 | 306 | /////////////////////////////////////////////////////////////////////////// 307 | // 32-bit atomic add 308 | // Returns new value of *pAddr 309 | /////////////////////////////////////////////////////////////////////////// 310 | static inline long atomic_add(volatile long* pAddr, long amount) 311 | { 312 | #if defined(HAS_BUILTIN_SYNC_ADD_AND_FETCH) 313 | return __sync_add_and_fetch(pAddr, amount); 314 | 315 | #elif defined(__ppc__) || defined(__powerpc__) // PowerPC 316 | long val; 317 | __asm__ __volatile__ ( 318 | "sync \n" 319 | "1: lwarx %0, 0, %1 \n" 320 | "add %0, %2, %0 \n" 321 | "stwcx. %0, 0, %1 \n" 322 | "bne- 1b \n" 323 | "isync" 324 | : "=&r" (val) 325 | : "r" (pAddr), "r" (amount) 326 | : "cc", "memory"); 327 | return val; 328 | 329 | #elif defined(__arm__) && !defined(__ARM_ARCH_5__) 330 | register long val; 331 | asm volatile ( 332 | "dmb ish \n" // Memory barrier. Make sure all memory accesses appearing before this complete before any that appear after 333 | "1: \n" 334 | "ldrex %0, [%1] \n" // (val = *pAddr) 335 | "add %0, %2 \n" // (val += amount) 336 | "strex r1, %0, [%1] \n" 337 | "cmp r1, #0 \n" 338 | "bne 1b \n" 339 | "dmb ish \n" // Memory barrier. 340 | : "=&r" (val) 341 | : "r"(pAddr), "r"(amount) 342 | : "r1" 343 | ); 344 | return val; 345 | 346 | #elif defined(__mips__) 347 | // TODO: 348 | long val; 349 | #error AtomicAdd undefined for mips 350 | return val; 351 | 352 | #elif defined(__WINDOWS__) 353 | __asm 354 | { 355 | mov eax, amount; 356 | mov ebx, pAddr; 357 | lock xadd dword ptr [ebx], eax; 358 | mov ebx, [ebx]; 359 | mov amount, ebx; 360 | } 361 | return amount; 362 | 363 | #elif defined(__x86_64__) 364 | register long result; 365 | __asm__ __volatile__ ( 366 | "lock/xaddq %q0, %1" 367 | : "=r" (result), "=m" (*pAddr) 368 | : "0" ((long) (amount)), "m" (*pAddr)); 369 | return *pAddr; 370 | 371 | #else // Linux / OSX86 (GCC) 372 | register long reg __asm__ ("eax") = amount; 373 | __asm__ __volatile__ ( 374 | "lock/xadd %0, %1 \n" 375 | "dec %%eax" 376 | : "+r" (reg) 377 | : "m" (*pAddr) 378 | : "memory" ); 379 | return reg; 380 | 381 | #endif 382 | } 383 | 384 | /////////////////////////////////////////////////////////////////////////// 385 | // 32-bit atomic subtract 386 | // Returns new value of *pAddr 387 | /////////////////////////////////////////////////////////////////////////// 388 | static inline long atomic_sub(volatile long* pAddr, long amount) 389 | { 390 | #if defined(HAS_BUILTIN_SYNC_SUB_AND_FETCH) 391 | return __sync_sub_and_fetch(pAddr, amount); 392 | 393 | #elif defined(__ppc__) || defined(__powerpc__) // PowerPC 394 | long val; 395 | amount *= -1; 396 | __asm__ __volatile__ ( 397 | "sync \n" 398 | "1: lwarx %0, 0, %1 \n" 399 | "add %0, %2, %0 \n" 400 | "stwcx. %0, 0, %1 \n" 401 | "bne- 1b \n" 402 | "isync" 403 | : "=&r" (val) 404 | : "r" (pAddr), "r" (amount) 405 | : "cc", "memory"); 406 | return val; 407 | 408 | #elif defined(__arm__) 409 | register long val; 410 | asm volatile ( 411 | "dmb ish \n" // Memory barrier. Make sure all memory accesses appearing before this complete before any that appear after 412 | "1: \n" 413 | "ldrex %0, [%1] \n" // (val = *pAddr) 414 | "sub %0, %2 \n" // (val -= amount) 415 | "strex r1, %0, [%1] \n" 416 | "cmp r1, #0 \n" 417 | "bne 1b \n" 418 | "dmb ish \n" // Memory barrier. 419 | : "=&r" (val) 420 | : "r"(pAddr), "r"(amount) 421 | : "r1" 422 | ); 423 | return val; 424 | 425 | #elif defined(__mips__) 426 | // TODO: 427 | #error AtomicSubtract undefined for mips 428 | return val; 429 | 430 | #elif defined(__WINDOWS__) 431 | amount *= -1; 432 | __asm 433 | { 434 | mov eax, amount; 435 | mov ebx, pAddr; 436 | lock xadd dword ptr [ebx], eax; 437 | mov ebx, [ebx]; 438 | mov amount, ebx; 439 | } 440 | return amount; 441 | 442 | #elif defined(__x86_64__) 443 | register long result; 444 | __asm__ __volatile__ ( 445 | "lock/xaddq %q0, %1" 446 | : "=r" (result), "=m" (*pAddr) 447 | : "0" ((long) (-1 * amount)), "m" (*pAddr)); 448 | return *pAddr; 449 | 450 | #else // Linux / OSX86 (GCC) 451 | register long reg __asm__ ("eax") = -1 * amount; 452 | __asm__ __volatile__ ( 453 | "lock/xadd %0, %1 \n" 454 | "dec %%eax" 455 | : "+r" (reg) 456 | : "m" (*pAddr) 457 | : "memory" ); 458 | return reg; 459 | 460 | #endif 461 | 462 | } 463 | } 464 | -------------------------------------------------------------------------------- /src/threads/mutex.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | * This file is part of the libCEC(R) library. 4 | * 5 | * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. 6 | * libCEC(R) is an original work, containing original code. 7 | * 8 | * libCEC(R) is a trademark of Pulse-Eight Limited. 9 | * 10 | * This program is dual-licensed; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 | * 24 | * 25 | * Alternatively, you can license this library under a commercial license, 26 | * please contact Pulse-Eight Licensing for more information. 27 | * 28 | * For more information contact: 29 | * Pulse-Eight Licensing 30 | * http://www.pulse-eight.com/ 31 | * http://www.pulse-eight.net/ 32 | */ 33 | 34 | #include "../os.h" 35 | 36 | #if defined(__WINDOWS__) 37 | #include "../windows/os-threads.h" 38 | #else 39 | #include "../posix/os-threads.h" 40 | #endif 41 | 42 | #include "../util/timeutils.h" 43 | 44 | namespace P8PLATFORM 45 | { 46 | class PreventCopy 47 | { 48 | public: 49 | inline PreventCopy(void) {} 50 | inline ~PreventCopy(void) {} 51 | 52 | private: 53 | inline PreventCopy(const PreventCopy &c) { *this = c; } 54 | inline PreventCopy &operator=(const PreventCopy &c){ (void)c; return *this; } 55 | }; 56 | 57 | template 58 | class CCondition; 59 | 60 | class CMutex : public PreventCopy 61 | { 62 | template 63 | friend class CCondition; 64 | public: 65 | inline CMutex(void) : 66 | m_iLockCount(0) 67 | { 68 | MutexCreate(m_mutex); 69 | } 70 | 71 | inline ~CMutex(void) 72 | { 73 | Clear(); 74 | MutexDelete(m_mutex); 75 | } 76 | 77 | inline bool TryLock(void) 78 | { 79 | if (MutexTryLock(m_mutex)) 80 | { 81 | ++m_iLockCount; 82 | return true; 83 | } 84 | return false; 85 | } 86 | 87 | inline bool Lock(void) 88 | { 89 | MutexLock(m_mutex); 90 | ++m_iLockCount; 91 | return true; 92 | } 93 | 94 | inline void Unlock(void) 95 | { 96 | if (Lock()) 97 | { 98 | if (m_iLockCount >= 2) 99 | { 100 | --m_iLockCount; 101 | MutexUnlock(m_mutex); 102 | } 103 | 104 | --m_iLockCount; 105 | MutexUnlock(m_mutex); 106 | } 107 | } 108 | 109 | inline bool Clear(void) 110 | { 111 | bool bReturn(false); 112 | if (TryLock()) 113 | { 114 | unsigned int iLockCount = m_iLockCount; 115 | for (unsigned int iPtr = 0; iPtr < iLockCount; iPtr++) 116 | Unlock(); 117 | bReturn = true; 118 | } 119 | return bReturn; 120 | } 121 | 122 | private: 123 | mutex_t m_mutex; 124 | volatile unsigned int m_iLockCount; 125 | }; 126 | 127 | class CLockObject : public PreventCopy 128 | { 129 | public: 130 | inline CLockObject(CMutex &mutex, bool bClearOnExit = false) : 131 | m_mutex(mutex), 132 | m_bClearOnExit(bClearOnExit) 133 | { 134 | m_mutex.Lock(); 135 | } 136 | 137 | inline ~CLockObject(void) 138 | { 139 | if (m_bClearOnExit) 140 | Clear(); 141 | else 142 | Unlock(); 143 | } 144 | 145 | inline bool TryLock(void) 146 | { 147 | return m_mutex.TryLock(); 148 | } 149 | 150 | inline void Unlock(void) 151 | { 152 | m_mutex.Unlock(); 153 | } 154 | 155 | inline bool Clear(void) 156 | { 157 | return m_mutex.Clear(); 158 | } 159 | 160 | inline bool Lock(void) 161 | { 162 | return m_mutex.Lock(); 163 | } 164 | 165 | private: 166 | CMutex &m_mutex; 167 | bool m_bClearOnExit; 168 | }; 169 | 170 | class CTryLockObject : public PreventCopy 171 | { 172 | public: 173 | inline CTryLockObject(CMutex &mutex, bool bClearOnExit = false) : 174 | m_mutex(mutex), 175 | m_bClearOnExit(bClearOnExit), 176 | m_bIsLocked(m_mutex.TryLock()) 177 | { 178 | } 179 | 180 | inline ~CTryLockObject(void) 181 | { 182 | if (m_bClearOnExit) 183 | Clear(); 184 | else if (m_bIsLocked) 185 | Unlock(); 186 | } 187 | 188 | inline bool TryLock(void) 189 | { 190 | bool bReturn = m_mutex.TryLock(); 191 | m_bIsLocked |= bReturn; 192 | return bReturn; 193 | } 194 | 195 | inline void Unlock(void) 196 | { 197 | if (m_bIsLocked) 198 | { 199 | m_bIsLocked = false; 200 | m_mutex.Unlock(); 201 | } 202 | } 203 | 204 | inline bool Clear(void) 205 | { 206 | m_bIsLocked = false; 207 | return m_mutex.Clear(); 208 | } 209 | 210 | inline bool Lock(void) 211 | { 212 | bool bReturn = m_mutex.Lock(); 213 | m_bIsLocked |= bReturn; 214 | return bReturn; 215 | } 216 | 217 | inline bool IsLocked(void) const 218 | { 219 | return m_bIsLocked; 220 | } 221 | 222 | private: 223 | CMutex & m_mutex; 224 | bool m_bClearOnExit; 225 | volatile bool m_bIsLocked; 226 | }; 227 | 228 | typedef bool (*PredicateCallback) (void *param); 229 | 230 | template 231 | class CCondition : public PreventCopy 232 | { 233 | private: 234 | static bool _PredicateCallbackDefault ( void *param ) 235 | { 236 | _Predicate *p = (_Predicate*)param; 237 | return (*p); 238 | } 239 | public: 240 | inline CCondition(void) {} 241 | inline ~CCondition(void) 242 | { 243 | m_condition.Broadcast(); 244 | } 245 | 246 | inline void Broadcast(void) 247 | { 248 | m_condition.Broadcast(); 249 | } 250 | 251 | inline void Signal(void) 252 | { 253 | m_condition.Signal(); 254 | } 255 | 256 | inline bool Wait(CMutex &mutex, uint32_t iTimeout) 257 | { 258 | return m_condition.Wait(mutex.m_mutex, iTimeout); 259 | } 260 | 261 | inline bool Wait(CMutex &mutex, PredicateCallback callback, void *param, uint32_t iTimeout) 262 | { 263 | bool bReturn(false); 264 | CTimeout timeout(iTimeout); 265 | 266 | while (!bReturn) 267 | { 268 | if ((bReturn = callback(param)) == true) 269 | break; 270 | uint32_t iMsLeft = timeout.TimeLeft(); 271 | if ((iTimeout != 0) && (iMsLeft == 0)) 272 | break; 273 | m_condition.Wait(mutex.m_mutex, iMsLeft); 274 | } 275 | 276 | return bReturn; 277 | } 278 | 279 | inline bool Wait(CMutex &mutex, _Predicate &predicate, uint32_t iTimeout = 0) 280 | { 281 | return Wait(mutex, _PredicateCallbackDefault, (void*)&predicate, iTimeout); 282 | } 283 | 284 | private: 285 | CConditionImpl m_condition; 286 | }; 287 | 288 | class CEvent 289 | { 290 | public: 291 | CEvent(bool bAutoReset = true) : 292 | m_bSignaled(false), 293 | m_bBroadcast(false), 294 | m_iWaitingThreads(0), 295 | m_bAutoReset(bAutoReset) {} 296 | virtual ~CEvent(void) {} 297 | 298 | void Broadcast(void) 299 | { 300 | Set(true); 301 | m_condition.Broadcast(); 302 | } 303 | 304 | void Signal(void) 305 | { 306 | Set(false); 307 | m_condition.Signal(); 308 | } 309 | 310 | bool Wait(void) 311 | { 312 | CLockObject lock(m_mutex); 313 | ++m_iWaitingThreads; 314 | 315 | bool bReturn = m_condition.Wait(m_mutex, m_bSignaled); 316 | return ResetAndReturn() && bReturn; 317 | } 318 | 319 | bool Wait(uint32_t iTimeout) 320 | { 321 | if (iTimeout == 0) 322 | return Wait(); 323 | 324 | CLockObject lock(m_mutex); 325 | ++m_iWaitingThreads; 326 | bool bReturn = m_condition.Wait(m_mutex, m_bSignaled, iTimeout); 327 | return ResetAndReturn() && bReturn; 328 | } 329 | 330 | static void Sleep(uint32_t iTimeout) 331 | { 332 | CEvent event; 333 | event.Wait(iTimeout); 334 | } 335 | 336 | void Reset(void) 337 | { 338 | CLockObject lock(m_mutex); 339 | m_bSignaled = false; 340 | } 341 | 342 | private: 343 | void Set(bool bBroadcast = false) 344 | { 345 | CLockObject lock(m_mutex); 346 | m_bSignaled = true; 347 | m_bBroadcast = bBroadcast; 348 | } 349 | 350 | bool ResetAndReturn(void) 351 | { 352 | CLockObject lock(m_mutex); 353 | bool bReturn(m_bSignaled); 354 | --m_iWaitingThreads; 355 | if (bReturn && (m_iWaitingThreads == 0 || !m_bBroadcast) && m_bAutoReset) 356 | m_bSignaled = false; 357 | return bReturn; 358 | } 359 | 360 | volatile bool m_bSignaled; 361 | CCondition m_condition; 362 | CMutex m_mutex; 363 | volatile bool m_bBroadcast; 364 | unsigned int m_iWaitingThreads; 365 | bool m_bAutoReset; 366 | }; 367 | } 368 | -------------------------------------------------------------------------------- /src/threads/threads.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | * This file is part of the libCEC(R) library. 4 | * 5 | * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. 6 | * libCEC(R) is an original work, containing original code. 7 | * 8 | * libCEC(R) is a trademark of Pulse-Eight Limited. 9 | * 10 | * This program is dual-licensed; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 | * 24 | * 25 | * Alternatively, you can license this library under a commercial license, 26 | * please contact Pulse-Eight Licensing for more information. 27 | * 28 | * For more information contact: 29 | * Pulse-Eight Licensing 30 | * http://www.pulse-eight.com/ 31 | * http://www.pulse-eight.net/ 32 | */ 33 | 34 | #include "mutex.h" 35 | 36 | namespace P8PLATFORM 37 | { 38 | class CThread 39 | { 40 | public: 41 | CThread(void) : 42 | m_bStop(false), 43 | m_bRunning(false), 44 | m_bStopped(false) {} 45 | 46 | virtual ~CThread(void) 47 | { 48 | StopThread(0); 49 | } 50 | 51 | static void *ThreadHandler(void *_thread) 52 | { 53 | CThread *thread = static_cast(_thread); 54 | void *retVal = NULL; 55 | 56 | if (thread) 57 | { 58 | { 59 | CLockObject lock(thread->m_threadMutex); 60 | thread->m_bRunning = true; 61 | thread->m_bStopped = false; 62 | thread->m_threadCondition.Broadcast(); 63 | } 64 | 65 | retVal = thread->Process(); 66 | 67 | { 68 | CLockObject lock(thread->m_threadMutex); 69 | thread->m_bRunning = false; 70 | thread->m_bStopped = true; 71 | thread->m_threadCondition.Broadcast(); 72 | } 73 | } 74 | 75 | return retVal; 76 | } 77 | 78 | virtual bool IsRunning(void) 79 | { 80 | CLockObject lock(m_threadMutex); 81 | return m_bRunning; 82 | } 83 | 84 | virtual bool IsStopped(void) 85 | { 86 | CLockObject lock(m_threadMutex); 87 | return m_bStop; 88 | } 89 | 90 | virtual bool CreateThread(bool bWait = true) 91 | { 92 | bool bReturn(false); 93 | CLockObject lock(m_threadMutex); 94 | if (!IsRunning()) 95 | { 96 | m_bStop = false; 97 | if (ThreadsCreate(m_thread, CThread::ThreadHandler, ((void*)static_cast(this)))) 98 | { 99 | if (bWait) 100 | m_threadCondition.Wait(m_threadMutex, m_bRunning); 101 | bReturn = true; 102 | } 103 | } 104 | return bReturn; 105 | } 106 | 107 | /*! 108 | * @brief Stop the thread 109 | * @param iWaitMs negative = don't wait, 0 = infinite, or the amount of ms to wait 110 | */ 111 | virtual bool StopThread(int iWaitMs = 5000) 112 | { 113 | bool bReturn(true); 114 | bool bRunning(false); 115 | { 116 | CLockObject lock(m_threadMutex); 117 | bRunning = IsRunning(); 118 | m_bStop = true; 119 | } 120 | 121 | if (bRunning && iWaitMs >= 0) 122 | { 123 | CLockObject lock(m_threadMutex); 124 | bReturn = m_threadCondition.Wait(m_threadMutex, m_bStopped, iWaitMs); 125 | } 126 | else 127 | { 128 | bReturn = true; 129 | } 130 | 131 | return bReturn; 132 | } 133 | 134 | virtual bool Sleep(uint32_t iTimeout) 135 | { 136 | CLockObject lock(m_threadMutex); 137 | return m_bStop ? false : m_threadCondition.Wait(m_threadMutex, m_bStopped, iTimeout); 138 | } 139 | 140 | virtual void *Process(void) = 0; 141 | 142 | protected: 143 | void SetRunning(bool bSetTo); 144 | 145 | private: 146 | bool m_bStop; 147 | bool m_bRunning; 148 | bool m_bStopped; 149 | CCondition m_threadCondition; 150 | CMutex m_threadMutex; 151 | thread_t m_thread; 152 | }; 153 | }; 154 | -------------------------------------------------------------------------------- /src/util/StringUtils.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2005-2013 Team XBMC 3 | * http://xbmc.org 4 | * 5 | * This Program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2, or (at your option) 8 | * any later version. 9 | * 10 | * This Program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with XBMC; see the file COPYING. If not, see 17 | * . 18 | * 19 | */ 20 | //----------------------------------------------------------------------- 21 | // 22 | // File: StringUtils.cpp 23 | // 24 | // Purpose: ATL split string utility 25 | // Author: Paul J. Weiss 26 | // 27 | // Modified to use J O'Leary's std::string class by kraqh3d 28 | // 29 | //------------------------------------------------------------------------ 30 | 31 | 32 | #include "StringUtils.h" 33 | #include 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #define FORMAT_BLOCK_SIZE 2048 // # of bytes to increment per try 47 | 48 | using namespace std; 49 | 50 | /* empty string for use in returns by ref */ 51 | const std::string StringUtils::Empty = ""; 52 | std::string StringUtils::m_lastUUID = ""; 53 | 54 | // Copyright (c) Leigh Brasington 2012. All rights reserved. 55 | // This code may be used and reproduced without written permission. 56 | // http://www.leighb.com/tounicupper.htm 57 | // 58 | // The tables were constructed from 59 | // http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=%2Fnls%2Frbagslowtoupmaptable.htm 60 | 61 | static wchar_t unicode_lowers[] = { 62 | (wchar_t)0x0061, (wchar_t)0x0062, (wchar_t)0x0063, (wchar_t)0x0064, (wchar_t)0x0065, (wchar_t)0x0066, (wchar_t)0x0067, (wchar_t)0x0068, (wchar_t)0x0069, 63 | (wchar_t)0x006A, (wchar_t)0x006B, (wchar_t)0x006C, (wchar_t)0x006D, (wchar_t)0x006E, (wchar_t)0x006F, (wchar_t)0x0070, (wchar_t)0x0071, (wchar_t)0x0072, 64 | (wchar_t)0x0073, (wchar_t)0x0074, (wchar_t)0x0075, (wchar_t)0x0076, (wchar_t)0x0077, (wchar_t)0x0078, (wchar_t)0x0079, (wchar_t)0x007A, (wchar_t)0x00E0, 65 | (wchar_t)0x00E1, (wchar_t)0x00E2, (wchar_t)0x00E3, (wchar_t)0x00E4, (wchar_t)0x00E5, (wchar_t)0x00E6, (wchar_t)0x00E7, (wchar_t)0x00E8, (wchar_t)0x00E9, 66 | (wchar_t)0x00EA, (wchar_t)0x00EB, (wchar_t)0x00EC, (wchar_t)0x00ED, (wchar_t)0x00EE, (wchar_t)0x00EF, (wchar_t)0x00F0, (wchar_t)0x00F1, (wchar_t)0x00F2, 67 | (wchar_t)0x00F3, (wchar_t)0x00F4, (wchar_t)0x00F5, (wchar_t)0x00F6, (wchar_t)0x00F8, (wchar_t)0x00F9, (wchar_t)0x00FA, (wchar_t)0x00FB, (wchar_t)0x00FC, 68 | (wchar_t)0x00FD, (wchar_t)0x00FE, (wchar_t)0x00FF, (wchar_t)0x0101, (wchar_t)0x0103, (wchar_t)0x0105, (wchar_t)0x0107, (wchar_t)0x0109, (wchar_t)0x010B, 69 | (wchar_t)0x010D, (wchar_t)0x010F, (wchar_t)0x0111, (wchar_t)0x0113, (wchar_t)0x0115, (wchar_t)0x0117, (wchar_t)0x0119, (wchar_t)0x011B, (wchar_t)0x011D, 70 | (wchar_t)0x011F, (wchar_t)0x0121, (wchar_t)0x0123, (wchar_t)0x0125, (wchar_t)0x0127, (wchar_t)0x0129, (wchar_t)0x012B, (wchar_t)0x012D, (wchar_t)0x012F, 71 | (wchar_t)0x0131, (wchar_t)0x0133, (wchar_t)0x0135, (wchar_t)0x0137, (wchar_t)0x013A, (wchar_t)0x013C, (wchar_t)0x013E, (wchar_t)0x0140, (wchar_t)0x0142, 72 | (wchar_t)0x0144, (wchar_t)0x0146, (wchar_t)0x0148, (wchar_t)0x014B, (wchar_t)0x014D, (wchar_t)0x014F, (wchar_t)0x0151, (wchar_t)0x0153, (wchar_t)0x0155, 73 | (wchar_t)0x0157, (wchar_t)0x0159, (wchar_t)0x015B, (wchar_t)0x015D, (wchar_t)0x015F, (wchar_t)0x0161, (wchar_t)0x0163, (wchar_t)0x0165, (wchar_t)0x0167, 74 | (wchar_t)0x0169, (wchar_t)0x016B, (wchar_t)0x016D, (wchar_t)0x016F, (wchar_t)0x0171, (wchar_t)0x0173, (wchar_t)0x0175, (wchar_t)0x0177, (wchar_t)0x017A, 75 | (wchar_t)0x017C, (wchar_t)0x017E, (wchar_t)0x0183, (wchar_t)0x0185, (wchar_t)0x0188, (wchar_t)0x018C, (wchar_t)0x0192, (wchar_t)0x0199, (wchar_t)0x01A1, 76 | (wchar_t)0x01A3, (wchar_t)0x01A5, (wchar_t)0x01A8, (wchar_t)0x01AD, (wchar_t)0x01B0, (wchar_t)0x01B4, (wchar_t)0x01B6, (wchar_t)0x01B9, (wchar_t)0x01BD, 77 | (wchar_t)0x01C6, (wchar_t)0x01C9, (wchar_t)0x01CC, (wchar_t)0x01CE, (wchar_t)0x01D0, (wchar_t)0x01D2, (wchar_t)0x01D4, (wchar_t)0x01D6, (wchar_t)0x01D8, 78 | (wchar_t)0x01DA, (wchar_t)0x01DC, (wchar_t)0x01DF, (wchar_t)0x01E1, (wchar_t)0x01E3, (wchar_t)0x01E5, (wchar_t)0x01E7, (wchar_t)0x01E9, (wchar_t)0x01EB, 79 | (wchar_t)0x01ED, (wchar_t)0x01EF, (wchar_t)0x01F3, (wchar_t)0x01F5, (wchar_t)0x01FB, (wchar_t)0x01FD, (wchar_t)0x01FF, (wchar_t)0x0201, (wchar_t)0x0203, 80 | (wchar_t)0x0205, (wchar_t)0x0207, (wchar_t)0x0209, (wchar_t)0x020B, (wchar_t)0x020D, (wchar_t)0x020F, (wchar_t)0x0211, (wchar_t)0x0213, (wchar_t)0x0215, 81 | (wchar_t)0x0217, (wchar_t)0x0253, (wchar_t)0x0254, (wchar_t)0x0257, (wchar_t)0x0258, (wchar_t)0x0259, (wchar_t)0x025B, (wchar_t)0x0260, (wchar_t)0x0263, 82 | (wchar_t)0x0268, (wchar_t)0x0269, (wchar_t)0x026F, (wchar_t)0x0272, (wchar_t)0x0275, (wchar_t)0x0283, (wchar_t)0x0288, (wchar_t)0x028A, (wchar_t)0x028B, 83 | (wchar_t)0x0292, (wchar_t)0x03AC, (wchar_t)0x03AD, (wchar_t)0x03AE, (wchar_t)0x03AF, (wchar_t)0x03B1, (wchar_t)0x03B2, (wchar_t)0x03B3, (wchar_t)0x03B4, 84 | (wchar_t)0x03B5, (wchar_t)0x03B6, (wchar_t)0x03B7, (wchar_t)0x03B8, (wchar_t)0x03B9, (wchar_t)0x03BA, (wchar_t)0x03BB, (wchar_t)0x03BC, (wchar_t)0x03BD, 85 | (wchar_t)0x03BE, (wchar_t)0x03BF, (wchar_t)0x03C0, (wchar_t)0x03C1, (wchar_t)0x03C3, (wchar_t)0x03C4, (wchar_t)0x03C5, (wchar_t)0x03C6, (wchar_t)0x03C7, 86 | (wchar_t)0x03C8, (wchar_t)0x03C9, (wchar_t)0x03CA, (wchar_t)0x03CB, (wchar_t)0x03CC, (wchar_t)0x03CD, (wchar_t)0x03CE, (wchar_t)0x03E3, (wchar_t)0x03E5, 87 | (wchar_t)0x03E7, (wchar_t)0x03E9, (wchar_t)0x03EB, (wchar_t)0x03ED, (wchar_t)0x03EF, (wchar_t)0x0430, (wchar_t)0x0431, (wchar_t)0x0432, (wchar_t)0x0433, 88 | (wchar_t)0x0434, (wchar_t)0x0435, (wchar_t)0x0436, (wchar_t)0x0437, (wchar_t)0x0438, (wchar_t)0x0439, (wchar_t)0x043A, (wchar_t)0x043B, (wchar_t)0x043C, 89 | (wchar_t)0x043D, (wchar_t)0x043E, (wchar_t)0x043F, (wchar_t)0x0440, (wchar_t)0x0441, (wchar_t)0x0442, (wchar_t)0x0443, (wchar_t)0x0444, (wchar_t)0x0445, 90 | (wchar_t)0x0446, (wchar_t)0x0447, (wchar_t)0x0448, (wchar_t)0x0449, (wchar_t)0x044A, (wchar_t)0x044B, (wchar_t)0x044C, (wchar_t)0x044D, (wchar_t)0x044E, 91 | (wchar_t)0x044F, (wchar_t)0x0451, (wchar_t)0x0452, (wchar_t)0x0453, (wchar_t)0x0454, (wchar_t)0x0455, (wchar_t)0x0456, (wchar_t)0x0457, (wchar_t)0x0458, 92 | (wchar_t)0x0459, (wchar_t)0x045A, (wchar_t)0x045B, (wchar_t)0x045C, (wchar_t)0x045E, (wchar_t)0x045F, (wchar_t)0x0461, (wchar_t)0x0463, (wchar_t)0x0465, 93 | (wchar_t)0x0467, (wchar_t)0x0469, (wchar_t)0x046B, (wchar_t)0x046D, (wchar_t)0x046F, (wchar_t)0x0471, (wchar_t)0x0473, (wchar_t)0x0475, (wchar_t)0x0477, 94 | (wchar_t)0x0479, (wchar_t)0x047B, (wchar_t)0x047D, (wchar_t)0x047F, (wchar_t)0x0481, (wchar_t)0x0491, (wchar_t)0x0493, (wchar_t)0x0495, (wchar_t)0x0497, 95 | (wchar_t)0x0499, (wchar_t)0x049B, (wchar_t)0x049D, (wchar_t)0x049F, (wchar_t)0x04A1, (wchar_t)0x04A3, (wchar_t)0x04A5, (wchar_t)0x04A7, (wchar_t)0x04A9, 96 | (wchar_t)0x04AB, (wchar_t)0x04AD, (wchar_t)0x04AF, (wchar_t)0x04B1, (wchar_t)0x04B3, (wchar_t)0x04B5, (wchar_t)0x04B7, (wchar_t)0x04B9, (wchar_t)0x04BB, 97 | (wchar_t)0x04BD, (wchar_t)0x04BF, (wchar_t)0x04C2, (wchar_t)0x04C4, (wchar_t)0x04C8, (wchar_t)0x04CC, (wchar_t)0x04D1, (wchar_t)0x04D3, (wchar_t)0x04D5, 98 | (wchar_t)0x04D7, (wchar_t)0x04D9, (wchar_t)0x04DB, (wchar_t)0x04DD, (wchar_t)0x04DF, (wchar_t)0x04E1, (wchar_t)0x04E3, (wchar_t)0x04E5, (wchar_t)0x04E7, 99 | (wchar_t)0x04E9, (wchar_t)0x04EB, (wchar_t)0x04EF, (wchar_t)0x04F1, (wchar_t)0x04F3, (wchar_t)0x04F5, (wchar_t)0x04F9, (wchar_t)0x0561, (wchar_t)0x0562, 100 | (wchar_t)0x0563, (wchar_t)0x0564, (wchar_t)0x0565, (wchar_t)0x0566, (wchar_t)0x0567, (wchar_t)0x0568, (wchar_t)0x0569, (wchar_t)0x056A, (wchar_t)0x056B, 101 | (wchar_t)0x056C, (wchar_t)0x056D, (wchar_t)0x056E, (wchar_t)0x056F, (wchar_t)0x0570, (wchar_t)0x0571, (wchar_t)0x0572, (wchar_t)0x0573, (wchar_t)0x0574, 102 | (wchar_t)0x0575, (wchar_t)0x0576, (wchar_t)0x0577, (wchar_t)0x0578, (wchar_t)0x0579, (wchar_t)0x057A, (wchar_t)0x057B, (wchar_t)0x057C, (wchar_t)0x057D, 103 | (wchar_t)0x057E, (wchar_t)0x057F, (wchar_t)0x0580, (wchar_t)0x0581, (wchar_t)0x0582, (wchar_t)0x0583, (wchar_t)0x0584, (wchar_t)0x0585, (wchar_t)0x0586, 104 | (wchar_t)0x10D0, (wchar_t)0x10D1, (wchar_t)0x10D2, (wchar_t)0x10D3, (wchar_t)0x10D4, (wchar_t)0x10D5, (wchar_t)0x10D6, (wchar_t)0x10D7, (wchar_t)0x10D8, 105 | (wchar_t)0x10D9, (wchar_t)0x10DA, (wchar_t)0x10DB, (wchar_t)0x10DC, (wchar_t)0x10DD, (wchar_t)0x10DE, (wchar_t)0x10DF, (wchar_t)0x10E0, (wchar_t)0x10E1, 106 | (wchar_t)0x10E2, (wchar_t)0x10E3, (wchar_t)0x10E4, (wchar_t)0x10E5, (wchar_t)0x10E6, (wchar_t)0x10E7, (wchar_t)0x10E8, (wchar_t)0x10E9, (wchar_t)0x10EA, 107 | (wchar_t)0x10EB, (wchar_t)0x10EC, (wchar_t)0x10ED, (wchar_t)0x10EE, (wchar_t)0x10EF, (wchar_t)0x10F0, (wchar_t)0x10F1, (wchar_t)0x10F2, (wchar_t)0x10F3, 108 | (wchar_t)0x10F4, (wchar_t)0x10F5, (wchar_t)0x1E01, (wchar_t)0x1E03, (wchar_t)0x1E05, (wchar_t)0x1E07, (wchar_t)0x1E09, (wchar_t)0x1E0B, (wchar_t)0x1E0D, 109 | (wchar_t)0x1E0F, (wchar_t)0x1E11, (wchar_t)0x1E13, (wchar_t)0x1E15, (wchar_t)0x1E17, (wchar_t)0x1E19, (wchar_t)0x1E1B, (wchar_t)0x1E1D, (wchar_t)0x1E1F, 110 | (wchar_t)0x1E21, (wchar_t)0x1E23, (wchar_t)0x1E25, (wchar_t)0x1E27, (wchar_t)0x1E29, (wchar_t)0x1E2B, (wchar_t)0x1E2D, (wchar_t)0x1E2F, (wchar_t)0x1E31, 111 | (wchar_t)0x1E33, (wchar_t)0x1E35, (wchar_t)0x1E37, (wchar_t)0x1E39, (wchar_t)0x1E3B, (wchar_t)0x1E3D, (wchar_t)0x1E3F, (wchar_t)0x1E41, (wchar_t)0x1E43, 112 | (wchar_t)0x1E45, (wchar_t)0x1E47, (wchar_t)0x1E49, (wchar_t)0x1E4B, (wchar_t)0x1E4D, (wchar_t)0x1E4F, (wchar_t)0x1E51, (wchar_t)0x1E53, (wchar_t)0x1E55, 113 | (wchar_t)0x1E57, (wchar_t)0x1E59, (wchar_t)0x1E5B, (wchar_t)0x1E5D, (wchar_t)0x1E5F, (wchar_t)0x1E61, (wchar_t)0x1E63, (wchar_t)0x1E65, (wchar_t)0x1E67, 114 | (wchar_t)0x1E69, (wchar_t)0x1E6B, (wchar_t)0x1E6D, (wchar_t)0x1E6F, (wchar_t)0x1E71, (wchar_t)0x1E73, (wchar_t)0x1E75, (wchar_t)0x1E77, (wchar_t)0x1E79, 115 | (wchar_t)0x1E7B, (wchar_t)0x1E7D, (wchar_t)0x1E7F, (wchar_t)0x1E81, (wchar_t)0x1E83, (wchar_t)0x1E85, (wchar_t)0x1E87, (wchar_t)0x1E89, (wchar_t)0x1E8B, 116 | (wchar_t)0x1E8D, (wchar_t)0x1E8F, (wchar_t)0x1E91, (wchar_t)0x1E93, (wchar_t)0x1E95, (wchar_t)0x1EA1, (wchar_t)0x1EA3, (wchar_t)0x1EA5, (wchar_t)0x1EA7, 117 | (wchar_t)0x1EA9, (wchar_t)0x1EAB, (wchar_t)0x1EAD, (wchar_t)0x1EAF, (wchar_t)0x1EB1, (wchar_t)0x1EB3, (wchar_t)0x1EB5, (wchar_t)0x1EB7, (wchar_t)0x1EB9, 118 | (wchar_t)0x1EBB, (wchar_t)0x1EBD, (wchar_t)0x1EBF, (wchar_t)0x1EC1, (wchar_t)0x1EC3, (wchar_t)0x1EC5, (wchar_t)0x1EC7, (wchar_t)0x1EC9, (wchar_t)0x1ECB, 119 | (wchar_t)0x1ECD, (wchar_t)0x1ECF, (wchar_t)0x1ED1, (wchar_t)0x1ED3, (wchar_t)0x1ED5, (wchar_t)0x1ED7, (wchar_t)0x1ED9, (wchar_t)0x1EDB, (wchar_t)0x1EDD, 120 | (wchar_t)0x1EDF, (wchar_t)0x1EE1, (wchar_t)0x1EE3, (wchar_t)0x1EE5, (wchar_t)0x1EE7, (wchar_t)0x1EE9, (wchar_t)0x1EEB, (wchar_t)0x1EED, (wchar_t)0x1EEF, 121 | (wchar_t)0x1EF1, (wchar_t)0x1EF3, (wchar_t)0x1EF5, (wchar_t)0x1EF7, (wchar_t)0x1EF9, (wchar_t)0x1F00, (wchar_t)0x1F01, (wchar_t)0x1F02, (wchar_t)0x1F03, 122 | (wchar_t)0x1F04, (wchar_t)0x1F05, (wchar_t)0x1F06, (wchar_t)0x1F07, (wchar_t)0x1F10, (wchar_t)0x1F11, (wchar_t)0x1F12, (wchar_t)0x1F13, (wchar_t)0x1F14, 123 | (wchar_t)0x1F15, (wchar_t)0x1F20, (wchar_t)0x1F21, (wchar_t)0x1F22, (wchar_t)0x1F23, (wchar_t)0x1F24, (wchar_t)0x1F25, (wchar_t)0x1F26, (wchar_t)0x1F27, 124 | (wchar_t)0x1F30, (wchar_t)0x1F31, (wchar_t)0x1F32, (wchar_t)0x1F33, (wchar_t)0x1F34, (wchar_t)0x1F35, (wchar_t)0x1F36, (wchar_t)0x1F37, (wchar_t)0x1F40, 125 | (wchar_t)0x1F41, (wchar_t)0x1F42, (wchar_t)0x1F43, (wchar_t)0x1F44, (wchar_t)0x1F45, (wchar_t)0x1F51, (wchar_t)0x1F53, (wchar_t)0x1F55, (wchar_t)0x1F57, 126 | (wchar_t)0x1F60, (wchar_t)0x1F61, (wchar_t)0x1F62, (wchar_t)0x1F63, (wchar_t)0x1F64, (wchar_t)0x1F65, (wchar_t)0x1F66, (wchar_t)0x1F67, (wchar_t)0x1F80, 127 | (wchar_t)0x1F81, (wchar_t)0x1F82, (wchar_t)0x1F83, (wchar_t)0x1F84, (wchar_t)0x1F85, (wchar_t)0x1F86, (wchar_t)0x1F87, (wchar_t)0x1F90, (wchar_t)0x1F91, 128 | (wchar_t)0x1F92, (wchar_t)0x1F93, (wchar_t)0x1F94, (wchar_t)0x1F95, (wchar_t)0x1F96, (wchar_t)0x1F97, (wchar_t)0x1FA0, (wchar_t)0x1FA1, (wchar_t)0x1FA2, 129 | (wchar_t)0x1FA3, (wchar_t)0x1FA4, (wchar_t)0x1FA5, (wchar_t)0x1FA6, (wchar_t)0x1FA7, (wchar_t)0x1FB0, (wchar_t)0x1FB1, (wchar_t)0x1FD0, (wchar_t)0x1FD1, 130 | (wchar_t)0x1FE0, (wchar_t)0x1FE1, (wchar_t)0x24D0, (wchar_t)0x24D1, (wchar_t)0x24D2, (wchar_t)0x24D3, (wchar_t)0x24D4, (wchar_t)0x24D5, (wchar_t)0x24D6, 131 | (wchar_t)0x24D7, (wchar_t)0x24D8, (wchar_t)0x24D9, (wchar_t)0x24DA, (wchar_t)0x24DB, (wchar_t)0x24DC, (wchar_t)0x24DD, (wchar_t)0x24DE, (wchar_t)0x24DF, 132 | (wchar_t)0x24E0, (wchar_t)0x24E1, (wchar_t)0x24E2, (wchar_t)0x24E3, (wchar_t)0x24E4, (wchar_t)0x24E5, (wchar_t)0x24E6, (wchar_t)0x24E7, (wchar_t)0x24E8, 133 | (wchar_t)0x24E9, (wchar_t)0xFF41, (wchar_t)0xFF42, (wchar_t)0xFF43, (wchar_t)0xFF44, (wchar_t)0xFF45, (wchar_t)0xFF46, (wchar_t)0xFF47, (wchar_t)0xFF48, 134 | (wchar_t)0xFF49, (wchar_t)0xFF4A, (wchar_t)0xFF4B, (wchar_t)0xFF4C, (wchar_t)0xFF4D, (wchar_t)0xFF4E, (wchar_t)0xFF4F, (wchar_t)0xFF50, (wchar_t)0xFF51, 135 | (wchar_t)0xFF52, (wchar_t)0xFF53, (wchar_t)0xFF54, (wchar_t)0xFF55, (wchar_t)0xFF56, (wchar_t)0xFF57, (wchar_t)0xFF58, (wchar_t)0xFF59, (wchar_t)0xFF5A 136 | }; 137 | 138 | static const wchar_t unicode_uppers[] = { 139 | (wchar_t)0x0041, (wchar_t)0x0042, (wchar_t)0x0043, (wchar_t)0x0044, (wchar_t)0x0045, (wchar_t)0x0046, (wchar_t)0x0047, (wchar_t)0x0048, (wchar_t)0x0049, 140 | (wchar_t)0x004A, (wchar_t)0x004B, (wchar_t)0x004C, (wchar_t)0x004D, (wchar_t)0x004E, (wchar_t)0x004F, (wchar_t)0x0050, (wchar_t)0x0051, (wchar_t)0x0052, 141 | (wchar_t)0x0053, (wchar_t)0x0054, (wchar_t)0x0055, (wchar_t)0x0056, (wchar_t)0x0057, (wchar_t)0x0058, (wchar_t)0x0059, (wchar_t)0x005A, (wchar_t)0x00C0, 142 | (wchar_t)0x00C1, (wchar_t)0x00C2, (wchar_t)0x00C3, (wchar_t)0x00C4, (wchar_t)0x00C5, (wchar_t)0x00C6, (wchar_t)0x00C7, (wchar_t)0x00C8, (wchar_t)0x00C9, 143 | (wchar_t)0x00CA, (wchar_t)0x00CB, (wchar_t)0x00CC, (wchar_t)0x00CD, (wchar_t)0x00CE, (wchar_t)0x00CF, (wchar_t)0x00D0, (wchar_t)0x00D1, (wchar_t)0x00D2, 144 | (wchar_t)0x00D3, (wchar_t)0x00D4, (wchar_t)0x00D5, (wchar_t)0x00D6, (wchar_t)0x00D8, (wchar_t)0x00D9, (wchar_t)0x00DA, (wchar_t)0x00DB, (wchar_t)0x00DC, 145 | (wchar_t)0x00DD, (wchar_t)0x00DE, (wchar_t)0x0178, (wchar_t)0x0100, (wchar_t)0x0102, (wchar_t)0x0104, (wchar_t)0x0106, (wchar_t)0x0108, (wchar_t)0x010A, 146 | (wchar_t)0x010C, (wchar_t)0x010E, (wchar_t)0x0110, (wchar_t)0x0112, (wchar_t)0x0114, (wchar_t)0x0116, (wchar_t)0x0118, (wchar_t)0x011A, (wchar_t)0x011C, 147 | (wchar_t)0x011E, (wchar_t)0x0120, (wchar_t)0x0122, (wchar_t)0x0124, (wchar_t)0x0126, (wchar_t)0x0128, (wchar_t)0x012A, (wchar_t)0x012C, (wchar_t)0x012E, 148 | (wchar_t)0x0049, (wchar_t)0x0132, (wchar_t)0x0134, (wchar_t)0x0136, (wchar_t)0x0139, (wchar_t)0x013B, (wchar_t)0x013D, (wchar_t)0x013F, (wchar_t)0x0141, 149 | (wchar_t)0x0143, (wchar_t)0x0145, (wchar_t)0x0147, (wchar_t)0x014A, (wchar_t)0x014C, (wchar_t)0x014E, (wchar_t)0x0150, (wchar_t)0x0152, (wchar_t)0x0154, 150 | (wchar_t)0x0156, (wchar_t)0x0158, (wchar_t)0x015A, (wchar_t)0x015C, (wchar_t)0x015E, (wchar_t)0x0160, (wchar_t)0x0162, (wchar_t)0x0164, (wchar_t)0x0166, 151 | (wchar_t)0x0168, (wchar_t)0x016A, (wchar_t)0x016C, (wchar_t)0x016E, (wchar_t)0x0170, (wchar_t)0x0172, (wchar_t)0x0174, (wchar_t)0x0176, (wchar_t)0x0179, 152 | (wchar_t)0x017B, (wchar_t)0x017D, (wchar_t)0x0182, (wchar_t)0x0184, (wchar_t)0x0187, (wchar_t)0x018B, (wchar_t)0x0191, (wchar_t)0x0198, (wchar_t)0x01A0, 153 | (wchar_t)0x01A2, (wchar_t)0x01A4, (wchar_t)0x01A7, (wchar_t)0x01AC, (wchar_t)0x01AF, (wchar_t)0x01B3, (wchar_t)0x01B5, (wchar_t)0x01B8, (wchar_t)0x01BC, 154 | (wchar_t)0x01C4, (wchar_t)0x01C7, (wchar_t)0x01CA, (wchar_t)0x01CD, (wchar_t)0x01CF, (wchar_t)0x01D1, (wchar_t)0x01D3, (wchar_t)0x01D5, (wchar_t)0x01D7, 155 | (wchar_t)0x01D9, (wchar_t)0x01DB, (wchar_t)0x01DE, (wchar_t)0x01E0, (wchar_t)0x01E2, (wchar_t)0x01E4, (wchar_t)0x01E6, (wchar_t)0x01E8, (wchar_t)0x01EA, 156 | (wchar_t)0x01EC, (wchar_t)0x01EE, (wchar_t)0x01F1, (wchar_t)0x01F4, (wchar_t)0x01FA, (wchar_t)0x01FC, (wchar_t)0x01FE, (wchar_t)0x0200, (wchar_t)0x0202, 157 | (wchar_t)0x0204, (wchar_t)0x0206, (wchar_t)0x0208, (wchar_t)0x020A, (wchar_t)0x020C, (wchar_t)0x020E, (wchar_t)0x0210, (wchar_t)0x0212, (wchar_t)0x0214, 158 | (wchar_t)0x0216, (wchar_t)0x0181, (wchar_t)0x0186, (wchar_t)0x018A, (wchar_t)0x018E, (wchar_t)0x018F, (wchar_t)0x0190, (wchar_t)0x0193, (wchar_t)0x0194, 159 | (wchar_t)0x0197, (wchar_t)0x0196, (wchar_t)0x019C, (wchar_t)0x019D, (wchar_t)0x019F, (wchar_t)0x01A9, (wchar_t)0x01AE, (wchar_t)0x01B1, (wchar_t)0x01B2, 160 | (wchar_t)0x01B7, (wchar_t)0x0386, (wchar_t)0x0388, (wchar_t)0x0389, (wchar_t)0x038A, (wchar_t)0x0391, (wchar_t)0x0392, (wchar_t)0x0393, (wchar_t)0x0394, 161 | (wchar_t)0x0395, (wchar_t)0x0396, (wchar_t)0x0397, (wchar_t)0x0398, (wchar_t)0x0399, (wchar_t)0x039A, (wchar_t)0x039B, (wchar_t)0x039C, (wchar_t)0x039D, 162 | (wchar_t)0x039E, (wchar_t)0x039F, (wchar_t)0x03A0, (wchar_t)0x03A1, (wchar_t)0x03A3, (wchar_t)0x03A4, (wchar_t)0x03A5, (wchar_t)0x03A6, (wchar_t)0x03A7, 163 | (wchar_t)0x03A8, (wchar_t)0x03A9, (wchar_t)0x03AA, (wchar_t)0x03AB, (wchar_t)0x038C, (wchar_t)0x038E, (wchar_t)0x038F, (wchar_t)0x03E2, (wchar_t)0x03E4, 164 | (wchar_t)0x03E6, (wchar_t)0x03E8, (wchar_t)0x03EA, (wchar_t)0x03EC, (wchar_t)0x03EE, (wchar_t)0x0410, (wchar_t)0x0411, (wchar_t)0x0412, (wchar_t)0x0413, 165 | (wchar_t)0x0414, (wchar_t)0x0415, (wchar_t)0x0416, (wchar_t)0x0417, (wchar_t)0x0418, (wchar_t)0x0419, (wchar_t)0x041A, (wchar_t)0x041B, (wchar_t)0x041C, 166 | (wchar_t)0x041D, (wchar_t)0x041E, (wchar_t)0x041F, (wchar_t)0x0420, (wchar_t)0x0421, (wchar_t)0x0422, (wchar_t)0x0423, (wchar_t)0x0424, (wchar_t)0x0425, 167 | (wchar_t)0x0426, (wchar_t)0x0427, (wchar_t)0x0428, (wchar_t)0x0429, (wchar_t)0x042A, (wchar_t)0x042B, (wchar_t)0x042C, (wchar_t)0x042D, (wchar_t)0x042E, 168 | (wchar_t)0x042F, (wchar_t)0x0401, (wchar_t)0x0402, (wchar_t)0x0403, (wchar_t)0x0404, (wchar_t)0x0405, (wchar_t)0x0406, (wchar_t)0x0407, (wchar_t)0x0408, 169 | (wchar_t)0x0409, (wchar_t)0x040A, (wchar_t)0x040B, (wchar_t)0x040C, (wchar_t)0x040E, (wchar_t)0x040F, (wchar_t)0x0460, (wchar_t)0x0462, (wchar_t)0x0464, 170 | (wchar_t)0x0466, (wchar_t)0x0468, (wchar_t)0x046A, (wchar_t)0x046C, (wchar_t)0x046E, (wchar_t)0x0470, (wchar_t)0x0472, (wchar_t)0x0474, (wchar_t)0x0476, 171 | (wchar_t)0x0478, (wchar_t)0x047A, (wchar_t)0x047C, (wchar_t)0x047E, (wchar_t)0x0480, (wchar_t)0x0490, (wchar_t)0x0492, (wchar_t)0x0494, (wchar_t)0x0496, 172 | (wchar_t)0x0498, (wchar_t)0x049A, (wchar_t)0x049C, (wchar_t)0x049E, (wchar_t)0x04A0, (wchar_t)0x04A2, (wchar_t)0x04A4, (wchar_t)0x04A6, (wchar_t)0x04A8, 173 | (wchar_t)0x04AA, (wchar_t)0x04AC, (wchar_t)0x04AE, (wchar_t)0x04B0, (wchar_t)0x04B2, (wchar_t)0x04B4, (wchar_t)0x04B6, (wchar_t)0x04B8, (wchar_t)0x04BA, 174 | (wchar_t)0x04BC, (wchar_t)0x04BE, (wchar_t)0x04C1, (wchar_t)0x04C3, (wchar_t)0x04C7, (wchar_t)0x04CB, (wchar_t)0x04D0, (wchar_t)0x04D2, (wchar_t)0x04D4, 175 | (wchar_t)0x04D6, (wchar_t)0x04D8, (wchar_t)0x04DA, (wchar_t)0x04DC, (wchar_t)0x04DE, (wchar_t)0x04E0, (wchar_t)0x04E2, (wchar_t)0x04E4, (wchar_t)0x04E6, 176 | (wchar_t)0x04E8, (wchar_t)0x04EA, (wchar_t)0x04EE, (wchar_t)0x04F0, (wchar_t)0x04F2, (wchar_t)0x04F4, (wchar_t)0x04F8, (wchar_t)0x0531, (wchar_t)0x0532, 177 | (wchar_t)0x0533, (wchar_t)0x0534, (wchar_t)0x0535, (wchar_t)0x0536, (wchar_t)0x0537, (wchar_t)0x0538, (wchar_t)0x0539, (wchar_t)0x053A, (wchar_t)0x053B, 178 | (wchar_t)0x053C, (wchar_t)0x053D, (wchar_t)0x053E, (wchar_t)0x053F, (wchar_t)0x0540, (wchar_t)0x0541, (wchar_t)0x0542, (wchar_t)0x0543, (wchar_t)0x0544, 179 | (wchar_t)0x0545, (wchar_t)0x0546, (wchar_t)0x0547, (wchar_t)0x0548, (wchar_t)0x0549, (wchar_t)0x054A, (wchar_t)0x054B, (wchar_t)0x054C, (wchar_t)0x054D, 180 | (wchar_t)0x054E, (wchar_t)0x054F, (wchar_t)0x0550, (wchar_t)0x0551, (wchar_t)0x0552, (wchar_t)0x0553, (wchar_t)0x0554, (wchar_t)0x0555, (wchar_t)0x0556, 181 | (wchar_t)0x10A0, (wchar_t)0x10A1, (wchar_t)0x10A2, (wchar_t)0x10A3, (wchar_t)0x10A4, (wchar_t)0x10A5, (wchar_t)0x10A6, (wchar_t)0x10A7, (wchar_t)0x10A8, 182 | (wchar_t)0x10A9, (wchar_t)0x10AA, (wchar_t)0x10AB, (wchar_t)0x10AC, (wchar_t)0x10AD, (wchar_t)0x10AE, (wchar_t)0x10AF, (wchar_t)0x10B0, (wchar_t)0x10B1, 183 | (wchar_t)0x10B2, (wchar_t)0x10B3, (wchar_t)0x10B4, (wchar_t)0x10B5, (wchar_t)0x10B6, (wchar_t)0x10B7, (wchar_t)0x10B8, (wchar_t)0x10B9, (wchar_t)0x10BA, 184 | (wchar_t)0x10BB, (wchar_t)0x10BC, (wchar_t)0x10BD, (wchar_t)0x10BE, (wchar_t)0x10BF, (wchar_t)0x10C0, (wchar_t)0x10C1, (wchar_t)0x10C2, (wchar_t)0x10C3, 185 | (wchar_t)0x10C4, (wchar_t)0x10C5, (wchar_t)0x1E00, (wchar_t)0x1E02, (wchar_t)0x1E04, (wchar_t)0x1E06, (wchar_t)0x1E08, (wchar_t)0x1E0A, (wchar_t)0x1E0C, 186 | (wchar_t)0x1E0E, (wchar_t)0x1E10, (wchar_t)0x1E12, (wchar_t)0x1E14, (wchar_t)0x1E16, (wchar_t)0x1E18, (wchar_t)0x1E1A, (wchar_t)0x1E1C, (wchar_t)0x1E1E, 187 | (wchar_t)0x1E20, (wchar_t)0x1E22, (wchar_t)0x1E24, (wchar_t)0x1E26, (wchar_t)0x1E28, (wchar_t)0x1E2A, (wchar_t)0x1E2C, (wchar_t)0x1E2E, (wchar_t)0x1E30, 188 | (wchar_t)0x1E32, (wchar_t)0x1E34, (wchar_t)0x1E36, (wchar_t)0x1E38, (wchar_t)0x1E3A, (wchar_t)0x1E3C, (wchar_t)0x1E3E, (wchar_t)0x1E40, (wchar_t)0x1E42, 189 | (wchar_t)0x1E44, (wchar_t)0x1E46, (wchar_t)0x1E48, (wchar_t)0x1E4A, (wchar_t)0x1E4C, (wchar_t)0x1E4E, (wchar_t)0x1E50, (wchar_t)0x1E52, (wchar_t)0x1E54, 190 | (wchar_t)0x1E56, (wchar_t)0x1E58, (wchar_t)0x1E5A, (wchar_t)0x1E5C, (wchar_t)0x1E5E, (wchar_t)0x1E60, (wchar_t)0x1E62, (wchar_t)0x1E64, (wchar_t)0x1E66, 191 | (wchar_t)0x1E68, (wchar_t)0x1E6A, (wchar_t)0x1E6C, (wchar_t)0x1E6E, (wchar_t)0x1E70, (wchar_t)0x1E72, (wchar_t)0x1E74, (wchar_t)0x1E76, (wchar_t)0x1E78, 192 | (wchar_t)0x1E7A, (wchar_t)0x1E7C, (wchar_t)0x1E7E, (wchar_t)0x1E80, (wchar_t)0x1E82, (wchar_t)0x1E84, (wchar_t)0x1E86, (wchar_t)0x1E88, (wchar_t)0x1E8A, 193 | (wchar_t)0x1E8C, (wchar_t)0x1E8E, (wchar_t)0x1E90, (wchar_t)0x1E92, (wchar_t)0x1E94, (wchar_t)0x1EA0, (wchar_t)0x1EA2, (wchar_t)0x1EA4, (wchar_t)0x1EA6, 194 | (wchar_t)0x1EA8, (wchar_t)0x1EAA, (wchar_t)0x1EAC, (wchar_t)0x1EAE, (wchar_t)0x1EB0, (wchar_t)0x1EB2, (wchar_t)0x1EB4, (wchar_t)0x1EB6, (wchar_t)0x1EB8, 195 | (wchar_t)0x1EBA, (wchar_t)0x1EBC, (wchar_t)0x1EBE, (wchar_t)0x1EC0, (wchar_t)0x1EC2, (wchar_t)0x1EC4, (wchar_t)0x1EC6, (wchar_t)0x1EC8, (wchar_t)0x1ECA, 196 | (wchar_t)0x1ECC, (wchar_t)0x1ECE, (wchar_t)0x1ED0, (wchar_t)0x1ED2, (wchar_t)0x1ED4, (wchar_t)0x1ED6, (wchar_t)0x1ED8, (wchar_t)0x1EDA, (wchar_t)0x1EDC, 197 | (wchar_t)0x1EDE, (wchar_t)0x1EE0, (wchar_t)0x1EE2, (wchar_t)0x1EE4, (wchar_t)0x1EE6, (wchar_t)0x1EE8, (wchar_t)0x1EEA, (wchar_t)0x1EEC, (wchar_t)0x1EEE, 198 | (wchar_t)0x1EF0, (wchar_t)0x1EF2, (wchar_t)0x1EF4, (wchar_t)0x1EF6, (wchar_t)0x1EF8, (wchar_t)0x1F08, (wchar_t)0x1F09, (wchar_t)0x1F0A, (wchar_t)0x1F0B, 199 | (wchar_t)0x1F0C, (wchar_t)0x1F0D, (wchar_t)0x1F0E, (wchar_t)0x1F0F, (wchar_t)0x1F18, (wchar_t)0x1F19, (wchar_t)0x1F1A, (wchar_t)0x1F1B, (wchar_t)0x1F1C, 200 | (wchar_t)0x1F1D, (wchar_t)0x1F28, (wchar_t)0x1F29, (wchar_t)0x1F2A, (wchar_t)0x1F2B, (wchar_t)0x1F2C, (wchar_t)0x1F2D, (wchar_t)0x1F2E, (wchar_t)0x1F2F, 201 | (wchar_t)0x1F38, (wchar_t)0x1F39, (wchar_t)0x1F3A, (wchar_t)0x1F3B, (wchar_t)0x1F3C, (wchar_t)0x1F3D, (wchar_t)0x1F3E, (wchar_t)0x1F3F, (wchar_t)0x1F48, 202 | (wchar_t)0x1F49, (wchar_t)0x1F4A, (wchar_t)0x1F4B, (wchar_t)0x1F4C, (wchar_t)0x1F4D, (wchar_t)0x1F59, (wchar_t)0x1F5B, (wchar_t)0x1F5D, (wchar_t)0x1F5F, 203 | (wchar_t)0x1F68, (wchar_t)0x1F69, (wchar_t)0x1F6A, (wchar_t)0x1F6B, (wchar_t)0x1F6C, (wchar_t)0x1F6D, (wchar_t)0x1F6E, (wchar_t)0x1F6F, (wchar_t)0x1F88, 204 | (wchar_t)0x1F89, (wchar_t)0x1F8A, (wchar_t)0x1F8B, (wchar_t)0x1F8C, (wchar_t)0x1F8D, (wchar_t)0x1F8E, (wchar_t)0x1F8F, (wchar_t)0x1F98, (wchar_t)0x1F99, 205 | (wchar_t)0x1F9A, (wchar_t)0x1F9B, (wchar_t)0x1F9C, (wchar_t)0x1F9D, (wchar_t)0x1F9E, (wchar_t)0x1F9F, (wchar_t)0x1FA8, (wchar_t)0x1FA9, (wchar_t)0x1FAA, 206 | (wchar_t)0x1FAB, (wchar_t)0x1FAC, (wchar_t)0x1FAD, (wchar_t)0x1FAE, (wchar_t)0x1FAF, (wchar_t)0x1FB8, (wchar_t)0x1FB9, (wchar_t)0x1FD8, (wchar_t)0x1FD9, 207 | (wchar_t)0x1FE8, (wchar_t)0x1FE9, (wchar_t)0x24B6, (wchar_t)0x24B7, (wchar_t)0x24B8, (wchar_t)0x24B9, (wchar_t)0x24BA, (wchar_t)0x24BB, (wchar_t)0x24BC, 208 | (wchar_t)0x24BD, (wchar_t)0x24BE, (wchar_t)0x24BF, (wchar_t)0x24C0, (wchar_t)0x24C1, (wchar_t)0x24C2, (wchar_t)0x24C3, (wchar_t)0x24C4, (wchar_t)0x24C5, 209 | (wchar_t)0x24C6, (wchar_t)0x24C7, (wchar_t)0x24C8, (wchar_t)0x24C9, (wchar_t)0x24CA, (wchar_t)0x24CB, (wchar_t)0x24CC, (wchar_t)0x24CD, (wchar_t)0x24CE, 210 | (wchar_t)0x24CF, (wchar_t)0xFF21, (wchar_t)0xFF22, (wchar_t)0xFF23, (wchar_t)0xFF24, (wchar_t)0xFF25, (wchar_t)0xFF26, (wchar_t)0xFF27, (wchar_t)0xFF28, 211 | (wchar_t)0xFF29, (wchar_t)0xFF2A, (wchar_t)0xFF2B, (wchar_t)0xFF2C, (wchar_t)0xFF2D, (wchar_t)0xFF2E, (wchar_t)0xFF2F, (wchar_t)0xFF30, (wchar_t)0xFF31, 212 | (wchar_t)0xFF32, (wchar_t)0xFF33, (wchar_t)0xFF34, (wchar_t)0xFF35, (wchar_t)0xFF36, (wchar_t)0xFF37, (wchar_t)0xFF38, (wchar_t)0xFF39, (wchar_t)0xFF3A 213 | }; 214 | 215 | string StringUtils::Format(const char *fmt, ...) 216 | { 217 | va_list args; 218 | va_start(args, fmt); 219 | string str = FormatV(fmt, args); 220 | va_end(args); 221 | 222 | return str; 223 | } 224 | 225 | string StringUtils::FormatV(const char *fmt, va_list args) 226 | { 227 | if (fmt == NULL) 228 | return ""; 229 | 230 | int size = FORMAT_BLOCK_SIZE; 231 | va_list argCopy; 232 | 233 | char *cstr = reinterpret_cast(malloc(sizeof(char) * size)); 234 | if (cstr == NULL) 235 | return ""; 236 | 237 | while (1) 238 | { 239 | va_copy(argCopy, args); 240 | 241 | int nActual = vsnprintf(cstr, size, fmt, argCopy); 242 | va_end(argCopy); 243 | 244 | if (nActual > -1 && nActual < size) // We got a valid result 245 | { 246 | string str(cstr, nActual); 247 | free(cstr); 248 | return str; 249 | } 250 | if (nActual > -1) // Exactly what we will need (glibc 2.1) 251 | size = nActual + 1; 252 | else // Let's try to double the size (glibc 2.0) 253 | size *= 2; 254 | 255 | char *new_cstr = reinterpret_cast(realloc(cstr, sizeof(char) * size)); 256 | if (new_cstr == NULL) 257 | { 258 | free(cstr); 259 | return ""; 260 | } 261 | 262 | cstr = new_cstr; 263 | } 264 | 265 | free(cstr); 266 | return ""; 267 | } 268 | 269 | wstring StringUtils::Format(const wchar_t *fmt, ...) 270 | { 271 | va_list args; 272 | va_start(args, fmt); 273 | wstring str = FormatV(fmt, args); 274 | va_end(args); 275 | 276 | return str; 277 | } 278 | 279 | wstring StringUtils::FormatV(const wchar_t *fmt, va_list args) 280 | { 281 | if (fmt == NULL) 282 | return L""; 283 | 284 | int size = FORMAT_BLOCK_SIZE; 285 | va_list argCopy; 286 | 287 | wchar_t *cstr = reinterpret_cast(malloc(sizeof(wchar_t) * size)); 288 | if (cstr == NULL) 289 | return L""; 290 | 291 | while (1) 292 | { 293 | va_copy(argCopy, args); 294 | 295 | int nActual = vswprintf(cstr, size, fmt, argCopy); 296 | va_end(argCopy); 297 | 298 | if (nActual > -1 && nActual < size) // We got a valid result 299 | { 300 | wstring str(cstr, nActual); 301 | free(cstr); 302 | return str; 303 | } 304 | if (nActual > -1) // Exactly what we will need (glibc 2.1) 305 | size = nActual + 1; 306 | else // Let's try to double the size (glibc 2.0) 307 | size *= 2; 308 | 309 | wchar_t *new_cstr = reinterpret_cast(realloc(cstr, sizeof(wchar_t) * size)); 310 | if (new_cstr == NULL) 311 | { 312 | free(cstr); 313 | return L""; 314 | } 315 | 316 | cstr = new_cstr; 317 | } 318 | 319 | return L""; 320 | } 321 | 322 | int compareWchar (const void* a, const void* b) 323 | { 324 | if (*(wchar_t*)a < *(wchar_t*)b) 325 | return -1; 326 | else if (*(wchar_t*)a > *(wchar_t*)b) 327 | return 1; 328 | return 0; 329 | } 330 | 331 | wchar_t tolowerUnicode(const wchar_t& c) 332 | { 333 | wchar_t* p = (wchar_t*) bsearch (&c, unicode_uppers, sizeof(unicode_uppers) / sizeof(wchar_t), sizeof(wchar_t), compareWchar); 334 | if (p) 335 | return *(unicode_lowers + (p - unicode_uppers)); 336 | 337 | return c; 338 | } 339 | 340 | wchar_t toupperUnicode(const wchar_t& c) 341 | { 342 | wchar_t* p = (wchar_t*) bsearch (&c, unicode_lowers, sizeof(unicode_lowers) / sizeof(wchar_t), sizeof(wchar_t), compareWchar); 343 | if (p) 344 | return *(unicode_uppers + (p - unicode_lowers)); 345 | 346 | return c; 347 | } 348 | 349 | void StringUtils::ToUpper(string &str) 350 | { 351 | std::transform(str.begin(), str.end(), str.begin(), ::toupper); 352 | } 353 | 354 | void StringUtils::ToUpper(wstring &str) 355 | { 356 | transform(str.begin(), str.end(), str.begin(), toupperUnicode); 357 | } 358 | 359 | void StringUtils::ToLower(string &str) 360 | { 361 | transform(str.begin(), str.end(), str.begin(), ::tolower); 362 | } 363 | 364 | void StringUtils::ToLower(wstring &str) 365 | { 366 | transform(str.begin(), str.end(), str.begin(), tolowerUnicode); 367 | } 368 | 369 | bool StringUtils::EqualsNoCase(const std::string &str1, const std::string &str2) 370 | { 371 | return EqualsNoCase(str1.c_str(), str2.c_str()); 372 | } 373 | 374 | bool StringUtils::EqualsNoCase(const std::string &str1, const char *s2) 375 | { 376 | return EqualsNoCase(str1.c_str(), s2); 377 | } 378 | 379 | bool StringUtils::EqualsNoCase(const char *s1, const char *s2) 380 | { 381 | char c2; // we need only one char outside the loop 382 | do 383 | { 384 | const char c1 = *s1++; // const local variable should help compiler to optimize 385 | c2 = *s2++; 386 | if (c1 != c2 && ::tolower(c1) != ::tolower(c2)) // This includes the possibility that one of the characters is the null-terminator, which implies a string mismatch. 387 | return false; 388 | } while (c2 != '\0'); // At this point, we know c1 == c2, so there's no need to test them both. 389 | return true; 390 | } 391 | 392 | int StringUtils::CompareNoCase(const std::string &str1, const std::string &str2) 393 | { 394 | return CompareNoCase(str1.c_str(), str2.c_str()); 395 | } 396 | 397 | int StringUtils::CompareNoCase(const char *s1, const char *s2) 398 | { 399 | char c2; // we need only one char outside the loop 400 | do 401 | { 402 | const char c1 = *s1++; // const local variable should help compiler to optimize 403 | c2 = *s2++; 404 | if (c1 != c2 && ::tolower(c1) != ::tolower(c2)) // This includes the possibility that one of the characters is the null-terminator, which implies a string mismatch. 405 | return ::tolower(c1) - ::tolower(c2); 406 | } while (c2 != '\0'); // At this point, we know c1 == c2, so there's no need to test them both. 407 | return 0; 408 | } 409 | 410 | string StringUtils::Left(const string &str, size_t count) 411 | { 412 | count = max((size_t)0, min(count, str.size())); 413 | return str.substr(0, count); 414 | } 415 | 416 | string StringUtils::Mid(const string &str, size_t first, size_t count /* = string::npos */) 417 | { 418 | if (first + count > str.size()) 419 | count = str.size() - first; 420 | 421 | if (first > str.size()) 422 | return string(); 423 | 424 | assert(first + count <= str.size()); 425 | 426 | return str.substr(first, count); 427 | } 428 | 429 | string StringUtils::Right(const string &str, size_t count) 430 | { 431 | count = max((size_t)0, min(count, str.size())); 432 | return str.substr(str.size() - count); 433 | } 434 | 435 | std::string& StringUtils::Trim(std::string &str) 436 | { 437 | TrimLeft(str); 438 | return TrimRight(str); 439 | } 440 | 441 | std::string& StringUtils::Trim(std::string &str, const char* const chars) 442 | { 443 | TrimLeft(str, chars); 444 | return TrimRight(str, chars); 445 | } 446 | 447 | // hack to ensure that std::string::iterator will be dereferenced as _unsigned_ char 448 | // without this hack "TrimX" functions failed on Win32 with UTF-8 strings 449 | static int isspace_c(char c) 450 | { 451 | return ::isspace((unsigned char)c); 452 | } 453 | 454 | std::string& StringUtils::TrimLeft(std::string &str) 455 | { 456 | str.erase(str.begin(), ::find_if(str.begin(), str.end(), [](char s) { return isspace_c(s) == 0; })); 457 | return str; 458 | } 459 | 460 | std::string& StringUtils::TrimLeft(std::string &str, const char* const chars) 461 | { 462 | size_t nidx = str.find_first_not_of(chars); 463 | str.erase(0, nidx); 464 | return str; 465 | } 466 | 467 | std::string& StringUtils::TrimRight(std::string &str) 468 | { 469 | str.erase(::find_if(str.rbegin(), str.rend(), [](char s) { return isspace_c(s) == 0; }).base(), str.end()); 470 | return str; 471 | } 472 | 473 | std::string& StringUtils::TrimRight(std::string &str, const char* const chars) 474 | { 475 | size_t nidx = str.find_last_not_of(chars); 476 | str.erase(str.npos == nidx ? 0 : ++nidx); 477 | return str; 478 | } 479 | 480 | std::string& StringUtils::RemoveDuplicatedSpacesAndTabs(std::string& str) 481 | { 482 | std::string::iterator it = str.begin(); 483 | bool onSpace = false; 484 | while(it != str.end()) 485 | { 486 | if (*it == '\t') 487 | *it = ' '; 488 | 489 | if (*it == ' ') 490 | { 491 | if (onSpace) 492 | { 493 | it = str.erase(it); 494 | continue; 495 | } 496 | else 497 | onSpace = true; 498 | } 499 | else 500 | onSpace = false; 501 | 502 | ++it; 503 | } 504 | return str; 505 | } 506 | 507 | int StringUtils::Replace(string &str, char oldChar, char newChar) 508 | { 509 | int replacedChars = 0; 510 | for (string::iterator it = str.begin(); it != str.end(); ++it) 511 | { 512 | if (*it == oldChar) 513 | { 514 | *it = newChar; 515 | replacedChars++; 516 | } 517 | } 518 | 519 | return replacedChars; 520 | } 521 | 522 | int StringUtils::Replace(std::string &str, const std::string &oldStr, const std::string &newStr) 523 | { 524 | if (oldStr.empty()) 525 | return 0; 526 | 527 | int replacedChars = 0; 528 | size_t index = 0; 529 | 530 | while (index < str.size() && (index = str.find(oldStr, index)) != string::npos) 531 | { 532 | str.replace(index, oldStr.size(), newStr); 533 | index += newStr.size(); 534 | replacedChars++; 535 | } 536 | 537 | return replacedChars; 538 | } 539 | 540 | int StringUtils::Replace(std::wstring &str, const std::wstring &oldStr, const std::wstring &newStr) 541 | { 542 | if (oldStr.empty()) 543 | return 0; 544 | 545 | int replacedChars = 0; 546 | size_t index = 0; 547 | 548 | while (index < str.size() && (index = str.find(oldStr, index)) != string::npos) 549 | { 550 | str.replace(index, oldStr.size(), newStr); 551 | index += newStr.size(); 552 | replacedChars++; 553 | } 554 | 555 | return replacedChars; 556 | } 557 | 558 | bool StringUtils::StartsWith(const std::string &str1, const std::string &str2) 559 | { 560 | return str1.compare(0, str2.size(), str2) == 0; 561 | } 562 | 563 | bool StringUtils::StartsWith(const std::string &str1, const char *s2) 564 | { 565 | return StartsWith(str1.c_str(), s2); 566 | } 567 | 568 | bool StringUtils::StartsWith(const char *s1, const char *s2) 569 | { 570 | while (*s2 != '\0') 571 | { 572 | if (*s1 != *s2) 573 | return false; 574 | s1++; 575 | s2++; 576 | } 577 | return true; 578 | } 579 | 580 | bool StringUtils::StartsWithNoCase(const std::string &str1, const std::string &str2) 581 | { 582 | return StartsWithNoCase(str1.c_str(), str2.c_str()); 583 | } 584 | 585 | bool StringUtils::StartsWithNoCase(const std::string &str1, const char *s2) 586 | { 587 | return StartsWithNoCase(str1.c_str(), s2); 588 | } 589 | 590 | bool StringUtils::StartsWithNoCase(const char *s1, const char *s2) 591 | { 592 | while (*s2 != '\0') 593 | { 594 | if (::tolower(*s1) != ::tolower(*s2)) 595 | return false; 596 | s1++; 597 | s2++; 598 | } 599 | return true; 600 | } 601 | 602 | bool StringUtils::EndsWith(const std::string &str1, const std::string &str2) 603 | { 604 | if (str1.size() < str2.size()) 605 | return false; 606 | return str1.compare(str1.size() - str2.size(), str2.size(), str2) == 0; 607 | } 608 | 609 | bool StringUtils::EndsWith(const std::string &str1, const char *s2) 610 | { 611 | size_t len2 = strlen(s2); 612 | if (str1.size() < len2) 613 | return false; 614 | return str1.compare(str1.size() - len2, len2, s2) == 0; 615 | } 616 | 617 | bool StringUtils::EndsWithNoCase(const std::string &str1, const std::string &str2) 618 | { 619 | if (str1.size() < str2.size()) 620 | return false; 621 | const char *s1 = str1.c_str() + str1.size() - str2.size(); 622 | const char *s2 = str2.c_str(); 623 | while (*s2 != '\0') 624 | { 625 | if (::tolower(*s1) != ::tolower(*s2)) 626 | return false; 627 | s1++; 628 | s2++; 629 | } 630 | return true; 631 | } 632 | 633 | bool StringUtils::EndsWithNoCase(const std::string &str1, const char *s2) 634 | { 635 | size_t len2 = strlen(s2); 636 | if (str1.size() < len2) 637 | return false; 638 | const char *s1 = str1.c_str() + str1.size() - len2; 639 | while (*s2 != '\0') 640 | { 641 | if (::tolower(*s1) != ::tolower(*s2)) 642 | return false; 643 | s1++; 644 | s2++; 645 | } 646 | return true; 647 | } 648 | 649 | std::string StringUtils::Join(const vector &strings, const std::string& delimiter) 650 | { 651 | std::string result; 652 | for(vector::const_iterator it = strings.begin(); it != strings.end(); it++ ) 653 | result += (*it) + delimiter; 654 | 655 | if (!result.empty()) 656 | result.erase(result.size() - delimiter.size()); 657 | return result; 658 | } 659 | 660 | vector StringUtils::Split(const std::string& input, const std::string& delimiter, unsigned int iMaxStrings /* = 0 */) 661 | { 662 | vector results; 663 | if (input.empty()) 664 | return results; 665 | 666 | size_t iPos = std::string::npos; 667 | size_t newPos = std::string::npos; 668 | size_t sizeS2 = delimiter.size(); 669 | size_t isize = input.size(); 670 | 671 | vector positions; 672 | 673 | newPos = input.find(delimiter, 0); 674 | 675 | if (newPos == std::string::npos) 676 | { 677 | results.push_back(input); 678 | return results; 679 | } 680 | 681 | while (newPos != std::string::npos) 682 | { 683 | positions.push_back(newPos); 684 | iPos = newPos; 685 | newPos = input.find(delimiter, iPos + sizeS2); 686 | } 687 | 688 | // numFound is the number of delimiters which is one less 689 | // than the number of substrings 690 | size_t numFound = positions.size(); 691 | if (iMaxStrings > 0 && numFound >= iMaxStrings) 692 | numFound = iMaxStrings - 1; 693 | 694 | for ( size_t i = 0; i <= numFound; i++ ) 695 | { 696 | string s; 697 | if ( i == 0 ) 698 | { 699 | if ( i == numFound ) 700 | s = input; 701 | else 702 | s = input.substr(i, positions[i]); 703 | } 704 | else 705 | { 706 | size_t offset = positions[i - 1] + sizeS2; 707 | if ( offset < isize ) 708 | { 709 | if ( i == numFound ) 710 | s = input.substr(offset); 711 | else if ( i > 0 ) 712 | s = input.substr( positions[i - 1] + sizeS2, 713 | positions[i] - positions[i - 1] - sizeS2 ); 714 | } 715 | } 716 | results.push_back(s); 717 | } 718 | return results; 719 | } 720 | 721 | // returns the number of occurrences of strFind in strInput. 722 | int StringUtils::FindNumber(const std::string& strInput, const std::string &strFind) 723 | { 724 | size_t pos = strInput.find(strFind, 0); 725 | int numfound = 0; 726 | while (pos != std::string::npos) 727 | { 728 | numfound++; 729 | pos = strInput.find(strFind, pos + 1); 730 | } 731 | return numfound; 732 | } 733 | 734 | // Compares separately the numeric and alphabetic parts of a string. 735 | // returns negative if left < right, positive if left > right 736 | // and 0 if they are identical (essentially calculates left - right) 737 | int64_t StringUtils::AlphaNumericCompare(const wchar_t *left, const wchar_t *right) 738 | { 739 | wchar_t *l = (wchar_t *)left; 740 | wchar_t *r = (wchar_t *)right; 741 | wchar_t *ld, *rd; 742 | wchar_t lc, rc; 743 | int64_t lnum, rnum; 744 | const collate& coll = use_facet< collate >( locale() ); 745 | int cmp_res = 0; 746 | while (*l != 0 && *r != 0) 747 | { 748 | // check if we have a numerical value 749 | if (*l >= L'0' && *l <= L'9' && *r >= L'0' && *r <= L'9') 750 | { 751 | ld = l; 752 | lnum = 0; 753 | while (*ld >= L'0' && *ld <= L'9' && ld < l + 15) 754 | { // compare only up to 15 digits 755 | lnum *= 10; 756 | lnum += *ld++ - '0'; 757 | } 758 | rd = r; 759 | rnum = 0; 760 | while (*rd >= L'0' && *rd <= L'9' && rd < r + 15) 761 | { // compare only up to 15 digits 762 | rnum *= 10; 763 | rnum += *rd++ - L'0'; 764 | } 765 | // do we have numbers? 766 | if (lnum != rnum) 767 | { // yes - and they're different! 768 | return lnum - rnum; 769 | } 770 | l = ld; 771 | r = rd; 772 | continue; 773 | } 774 | // do case less comparison 775 | lc = *l; 776 | if (lc >= L'A' && lc <= L'Z') 777 | lc += L'a'-L'A'; 778 | rc = *r; 779 | if (rc >= L'A' && rc <= L'Z') 780 | rc += L'a'- L'A'; 781 | 782 | // ok, do a normal comparison, taking current locale into account. Add special case stuff (eg '(' characters)) in here later 783 | if ((cmp_res = coll.compare(&lc, &lc + 1, &rc, &rc + 1)) != 0) 784 | { 785 | return cmp_res; 786 | } 787 | l++; r++; 788 | } 789 | if (*r) 790 | { // r is longer 791 | return -1; 792 | } 793 | else if (*l) 794 | { // l is longer 795 | return 1; 796 | } 797 | return 0; // files are the same 798 | } 799 | 800 | int StringUtils::DateStringToYYYYMMDD(const std::string &dateString) 801 | { 802 | vector days = StringUtils::Split(dateString, "-"); 803 | if (days.size() == 1) 804 | return atoi(days[0].c_str()); 805 | else if (days.size() == 2) 806 | return atoi(days[0].c_str())*100+atoi(days[1].c_str()); 807 | else if (days.size() == 3) 808 | return atoi(days[0].c_str())*10000+atoi(days[1].c_str())*100+atoi(days[2].c_str()); 809 | else 810 | return -1; 811 | } 812 | 813 | long StringUtils::TimeStringToSeconds(const std::string &timeString) 814 | { 815 | std::string strCopy(timeString); 816 | StringUtils::Trim(strCopy); 817 | if(StringUtils::EndsWithNoCase(strCopy, " min")) 818 | { 819 | // this is imdb format of "XXX min" 820 | return 60 * atoi(strCopy.c_str()); 821 | } 822 | else 823 | { 824 | vector secs = StringUtils::Split(strCopy, ":"); 825 | int timeInSecs = 0; 826 | for (unsigned int i = 0; i < 3 && i < secs.size(); i++) 827 | { 828 | timeInSecs *= 60; 829 | timeInSecs += atoi(secs[i].c_str()); 830 | } 831 | return timeInSecs; 832 | } 833 | } 834 | 835 | std::string StringUtils::SecondsToTimeString(long lSeconds, TIME_FORMAT format) 836 | { 837 | int hh = lSeconds / 3600; 838 | lSeconds = lSeconds % 3600; 839 | int mm = lSeconds / 60; 840 | int ss = lSeconds % 60; 841 | 842 | if (format == TIME_FORMAT_GUESS) 843 | format = (hh >= 1) ? TIME_FORMAT_HH_MM_SS : TIME_FORMAT_MM_SS; 844 | std::string strHMS; 845 | if (format & TIME_FORMAT_HH) 846 | strHMS += StringUtils::Format("%02.2i", hh); 847 | else if (format & TIME_FORMAT_H) 848 | strHMS += StringUtils::Format("%i", hh); 849 | if (format & TIME_FORMAT_MM) 850 | strHMS += StringUtils::Format(strHMS.empty() ? "%02.2i" : ":%02.2i", mm); 851 | if (format & TIME_FORMAT_SS) 852 | strHMS += StringUtils::Format(strHMS.empty() ? "%02.2i" : ":%02.2i", ss); 853 | return strHMS; 854 | } 855 | 856 | bool StringUtils::IsNaturalNumber(const std::string& str) 857 | { 858 | size_t i = 0, n = 0; 859 | // allow whitespace,digits,whitespace 860 | while (i < str.size() && isspace((unsigned char) str[i])) 861 | i++; 862 | while (i < str.size() && isdigit((unsigned char) str[i])) 863 | { 864 | i++; n++; 865 | } 866 | while (i < str.size() && isspace((unsigned char) str[i])) 867 | i++; 868 | return i == str.size() && n > 0; 869 | } 870 | 871 | bool StringUtils::IsInteger(const std::string& str) 872 | { 873 | size_t i = 0, n = 0; 874 | // allow whitespace,-,digits,whitespace 875 | while (i < str.size() && isspace((unsigned char) str[i])) 876 | i++; 877 | if (i < str.size() && str[i] == '-') 878 | i++; 879 | while (i < str.size() && isdigit((unsigned char) str[i])) 880 | { 881 | i++; n++; 882 | } 883 | while (i < str.size() && isspace((unsigned char) str[i])) 884 | i++; 885 | return i == str.size() && n > 0; 886 | } 887 | 888 | int StringUtils::asciidigitvalue(char chr) 889 | { 890 | if (!isasciidigit(chr)) 891 | return -1; 892 | 893 | return chr - '0'; 894 | } 895 | 896 | int StringUtils::asciixdigitvalue(char chr) 897 | { 898 | int v = asciidigitvalue(chr); 899 | if (v >= 0) 900 | return v; 901 | if (chr >= 'a' && chr <= 'f') 902 | return chr - 'a' + 10; 903 | if (chr >= 'A' && chr <= 'F') 904 | return chr - 'A' + 10; 905 | 906 | return -1; 907 | } 908 | 909 | 910 | void StringUtils::RemoveCRLF(std::string& strLine) 911 | { 912 | StringUtils::TrimRight(strLine, "\n\r"); 913 | } 914 | 915 | std::string StringUtils::SizeToString(int64_t size) 916 | { 917 | std::string strLabel; 918 | const char prefixes[] = {' ','k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'}; 919 | unsigned int i = 0; 920 | double s = (double)size; 921 | while (i < sizeof(prefixes)/sizeof(prefixes[0]) && s >= 1000.0) 922 | { 923 | s /= 1024.0; 924 | i++; 925 | } 926 | 927 | if (!i) 928 | strLabel = StringUtils::Format("%.0lf %cB ", s, prefixes[i]); 929 | else if (s >= 100.0) 930 | strLabel = StringUtils::Format("%.1lf %cB", s, prefixes[i]); 931 | else 932 | strLabel = StringUtils::Format("%.2lf %cB", s, prefixes[i]); 933 | 934 | return strLabel; 935 | } 936 | 937 | // return -1 if not, else return the utf8 char length. 938 | int IsUTF8Letter(const unsigned char *str) 939 | { 940 | // reference: 941 | // unicode -> utf8 table: http://www.utf8-chartable.de/ 942 | // latin characters in unicode: http://en.wikipedia.org/wiki/Latin_characters_in_Unicode 943 | unsigned char ch = str[0]; 944 | if (!ch) 945 | return -1; 946 | if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) 947 | return 1; 948 | if (!(ch & 0x80)) 949 | return -1; 950 | unsigned char ch2 = str[1]; 951 | if (!ch2) 952 | return -1; 953 | // check latin 1 letter table: http://en.wikipedia.org/wiki/C1_Controls_and_Latin-1_Supplement 954 | if (ch == 0xC3 && ch2 >= 0x80 && ch2 <= 0xBF && ch2 != 0x97 && ch2 != 0xB7) 955 | return 2; 956 | // check latin extended A table: http://en.wikipedia.org/wiki/Latin_Extended-A 957 | if (ch >= 0xC4 && ch <= 0xC7 && ch2 >= 0x80 && ch2 <= 0xBF) 958 | return 2; 959 | // check latin extended B table: http://en.wikipedia.org/wiki/Latin_Extended-B 960 | // and International Phonetic Alphabet: http://en.wikipedia.org/wiki/IPA_Extensions_(Unicode_block) 961 | if (((ch == 0xC8 || ch == 0xC9) && ch2 >= 0x80 && ch2 <= 0xBF) 962 | || (ch == 0xCA && ch2 >= 0x80 && ch2 <= 0xAF)) 963 | return 2; 964 | return -1; 965 | } 966 | 967 | size_t StringUtils::FindWords(const char *str, const char *wordLowerCase) 968 | { 969 | // NOTE: This assumes word is lowercase! 970 | unsigned char *s = (unsigned char *)str; 971 | do 972 | { 973 | // start with a compare 974 | unsigned char *c = s; 975 | unsigned char *w = (unsigned char *)wordLowerCase; 976 | bool same = true; 977 | while (same && *c && *w) 978 | { 979 | unsigned char lc = *c++; 980 | if (lc >= 'A' && lc <= 'Z') 981 | lc += 'a'-'A'; 982 | 983 | if (lc != *w++) // different 984 | same = false; 985 | } 986 | if (same && *w == 0) // only the same if word has been exhausted 987 | return (const char *)s - str; 988 | 989 | // otherwise, skip current word (composed by latin letters) or number 990 | int l; 991 | if (*s >= '0' && *s <= '9') 992 | { 993 | ++s; 994 | while (*s >= '0' && *s <= '9') ++s; 995 | } 996 | else if ((l = IsUTF8Letter(s)) > 0) 997 | { 998 | s += l; 999 | while ((l = IsUTF8Letter(s)) > 0) s += l; 1000 | } 1001 | else 1002 | ++s; 1003 | while (*s && *s == ' ') s++; 1004 | 1005 | // and repeat until we're done 1006 | } while (*s); 1007 | 1008 | return std::string::npos; 1009 | } 1010 | 1011 | // assumes it is called from after the first open bracket is found 1012 | int StringUtils::FindEndBracket(const std::string &str, char opener, char closer, int startPos) 1013 | { 1014 | int blocks = 1; 1015 | for (unsigned int i = startPos; i < str.size(); i++) 1016 | { 1017 | if (str[i] == opener) 1018 | blocks++; 1019 | else if (str[i] == closer) 1020 | { 1021 | blocks--; 1022 | if (!blocks) 1023 | return i; 1024 | } 1025 | } 1026 | 1027 | return (int)std::string::npos; 1028 | } 1029 | 1030 | void StringUtils::WordToDigits(std::string &word) 1031 | { 1032 | static const char word_to_letter[] = "22233344455566677778889999"; 1033 | StringUtils::ToLower(word); 1034 | for (unsigned int i = 0; i < word.size(); ++i) 1035 | { // NB: This assumes ascii, which probably needs extending at some point. 1036 | char letter = word[i]; 1037 | if ((letter >= 'a' && letter <= 'z')) // assume contiguous letter range 1038 | { 1039 | word[i] = word_to_letter[letter-'a']; 1040 | } 1041 | else if (letter < '0' || letter > '9') // We want to keep 0-9! 1042 | { 1043 | word[i] = ' '; // replace everything else with a space 1044 | } 1045 | } 1046 | } 1047 | 1048 | std::string StringUtils::CreateUUID() 1049 | { 1050 | /* This function generate a DCE 1.1, ISO/IEC 11578:1996 and IETF RFC-4122 1051 | * Version 4 conform local unique UUID based upon random number generation. 1052 | */ 1053 | char UuidStrTmp[40]; 1054 | char *pUuidStr = UuidStrTmp; 1055 | int i; 1056 | 1057 | static bool m_uuidInitialized = false; 1058 | if (!m_uuidInitialized) 1059 | { 1060 | /* use current time as the seed for rand()*/ 1061 | srand((unsigned int)time(NULL)); 1062 | m_uuidInitialized = true; 1063 | } 1064 | 1065 | /*Data1 - 8 characters.*/ 1066 | for(i = 0; i < 8; i++, pUuidStr++) 1067 | ((*pUuidStr = (rand() % 16)) < 10) ? *pUuidStr += 48 : *pUuidStr += 55; 1068 | 1069 | /*Data2 - 4 characters.*/ 1070 | *pUuidStr++ = '-'; 1071 | for(i = 0; i < 4; i++, pUuidStr++) 1072 | ((*pUuidStr = (rand() % 16)) < 10) ? *pUuidStr += 48 : *pUuidStr += 55; 1073 | 1074 | /*Data3 - 4 characters.*/ 1075 | *pUuidStr++ = '-'; 1076 | for(i = 0; i < 4; i++, pUuidStr++) 1077 | ((*pUuidStr = (rand() % 16)) < 10) ? *pUuidStr += 48 : *pUuidStr += 55; 1078 | 1079 | /*Data4 - 4 characters.*/ 1080 | *pUuidStr++ = '-'; 1081 | for(i = 0; i < 4; i++, pUuidStr++) 1082 | ((*pUuidStr = (rand() % 16)) < 10) ? *pUuidStr += 48 : *pUuidStr += 55; 1083 | 1084 | /*Data5 - 12 characters.*/ 1085 | *pUuidStr++ = '-'; 1086 | for(i = 0; i < 12; i++, pUuidStr++) 1087 | ((*pUuidStr = (rand() % 16)) < 10) ? *pUuidStr += 48 : *pUuidStr += 55; 1088 | 1089 | *pUuidStr = '\0'; 1090 | 1091 | m_lastUUID = UuidStrTmp; 1092 | return UuidStrTmp; 1093 | } 1094 | 1095 | bool StringUtils::ContainsKeyword(const std::string &str, const vector &keywords) 1096 | { 1097 | for (vector::const_iterator it = keywords.begin(); it != keywords.end(); ++it) 1098 | { 1099 | if (str.find(*it) != str.npos) 1100 | return true; 1101 | } 1102 | return false; 1103 | } 1104 | 1105 | size_t StringUtils::utf8_strlen(const char *s) 1106 | { 1107 | size_t length = 0; 1108 | while (*s) 1109 | { 1110 | if ((*s++ & 0xC0) != 0x80) 1111 | length++; 1112 | } 1113 | return length; 1114 | } 1115 | 1116 | std::string StringUtils::Paramify(const std::string ¶m) 1117 | { 1118 | std::string result = param; 1119 | // escape backspaces 1120 | StringUtils::Replace(result, "\\", "\\\\"); 1121 | // escape double quotes 1122 | StringUtils::Replace(result, "\"", "\\\""); 1123 | 1124 | // add double quotes around the whole string 1125 | return "\"" + result + "\""; 1126 | } 1127 | 1128 | std::vector StringUtils::Tokenize(const std::string &input, const std::string &delimiters) 1129 | { 1130 | std::vector tokens; 1131 | Tokenize(input, tokens, delimiters); 1132 | return tokens; 1133 | } 1134 | 1135 | void StringUtils::Tokenize(const std::string& input, std::vector& tokens, const std::string& delimiters) 1136 | { 1137 | tokens.clear(); 1138 | // Skip delimiters at beginning. 1139 | std::string::size_type dataPos = input.find_first_not_of(delimiters); 1140 | while (dataPos != std::string::npos) 1141 | { 1142 | // Find next delimiter 1143 | const std::string::size_type nextDelimPos = input.find_first_of(delimiters, dataPos); 1144 | // Found a token, add it to the vector. 1145 | tokens.push_back(input.substr(dataPos, nextDelimPos - dataPos)); 1146 | // Skip delimiters. Note the "not_of" 1147 | dataPos = input.find_first_not_of(delimiters, nextDelimPos); 1148 | } 1149 | } 1150 | -------------------------------------------------------------------------------- /src/util/StringUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | * Copyright (C) 2005-2013 Team XBMC 4 | * http://xbmc.org 5 | * 6 | * This Program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2, or (at your option) 9 | * any later version. 10 | * 11 | * This Program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with XBMC; see the file COPYING. If not, see 18 | * . 19 | * 20 | */ 21 | //----------------------------------------------------------------------- 22 | // 23 | // File: StringUtils.h 24 | // 25 | // Purpose: ATL split string utility 26 | // Author: Paul J. Weiss 27 | // 28 | // Modified to support J O'Leary's std::string class by kraqh3d 29 | // 30 | //------------------------------------------------------------------------ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | /*! \brief TIME_FORMAT enum/bitmask used for formatting time strings 38 | Note the use of bitmasking, e.g. 39 | TIME_FORMAT_HH_MM_SS = TIME_FORMAT_HH | TIME_FORMAT_MM | TIME_FORMAT_SS 40 | \sa StringUtils::SecondsToTimeString 41 | */ 42 | enum TIME_FORMAT { TIME_FORMAT_GUESS = 0, 43 | TIME_FORMAT_SS = 1, 44 | TIME_FORMAT_MM = 2, 45 | TIME_FORMAT_MM_SS = 3, 46 | TIME_FORMAT_HH = 4, 47 | TIME_FORMAT_HH_SS = 5, // not particularly useful 48 | TIME_FORMAT_HH_MM = 6, 49 | TIME_FORMAT_HH_MM_SS = 7, 50 | TIME_FORMAT_XX = 8, // AM/PM 51 | TIME_FORMAT_HH_MM_XX = 14, 52 | TIME_FORMAT_HH_MM_SS_XX = 15, 53 | TIME_FORMAT_H = 16, 54 | TIME_FORMAT_H_MM_SS = 19, 55 | TIME_FORMAT_H_MM_SS_XX = 27}; 56 | 57 | class StringUtils 58 | { 59 | public: 60 | /*! \brief Get a formatted string similar to sprintf 61 | 62 | Beware that this does not support directly passing in 63 | std::string objects. You need to call c_str() to pass 64 | the const char* buffer representing the value of the 65 | std::string object. 66 | 67 | \param fmt Format of the resulting string 68 | \param ... variable number of value type arguments 69 | \return Formatted string 70 | */ 71 | static std::string Format(const char *fmt, ...); 72 | static std::string FormatV(const char *fmt, va_list args); 73 | static std::wstring Format(const wchar_t *fmt, ...); 74 | static std::wstring FormatV(const wchar_t *fmt, va_list args); 75 | static void ToUpper(std::string &str); 76 | static void ToUpper(std::wstring &str); 77 | static void ToLower(std::string &str); 78 | static void ToLower(std::wstring &str); 79 | static bool EqualsNoCase(const std::string &str1, const std::string &str2); 80 | static bool EqualsNoCase(const std::string &str1, const char *s2); 81 | static bool EqualsNoCase(const char *s1, const char *s2); 82 | static int CompareNoCase(const std::string &str1, const std::string &str2); 83 | static int CompareNoCase(const char *s1, const char *s2); 84 | static std::string Left(const std::string &str, size_t count); 85 | static std::string Mid(const std::string &str, size_t first, size_t count = std::string::npos); 86 | static std::string Right(const std::string &str, size_t count); 87 | static std::string& Trim(std::string &str); 88 | static std::string& Trim(std::string &str, const char* const chars); 89 | static std::string& TrimLeft(std::string &str); 90 | static std::string& TrimLeft(std::string &str, const char* const chars); 91 | static std::string& TrimRight(std::string &str); 92 | static std::string& TrimRight(std::string &str, const char* const chars); 93 | static std::string& RemoveDuplicatedSpacesAndTabs(std::string& str); 94 | static int Replace(std::string &str, char oldChar, char newChar); 95 | static int Replace(std::string &str, const std::string &oldStr, const std::string &newStr); 96 | static int Replace(std::wstring &str, const std::wstring &oldStr, const std::wstring &newStr); 97 | static bool StartsWith(const std::string &str1, const std::string &str2); 98 | static bool StartsWith(const std::string &str1, const char *s2); 99 | static bool StartsWith(const char *s1, const char *s2); 100 | static bool StartsWithNoCase(const std::string &str1, const std::string &str2); 101 | static bool StartsWithNoCase(const std::string &str1, const char *s2); 102 | static bool StartsWithNoCase(const char *s1, const char *s2); 103 | static bool EndsWith(const std::string &str1, const std::string &str2); 104 | static bool EndsWith(const std::string &str1, const char *s2); 105 | static bool EndsWithNoCase(const std::string &str1, const std::string &str2); 106 | static bool EndsWithNoCase(const std::string &str1, const char *s2); 107 | 108 | static std::string Join(const std::vector &strings, const std::string& delimiter); 109 | /*! \brief Splits the given input string using the given delimiter into separate strings. 110 | 111 | If the given input string is empty the result will be an empty array (not 112 | an array containing an empty string). 113 | 114 | \param input Input string to be split 115 | \param delimiter Delimiter to be used to split the input string 116 | \param iMaxStrings (optional) Maximum number of splitted strings 117 | */ 118 | static std::vector Split(const std::string& input, const std::string& delimiter, unsigned int iMaxStrings = 0); 119 | static int FindNumber(const std::string& strInput, const std::string &strFind); 120 | static int64_t AlphaNumericCompare(const wchar_t *left, const wchar_t *right); 121 | static long TimeStringToSeconds(const std::string &timeString); 122 | static void RemoveCRLF(std::string& strLine); 123 | 124 | /*! \brief utf8 version of strlen - skips any non-starting bytes in the count, thus returning the number of utf8 characters 125 | \param s c-string to find the length of. 126 | \return the number of utf8 characters in the string. 127 | */ 128 | static size_t utf8_strlen(const char *s); 129 | 130 | /*! \brief convert a time in seconds to a string based on the given time format 131 | \param seconds time in seconds 132 | \param format the format we want the time in. 133 | \return the formatted time 134 | \sa TIME_FORMAT 135 | */ 136 | static std::string SecondsToTimeString(long seconds, TIME_FORMAT format = TIME_FORMAT_GUESS); 137 | 138 | /*! \brief check whether a string is a natural number. 139 | Matches [ \t]*[0-9]+[ \t]* 140 | \param str the string to check 141 | \return true if the string is a natural number, false otherwise. 142 | */ 143 | static bool IsNaturalNumber(const std::string& str); 144 | 145 | /*! \brief check whether a string is an integer. 146 | Matches [ \t]*[\-]*[0-9]+[ \t]* 147 | \param str the string to check 148 | \return true if the string is an integer, false otherwise. 149 | */ 150 | static bool IsInteger(const std::string& str); 151 | 152 | /* The next several isasciiXX and asciiXXvalue functions are locale independent (US-ASCII only), 153 | * as opposed to standard ::isXX (::isalpha, ::isdigit...) which are locale dependent. 154 | * Next functions get parameter as char and don't need double cast ((int)(unsigned char) is required for standard functions). */ 155 | inline static bool isasciidigit(char chr) // locale independent 156 | { 157 | return chr >= '0' && chr <= '9'; 158 | } 159 | inline static bool isasciixdigit(char chr) // locale independent 160 | { 161 | return (chr >= '0' && chr <= '9') || (chr >= 'a' && chr <= 'f') || (chr >= 'A' && chr <= 'F'); 162 | } 163 | static int asciidigitvalue(char chr); // locale independent 164 | static int asciixdigitvalue(char chr); // locale independent 165 | inline static bool isasciiuppercaseletter(char chr) // locale independent 166 | { 167 | return (chr >= 'A' && chr <= 'Z'); 168 | } 169 | inline static bool isasciilowercaseletter(char chr) // locale independent 170 | { 171 | return (chr >= 'a' && chr <= 'z'); 172 | } 173 | inline static bool isasciialphanum(char chr) // locale independent 174 | { 175 | return isasciiuppercaseletter(chr) || isasciilowercaseletter(chr) || isasciidigit(chr); 176 | } 177 | static std::string SizeToString(int64_t size); 178 | static const std::string Empty; 179 | static size_t FindWords(const char *str, const char *wordLowerCase); 180 | static int FindEndBracket(const std::string &str, char opener, char closer, int startPos = 0); 181 | static int DateStringToYYYYMMDD(const std::string &dateString); 182 | static void WordToDigits(std::string &word); 183 | static std::string CreateUUID(); 184 | static bool ContainsKeyword(const std::string &str, const std::vector &keywords); 185 | 186 | /*! \brief Escapes the given string to be able to be used as a parameter. 187 | 188 | Escapes backslashes and double-quotes with an additional backslash and 189 | adds double-quotes around the whole string. 190 | 191 | \param param String to escape/paramify 192 | \return Escaped/Paramified string 193 | */ 194 | static std::string Paramify(const std::string ¶m); 195 | 196 | /*! \brief Split a string by the specified delimiters. 197 | Splits a string using one or more delimiting characters, ignoring empty tokens. 198 | Differs from Split() in two ways: 199 | 1. The delimiters are treated as individual characters, rather than a single delimiting string. 200 | 2. Empty tokens are ignored. 201 | \return a vector of tokens 202 | */ 203 | static std::vector Tokenize(const std::string& input, const std::string& delimiters); 204 | static void Tokenize(const std::string& input, std::vector& tokens, const std::string& delimiters); 205 | private: 206 | static std::string m_lastUUID; 207 | }; 208 | -------------------------------------------------------------------------------- /src/util/atomic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | * Copyright (C) 2005-2012 Team XBMC 4 | * http://www.kodi.tv 5 | * 6 | * This Program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2, or (at your option) 9 | * any later version. 10 | * 11 | * This Program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with XBMC; see the file COPYING. If not, see 18 | * . 19 | * 20 | */ 21 | 22 | #ifdef _MSC_VER 23 | #include 24 | #endif 25 | 26 | /////////////////////////////////////////////////////////////////////////// 27 | // 32-bit atomic increment 28 | // Returns new value of *pAddr 29 | /////////////////////////////////////////////////////////////////////////// 30 | static inline long atomic_inc(volatile long* pAddr) 31 | { 32 | #if defined(HAS_BUILTIN_SYNC_ADD_AND_FETCH) 33 | return __sync_add_and_fetch(pAddr, 1); 34 | 35 | #elif defined(__ppc__) || defined(__powerpc__) // PowerPC 36 | long val; 37 | __asm__ __volatile__ ( 38 | "sync \n" 39 | "1: lwarx %0, 0, %1 \n" 40 | "addic %0, %0, 1 \n" 41 | "stwcx. %0, 0, %1 \n" 42 | "bne- 1b \n" 43 | "isync" 44 | : "=&r" (val) 45 | : "r" (pAddr) 46 | : "cc", "xer", "memory"); 47 | return val; 48 | 49 | #elif defined(__arm__) && !defined(__ARM_ARCH_5__) 50 | register long val; 51 | asm volatile ( 52 | "dmb ish \n" // Memory barrier. Make sure all memory accesses appearing before this complete before any that appear after 53 | "1: \n" 54 | "ldrex %0, [%1] \n" // (val = *pAddr) 55 | "add %0, #1 \n" // (val += 1) 56 | "strex r1, %0, [%1] \n" 57 | "cmp r1, #0 \n" 58 | "bne 1b \n" 59 | "dmb ish \n" // Memory barrier. 60 | : "=&r" (val) 61 | : "r"(pAddr) 62 | : "r1" 63 | ); 64 | return val; 65 | 66 | #elif defined(__mips__) 67 | // TODO: 68 | long val; 69 | #error AtomicIncrement undefined for mips 70 | return val; 71 | 72 | #elif defined(WIN32) 73 | long val; 74 | __asm 75 | { 76 | mov eax, pAddr ; 77 | lock inc dword ptr [eax] ; 78 | mov eax, [eax] ; 79 | mov val, eax ; 80 | } 81 | return val; 82 | 83 | #elif defined(__x86_64__) 84 | register long result; 85 | __asm__ __volatile__ ( 86 | "lock/xaddq %q0, %1" 87 | : "=r" (result), "=m" (*pAddr) 88 | : "0" ((long) (1)), "m" (*pAddr)); 89 | return *pAddr; 90 | 91 | #else // Linux / OSX86 (GCC) 92 | register long reg __asm__ ("eax") = 1; 93 | __asm__ __volatile__ ( 94 | "lock/xadd %0, %1 \n" 95 | "inc %%eax" 96 | : "+r" (reg) 97 | : "m" (*pAddr) 98 | : "memory" ); 99 | return reg; 100 | 101 | #endif 102 | } 103 | -------------------------------------------------------------------------------- /src/util/buffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | * This file is part of the libCEC(R) library. 4 | * 5 | * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. 6 | * libCEC(R) is an original work, containing original code. 7 | * 8 | * libCEC(R) is a trademark of Pulse-Eight Limited. 9 | * 10 | * This program is dual-licensed; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 | * 24 | * 25 | * Alternatively, you can license this library under a commercial license, 26 | * please contact Pulse-Eight Licensing for more information. 27 | * 28 | * For more information contact: 29 | * Pulse-Eight Licensing 30 | * http://www.pulse-eight.com/ 31 | * http://www.pulse-eight.net/ 32 | */ 33 | 34 | #include "../threads/mutex.h" 35 | #include 36 | 37 | namespace P8PLATFORM 38 | { 39 | template 40 | struct SyncedBuffer 41 | { 42 | public: 43 | SyncedBuffer(size_t iMaxSize = 100) : 44 | m_maxSize(iMaxSize), 45 | m_bHasData(false) {} 46 | 47 | virtual ~SyncedBuffer(void) 48 | { 49 | Clear(); 50 | } 51 | 52 | void Clear(void) 53 | { 54 | CLockObject lock(m_mutex); 55 | while (!m_buffer.empty()) 56 | m_buffer.pop(); 57 | m_bHasData = false; 58 | m_condition.Broadcast(); 59 | } 60 | 61 | size_t Size(void) 62 | { 63 | CLockObject lock(m_mutex); 64 | return m_buffer.size(); 65 | } 66 | 67 | bool IsEmpty(void) 68 | { 69 | CLockObject lock(m_mutex); 70 | return !m_bHasData; 71 | } 72 | 73 | bool Push(_BType entry) 74 | { 75 | CLockObject lock(m_mutex); 76 | if (m_buffer.size() == m_maxSize) 77 | return false; 78 | 79 | m_buffer.push(entry); 80 | m_bHasData = true; 81 | m_condition.Signal(); 82 | return true; 83 | } 84 | 85 | bool Pop(_BType &entry, int32_t iTimeoutMs = 0) 86 | { 87 | CLockObject lock(m_mutex); 88 | if (m_buffer.empty()) 89 | { 90 | if (iTimeoutMs == 0) 91 | return false; 92 | if (!m_condition.Wait(m_mutex, m_bHasData, iTimeoutMs)) 93 | return false; 94 | } 95 | 96 | entry = m_buffer.front(); 97 | m_buffer.pop(); 98 | m_bHasData = !m_buffer.empty(); 99 | return true; 100 | } 101 | 102 | private: 103 | size_t m_maxSize; 104 | std::queue<_BType> m_buffer; 105 | CMutex m_mutex; 106 | bool m_bHasData; 107 | CCondition m_condition; 108 | }; 109 | }; 110 | -------------------------------------------------------------------------------- /src/util/timeutils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | * This file is part of the libCEC(R) library. 4 | * 5 | * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. 6 | * libCEC(R) is an original work, containing original code. 7 | * 8 | * libCEC(R) is a trademark of Pulse-Eight Limited. 9 | * 10 | * This program is dual-licensed; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 | * 24 | * 25 | * Alternatively, you can license this library under a commercial license, 26 | * please contact Pulse-Eight Licensing for more information. 27 | * 28 | * For more information contact: 29 | * Pulse-Eight Licensing 30 | * http://www.pulse-eight.com/ 31 | * http://www.pulse-eight.net/ 32 | */ 33 | 34 | #include "../os.h" 35 | 36 | #if defined(__APPLE__) 37 | #include 38 | #include 39 | #elif defined(__WINDOWS__) 40 | #include 41 | #else 42 | #include 43 | #endif 44 | 45 | namespace P8PLATFORM 46 | { 47 | #if defined(__WINDOWS__) && !defined(SWIGPYTHON) 48 | struct timezone 49 | { 50 | int tz_minuteswest; 51 | int tz_dsttime; 52 | }; 53 | 54 | #define usleep(t) Sleep((DWORD)(t)/1000) 55 | 56 | inline int gettimeofday(struct timeval *pcur_time, struct timezone *tz) 57 | { 58 | if (pcur_time == NULL) 59 | { 60 | SetLastError(EFAULT); 61 | return -1; 62 | } 63 | struct _timeb current; 64 | 65 | _ftime(¤t); 66 | 67 | pcur_time->tv_sec = (long) current.time; 68 | pcur_time->tv_usec = current.millitm * 1000L; 69 | if (tz) 70 | { 71 | tz->tz_minuteswest = current.timezone; /* minutes west of Greenwich */ 72 | tz->tz_dsttime = current.dstflag; /* type of dst correction */ 73 | } 74 | return 0; 75 | } 76 | #endif // defined(__WINDOWS__) && !defined(SWIGPYTHON) 77 | 78 | inline int64_t GetTimeMs() 79 | { 80 | #if defined(__APPLE__) 81 | return (int64_t) (CVGetCurrentHostTime() / (int64_t)(CVGetHostClockFrequency() * 0.001)); 82 | #elif defined(__WINDOWS__) 83 | LARGE_INTEGER tickPerSecond; 84 | LARGE_INTEGER tick; 85 | if (QueryPerformanceFrequency(&tickPerSecond)) 86 | { 87 | QueryPerformanceCounter(&tick); 88 | return (int64_t) (tick.QuadPart / (tickPerSecond.QuadPart / 1000.)); 89 | } 90 | return -1; 91 | #else 92 | timespec time; 93 | clock_gettime(CLOCK_MONOTONIC, &time); 94 | return (int64_t)time.tv_sec * 1000 + time.tv_nsec / 1000000; 95 | #endif 96 | } 97 | 98 | template 99 | inline T GetTimeSec() 100 | { 101 | return (T)GetTimeMs() / (T)1000.0; 102 | } 103 | 104 | class CTimeout 105 | { 106 | public: 107 | CTimeout(void) : m_iTarget(0) {} 108 | CTimeout(uint32_t iTimeout) { Init(iTimeout); } 109 | 110 | bool IsSet(void) const { return m_iTarget > 0; } 111 | void Init(uint32_t iTimeout) { m_iTarget = GetTimeMs() + iTimeout; } 112 | 113 | uint32_t TimeLeft(void) const 114 | { 115 | uint64_t iNow = GetTimeMs(); 116 | return (iNow > m_iTarget) ? 0 : (uint32_t)(m_iTarget - iNow); 117 | } 118 | 119 | private: 120 | uint64_t m_iTarget; 121 | }; 122 | }; 123 | -------------------------------------------------------------------------------- /src/util/util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | * Copyright (C) 2012 Team XBMC 4 | * http://www.xbmc.org 5 | * 6 | * This Program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2, or (at your option) 9 | * any later version. 10 | * 11 | * This Program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with XBMC; see the file COPYING. If not, see 18 | * . 19 | * 20 | */ 21 | 22 | #ifndef SAFE_DELETE 23 | #define SAFE_DELETE(p) do { delete (p); (p)=NULL; } while (0) 24 | #endif 25 | #ifndef SAFE_DELETE_ARRAY 26 | #define SAFE_DELETE_ARRAY(p) do { delete[] (p); (p)=NULL; } while (0) 27 | #endif 28 | -------------------------------------------------------------------------------- /src/windows/dlfcn-win32.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * dlfcn-win32 3 | * Copyright (c) 2007 Ramiro Polla 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | #include "dlfcn-win32.h" 24 | 25 | /* Note: 26 | * MSDN says these functions are not thread-safe. We make no efforts to have 27 | * any kind of thread safety. 28 | */ 29 | 30 | /* I have no special reason to have set MAX_GLOBAL_OBJECTS to this value. Any 31 | * comments are welcome. 32 | */ 33 | #define MAX_OBJECTS 255 34 | 35 | static HMODULE global_objects[MAX_OBJECTS]; 36 | 37 | /* This function adds an object to the list of global objects. 38 | * The implementation is very simple and slow. 39 | * TODO: should failing this function be enough to fail the call to dlopen( )? 40 | */ 41 | static void global_object_add( HMODULE hModule ) 42 | { 43 | int i; 44 | 45 | for( i = 0 ; i < MAX_OBJECTS ; i++ ) 46 | { 47 | if( !global_objects[i] ) 48 | { 49 | global_objects[i] = hModule; 50 | break; 51 | } 52 | } 53 | } 54 | 55 | static void global_object_rem( HMODULE hModule ) 56 | { 57 | int i; 58 | 59 | for( i = 0 ; i < MAX_OBJECTS ; i++ ) 60 | { 61 | if( global_objects[i] == hModule ) 62 | { 63 | global_objects[i] = 0; 64 | break; 65 | } 66 | } 67 | } 68 | 69 | /* Argument to last function. Used in dlerror( ) */ 70 | static char last_name[MAX_PATH]; 71 | 72 | static int copy_string( char *dest, int dest_size, const char *src ) 73 | { 74 | int i = 0; 75 | 76 | if( src && dest ) 77 | { 78 | for( i = 0 ; i < dest_size-1 ; i++ ) 79 | { 80 | if( !src[i] ) 81 | break; 82 | else 83 | dest[i] = src[i]; 84 | } 85 | } 86 | dest[i] = '\0'; 87 | 88 | return i; 89 | } 90 | 91 | void *dlopen( const char *file, int mode ) 92 | { 93 | HMODULE hModule; 94 | UINT uMode; 95 | 96 | /* Do not let Windows display the critical-error-handler message box */ 97 | uMode = SetErrorMode( SEM_FAILCRITICALERRORS ); 98 | 99 | if( file == 0 ) 100 | { 101 | /* Save NULL pointer for error message */ 102 | _snprintf_s( last_name, MAX_PATH, MAX_PATH, "0x%p", file ); 103 | 104 | /* POSIX says that if the value of file is 0, a handle on a global 105 | * symbol object must be provided. That object must be able to access 106 | * all symbols from the original program file, and any objects loaded 107 | * with the RTLD_GLOBAL flag. 108 | * The return value from GetModuleHandle( ) allows us to retrieve 109 | * symbols only from the original program file. For objects loaded with 110 | * the RTLD_GLOBAL flag, we create our own list later on. 111 | */ 112 | hModule = GetModuleHandle( NULL ); 113 | } 114 | else 115 | { 116 | char lpFileName[MAX_PATH]; 117 | int i; 118 | 119 | /* MSDN says backslashes *must* be used instead of forward slashes. */ 120 | for( i = 0 ; i < sizeof(lpFileName)-1 ; i++ ) 121 | { 122 | if( !file[i] ) 123 | break; 124 | else if( file[i] == '/' ) 125 | lpFileName[i] = '\\'; 126 | else 127 | lpFileName[i] = file[i]; 128 | } 129 | lpFileName[i] = '\0'; 130 | 131 | /* Save file name for error message */ 132 | copy_string( last_name, sizeof(last_name), lpFileName ); 133 | 134 | /* POSIX says the search path is implementation-defined. 135 | * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely 136 | * to UNIX's search paths (start with system folders instead of current 137 | * folder). 138 | */ 139 | hModule = LoadLibraryEx( (LPSTR) lpFileName, NULL, 140 | LOAD_WITH_ALTERED_SEARCH_PATH ); 141 | /* If the object was loaded with RTLD_GLOBAL, add it to list of global 142 | * objects, so that its symbols may be retrieved even if the handle for 143 | * the original program file is passed. POSIX says that if the same 144 | * file is specified in multiple invocations, and any of them are 145 | * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the 146 | * symbols will remain global. 147 | */ 148 | 149 | if( hModule && (mode & RTLD_GLOBAL) ) 150 | global_object_add( hModule ); 151 | } 152 | 153 | /* Return to previous state of the error-mode bit flags. */ 154 | SetErrorMode( uMode ); 155 | 156 | return (void *) hModule; 157 | } 158 | 159 | int dlclose( void *handle ) 160 | { 161 | HMODULE hModule = (HMODULE) handle; 162 | BOOL ret; 163 | 164 | /* Save handle for error message */ 165 | _snprintf_s( last_name, MAX_PATH, MAX_PATH, "0x%p", handle ); 166 | 167 | ret = FreeLibrary( hModule ); 168 | 169 | /* If the object was loaded with RTLD_GLOBAL, remove it from list of global 170 | * objects. 171 | */ 172 | if( ret ) 173 | global_object_rem( hModule ); 174 | 175 | /* dlclose's return value in inverted in relation to FreeLibrary's. */ 176 | ret = !ret; 177 | 178 | return (int) ret; 179 | } 180 | 181 | void *dlsym( void *handle, const char *name ) 182 | { 183 | FARPROC symbol; 184 | HMODULE myhandle = (HMODULE) handle; 185 | 186 | /* Save symbol name for error message */ 187 | copy_string( last_name, sizeof(last_name), name ); 188 | 189 | symbol = GetProcAddress( myhandle, name ); 190 | #if 0 191 | if( symbol == NULL ) 192 | { 193 | HMODULE hModule; 194 | 195 | /* If the handle for the original program file is passed, also search 196 | * in all globally loaded objects. 197 | */ 198 | 199 | hModule = GetModuleHandle( NULL ); 200 | 201 | if( hModule == handle ) 202 | { 203 | int i; 204 | 205 | for( i = 0 ; i < MAX_OBJECTS ; i++ ) 206 | { 207 | if( global_objects[i] != 0 ) 208 | { 209 | symbol = GetProcAddress( global_objects[i], name ); 210 | if( symbol != NULL ) 211 | break; 212 | } 213 | } 214 | } 215 | 216 | 217 | CloseHandle( hModule ); 218 | } 219 | #endif 220 | return (void*) symbol; 221 | } 222 | 223 | char *dlerror( void ) 224 | { 225 | DWORD dwMessageId; 226 | /* POSIX says this function doesn't have to be thread-safe, so we use one 227 | * static buffer. 228 | * MSDN says the buffer cannot be larger than 64K bytes, so we set it to 229 | * the limit. 230 | */ 231 | static char lpBuffer[65535]; 232 | DWORD ret; 233 | 234 | dwMessageId = GetLastError( ); 235 | 236 | if( dwMessageId == 0 ) 237 | return NULL; 238 | 239 | /* Format error message to: 240 | * "": 241 | */ 242 | ret = copy_string( lpBuffer, sizeof(lpBuffer), "\"" ); 243 | ret += copy_string( lpBuffer+ret, sizeof(lpBuffer)-ret, last_name ); 244 | ret += copy_string( lpBuffer+ret, sizeof(lpBuffer)-ret, "\": " ); 245 | ret += FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwMessageId, 246 | MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), 247 | lpBuffer+ret, sizeof(lpBuffer)-ret, NULL ); 248 | 249 | if( ret > 1 ) 250 | { 251 | /* POSIX says the string must not have trailing */ 252 | if( lpBuffer[ret-2] == '\r' && lpBuffer[ret-1] == '\n' ) 253 | lpBuffer[ret-2] = '\0'; 254 | } 255 | 256 | /* POSIX says that invoking dlerror( ) a second time, immediately following 257 | * a prior invocation, shall result in NULL being returned. 258 | */ 259 | SetLastError(0); 260 | 261 | return lpBuffer; 262 | } 263 | 264 | -------------------------------------------------------------------------------- /src/windows/dlfcn-win32.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | * dlfcn-win32 4 | * Copyright (c) 2007 Ramiro Polla 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #ifndef DLFCN_H 22 | #define DLFCN_H 23 | 24 | /* POSIX says these are implementation-defined. 25 | * To simplify use with Windows API, we treat them the same way. 26 | */ 27 | 28 | #define RTLD_LAZY 0 29 | #define RTLD_NOW 0 30 | 31 | #define RTLD_GLOBAL (1 << 1) 32 | #define RTLD_LOCAL (1 << 2) 33 | 34 | /* These two were added in The Open Group Base Specifications Issue 6. 35 | * Note: All other RTLD_* flags in any dlfcn.h are not standard compliant. 36 | */ 37 | 38 | #define RTLD_DEFAULT 0 39 | #define RTLD_NEXT 0 40 | 41 | void *dlopen ( const char *file, int mode ); 42 | int dlclose( void *handle ); 43 | void *dlsym ( void *handle, const char *name ); 44 | char *dlerror( void ); 45 | 46 | #endif /* DLFCN-WIN32_H */ 47 | -------------------------------------------------------------------------------- /src/windows/inttypes.h: -------------------------------------------------------------------------------- 1 | // ISO C9x compliant inttypes.h for Microsoft Visual Studio 2 | // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 3 | // 4 | // Copyright (c) 2006 Alexander Chemeris 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // 1. Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // 2. Redistributions in binary form must reproduce the above copyright 13 | // notice, this list of conditions and the following disclaimer in the 14 | // documentation and/or other materials provided with the distribution. 15 | // 16 | // 3. The name of the author may be used to endorse or promote products 17 | // derived from this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 20 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 25 | // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 27 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 28 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | /////////////////////////////////////////////////////////////////////////////// 31 | 32 | #ifndef _MSC_VER // [ 33 | #error "Use this header only with Microsoft Visual C++ compilers!" 34 | #endif // _MSC_VER ] 35 | 36 | #ifndef _MSC_INTTYPES_H_ // [ 37 | #define _MSC_INTTYPES_H_ 38 | 39 | #if _MSC_VER > 1000 40 | #pragma once 41 | #endif 42 | 43 | #include "stdint.h" 44 | 45 | // 7.8 Format conversion of integer types 46 | 47 | typedef struct { 48 | intmax_t quot; 49 | intmax_t rem; 50 | } imaxdiv_t; 51 | 52 | // 7.8.1 Macros for format specifiers 53 | 54 | #if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 55 | 56 | // The fprintf macros for signed integers are: 57 | #define PRId8 "d" 58 | #define PRIi8 "i" 59 | #define PRIdLEAST8 "d" 60 | #define PRIiLEAST8 "i" 61 | #define PRIdFAST8 "d" 62 | #define PRIiFAST8 "i" 63 | 64 | #define PRId16 "hd" 65 | #define PRIi16 "hi" 66 | #define PRIdLEAST16 "hd" 67 | #define PRIiLEAST16 "hi" 68 | #define PRIdFAST16 "hd" 69 | #define PRIiFAST16 "hi" 70 | 71 | #define PRId32 "I32d" 72 | #define PRIi32 "I32i" 73 | #define PRIdLEAST32 "I32d" 74 | #define PRIiLEAST32 "I32i" 75 | #define PRIdFAST32 "I32d" 76 | #define PRIiFAST32 "I32i" 77 | 78 | #define PRId64 "I64d" 79 | #define PRIi64 "I64i" 80 | #define PRIdLEAST64 "I64d" 81 | #define PRIiLEAST64 "I64i" 82 | #define PRIdFAST64 "I64d" 83 | #define PRIiFAST64 "I64i" 84 | 85 | #define PRIdMAX "I64d" 86 | #define PRIiMAX "I64i" 87 | 88 | #define PRIdPTR "Id" 89 | #define PRIiPTR "Ii" 90 | 91 | // The fprintf macros for unsigned integers are: 92 | #define PRIo8 "o" 93 | #define PRIu8 "u" 94 | #define PRIx8 "x" 95 | #define PRIX8 "X" 96 | #define PRIoLEAST8 "o" 97 | #define PRIuLEAST8 "u" 98 | #define PRIxLEAST8 "x" 99 | #define PRIXLEAST8 "X" 100 | #define PRIoFAST8 "o" 101 | #define PRIuFAST8 "u" 102 | #define PRIxFAST8 "x" 103 | #define PRIXFAST8 "X" 104 | 105 | #define PRIo16 "ho" 106 | #define PRIu16 "hu" 107 | #define PRIx16 "hx" 108 | #define PRIX16 "hX" 109 | #define PRIoLEAST16 "ho" 110 | #define PRIuLEAST16 "hu" 111 | #define PRIxLEAST16 "hx" 112 | #define PRIXLEAST16 "hX" 113 | #define PRIoFAST16 "ho" 114 | #define PRIuFAST16 "hu" 115 | #define PRIxFAST16 "hx" 116 | #define PRIXFAST16 "hX" 117 | 118 | #define PRIo32 "I32o" 119 | #define PRIu32 "I32u" 120 | #define PRIx32 "I32x" 121 | #define PRIX32 "I32X" 122 | #define PRIoLEAST32 "I32o" 123 | #define PRIuLEAST32 "I32u" 124 | #define PRIxLEAST32 "I32x" 125 | #define PRIXLEAST32 "I32X" 126 | #define PRIoFAST32 "I32o" 127 | #define PRIuFAST32 "I32u" 128 | #define PRIxFAST32 "I32x" 129 | #define PRIXFAST32 "I32X" 130 | 131 | #define PRIo64 "I64o" 132 | #define PRIu64 "I64u" 133 | #define PRIx64 "I64x" 134 | #define PRIX64 "I64X" 135 | #define PRIoLEAST64 "I64o" 136 | #define PRIuLEAST64 "I64u" 137 | #define PRIxLEAST64 "I64x" 138 | #define PRIXLEAST64 "I64X" 139 | #define PRIoFAST64 "I64o" 140 | #define PRIuFAST64 "I64u" 141 | #define PRIxFAST64 "I64x" 142 | #define PRIXFAST64 "I64X" 143 | 144 | #define PRIoMAX "I64o" 145 | #define PRIuMAX "I64u" 146 | #define PRIxMAX "I64x" 147 | #define PRIXMAX "I64X" 148 | 149 | #define PRIoPTR "Io" 150 | #define PRIuPTR "Iu" 151 | #define PRIxPTR "Ix" 152 | #define PRIXPTR "IX" 153 | 154 | #define PRIdS "Id" 155 | #define PRIuS "Iu" 156 | 157 | // The fscanf macros for signed integers are: 158 | #define SCNd8 "d" 159 | #define SCNi8 "i" 160 | #define SCNdLEAST8 "d" 161 | #define SCNiLEAST8 "i" 162 | #define SCNdFAST8 "d" 163 | #define SCNiFAST8 "i" 164 | 165 | #define SCNd16 "hd" 166 | #define SCNi16 "hi" 167 | #define SCNdLEAST16 "hd" 168 | #define SCNiLEAST16 "hi" 169 | #define SCNdFAST16 "hd" 170 | #define SCNiFAST16 "hi" 171 | 172 | #define SCNd32 "ld" 173 | #define SCNi32 "li" 174 | #define SCNdLEAST32 "ld" 175 | #define SCNiLEAST32 "li" 176 | #define SCNdFAST32 "ld" 177 | #define SCNiFAST32 "li" 178 | 179 | #define SCNd64 "I64d" 180 | #define SCNi64 "I64i" 181 | #define SCNdLEAST64 "I64d" 182 | #define SCNiLEAST64 "I64i" 183 | #define SCNdFAST64 "I64d" 184 | #define SCNiFAST64 "I64i" 185 | 186 | #define SCNdMAX "I64d" 187 | #define SCNiMAX "I64i" 188 | 189 | #if defined(_WIN64) || defined(_M_ARM64) // [ 190 | # define SCNdPTR "I64d" 191 | # define SCNiPTR "I64i" 192 | #else // _WIN64 || _M_ARM64 ][ 193 | # define SCNdPTR "ld" 194 | # define SCNiPTR "li" 195 | #endif // _WIN64 || _M_ARM64] 196 | 197 | // The fscanf macros for unsigned integers are: 198 | #define SCNo8 "o" 199 | #define SCNu8 "u" 200 | #define SCNx8 "x" 201 | #define SCNX8 "X" 202 | #define SCNoLEAST8 "o" 203 | #define SCNuLEAST8 "u" 204 | #define SCNxLEAST8 "x" 205 | #define SCNXLEAST8 "X" 206 | #define SCNoFAST8 "o" 207 | #define SCNuFAST8 "u" 208 | #define SCNxFAST8 "x" 209 | #define SCNXFAST8 "X" 210 | 211 | #define SCNo16 "ho" 212 | #define SCNu16 "hu" 213 | #define SCNx16 "hx" 214 | #define SCNX16 "hX" 215 | #define SCNoLEAST16 "ho" 216 | #define SCNuLEAST16 "hu" 217 | #define SCNxLEAST16 "hx" 218 | #define SCNXLEAST16 "hX" 219 | #define SCNoFAST16 "ho" 220 | #define SCNuFAST16 "hu" 221 | #define SCNxFAST16 "hx" 222 | #define SCNXFAST16 "hX" 223 | 224 | #define SCNo32 "lo" 225 | #define SCNu32 "lu" 226 | #define SCNx32 "lx" 227 | #define SCNX32 "lX" 228 | #define SCNoLEAST32 "lo" 229 | #define SCNuLEAST32 "lu" 230 | #define SCNxLEAST32 "lx" 231 | #define SCNXLEAST32 "lX" 232 | #define SCNoFAST32 "lo" 233 | #define SCNuFAST32 "lu" 234 | #define SCNxFAST32 "lx" 235 | #define SCNXFAST32 "lX" 236 | 237 | #define SCNo64 "I64o" 238 | #define SCNu64 "I64u" 239 | #define SCNx64 "I64x" 240 | #define SCNX64 "I64X" 241 | #define SCNoLEAST64 "I64o" 242 | #define SCNuLEAST64 "I64u" 243 | #define SCNxLEAST64 "I64x" 244 | #define SCNXLEAST64 "I64X" 245 | #define SCNoFAST64 "I64o" 246 | #define SCNuFAST64 "I64u" 247 | #define SCNxFAST64 "I64x" 248 | #define SCNXFAST64 "I64X" 249 | 250 | #define SCNoMAX "I64o" 251 | #define SCNuMAX "I64u" 252 | #define SCNxMAX "I64x" 253 | #define SCNXMAX "I64X" 254 | 255 | #defined(_WIN64) || defined(_M_ARM64) // [ 256 | # define SCNoPTR "I64o" 257 | # define SCNuPTR "I64u" 258 | # define SCNxPTR "I64x" 259 | # define SCNXPTR "I64X" 260 | #else // _WIN64 || _M_ARM64 ][ 261 | # define SCNoPTR "lo" 262 | # define SCNuPTR "lu" 263 | # define SCNxPTR "lx" 264 | # define SCNXPTR "lX" 265 | #endif // _WIN64 || _M_ARM64 ] 266 | 267 | #endif // __STDC_FORMAT_MACROS ] 268 | 269 | // 7.8.2 Functions for greatest-width integer types 270 | 271 | // 7.8.2.1 The imaxabs function 272 | #define imaxabs _abs64 273 | 274 | // 7.8.2.2 The imaxdiv function 275 | 276 | // This is modified version of div() function from Microsoft's div.c found 277 | // in %MSVC.NET%\crt\src\div.c 278 | #ifdef STATIC_IMAXDIV // [ 279 | static 280 | #else // STATIC_IMAXDIV ][ 281 | _inline 282 | #endif // STATIC_IMAXDIV ] 283 | imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) 284 | { 285 | imaxdiv_t result; 286 | 287 | result.quot = numer / denom; 288 | result.rem = numer % denom; 289 | 290 | if (numer < 0 && result.rem > 0) { 291 | // did division wrong; must fix up 292 | ++result.quot; 293 | result.rem -= denom; 294 | } 295 | 296 | return result; 297 | } 298 | 299 | // 7.8.2.3 The strtoimax and strtoumax functions 300 | #define strtoimax _strtoi64 301 | #define strtoumax _strtoui64 302 | 303 | // 7.8.2.4 The wcstoimax and wcstoumax functions 304 | #define wcstoimax _wcstoi64 305 | #define wcstoumax _wcstoui64 306 | 307 | 308 | #endif // _MSC_INTTYPES_H_ ] 309 | -------------------------------------------------------------------------------- /src/windows/os-socket.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | * This file is part of the libCEC(R) library. 4 | * 5 | * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. 6 | * libCEC(R) is an original work, containing original code. 7 | * 8 | * libCEC(R) is a trademark of Pulse-Eight Limited. 9 | * 10 | * This program is dual-licensed; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 | * 24 | * 25 | * Alternatively, you can license this library under a commercial license, 26 | * please contact Pulse-Eight Licensing for more information. 27 | * 28 | * For more information contact: 29 | * Pulse-Eight Licensing 30 | * http://www.pulse-eight.com/ 31 | * http://www.pulse-eight.net/ 32 | */ 33 | 34 | #include "../os.h" 35 | #include "../util/timeutils.h" 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #define SHUT_RDWR SD_BOTH 43 | 44 | #ifndef ETIMEDOUT 45 | #define ETIMEDOUT 138 46 | #endif 47 | 48 | namespace P8PLATFORM 49 | { 50 | #ifndef MSG_WAITALL 51 | #define MSG_WAITALL 0x8 52 | #endif 53 | 54 | inline int GetSocketError(void) 55 | { 56 | int error = WSAGetLastError(); 57 | switch(error) 58 | { 59 | case WSAEINPROGRESS: return EINPROGRESS; 60 | case WSAECONNRESET : return ECONNRESET; 61 | case WSAETIMEDOUT : return ETIMEDOUT; 62 | case WSAEWOULDBLOCK: return EAGAIN; 63 | default : return error; 64 | } 65 | } 66 | 67 | // Serial port 68 | //@{ 69 | inline void SerialSocketClose(serial_socket_t socket) 70 | { 71 | if (socket != INVALID_HANDLE_VALUE) 72 | CloseHandle(socket); 73 | } 74 | 75 | inline ssize_t SerialSocketWrite(serial_socket_t socket, int *iError, void* data, size_t len) 76 | { 77 | if (len != (DWORD)len) 78 | { 79 | *iError = EINVAL; 80 | return -1; 81 | } 82 | 83 | DWORD iBytesWritten(0); 84 | if (socket != INVALID_HANDLE_VALUE) 85 | { 86 | if (!WriteFile(socket, data, (DWORD)len, &iBytesWritten, NULL)) 87 | { 88 | *iError = GetLastError(); 89 | return -1; 90 | } 91 | return (ssize_t)iBytesWritten; 92 | } 93 | 94 | return -1; 95 | } 96 | 97 | inline ssize_t SerialSocketRead(serial_socket_t socket, int *iError, void* data, size_t len, uint64_t iTimeoutMs /*= 0*/) 98 | { 99 | if (len != (DWORD)len) 100 | { 101 | *iError = EINVAL; 102 | return -1; 103 | } 104 | 105 | DWORD iBytesRead(0); 106 | if (socket != INVALID_HANDLE_VALUE) 107 | { 108 | if(!ReadFile(socket, data, (DWORD)len, &iBytesRead, NULL) != 0) 109 | { 110 | *iError = GetLastError(); 111 | return -1; 112 | } 113 | return (ssize_t)iBytesRead; 114 | } 115 | return -1; 116 | } 117 | //@} 118 | 119 | // TCP 120 | //@{ 121 | inline void TcpSocketSetBlocking(tcp_socket_t socket, bool bSetTo) 122 | { 123 | u_long iSetTo = bSetTo ? 0 : 1; 124 | ioctlsocket(socket, FIONBIO, &iSetTo); 125 | } 126 | 127 | inline void TcpSocketClose(tcp_socket_t socket) 128 | { 129 | closesocket(socket); 130 | } 131 | 132 | inline void TcpSocketShutdown(tcp_socket_t socket) 133 | { 134 | if (socket != INVALID_SOCKET && 135 | socket != SOCKET_ERROR) 136 | shutdown(socket, SHUT_RDWR); 137 | } 138 | 139 | inline ssize_t TcpSocketWrite(tcp_socket_t socket, int *iError, void* data, size_t len) 140 | { 141 | if (socket == INVALID_SOCKET || 142 | socket == SOCKET_ERROR || 143 | len != (int)len) 144 | { 145 | *iError = EINVAL; 146 | return -1; 147 | } 148 | 149 | ssize_t iReturn = send(socket, (char*)data, (int)len, 0); 150 | if (iReturn < (ssize_t)len) 151 | *iError = GetSocketError(); 152 | return iReturn; 153 | } 154 | 155 | inline ssize_t TcpSocketRead(tcp_socket_t socket, int *iError, void* data, size_t len, uint64_t iTimeoutMs /*= 0*/) 156 | { 157 | int64_t iNow(0), iTarget(0); 158 | ssize_t iBytesRead(0); 159 | *iError = 0; 160 | 161 | if (socket == INVALID_SOCKET || 162 | socket == SOCKET_ERROR || 163 | len != (int)len) 164 | { 165 | *iError = EINVAL; 166 | return -1; 167 | } 168 | 169 | if (iTimeoutMs > 0) 170 | { 171 | iNow = GetTimeMs(); 172 | iTarget = iNow + (int64_t) iTimeoutMs; 173 | } 174 | 175 | fd_set fd_read; 176 | struct timeval tv; 177 | while (iBytesRead >= 0 && iBytesRead < (ssize_t)len && (iTimeoutMs == 0 || iTarget > iNow) && *iError == 0) 178 | { 179 | if (iTimeoutMs > 0) 180 | { 181 | tv.tv_sec = (long)(iTimeoutMs / 1000); 182 | tv.tv_usec = 1000 * (long)(iTimeoutMs % 1000); 183 | 184 | FD_ZERO(&fd_read); 185 | FD_SET(socket, &fd_read); 186 | 187 | if (select((int)socket + 1, &fd_read, NULL, NULL, &tv) == 0) 188 | { 189 | *iError = ETIMEDOUT; 190 | } 191 | TcpSocketSetBlocking(socket, false); 192 | } 193 | 194 | ssize_t iReadResult = (iTimeoutMs > 0) ? 195 | recv(socket, (char*)data + iBytesRead, (int)(len - iBytesRead), 0) : 196 | recv(socket, (char*)data, (int)len, MSG_WAITALL); 197 | int iSocketError = GetSocketError(); 198 | 199 | if (iTimeoutMs > 0) 200 | { 201 | TcpSocketSetBlocking(socket, true); 202 | iNow = GetTimeMs(); 203 | } 204 | 205 | if (iReadResult < 0) 206 | { 207 | if (iSocketError == EAGAIN && iTimeoutMs > 0) 208 | continue; 209 | *iError = iSocketError; 210 | return (iBytesRead > 0) ? iBytesRead : -iSocketError; 211 | } 212 | else if (iReadResult == 0 || (iReadResult != (ssize_t)len && iTimeoutMs == 0)) 213 | { 214 | *iError = ECONNRESET; 215 | } 216 | 217 | iBytesRead += iReadResult; 218 | } 219 | 220 | if (iBytesRead < (ssize_t)len && *iError == 0) 221 | *iError = ETIMEDOUT; 222 | 223 | return iBytesRead; 224 | } 225 | 226 | inline bool TcpResolveAddress(const char *strHost, uint16_t iPort, int *iError, struct addrinfo **info) 227 | { 228 | struct addrinfo hints; 229 | char service[33]; 230 | memset(&hints, 0, sizeof(hints)); 231 | hints.ai_family = AF_UNSPEC; 232 | hints.ai_socktype = SOCK_STREAM; 233 | hints.ai_protocol = IPPROTO_TCP; 234 | sprintf(service, "%d", iPort); 235 | 236 | *iError = getaddrinfo(strHost, service, &hints, info); 237 | return !(*iError); 238 | } 239 | 240 | inline int TcpGetSocketError(tcp_socket_t socket) 241 | { 242 | int iReturn(0); 243 | socklen_t optLen = sizeof(tcp_socket_t); 244 | getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *)&iReturn, &optLen); 245 | return iReturn; 246 | } 247 | 248 | inline bool TcpSetNoDelay(tcp_socket_t socket) 249 | { 250 | int iSetTo(1); 251 | setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (const char*)&iSetTo, sizeof(iSetTo)); 252 | return true; 253 | } 254 | 255 | inline bool TcpConnectSocket(tcp_socket_t socket, struct addrinfo* addr, int *iError, uint64_t iTimeout = 0) 256 | { 257 | TcpSocketSetBlocking(socket, false); 258 | 259 | *iError = 0; 260 | int iConnectResult = connect(socket, addr->ai_addr, (int)addr->ai_addrlen); 261 | if (iConnectResult == -1) 262 | { 263 | if (GetSocketError() == EINPROGRESS || 264 | GetSocketError() == EAGAIN) 265 | { 266 | fd_set fd_write, fd_except; 267 | struct timeval tv; 268 | tv.tv_sec = (long)(iTimeout / 1000); 269 | tv.tv_usec = 1000 * (long)(iTimeout % 1000); 270 | 271 | FD_ZERO(&fd_write); 272 | FD_ZERO(&fd_except); 273 | FD_SET(socket, &fd_write); 274 | FD_SET(socket, &fd_except); 275 | 276 | int iPollResult = select(sizeof(socket)*8, NULL, &fd_write, &fd_except, &tv); 277 | if (iPollResult == 0) 278 | *iError = ETIMEDOUT; 279 | else if (iPollResult == -1) 280 | *iError = GetSocketError(); 281 | else 282 | { 283 | socklen_t errlen = sizeof(int); 284 | getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *)iError, &errlen); 285 | } 286 | } 287 | else 288 | { 289 | *iError = GetSocketError(); 290 | } 291 | } 292 | 293 | TcpSocketSetBlocking(socket, true); 294 | 295 | return *iError == 0; 296 | } 297 | } 298 | -------------------------------------------------------------------------------- /src/windows/os-threads.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the libCEC(R) library. 3 | * 4 | * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. 5 | * libCEC(R) is an original work, containing original code. 6 | * 7 | * libCEC(R) is a trademark of Pulse-Eight Limited. 8 | * 9 | * This program is dual-licensed; you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation; either version 2 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program; if not, write to the Free Software 21 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 | * 23 | * 24 | * Alternatively, you can license this library under a commercial license, 25 | * please contact Pulse-Eight Licensing for more information. 26 | * 27 | * For more information contact: 28 | * Pulse-Eight Licensing 29 | * http://www.pulse-eight.com/ 30 | * http://www.pulse-eight.net/ 31 | */ 32 | 33 | #include "../os.h" 34 | #include "os-threads.h" 35 | using namespace P8PLATFORM; 36 | 37 | static ConditionArg g_InitializeConditionVariable; 38 | static ConditionArg g_WakeConditionVariable; 39 | static ConditionArg g_WakeAllConditionVariable; 40 | static ConditionMutexArg g_SleepConditionVariableCS; 41 | 42 | // check whether vista+ conditions are available at runtime 43 | static bool CheckVistaConditionFunctions(void) 44 | { 45 | static int iHasVistaConditionFunctions(-1); 46 | if (iHasVistaConditionFunctions == -1) 47 | { 48 | HMODULE handle = GetModuleHandle("Kernel32"); 49 | if (handle == NULL) 50 | { 51 | iHasVistaConditionFunctions = 0; 52 | } 53 | else 54 | { 55 | g_InitializeConditionVariable = (ConditionArg) GetProcAddress(handle,"InitializeConditionVariable"); 56 | g_WakeConditionVariable = (ConditionArg) GetProcAddress(handle,"WakeConditionVariable"); 57 | g_WakeAllConditionVariable = (ConditionArg) GetProcAddress(handle,"WakeAllConditionVariable"); 58 | g_SleepConditionVariableCS = (ConditionMutexArg)GetProcAddress(handle,"SleepConditionVariableCS"); 59 | 60 | // 1 when everything is resolved, 0 otherwise 61 | iHasVistaConditionFunctions = g_InitializeConditionVariable && 62 | g_WakeConditionVariable && 63 | g_WakeAllConditionVariable && 64 | g_SleepConditionVariableCS ? 1 : 0; 65 | } 66 | } 67 | return iHasVistaConditionFunctions == 1; 68 | } 69 | 70 | CConditionImpl::CConditionImpl(void) 71 | { 72 | m_bOnVista = CheckVistaConditionFunctions(); 73 | if (m_bOnVista) 74 | (*g_InitializeConditionVariable)(m_conditionVista = new CONDITION_VARIABLE); 75 | else 76 | m_conditionPreVista = ::CreateEvent(NULL, TRUE, FALSE, NULL); 77 | } 78 | 79 | CConditionImpl::~CConditionImpl(void) 80 | { 81 | if (m_bOnVista) 82 | delete m_conditionVista; 83 | else 84 | ::CloseHandle(m_conditionPreVista); 85 | } 86 | 87 | void CConditionImpl::Signal(void) 88 | { 89 | if (m_bOnVista) 90 | (*g_WakeConditionVariable)(m_conditionVista); 91 | else 92 | ::SetEvent(m_conditionPreVista); 93 | } 94 | 95 | void CConditionImpl::Broadcast(void) 96 | { 97 | if (m_bOnVista) 98 | (*g_WakeAllConditionVariable)(m_conditionVista); 99 | else 100 | ::SetEvent(m_conditionPreVista); 101 | } 102 | 103 | bool CConditionImpl::Wait(mutex_t &mutex) 104 | { 105 | if (m_bOnVista) 106 | { 107 | return ((*g_SleepConditionVariableCS)(m_conditionVista, mutex, INFINITE) ? true : false); 108 | } 109 | else 110 | { 111 | ::ResetEvent(m_conditionPreVista); 112 | MutexUnlock(mutex); 113 | DWORD iWaitReturn = ::WaitForSingleObject(m_conditionPreVista, 1000); 114 | MutexLock(mutex); 115 | return (iWaitReturn == 0); 116 | } 117 | } 118 | 119 | bool CConditionImpl::Wait(mutex_t &mutex, uint32_t iTimeoutMs) 120 | { 121 | if (iTimeoutMs == 0) 122 | return Wait(mutex); 123 | 124 | if (m_bOnVista) 125 | { 126 | return ((*g_SleepConditionVariableCS)(m_conditionVista, mutex, iTimeoutMs) ? true : false); 127 | } 128 | else 129 | { 130 | ::ResetEvent(m_conditionPreVista); 131 | MutexUnlock(mutex); 132 | DWORD iWaitReturn = ::WaitForSingleObject(m_conditionPreVista, iTimeoutMs); 133 | MutexLock(mutex); 134 | return (iWaitReturn == 0); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/windows/os-threads.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | * This file is part of the libCEC(R) library. 4 | * 5 | * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. 6 | * libCEC(R) is an original work, containing original code. 7 | * 8 | * libCEC(R) is a trademark of Pulse-Eight Limited. 9 | * 10 | * This program is dual-licensed; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 | * 24 | * 25 | * Alternatively, you can license this library under a commercial license, 26 | * please contact Pulse-Eight Licensing for more information. 27 | * 28 | * For more information contact: 29 | * Pulse-Eight Licensing 30 | * http://www.pulse-eight.com/ 31 | * http://www.pulse-eight.net/ 32 | */ 33 | 34 | namespace P8PLATFORM 35 | { 36 | #define thread_t HANDLE 37 | #define ThreadsWait(thread, retVal) (::WaitForSingleObject(thread, INFINITE) < 0) 38 | #define ThreadsCreate(thread, func, arg) ((thread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)func, arg, 0, NULL)) == NULL ? false : true) 39 | 40 | typedef CRITICAL_SECTION* mutex_t; 41 | #define MutexCreate(mutex) ::InitializeCriticalSection(mutex = new CRITICAL_SECTION) 42 | #define MutexDelete(mutex) ::DeleteCriticalSection(mutex); delete mutex 43 | #define MutexLock(mutex) ::EnterCriticalSection(mutex) 44 | #define MutexTryLock(mutex) (::TryEnterCriticalSection(mutex) != 0) 45 | #define MutexUnlock(mutex) ::LeaveCriticalSection(mutex) 46 | 47 | // windows vista+ conditions 48 | typedef VOID (WINAPI *ConditionArg) (CONDITION_VARIABLE*); 49 | typedef BOOL (WINAPI *ConditionMutexArg)(CONDITION_VARIABLE*, CRITICAL_SECTION*, DWORD); 50 | 51 | class CConditionImpl 52 | { 53 | public: 54 | CConditionImpl(void); 55 | virtual ~CConditionImpl(void); 56 | void Signal(void); 57 | void Broadcast(void); 58 | bool Wait(mutex_t &mutex); 59 | bool Wait(mutex_t &mutex, uint32_t iTimeoutMs); 60 | 61 | bool m_bOnVista; 62 | CONDITION_VARIABLE *m_conditionVista; 63 | HANDLE m_conditionPreVista; 64 | }; 65 | } 66 | -------------------------------------------------------------------------------- /src/windows/os-types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | * This file is part of the libCEC(R) library. 4 | * 5 | * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. 6 | * libCEC(R) is an original work, containing original code. 7 | * 8 | * libCEC(R) is a trademark of Pulse-Eight Limited. 9 | * 10 | * This program is dual-licensed; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 | * 24 | * 25 | * Alternatively, you can license this library under a commercial license, 26 | * please contact Pulse-Eight Licensing for more information. 27 | * 28 | * For more information contact: 29 | * Pulse-Eight Licensing 30 | * http://www.pulse-eight.com/ 31 | * http://www.pulse-eight.net/ 32 | */ 33 | 34 | #if !defined(__WINDOWS__) 35 | #define __WINDOWS__ 36 | #endif 37 | 38 | #ifndef _WINSOCKAPI_ 39 | #define _WINSOCKAPI_ 40 | #endif 41 | 42 | #define WIN32_LEAN_AND_MEAN // Enable LEAN_AND_MEAN support 43 | #ifndef NOMINMAX 44 | #define NOMINMAX // don't define min() and max() to prevent a clash with std::min() and std::max 45 | #endif 46 | #include 47 | #include 48 | 49 | /* Platform dependent path separator */ 50 | #ifndef PATH_SEPARATOR_CHAR 51 | #define PATH_SEPARATOR_CHAR '\\' 52 | #define PATH_SEPARATOR_STRING "\\" 53 | #endif 54 | 55 | /* Handling of 2-byte Windows wchar strings */ 56 | #define WcsLen wcslen 57 | #define WcsToMbs wcstombs 58 | typedef wchar_t Wchar_t; /* sizeof(wchar_t) = 2 bytes on Windows */ 59 | 60 | #pragma warning(disable:4005) // Disable "warning C4005: '_WINSOCKAPI_' : macro redefinition" 61 | #include 62 | #pragma warning(default:4005) 63 | 64 | #include 65 | #include 66 | #include 67 | #include 68 | #include 69 | #include 70 | #include 71 | #include 72 | 73 | typedef SOCKET tcp_socket_t; 74 | #define INVALID_SOCKET_VALUE INVALID_SOCKET 75 | typedef HANDLE serial_socket_t; 76 | #define INVALID_SERIAL_SOCKET_VALUE INVALID_HANDLE_VALUE 77 | 78 | #ifndef _SSIZE_T_DEFINED 79 | #if defined(_WIN64) || defined(_M_ARM64) 80 | typedef __int64 ssize_t; 81 | #else 82 | typedef _W64 int ssize_t; 83 | #endif 84 | #define _SSIZE_T_DEFINED 85 | #endif 86 | 87 | /* Prevent deprecation warnings */ 88 | #ifndef snprintf 89 | #define snprintf _snprintf 90 | #endif 91 | #define strnicmp _strnicmp 92 | 93 | #if defined(_MSC_VER) 94 | #pragma warning (push) 95 | #endif 96 | 97 | #define NOGDI 98 | #if defined(_MSC_VER) /* prevent inclusion of wingdi.h */ 99 | #pragma warning (pop) 100 | #endif 101 | 102 | #pragma warning(disable:4189) /* disable 'defined but not used' */ 103 | #pragma warning(disable:4100) /* disable 'unreferenced formal parameter' */ 104 | -------------------------------------------------------------------------------- /src/windows/stdint.h: -------------------------------------------------------------------------------- 1 | // ISO C9x compliant stdint.h for Microsoft Visual Studio 2 | // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 3 | // 4 | // Copyright (c) 2006-2008 Alexander Chemeris 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // 1. Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // 2. Redistributions in binary form must reproduce the above copyright 13 | // notice, this list of conditions and the following disclaimer in the 14 | // documentation and/or other materials provided with the distribution. 15 | // 16 | // 3. The name of the author may be used to endorse or promote products 17 | // derived from this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 20 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 25 | // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 27 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 28 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | /////////////////////////////////////////////////////////////////////////////// 31 | 32 | #ifndef _MSC_VER // [ 33 | #error "Use this header only with Microsoft Visual C++ compilers!" 34 | #endif // _MSC_VER ] 35 | 36 | #ifndef _MSC_STDINT_H_ // [ 37 | #define _MSC_STDINT_H_ 38 | 39 | #if _MSC_VER > 1000 40 | #pragma once 41 | #endif 42 | 43 | #include 44 | 45 | // For Visual Studio 6 in C++ mode and for many Visual Studio versions when 46 | // compiling for ARM we should wrap include with 'extern "C++" {}' 47 | // or compiler give many errors like this: 48 | // error C2733: second C linkage of overloaded function 'wmemchr' not allowed 49 | #ifdef __cplusplus 50 | extern "C" { 51 | #endif 52 | # include 53 | #ifdef __cplusplus 54 | } 55 | #endif 56 | 57 | // Define _W64 macros to mark types changing their size, like intptr_t. 58 | #ifndef _W64 59 | # if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 60 | # define _W64 __w64 61 | # else 62 | # define _W64 63 | # endif 64 | #endif 65 | 66 | 67 | // 7.18.1 Integer types 68 | 69 | // 7.18.1.1 Exact-width integer types 70 | 71 | // Visual Studio 6 and Embedded Visual C++ 4 doesn't 72 | // realize that, e.g. char has the same size as __int8 73 | // so we give up on __intX for them. 74 | #if (_MSC_VER < 1300) 75 | typedef signed char int8_t; 76 | typedef signed short int16_t; 77 | typedef signed int int32_t; 78 | typedef unsigned char uint8_t; 79 | typedef unsigned short uint16_t; 80 | typedef unsigned int uint32_t; 81 | #else 82 | typedef signed __int8 int8_t; 83 | typedef signed __int16 int16_t; 84 | typedef signed __int32 int32_t; 85 | typedef unsigned __int8 uint8_t; 86 | typedef unsigned __int16 uint16_t; 87 | typedef unsigned __int32 uint32_t; 88 | #endif 89 | typedef signed __int64 int64_t; 90 | typedef unsigned __int64 uint64_t; 91 | 92 | 93 | // 7.18.1.2 Minimum-width integer types 94 | typedef int8_t int_least8_t; 95 | typedef int16_t int_least16_t; 96 | typedef int32_t int_least32_t; 97 | typedef int64_t int_least64_t; 98 | typedef uint8_t uint_least8_t; 99 | typedef uint16_t uint_least16_t; 100 | typedef uint32_t uint_least32_t; 101 | typedef uint64_t uint_least64_t; 102 | 103 | // 7.18.1.3 Fastest minimum-width integer types 104 | typedef int8_t int_fast8_t; 105 | typedef int16_t int_fast16_t; 106 | typedef int32_t int_fast32_t; 107 | typedef int64_t int_fast64_t; 108 | typedef uint8_t uint_fast8_t; 109 | typedef uint16_t uint_fast16_t; 110 | typedef uint32_t uint_fast32_t; 111 | typedef uint64_t uint_fast64_t; 112 | 113 | // 7.18.1.4 Integer types capable of holding object pointers 114 | #if defined(_WIN64) || defined(_M_ARM64) // [ 115 | typedef signed __int64 intptr_t; 116 | typedef unsigned __int64 uintptr_t; 117 | #else // _WIN64 || _M_ARM64 ][ 118 | typedef _W64 signed int intptr_t; 119 | typedef _W64 unsigned int uintptr_t; 120 | #endif // _WIN64 || _M_ARM64 ] 121 | 122 | // 7.18.1.5 Greatest-width integer types 123 | typedef int64_t intmax_t; 124 | typedef uint64_t uintmax_t; 125 | 126 | 127 | // 7.18.2 Limits of specified-width integer types 128 | 129 | #if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 130 | 131 | // 7.18.2.1 Limits of exact-width integer types 132 | #define INT8_MIN ((int8_t)_I8_MIN) 133 | #define INT8_MAX _I8_MAX 134 | #define INT16_MIN ((int16_t)_I16_MIN) 135 | #define INT16_MAX _I16_MAX 136 | #define INT32_MIN ((int32_t)_I32_MIN) 137 | #define INT32_MAX _I32_MAX 138 | #define INT64_MIN ((int64_t)_I64_MIN) 139 | #define INT64_MAX _I64_MAX 140 | #define UINT8_MAX _UI8_MAX 141 | #define UINT16_MAX _UI16_MAX 142 | #define UINT32_MAX _UI32_MAX 143 | #define UINT64_MAX _UI64_MAX 144 | 145 | // 7.18.2.2 Limits of minimum-width integer types 146 | #define INT_LEAST8_MIN INT8_MIN 147 | #define INT_LEAST8_MAX INT8_MAX 148 | #define INT_LEAST16_MIN INT16_MIN 149 | #define INT_LEAST16_MAX INT16_MAX 150 | #define INT_LEAST32_MIN INT32_MIN 151 | #define INT_LEAST32_MAX INT32_MAX 152 | #define INT_LEAST64_MIN INT64_MIN 153 | #define INT_LEAST64_MAX INT64_MAX 154 | #define UINT_LEAST8_MAX UINT8_MAX 155 | #define UINT_LEAST16_MAX UINT16_MAX 156 | #define UINT_LEAST32_MAX UINT32_MAX 157 | #define UINT_LEAST64_MAX UINT64_MAX 158 | 159 | // 7.18.2.3 Limits of fastest minimum-width integer types 160 | #define INT_FAST8_MIN INT8_MIN 161 | #define INT_FAST8_MAX INT8_MAX 162 | #define INT_FAST16_MIN INT16_MIN 163 | #define INT_FAST16_MAX INT16_MAX 164 | #define INT_FAST32_MIN INT32_MIN 165 | #define INT_FAST32_MAX INT32_MAX 166 | #define INT_FAST64_MIN INT64_MIN 167 | #define INT_FAST64_MAX INT64_MAX 168 | #define UINT_FAST8_MAX UINT8_MAX 169 | #define UINT_FAST16_MAX UINT16_MAX 170 | #define UINT_FAST32_MAX UINT32_MAX 171 | #define UINT_FAST64_MAX UINT64_MAX 172 | 173 | // 7.18.2.4 Limits of integer types capable of holding object pointers 174 | #if defined(_WIN64) || defined(_M_ARM64)// [ 175 | # define INTPTR_MIN INT64_MIN 176 | # define INTPTR_MAX INT64_MAX 177 | # define UINTPTR_MAX UINT64_MAX 178 | #else // _WIN64 || _M_ARM64 ][ 179 | # define INTPTR_MIN INT32_MIN 180 | # define INTPTR_MAX INT32_MAX 181 | # define UINTPTR_MAX UINT32_MAX 182 | #endif // _WIN64 || _M_ARM64 ] 183 | 184 | // 7.18.2.5 Limits of greatest-width integer types 185 | #define INTMAX_MIN INT64_MIN 186 | #define INTMAX_MAX INT64_MAX 187 | #define UINTMAX_MAX UINT64_MAX 188 | 189 | // 7.18.3 Limits of other integer types 190 | 191 | #if defined(_WIN64) || defined(_M_ARM64)// [ 192 | # define PTRDIFF_MIN _I64_MIN 193 | # define PTRDIFF_MAX _I64_MAX 194 | #else // _WIN64 || _M_ARM64 ][ 195 | # define PTRDIFF_MIN _I32_MIN 196 | # define PTRDIFF_MAX _I32_MAX 197 | #endif // _WIN64 || _M_ARM64 ] 198 | 199 | #define SIG_ATOMIC_MIN INT_MIN 200 | #define SIG_ATOMIC_MAX INT_MAX 201 | 202 | #ifndef SIZE_MAX // [ 203 | # if defined(_WIN64) || defined(_M_ARM64)// [ 204 | # define SIZE_MAX _UI64_MAX 205 | # else // _WIN64 || _M_ARM64 ][ 206 | # define SIZE_MAX _UI32_MAX 207 | # endif // _WIN64 || _M_ARM64 ] 208 | #endif // SIZE_MAX ] 209 | 210 | // WCHAR_MIN and WCHAR_MAX are also defined in 211 | #ifndef WCHAR_MIN // [ 212 | # define WCHAR_MIN 0 213 | #endif // WCHAR_MIN ] 214 | #ifndef WCHAR_MAX // [ 215 | # define WCHAR_MAX _UI16_MAX 216 | #endif // WCHAR_MAX ] 217 | 218 | #define WINT_MIN 0 219 | #define WINT_MAX _UI16_MAX 220 | 221 | #endif // __STDC_LIMIT_MACROS ] 222 | 223 | 224 | // 7.18.4 Limits of other integer types 225 | 226 | #if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 227 | 228 | // 7.18.4.1 Macros for minimum-width integer constants 229 | 230 | #define INT8_C(val) val##i8 231 | #define INT16_C(val) val##i16 232 | #define INT32_C(val) val##i32 233 | #define INT64_C(val) val##i64 234 | 235 | #define UINT8_C(val) val##ui8 236 | #define UINT16_C(val) val##ui16 237 | #define UINT32_C(val) val##ui32 238 | #define UINT64_C(val) val##ui64 239 | 240 | // 7.18.4.2 Macros for greatest-width integer constants 241 | #define INTMAX_C INT64_C 242 | #define UINTMAX_C UINT64_C 243 | 244 | #endif // __STDC_CONSTANT_MACROS ] 245 | 246 | 247 | #endif // _MSC_STDINT_H_ ] 248 | -------------------------------------------------------------------------------- /windows/build-lib.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | rem Build the p8 platform library for Windows 4 | 5 | SETLOCAL 6 | 7 | SET MYDIR=%~dp0 8 | SET BUILDARCH=%1 9 | SET BUILDTYPE=%2 10 | SET VSVERSION=%3 11 | SET INSTALLPATH=%4 12 | IF [%4] == [] GOTO missingparams 13 | 14 | SET INSTALLPATH=%INSTALLPATH:"=% 15 | SET BUILDTARGET=%INSTALLPATH%\cmake\%BUILDARCH% 16 | SET TARGET=%INSTALLPATH%\%BUILDARCH% 17 | 18 | rem Check support submodule 19 | IF NOT EXIST "%MYDIR%..\support\windows\cmake\build.cmd" ( 20 | rem Try to init the git submodules 21 | cd "%MYDIR%.." 22 | git submodule update --init -r >nul 2>&1 23 | 24 | IF NOT EXIST "%MYDIR%..\support\windows\cmake\build.cmd" ( 25 | ECHO.*** support git submodule has not been checked out *** 26 | ECHO. 27 | ECHO.See docs\README.windows.md 28 | EXIT /b 2 29 | ) 30 | ) 31 | 32 | CALL "%MYDIR%..\support\windows\cmake\generate.cmd" %BUILDARCH% nmake "%MYDIR%..\" "%BUILDTARGET%" "%TARGET%" %BUILDTYPE% %VSVERSION% static 33 | CALL "%MYDIR%..\support\windows\cmake\build.cmd" %BUILDARCH% "%BUILDTARGET%" %VSVERSION% 34 | GOTO exit 35 | 36 | :missingparams 37 | ECHO.%~dp0 requires 4 parameters 38 | ECHO. %~dp0 [architecture] [type] [version] [install path] 39 | ECHO. 40 | ECHO. architecture: amd64 x86 arm64 41 | ECHO. type: Release Debug 42 | ECHO. version: Visual Studio version (2019) 43 | ECHO. install path: installation path without quotes 44 | exit /b 99 45 | 46 | :exit 47 | -------------------------------------------------------------------------------- /windows/build.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | rem Build the p8 platform library for Windows 4 | 5 | SETLOCAL 6 | 7 | SET MYDIR=%~dp0 8 | SET BUILDTYPE=Release 9 | SET VSVERSION=2022 10 | SET INSTALLPATH=%MYDIR%..\build 11 | 12 | IF EXIST "%MYDIR%..\build" ( 13 | RMDIR /s /q "%MYDIR%..\build" 14 | ) 15 | 16 | FOR %%T IN (amd64 x86 arm64) DO ( 17 | CALL "%MYDIR%\build-lib.cmd" %%T %BUILDTYPE% %VSVERSION% "%INSTALLPATH%" 18 | ) 19 | 20 | RMDIR /s /q "%MYDIR%..\build\cmake" 21 | --------------------------------------------------------------------------------