├── .gitattributes ├── .gitignore ├── .travis.yml ├── .vscode └── .cmaketools.json ├── CMakeLists.txt ├── LICENSE ├── README.md ├── android.sh ├── android ├── .gitignore ├── ant.properties ├── app │ ├── .gitignore │ ├── CMakeLists.txt │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── cpp │ │ └── jnitest.cpp │ │ ├── java │ │ └── ca │ │ │ └── graemehill │ │ │ └── crossguid │ │ │ └── testapp │ │ │ └── MainActivity.java │ │ └── res │ │ ├── layout │ │ └── main.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml ├── build.gradle ├── build.xml ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── proguard-project.txt ├── project.properties └── settings.gradle ├── cmake └── FindLibuuid.cmake ├── crossguid.pc.in ├── include └── crossguid │ └── guid.hpp ├── src └── guid.cpp └── test ├── Test.cpp ├── Test.hpp └── TestMain.cpp /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *.tmp 3 | *.bak 4 | *.swp 5 | android/libs/ 6 | android/obj/ 7 | cmake_build 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | language: cpp 3 | dist: trusty 4 | 5 | matrix: 6 | include: 7 | 8 | - os: linux 9 | addons: 10 | apt: 11 | sources: 12 | - ubuntu-toolchain-r-test 13 | packages: 14 | - g++-8 15 | env: 16 | - MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" 17 | 18 | - os: osx 19 | osx_image: xcode9.2 20 | compiler: clang 21 | 22 | before_install: 23 | # Make sure we set correct env for platform 24 | - eval "$(MATRIX_EVAL)" 25 | 26 | # Workaround for Travis CI macOS bug (https://github.com/travis-ci/travis-ci/issues/6307) 27 | # See https://github.com/searchivarius/nmslib/pull/259 28 | - | 29 | if [ "${TRAVIS_OS_NAME}" == "osx" ]; then 30 | command curl -sSL https://rvm.io/mpapis.asc | gpg --import -; 31 | rvm get head || true 32 | fi 33 | 34 | script: 35 | - export CHECKOUT_PATH=`pwd`; 36 | - echo "ROOT_PATH= $ROOT_PATH" 37 | - echo "CHECKOUT_PATH= $CHECKOUT_PATH" 38 | 39 | ####################################################################################### 40 | # Install a recent CMake (unless already installed on OS X) 41 | ####################################################################################### 42 | - | 43 | if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then 44 | CMAKE_URL="http://www.cmake.org/files/v3.10/cmake-3.10.2-Linux-x86_64.tar.gz" 45 | mkdir cmake && travis_retry wget --no-check-certificate --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake 46 | export PATH=${DEPS_DIR}/cmake/bin:${PATH} 47 | else 48 | brew upgrade cmake || echo "suppress failures in order to ignore warnings" 49 | brew link --overwrite cmake 50 | fi 51 | - cmake --version 52 | 53 | - | 54 | if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then 55 | sudo apt-get install uuid-dev 56 | fi 57 | ####################################################################################### 58 | # Build the library 59 | ####################################################################################### 60 | - | 61 | cd "${CHECKOUT_PATH}" 62 | mkdir build 63 | cd build 64 | cmake .. -DCMAKE_BUILD_TYPE="Debug" 65 | sudo make install 66 | ####################################################################################### 67 | # Run the tests 68 | ####################################################################################### 69 | - ./crossguid-test 70 | -------------------------------------------------------------------------------- /.vscode/.cmaketools.json: -------------------------------------------------------------------------------- 1 | { 2 | "variant": null, 3 | "activeEnvironments": [], 4 | "codeModel": null 5 | } -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5.1) 2 | project(CrossGuid VERSION 0.2.3) 3 | 4 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake") 5 | 6 | option(CROSSGUID_TESTS "Build test runner" ON) 7 | 8 | set(CMAKE_CXX_STANDARD 17) 9 | set(CMAKE_CXX_EXTENSIONS OFF) 10 | set(CMAKE_DEBUG_POSTFIX "-dgb") 11 | 12 | # Set the build type if not set 13 | if(NOT CMAKE_BUILD_TYPE) 14 | set(CMAKE_BUILD_TYPE "Release") 15 | endif() 16 | 17 | add_library(crossguid ${CMAKE_CURRENT_SOURCE_DIR}/src/guid.cpp) 18 | set_property(TARGET crossguid PROPERTY POSITION_INDEPENDENT_CODE ON) 19 | target_include_directories(crossguid PUBLIC 20 | $ 21 | $) 22 | 23 | if(WIN32) 24 | target_compile_definitions(crossguid PRIVATE GUID_WINDOWS) 25 | elseif(APPLE) 26 | find_library(CFLIB CoreFoundation) 27 | target_link_libraries(crossguid ${CFLIB}) 28 | target_compile_definitions(crossguid PRIVATE GUID_CFUUID) 29 | elseif(ANDROID) 30 | # GUID_ANDROID is used in the headers, so make PUBLIC 31 | target_compile_definitions(crossguid PUBLIC GUID_ANDROID) 32 | else() 33 | find_package(Libuuid REQUIRED) 34 | if (NOT LIBUUID_FOUND) 35 | message(FATAL_ERROR 36 | "You might need to run 'sudo apt-get install uuid-dev' or similar") 37 | endif() 38 | target_include_directories(crossguid PRIVATE ${LIBUUID_INCLUDE_DIR}) 39 | target_link_libraries(crossguid ${LIBUUID_LIBRARY}) 40 | target_compile_definitions(crossguid PRIVATE GUID_LIBUUID) 41 | endif() 42 | 43 | if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 44 | set(WARNINGS "-Werror" "-Wall") 45 | elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") 46 | set(WARNINGS "-Werror" "-Wall") 47 | elseif(MSVC) 48 | set(WARNINGS "/WX" "/W4") 49 | endif() 50 | target_compile_options(crossguid PRIVATE ${WARNINGS}) 51 | 52 | set_target_properties(crossguid 53 | PROPERTIES 54 | VERSION ${PROJECT_VERSION} 55 | SOVERSION ${PROJECT_VERSION_MAJOR} 56 | DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) 57 | 58 | if (${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) 59 | include(GNUInstallDirs) 60 | 61 | set(CROSSGUID_INC_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}") 62 | set(CROSSGUID_RUNTIME_INSTALL_DIR "${CMAKE_INSTALL_BINDIR}") 63 | set(CROSSGUID_LIBRARY_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}") 64 | set(CROSSGUID_ARCHIVE_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}") 65 | set(CROSSGUID_FRAMEWORK_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}") 66 | 67 | set(CROSSGUID_CMAKE_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/crossguid/cmake") 68 | set(CROSSGUID_ADDITIONAL_FILES_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/crossguid") 69 | 70 | # Install target 71 | install(TARGETS crossguid EXPORT crossguidTargets 72 | RUNTIME DESTINATION ${CROSSGUID_RUNTIME_INSTALL_DIR} 73 | LIBRARY DESTINATION ${CROSSGUID_LIBRARY_INSTALL_DIR} 74 | ARCHIVE DESTINATION ${CROSSGUID_ARCHIVE_INSTALL_DIR} 75 | FRAMEWORK DESTINATION ${CROSSGUID_FRAMEWORK_INSTALL_DIR}) 76 | 77 | # Install headers 78 | install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" 79 | DESTINATION ${CROSSGUID_INC_INSTALL_DIR}) 80 | 81 | # Make cmake config files for all targets 82 | install(EXPORT crossguidTargets 83 | DESTINATION ${CROSSGUID_CMAKE_CONFIG_INSTALL_DIR} 84 | FILE crossguid-config.cmake) 85 | 86 | # Install readme and license 87 | install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE" "${CMAKE_CURRENT_SOURCE_DIR}/README.md" 88 | DESTINATION ${CROSSGUID_ADDITIONAL_FILES_INSTALL_DIR}) 89 | 90 | configure_file(crossguid.pc.in ${PROJECT_BINARY_DIR}/crossguid.pc @ONLY) 91 | install(FILES ${PROJECT_BINARY_DIR}/crossguid.pc DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig) 92 | endif() 93 | 94 | if (CROSSGUID_TESTS) 95 | add_executable(crossguid-test test/TestMain.cpp test/Test.cpp) 96 | target_link_libraries(crossguid-test crossguid) 97 | endif() 98 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Graeme Hill (http://graemehill.ca) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CrossGuid [![Build Status](https://travis-ci.org/graeme-hill/crossguid.svg?branch=master)](https://travis-ci.org/graeme-hill/crossguid) 2 | 3 | CrossGuid is a minimal, cross platform, C++ GUID library. It uses the best 4 | native GUID/UUID generator on the given platform and has a generic class for 5 | parsing, stringifying, and comparing IDs. The guid generation technique is 6 | determined by your platform: 7 | 8 | ## Linux 9 | 10 | On linux you can use `libuuid` which is pretty standard. On distros like Ubuntu 11 | it is available by default but to use it you need the header files so you have 12 | to do: 13 | 14 | sudo apt-get install uuid-dev 15 | 16 | ## Mac/iOS 17 | 18 | On Mac or iOS you can use `CFUUIDCreate` from `CoreFoundation`. Since it's a 19 | plain C function you don't even need to compile as Objective-C++. 20 | 21 | ## Windows 22 | 23 | On Windows we just use the the built-in function `CoCreateGuid`. CMake can 24 | generate a Visual Studio project if that's your thing. 25 | 26 | ## Android 27 | 28 | The Android version uses a handle to a `JNIEnv` object to invoke the 29 | `randomUUID()` function on `java.util.UUID` from C++. The Android specific code 30 | is all in the `android/` subdirectory. If you have an emulator already running, 31 | then you can run the `android.sh` script in the root directory. It has the 32 | following requirements: 33 | 34 | - Android emulator is already running (or you have physical device connected). 35 | - You're using bash. 36 | - adb is in your path. 37 | - You have an Android sdk setup including `ANDROID_HOME` environment variable. 38 | 39 | ## Versions 40 | 41 | This is version 0.2 of CrossGuid. If you all already using CrossGuid and your code 42 | uses `GuidGenerator` then you are using version 0.1. Differences in version 0.2: 43 | 44 | - Put everything inside the namespace `xg` instead of using the global 45 | namespace. 46 | - Removed `GuidGenerator` class and replaced with the free function 47 | `xg::newGuid`. This is the way I originally wanted it to work but since Android 48 | is a special snowflake requiring state (`JNIEnv *`) I introduced the 49 | `GuidGenerator` class specifically so that there would be somewhere to store 50 | the `JNIEnv *` when running on Android. However, this basically meant 51 | complicating the library for the sake of one platform. In version 0.2 the goal is 52 | to design for the normal platforms and let Android be weird. In Android you just 53 | need to run `xg::initJni(JNIEnv *)` before you create any guids. The `JNIEnv *` 54 | is just stored as a global variable. 55 | - Added CMake build system. Instead of different scripts for each platform you 56 | can just run cmake and it should handle each platform (except Android which 57 | again is special). 58 | - Actual guid bytes are stored in `std::array` instead of 59 | `std::vector`. 60 | - More error checking (like if you try to create a guid with invalid number of 61 | bytes). 62 | 63 | If you're happily using version 0.1 then there's not really any reason to 64 | change. 65 | 66 | ## Compiling 67 | 68 | Just do the normal cmake thing: 69 | 70 | ``` 71 | mkdir build 72 | cd build 73 | cmake .. 74 | make install 75 | ``` 76 | 77 | ## Running tests 78 | 79 | After compiling as described above you should get two files: `libcrossguid.a` (the 80 | static library) and `crossguid-test` (the test runner). So to run the tests just do: 81 | 82 | ``` 83 | ./crossguid-test 84 | ``` 85 | 86 | ## Basic usage 87 | 88 | ### Creating guids 89 | 90 | Create a new random guid: 91 | 92 | ```cpp 93 | #include 94 | ... 95 | auto g = xg::newGuid(); 96 | ``` 97 | 98 | **NOTE:** On Android you need to call `xg::initJni(JNIEnv *)` first so that it 99 | is possible for `xg::newGuid()` to call back into java libraries. `initJni` 100 | only needs to be called once when the process starts. 101 | 102 | Create a new zero guid: 103 | 104 | ```cpp 105 | xg::Guid g; 106 | ``` 107 | 108 | Create from a string: 109 | 110 | ```cpp 111 | xg::Guid g("c405c66c-ccbb-4ffd-9b62-c286c0fd7a3b"); 112 | ``` 113 | 114 | ### Checking validity 115 | 116 | If you have some string value and you need to check whether it is a valid guid 117 | then you can simply attempt to construct the guid: 118 | 119 | ```cpp 120 | xg::Guid g("bad-guid-string"); 121 | if (!g.isValid()) 122 | { 123 | // do stuff 124 | } 125 | ``` 126 | 127 | If the guid string is not valid then all bytes are set to zero and `isValid()` 128 | returns `false`. 129 | 130 | ### Converting guid to string 131 | 132 | First of all, there is normally no reason to convert a guid to a string except 133 | for in debugging or when serializing for API calls or whatever. You should 134 | definitely avoid storing guids as strings or using strings for any 135 | computations. If you do need to convert a guid to a string, then you can 136 | utilize strings because the `<<` operator is overloaded. To print a guid to 137 | `std::cout`: 138 | 139 | ```cpp 140 | void doGuidStuff() 141 | { 142 | auto myGuid = xg::newGuid(); 143 | std::cout << "Here is a guid: " << myGuid << std::endl; 144 | } 145 | ``` 146 | 147 | Or to store a guid in a `std::string`: 148 | 149 | ```cpp 150 | void doGuidStuff() 151 | { 152 | auto myGuid = xg::newGuid(); 153 | std::stringstream stream; 154 | stream << myGuid; 155 | auto guidString = stream.str(); 156 | } 157 | ``` 158 | 159 | There is also a `str()` function that returns a `std::string`: 160 | 161 | ```cpp 162 | std::string guidStr = xg::newGuid().str(); 163 | ``` 164 | 165 | ### Creating a guid from raw bytes 166 | 167 | It's unlikely that you will need this, but this is done within the library 168 | internally to construct a `Guid` object from the raw data given by the system's 169 | built-in guid generation function. There are two key constructors for this: 170 | 171 | ```cpp 172 | Guid(std::array &bytes); 173 | ``` 174 | 175 | and 176 | 177 | ```cpp 178 | Guid(const unsigned char * bytes); 179 | ``` 180 | 181 | When possible prefer the `std::array` constructor because it is safer. If you 182 | pass in an incorrectly sized C array then bad things will happen. 183 | 184 | ### Comparing guids 185 | 186 | `==` and `!=` are implemented, so the following works as expected: 187 | 188 | ```cpp 189 | void doGuidStuff() 190 | { 191 | auto guid1 = xg::newGuid(); 192 | auto guid2 = xg::newGuid(); 193 | 194 | auto guidsAreEqual = guid1 == guid2; 195 | auto guidsAreNotEqual = guid1 != guid2; 196 | } 197 | ``` 198 | 199 | ### Hashing guids 200 | 201 | Guids can be used directly in containers requireing `std::hash` such as `std::map,`std::unordered_map` etc. 202 | 203 | ## License 204 | 205 | The MIT License (MIT) 206 | 207 | Copyright (c) 2014 Graeme Hill (http://graemehill.ca) 208 | 209 | Permission is hereby granted, free of charge, to any person obtaining a copy 210 | of this software and associated documentation files (the "Software"), to deal 211 | in the Software without restriction, including without limitation the rights 212 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 213 | copies of the Software, and to permit persons to whom the Software is 214 | furnished to do so, subject to the following conditions: 215 | 216 | The above copyright notice and this permission notice shall be included in 217 | all copies or substantial portions of the Software. 218 | 219 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 220 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 221 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 222 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 223 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 224 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 225 | THE SOFTWARE. 226 | -------------------------------------------------------------------------------- /android.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export LC_NUMERIC="en_US.UTF-8" 4 | 5 | pushd android 6 | ./gradlew clean assembleDebug 7 | adb uninstall ca.graemehill.crossguid.testapp || { exit 1; } 8 | adb install app/build/outputs/apk/debug/app-debug.apk || { exit 1; } 9 | adb shell am start -n ca.graemehill.crossguid.testapp/ca.graemehill.crossguid.testapp.MainActivity 10 | popd 11 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | .idea 11 | -------------------------------------------------------------------------------- /android/ant.properties: -------------------------------------------------------------------------------- 1 | # This file is used to override default values used by the Ant build system. 2 | # 3 | # This file must be checked into Version Control Systems, as it is 4 | # integral to the build system of your project. 5 | 6 | # This file is only used by the Ant script. 7 | 8 | # You can use this to override default values such as 9 | # 'source.dir' for the location of your java source folder and 10 | # 'out.dir' for the location of your output folder. 11 | 12 | # You can also use it define how the release builds are signed by declaring 13 | # the following properties: 14 | # 'key.store' for the location of your keystore and 15 | # 'key.alias' for the name of the key to use. 16 | # The password will be asked during the build when you use the 'release' target. 17 | 18 | -------------------------------------------------------------------------------- /android/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /android/app/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4.1) 2 | 3 | set(LIB_NAME crossguidtest) 4 | set(XG_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) 5 | set(XG_TEST_DIR ${XG_DIR}/test) 6 | 7 | add_library(${LIB_NAME} SHARED src/main/cpp/jnitest.cpp ${XG_TEST_DIR}/Test.cpp) 8 | 9 | target_include_directories(${LIB_NAME} PRIVATE 10 | ${XG_DIR} 11 | ${XG_TEST_DIR}) 12 | 13 | target_compile_definitions(${LIB_NAME} PRIVATE GUID_ANDROID) 14 | 15 | set(XG_TESTS OFF CACHE BOOL "disable tests") 16 | add_subdirectory(${XG_DIR} ${XG_DIR}/cmake_build) 17 | 18 | target_link_libraries(${LIB_NAME} xg) -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "26.0.0" 6 | defaultConfig { 7 | applicationId "ca.graemehill.crossguid.testapp" 8 | minSdkVersion 14 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.0" 12 | externalNativeBuild { 13 | cmake { 14 | cppFlags "-std=c++11 -frtti -fexceptions" 15 | arguments "-DANDROID_TOOLCHAIN=clang" 16 | } 17 | } 18 | } 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | externalNativeBuild { 26 | cmake { 27 | path "CMakeLists.txt" 28 | } 29 | } 30 | } 31 | 32 | dependencies { 33 | implementation fileTree(dir: 'libs', include: ['*.jar']) 34 | androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.0', { 35 | exclude group: 'com.android.support', module: 'support-annotations' 36 | }) 37 | implementation 'com.android.support:appcompat-v7:25.4.0' 38 | testImplementation 'junit:junit:4.12' 39 | } 40 | -------------------------------------------------------------------------------- /android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.4.1_1/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /android/app/src/main/cpp/jnitest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 7 | 8 | #include "Test.hpp" 9 | 10 | JavaVM *&javaVM() { 11 | static JavaVM *jvm; 12 | return jvm; 13 | } 14 | 15 | extern "C" 16 | { 17 | 18 | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void * /* reserved */) { 19 | javaVM() = jvm; 20 | return JNI_VERSION_1_6; 21 | } 22 | 23 | JNIEXPORT jstring JNICALL 24 | Java_ca_graemehill_crossguid_testapp_MainActivity_test( 25 | JNIEnv *env, jobject /*thiz*/) 26 | { 27 | std::stringstream resultStream; 28 | xg::initJni(env); 29 | test(resultStream); 30 | return env->NewStringUTF(resultStream.str().c_str()); 31 | } 32 | 33 | JNIEXPORT jstring JNICALL 34 | Java_ca_graemehill_crossguid_testapp_MainActivity_newGuid( 35 | JNIEnv *env, jobject /*thiz*/) { 36 | return env->NewStringUTF(xg::newGuid(env).str().c_str()); 37 | } 38 | 39 | JNIEXPORT jstring JNICALL 40 | Java_ca_graemehill_crossguid_testapp_MainActivity_createGuidFromNativeThread( 41 | JNIEnv *env, jobject /*thiz*/) { 42 | 43 | // there is no promise<> in armeabi of ndk 44 | // so ugly atomic_bool wait solution 45 | std::atomic_bool ready { false }; 46 | std::string guid; 47 | 48 | std::thread([&ready, &guid](){ 49 | JNIEnv *threadEnv; 50 | javaVM()->AttachCurrentThread(&threadEnv, NULL); 51 | guid = xg::newGuid(threadEnv); 52 | javaVM()->DetachCurrentThread(); 53 | 54 | ready = true; 55 | }).detach(); 56 | 57 | while (!ready); 58 | return env->NewStringUTF(guid.c_str()); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /android/app/src/main/java/ca/graemehill/crossguid/testapp/MainActivity.java: -------------------------------------------------------------------------------- 1 | package ca.graemehill.crossguid.testapp; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.widget.TextView; 6 | 7 | import java.util.concurrent.CountDownLatch; 8 | 9 | public class MainActivity extends Activity { 10 | 11 | @Override 12 | public void onCreate(Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | setContentView(R.layout.main); 15 | 16 | final TextView textView = (TextView)findViewById(R.id.mainTextView); 17 | textView.setText(test()); 18 | 19 | final TextView javaThreadView = (TextView)findViewById(R.id.javaThreadView); 20 | javaThreadView.setText(createGuidFromJavaThread()); 21 | 22 | final TextView nativeThreadView = (TextView)findViewById(R.id.nativeThreadView); 23 | nativeThreadView.setText(createGuidFromNativeThread()); 24 | } 25 | 26 | public native String test(); 27 | 28 | private static class StringCapture { 29 | private String value; 30 | 31 | public String getValue() { 32 | return value; 33 | } 34 | 35 | public void setValue(String value) { 36 | this.value = value; 37 | } 38 | } 39 | 40 | public String createGuidFromJavaThread() { 41 | final CountDownLatch created = new CountDownLatch(1); 42 | final StringCapture result = new StringCapture(); 43 | new Thread(new Runnable() { 44 | @Override 45 | public void run() { 46 | result.setValue(newGuid()); 47 | created.countDown(); 48 | } 49 | }).start(); 50 | try { 51 | created.await(); 52 | } catch (InterruptedException e) { 53 | return "Could not get value: " + e.getMessage(); 54 | } 55 | return result.getValue(); 56 | } 57 | 58 | public native String newGuid(); 59 | 60 | public native String createGuidFromNativeThread(); 61 | static { 62 | System.loadLibrary("crossguidtest"); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /android/app/src/main/res/layout/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 16 | 21 | 25 | 30 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graeme-hill/crossguid/ca1bf4b810e2d188d04cb6286f957008ee1b7681/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graeme-hill/crossguid/ca1bf4b810e2d188d04cb6286f957008ee1b7681/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graeme-hill/crossguid/ca1bf4b810e2d188d04cb6286f957008ee1b7681/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graeme-hill/crossguid/ca1bf4b810e2d188d04cb6286f957008ee1b7681/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graeme-hill/crossguid/ca1bf4b810e2d188d04cb6286f957008ee1b7681/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graeme-hill/crossguid/ca1bf4b810e2d188d04cb6286f957008ee1b7681/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graeme-hill/crossguid/ca1bf4b810e2d188d04cb6286f957008ee1b7681/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graeme-hill/crossguid/ca1bf4b810e2d188d04cb6286f957008ee1b7681/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graeme-hill/crossguid/ca1bf4b810e2d188d04cb6286f957008ee1b7681/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graeme-hill/crossguid/ca1bf4b810e2d188d04cb6286f957008ee1b7681/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | TestApp 3 | GUID created from Native Thread 4 | GUID created from Java Thread 5 | Test results 6 | 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | maven { url 'https://maven.google.com' } 7 | jcenter() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.0.0-alpha3' 11 | 12 | // NOTE: Do not place your application dependencies here; they belong 13 | // in the individual module build.gradle files 14 | } 15 | } 16 | 17 | allprojects { 18 | repositories { 19 | maven { url 'https://maven.google.com' } 20 | jcenter() 21 | } 22 | } 23 | 24 | task clean(type: Delete) { 25 | delete rootProject.buildDir 26 | } 27 | -------------------------------------------------------------------------------- /android/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 | 49 | 50 | 51 | 52 | 56 | 57 | 69 | 70 | 71 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | android.enableAapt2=false 19 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graeme-hill/crossguid/ca1bf4b810e2d188d04cb6286f957008ee1b7681/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Aug 03 09:39:40 MSK 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-milestone-1-all.zip 7 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | LC_NUMERIC="en_US.UTF-8" 12 | 13 | APP_NAME="Gradle" 14 | APP_BASE_NAME=`basename "$0"` 15 | 16 | # Use the maximum available, or set MAX_FD != -1 to use that value. 17 | MAX_FD="maximum" 18 | 19 | warn ( ) { 20 | echo "$*" 21 | } 22 | 23 | die ( ) { 24 | echo 25 | echo "$*" 26 | echo 27 | exit 1 28 | } 29 | 30 | # OS specific support (must be 'true' or 'false'). 31 | cygwin=false 32 | msys=false 33 | darwin=false 34 | case "`uname`" in 35 | CYGWIN* ) 36 | cygwin=true 37 | ;; 38 | Darwin* ) 39 | darwin=true 40 | ;; 41 | MINGW* ) 42 | msys=true 43 | ;; 44 | esac 45 | 46 | # Attempt to set APP_HOME 47 | # Resolve links: $0 may be a link 48 | PRG="$0" 49 | # Need this for relative symlinks. 50 | while [ -h "$PRG" ] ; do 51 | ls=`ls -ld "$PRG"` 52 | link=`expr "$ls" : '.*-> \(.*\)$'` 53 | if expr "$link" : '/.*' > /dev/null; then 54 | PRG="$link" 55 | else 56 | PRG=`dirname "$PRG"`"/$link" 57 | fi 58 | done 59 | SAVED="`pwd`" 60 | cd "`dirname \"$PRG\"`/" >/dev/null 61 | APP_HOME="`pwd -P`" 62 | cd "$SAVED" >/dev/null 63 | 64 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 65 | 66 | # Determine the Java command to use to start the JVM. 67 | if [ -n "$JAVA_HOME" ] ; then 68 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 69 | # IBM's JDK on AIX uses strange locations for the executables 70 | JAVACMD="$JAVA_HOME/jre/sh/java" 71 | else 72 | JAVACMD="$JAVA_HOME/bin/java" 73 | fi 74 | if [ ! -x "$JAVACMD" ] ; then 75 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 76 | 77 | Please set the JAVA_HOME variable in your environment to match the 78 | location of your Java installation." 79 | fi 80 | else 81 | JAVACMD="java" 82 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 83 | 84 | Please set the JAVA_HOME variable in your environment to match the 85 | location of your Java installation." 86 | fi 87 | 88 | # Increase the maximum file descriptors if we can. 89 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 90 | MAX_FD_LIMIT=`ulimit -H -n` 91 | if [ $? -eq 0 ] ; then 92 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 93 | MAX_FD="$MAX_FD_LIMIT" 94 | fi 95 | ulimit -n $MAX_FD 96 | if [ $? -ne 0 ] ; then 97 | warn "Could not set maximum file descriptor limit: $MAX_FD" 98 | fi 99 | else 100 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 101 | fi 102 | fi 103 | 104 | # For Darwin, add options to specify how the application appears in the dock 105 | if $darwin; then 106 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 107 | fi 108 | 109 | # For Cygwin, switch paths to Windows format before running java 110 | if $cygwin ; then 111 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 112 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 113 | JAVACMD=`cygpath --unix "$JAVACMD"` 114 | 115 | # We build the pattern for arguments to be converted via cygpath 116 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 117 | SEP="" 118 | for dir in $ROOTDIRSRAW ; do 119 | ROOTDIRS="$ROOTDIRS$SEP$dir" 120 | SEP="|" 121 | done 122 | OURCYGPATTERN="(^($ROOTDIRS))" 123 | # Add a user-defined pattern to the cygpath arguments 124 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 125 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 126 | fi 127 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 128 | i=0 129 | for arg in "$@" ; do 130 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 131 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 132 | 133 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 134 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 135 | else 136 | eval `echo args$i`="\"$arg\"" 137 | fi 138 | i=$((i+1)) 139 | done 140 | case $i in 141 | (0) set -- ;; 142 | (1) set -- "$args0" ;; 143 | (2) set -- "$args0" "$args1" ;; 144 | (3) set -- "$args0" "$args1" "$args2" ;; 145 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 146 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 147 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 148 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 149 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 150 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 151 | esac 152 | fi 153 | 154 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 155 | function splitJvmOpts() { 156 | JVM_OPTS=("$@") 157 | } 158 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 159 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 160 | 161 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 162 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /android/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /android/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-19 15 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /cmake/FindLibuuid.cmake: -------------------------------------------------------------------------------- 1 | find_package(PkgConfig) 2 | 3 | pkg_check_modules(PKG_LIBUUID QUIET uuid) 4 | 5 | set(LIBUUID_DEFINITIONS ${PKG_LIBUUID_CFLAGS_OTHER}) 6 | set(LIBUUID_VERSION ${PKG_LIBUUID_VERSION}) 7 | 8 | find_path(LIBUUID_INCLUDE_DIR 9 | NAMES uuid/uuid.h 10 | HINTS ${PKG_LIBUUID_INCLUDE_DIRS} 11 | ) 12 | find_library(LIBUUID_LIBRARY 13 | NAMES uuid 14 | HINTS ${PKG_LIBUUID_LIBRARY_DIRS} 15 | ) 16 | 17 | include(FindPackageHandleStandardArgs) 18 | find_package_handle_standard_args(LibUUID 19 | FOUND_VAR 20 | LIBUUID_FOUND 21 | REQUIRED_VARS 22 | LIBUUID_LIBRARY 23 | LIBUUID_INCLUDE_DIR 24 | VERSION_VAR 25 | LIBUUID_VERSION 26 | ) 27 | 28 | if(LIBUUID_FOUND AND NOT TARGET LibUUID::UUID) 29 | add_library(LibUUID::UUID UNKNOWN IMPORTED) 30 | set_target_properties(LibUUID::UUID PROPERTIES 31 | IMPORTED_LOCATION "${LIBUUID_LIBRARY}" 32 | INTERFACE_COMPILE_OPTIONS "${LIBUUID_DEFINITIONS}" 33 | INTERFACE_INCLUDE_DIRECTORIES "${LIBUUID_INCLUDE_DIR}" 34 | ) 35 | endif() 36 | 37 | mark_as_advanced(LIBUUID_INCLUDE_DIR LIBUUID_LIBRARY) 38 | 39 | include(FeatureSummary) 40 | set_package_properties(LIBUUID PROPERTIES 41 | URL "http://www.kernel.org/pub/linux/utils/util-linux/" 42 | DESCRIPTION "uuid library in util-linux" 43 | ) 44 | -------------------------------------------------------------------------------- /crossguid.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | exec_prefix=${prefix} 3 | includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ 4 | libdir=@CMAKE_INSTALL_FULL_LIBDIR@ 5 | 6 | Name: crossguid 7 | Description: Lightweight cross platform C++ GUID/UUID library 8 | URL: https://github.com/graeme-hill/crossguid 9 | Version: @PROJECT_VERSION@ 10 | Cflags: -I${includedir} 11 | Libs: -L${libdir} -lcrossguid 12 | -------------------------------------------------------------------------------- /include/crossguid/guid.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2014 Graeme Hill (http://graemehill.ca) 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #ifdef GUID_ANDROID 28 | #include 29 | #include 30 | #endif 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #define BEGIN_XG_NAMESPACE namespace xg { 41 | #define END_XG_NAMESPACE } 42 | 43 | BEGIN_XG_NAMESPACE 44 | 45 | // Class to represent a GUID/UUID. Each instance acts as a wrapper around a 46 | // 16 byte value that can be passed around by value. It also supports 47 | // conversion to string (via the stream operator <<) and conversion from a 48 | // string via constructor. 49 | class Guid 50 | { 51 | public: 52 | explicit Guid(const std::array &bytes); 53 | explicit Guid(std::array &&bytes); 54 | 55 | explicit Guid(std::string_view fromString); 56 | Guid(); 57 | 58 | Guid(const Guid &other) = default; 59 | Guid &operator=(const Guid &other) = default; 60 | Guid(Guid &&other) = default; 61 | Guid &operator=(Guid &&other) = default; 62 | 63 | bool operator==(const Guid &other) const; 64 | bool operator!=(const Guid &other) const; 65 | 66 | std::string str() const; 67 | operator std::string() const; 68 | const std::array& bytes() const; 69 | void swap(Guid &other); 70 | bool isValid() const; 71 | 72 | private: 73 | void zeroify(); 74 | 75 | // actual data 76 | std::array _bytes; 77 | 78 | // make the << operator a friend so it can access _bytes 79 | friend std::ostream &operator<<(std::ostream &s, const Guid &guid); 80 | friend bool operator<(const Guid &lhs, const Guid &rhs); 81 | }; 82 | 83 | Guid newGuid(); 84 | 85 | #ifdef GUID_ANDROID 86 | struct AndroidGuidInfo 87 | { 88 | static AndroidGuidInfo fromJniEnv(JNIEnv *env); 89 | 90 | JNIEnv *env; 91 | jclass uuidClass; 92 | jmethodID newGuidMethod; 93 | jmethodID mostSignificantBitsMethod; 94 | jmethodID leastSignificantBitsMethod; 95 | std::thread::id initThreadId; 96 | }; 97 | 98 | extern AndroidGuidInfo androidInfo; 99 | 100 | void initJni(JNIEnv *env); 101 | 102 | // overloading for multi-threaded calls 103 | Guid newGuid(JNIEnv *env); 104 | #endif 105 | 106 | namespace details 107 | { 108 | template struct hash; 109 | 110 | template 111 | struct hash : public std::hash 112 | { 113 | using std::hash::hash; 114 | }; 115 | 116 | 117 | template 118 | struct hash 119 | { 120 | inline std::size_t operator()(const T& v, const Rest&... rest) { 121 | std::size_t seed = hash{}(rest...); 122 | seed ^= hash{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); 123 | return seed; 124 | } 125 | }; 126 | } 127 | 128 | END_XG_NAMESPACE 129 | 130 | namespace std 131 | { 132 | // Template specialization for std::swap() -- 133 | // See guid.cpp for the function definition 134 | template <> 135 | void swap(xg::Guid &guid0, xg::Guid &guid1) noexcept; 136 | 137 | // Specialization for std::hash -- this implementation 138 | // uses std::hash on the stringification of the guid 139 | // to calculate the hash 140 | template <> 141 | struct hash 142 | { 143 | std::size_t operator()(xg::Guid const &guid) const 144 | { 145 | const uint64_t* p = reinterpret_cast(guid.bytes().data()); 146 | return xg::details::hash{}(p[0], p[1]); 147 | } 148 | }; 149 | } 150 | -------------------------------------------------------------------------------- /src/guid.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2014 Graeme Hill (http://graemehill.ca) 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include "crossguid/guid.hpp" 27 | 28 | #ifdef GUID_LIBUUID 29 | #include 30 | #endif 31 | 32 | #ifdef GUID_CFUUID 33 | #include 34 | #endif 35 | 36 | #ifdef GUID_WINDOWS 37 | #include 38 | #endif 39 | 40 | #ifdef GUID_ANDROID 41 | #include 42 | #include 43 | #endif 44 | 45 | BEGIN_XG_NAMESPACE 46 | 47 | #ifdef GUID_ANDROID 48 | AndroidGuidInfo androidInfo; 49 | 50 | AndroidGuidInfo AndroidGuidInfo::fromJniEnv(JNIEnv *env) 51 | { 52 | AndroidGuidInfo info; 53 | info.env = env; 54 | auto localUuidClass = env->FindClass("java/util/UUID"); 55 | info.uuidClass = (jclass)env->NewGlobalRef(localUuidClass); 56 | env->DeleteLocalRef(localUuidClass); 57 | info.newGuidMethod = env->GetStaticMethodID( 58 | info.uuidClass, "randomUUID", "()Ljava/util/UUID;"); 59 | info.mostSignificantBitsMethod = env->GetMethodID( 60 | info.uuidClass, "getMostSignificantBits", "()J"); 61 | info.leastSignificantBitsMethod = env->GetMethodID( 62 | info.uuidClass, "getLeastSignificantBits", "()J"); 63 | info.initThreadId = std::this_thread::get_id(); 64 | return info; 65 | } 66 | 67 | void initJni(JNIEnv *env) 68 | { 69 | androidInfo = AndroidGuidInfo::fromJniEnv(env); 70 | } 71 | #endif 72 | 73 | // overload << so that it's easy to convert to a string 74 | std::ostream &operator<<(std::ostream &s, const Guid &guid) 75 | { 76 | std::ios_base::fmtflags f(s.flags()); // politely don't leave the ostream in hex mode 77 | s << std::hex << std::setfill('0') 78 | << std::setw(2) << (int)guid._bytes[0] 79 | << std::setw(2) << (int)guid._bytes[1] 80 | << std::setw(2) << (int)guid._bytes[2] 81 | << std::setw(2) << (int)guid._bytes[3] 82 | << "-" 83 | << std::setw(2) << (int)guid._bytes[4] 84 | << std::setw(2) << (int)guid._bytes[5] 85 | << "-" 86 | << std::setw(2) << (int)guid._bytes[6] 87 | << std::setw(2) << (int)guid._bytes[7] 88 | << "-" 89 | << std::setw(2) << (int)guid._bytes[8] 90 | << std::setw(2) << (int)guid._bytes[9] 91 | << "-" 92 | << std::setw(2) << (int)guid._bytes[10] 93 | << std::setw(2) << (int)guid._bytes[11] 94 | << std::setw(2) << (int)guid._bytes[12] 95 | << std::setw(2) << (int)guid._bytes[13] 96 | << std::setw(2) << (int)guid._bytes[14] 97 | << std::setw(2) << (int)guid._bytes[15]; 98 | s.flags(f); 99 | return s; 100 | } 101 | 102 | bool operator<(const xg::Guid &lhs, const xg::Guid &rhs) 103 | { 104 | return lhs.bytes() < rhs.bytes(); 105 | } 106 | 107 | bool Guid::isValid() const 108 | { 109 | xg::Guid empty; 110 | return *this != empty; 111 | } 112 | 113 | // convert to string using std::snprintf() and std::string 114 | std::string Guid::str() const 115 | { 116 | char one[10], two[6], three[6], four[6], five[14]; 117 | 118 | snprintf(one, 10, "%02x%02x%02x%02x", 119 | _bytes[0], _bytes[1], _bytes[2], _bytes[3]); 120 | snprintf(two, 6, "%02x%02x", 121 | _bytes[4], _bytes[5]); 122 | snprintf(three, 6, "%02x%02x", 123 | _bytes[6], _bytes[7]); 124 | snprintf(four, 6, "%02x%02x", 125 | _bytes[8], _bytes[9]); 126 | snprintf(five, 14, "%02x%02x%02x%02x%02x%02x", 127 | _bytes[10], _bytes[11], _bytes[12], _bytes[13], _bytes[14], _bytes[15]); 128 | const std::string sep("-"); 129 | std::string out(one); 130 | 131 | out += sep + two; 132 | out += sep + three; 133 | out += sep + four; 134 | out += sep + five; 135 | 136 | return out; 137 | } 138 | 139 | // conversion operator for std::string 140 | Guid::operator std::string() const 141 | { 142 | return str(); 143 | } 144 | 145 | // Access underlying bytes 146 | const std::array& Guid::bytes() const 147 | { 148 | return _bytes; 149 | } 150 | 151 | // create a guid from vector of bytes 152 | Guid::Guid(const std::array &bytes) : _bytes(bytes) 153 | { } 154 | 155 | // create a guid from vector of bytes 156 | Guid::Guid(std::array &&bytes) : _bytes(std::move(bytes)) 157 | { } 158 | 159 | // converts a single hex char to a number (0 - 15) 160 | unsigned char hexDigitToChar(char ch) 161 | { 162 | // 0-9 163 | if (ch > 47 && ch < 58) 164 | return ch - 48; 165 | 166 | // a-f 167 | if (ch > 96 && ch < 103) 168 | return ch - 87; 169 | 170 | // A-F 171 | if (ch > 64 && ch < 71) 172 | return ch - 55; 173 | 174 | return 0; 175 | } 176 | 177 | bool isValidHexChar(char ch) 178 | { 179 | // 0-9 180 | if (ch > 47 && ch < 58) 181 | return true; 182 | 183 | // a-f 184 | if (ch > 96 && ch < 103) 185 | return true; 186 | 187 | // A-F 188 | if (ch > 64 && ch < 71) 189 | return true; 190 | 191 | return false; 192 | } 193 | 194 | // converts the two hexadecimal characters to an unsigned char (a byte) 195 | unsigned char hexPairToChar(char a, char b) 196 | { 197 | return hexDigitToChar(a) * 16 + hexDigitToChar(b); 198 | } 199 | 200 | // create a guid from string 201 | Guid::Guid(std::string_view fromString) 202 | { 203 | char charOne = '\0'; 204 | char charTwo = '\0'; 205 | bool lookingForFirstChar = true; 206 | unsigned nextByte = 0; 207 | 208 | for (const char &ch : fromString) 209 | { 210 | if (ch == '-') 211 | continue; 212 | 213 | if (nextByte >= 16 || !isValidHexChar(ch)) 214 | { 215 | // Invalid string so bail 216 | zeroify(); 217 | return; 218 | } 219 | 220 | if (lookingForFirstChar) 221 | { 222 | charOne = ch; 223 | lookingForFirstChar = false; 224 | } 225 | else 226 | { 227 | charTwo = ch; 228 | auto byte = hexPairToChar(charOne, charTwo); 229 | _bytes[nextByte++] = byte; 230 | lookingForFirstChar = true; 231 | } 232 | } 233 | 234 | // if there were fewer than 16 bytes in the string then guid is bad 235 | if (nextByte < 16) 236 | { 237 | zeroify(); 238 | return; 239 | } 240 | } 241 | 242 | // create empty guid 243 | Guid::Guid() : _bytes{ {0} } 244 | { } 245 | 246 | // set all bytes to zero 247 | void Guid::zeroify() 248 | { 249 | std::fill(_bytes.begin(), _bytes.end(), static_cast(0)); 250 | } 251 | 252 | // overload equality operator 253 | bool Guid::operator==(const Guid &other) const 254 | { 255 | return _bytes == other._bytes; 256 | } 257 | 258 | // overload inequality operator 259 | bool Guid::operator!=(const Guid &other) const 260 | { 261 | return !((*this) == other); 262 | } 263 | 264 | // member swap function 265 | void Guid::swap(Guid &other) 266 | { 267 | _bytes.swap(other._bytes); 268 | } 269 | 270 | // This is the linux friendly implementation, but it could work on other 271 | // systems that have libuuid available 272 | #ifdef GUID_LIBUUID 273 | Guid newGuid() 274 | { 275 | std::array data; 276 | static_assert(std::is_same::value, "Wrong type!"); 277 | uuid_generate(data.data()); 278 | return Guid{std::move(data)}; 279 | } 280 | #endif 281 | 282 | // this is the mac and ios version 283 | #ifdef GUID_CFUUID 284 | Guid newGuid() 285 | { 286 | auto newId = CFUUIDCreate(NULL); 287 | auto bytes = CFUUIDGetUUIDBytes(newId); 288 | CFRelease(newId); 289 | 290 | std::array byteArray = 291 | {{ 292 | bytes.byte0, 293 | bytes.byte1, 294 | bytes.byte2, 295 | bytes.byte3, 296 | bytes.byte4, 297 | bytes.byte5, 298 | bytes.byte6, 299 | bytes.byte7, 300 | bytes.byte8, 301 | bytes.byte9, 302 | bytes.byte10, 303 | bytes.byte11, 304 | bytes.byte12, 305 | bytes.byte13, 306 | bytes.byte14, 307 | bytes.byte15 308 | }}; 309 | return Guid{std::move(byteArray)}; 310 | } 311 | #endif 312 | 313 | // obviously this is the windows version 314 | #ifdef GUID_WINDOWS 315 | Guid newGuid() 316 | { 317 | GUID newId; 318 | CoCreateGuid(&newId); 319 | 320 | std::array bytes = 321 | { 322 | (unsigned char)((newId.Data1 >> 24) & 0xFF), 323 | (unsigned char)((newId.Data1 >> 16) & 0xFF), 324 | (unsigned char)((newId.Data1 >> 8) & 0xFF), 325 | (unsigned char)((newId.Data1) & 0xff), 326 | 327 | (unsigned char)((newId.Data2 >> 8) & 0xFF), 328 | (unsigned char)((newId.Data2) & 0xff), 329 | 330 | (unsigned char)((newId.Data3 >> 8) & 0xFF), 331 | (unsigned char)((newId.Data3) & 0xFF), 332 | 333 | (unsigned char)newId.Data4[0], 334 | (unsigned char)newId.Data4[1], 335 | (unsigned char)newId.Data4[2], 336 | (unsigned char)newId.Data4[3], 337 | (unsigned char)newId.Data4[4], 338 | (unsigned char)newId.Data4[5], 339 | (unsigned char)newId.Data4[6], 340 | (unsigned char)newId.Data4[7] 341 | }; 342 | 343 | return Guid{std::move(bytes)}; 344 | } 345 | #endif 346 | 347 | // android version that uses a call to a java api 348 | #ifdef GUID_ANDROID 349 | Guid newGuid(JNIEnv *env) 350 | { 351 | assert(env != androidInfo.env || std::this_thread::get_id() == androidInfo.initThreadId); 352 | 353 | jobject javaUuid = env->CallStaticObjectMethod( 354 | androidInfo.uuidClass, androidInfo.newGuidMethod); 355 | jlong mostSignificant = env->CallLongMethod(javaUuid, 356 | androidInfo.mostSignificantBitsMethod); 357 | jlong leastSignificant = env->CallLongMethod(javaUuid, 358 | androidInfo.leastSignificantBitsMethod); 359 | 360 | std::array bytes = 361 | { 362 | (unsigned char)((mostSignificant >> 56) & 0xFF), 363 | (unsigned char)((mostSignificant >> 48) & 0xFF), 364 | (unsigned char)((mostSignificant >> 40) & 0xFF), 365 | (unsigned char)((mostSignificant >> 32) & 0xFF), 366 | (unsigned char)((mostSignificant >> 24) & 0xFF), 367 | (unsigned char)((mostSignificant >> 16) & 0xFF), 368 | (unsigned char)((mostSignificant >> 8) & 0xFF), 369 | (unsigned char)((mostSignificant) & 0xFF), 370 | (unsigned char)((leastSignificant >> 56) & 0xFF), 371 | (unsigned char)((leastSignificant >> 48) & 0xFF), 372 | (unsigned char)((leastSignificant >> 40) & 0xFF), 373 | (unsigned char)((leastSignificant >> 32) & 0xFF), 374 | (unsigned char)((leastSignificant >> 24) & 0xFF), 375 | (unsigned char)((leastSignificant >> 16) & 0xFF), 376 | (unsigned char)((leastSignificant >> 8) & 0xFF), 377 | (unsigned char)((leastSignificant) & 0xFF) 378 | }; 379 | 380 | env->DeleteLocalRef(javaUuid); 381 | 382 | return Guid{std::move(bytes)}; 383 | } 384 | 385 | Guid newGuid() 386 | { 387 | return newGuid(androidInfo.env); 388 | } 389 | #endif 390 | 391 | 392 | END_XG_NAMESPACE 393 | 394 | // Specialization for std::swap() -- 395 | // call member swap function of lhs, passing rhs 396 | namespace std 397 | { 398 | template <> 399 | void swap(xg::Guid &lhs, xg::Guid &rhs) noexcept 400 | { 401 | lhs.swap(rhs); 402 | } 403 | } 404 | -------------------------------------------------------------------------------- /test/Test.cpp: -------------------------------------------------------------------------------- 1 | #include "Test.hpp" 2 | 3 | int test(std::ostream &outStream) 4 | { 5 | int failed = 0; 6 | 7 | /************************************************************************* 8 | * HAPPY PATH TESTS 9 | *************************************************************************/ 10 | 11 | auto r1 = xg::newGuid(); 12 | auto r2 = xg::newGuid(); 13 | auto r3 = xg::newGuid(); 14 | 15 | outStream << r1 << std::endl << r2 << std::endl << r3 << std::endl; 16 | 17 | xg::Guid s1("7bcd757f-5b10-4f9b-af69-1a1f226f3b3e"); 18 | xg::Guid s2("16d1bd03-09a5-47d3-944b-5e326fd52d27"); 19 | xg::Guid s3("fdaba646-e07e-49de-9529-4499a5580c75"); 20 | xg::Guid s4("7bcd757f-5b10-4f9b-af69-1a1f226f3b3e"); 21 | xg::Guid s5("7bcd757f-5b10-4f9b-af69-1a1f226f3b31"); 22 | 23 | if (r1 == r2 || r1 == r3 || r2 == r3) 24 | { 25 | outStream << "FAIL - not all random guids are different" << std::endl; 26 | failed++; 27 | } 28 | 29 | if (s1 == s2) 30 | { 31 | outStream << "FAIL - s1 and s2 should be different" << std::endl; 32 | failed++; 33 | } 34 | 35 | if (s1 != s4) 36 | { 37 | outStream << "FAIL - s1 and s4 should be equal" << std::endl; 38 | failed++; 39 | } 40 | 41 | if (s4 < s5) { 42 | outStream << "FAIL - s5 should should less than s4" << std::endl; 43 | failed++; 44 | } 45 | 46 | std::stringstream ss1; 47 | ss1 << s1; 48 | if (ss1.str() != "7bcd757f-5b10-4f9b-af69-1a1f226f3b3e") 49 | { 50 | outStream << "FAIL - string from s1 stream is wrong" << std::endl; 51 | outStream << "--> " << ss1.str() << std::endl; 52 | failed++; 53 | } 54 | 55 | if (s1.str() != "7bcd757f-5b10-4f9b-af69-1a1f226f3b3e") 56 | { 57 | outStream << "FAIL - string from s1.str() is wrong" << std::endl; 58 | outStream << "--> " << s1.str() << std::endl; 59 | failed++; 60 | } 61 | 62 | std::stringstream ss2; 63 | ss2 << s2; 64 | if (ss2.str() != "16d1bd03-09a5-47d3-944b-5e326fd52d27") 65 | { 66 | outStream << "FAIL - string generated from s2 is wrong" << std::endl; 67 | outStream << "--> " << ss2.str() << std::endl; 68 | return 1; 69 | } 70 | 71 | std::stringstream ss3; 72 | ss3 << s3; 73 | if (ss3.str() != "fdaba646-e07e-49de-9529-4499a5580c75") 74 | { 75 | outStream << "FAIL - string generated from s3 is wrong" << std::endl; 76 | outStream << "--> " << ss3.str() << std::endl; 77 | failed++; 78 | } 79 | 80 | auto swap1 = xg::newGuid(); 81 | auto swap2 = xg::newGuid(); 82 | auto swap3 = swap1; 83 | auto swap4 = swap2; 84 | 85 | if (swap1 != swap3 || swap2 != swap4 || swap1 == swap2) 86 | { 87 | outStream << "FAIL - swap guids have bad initial state" << std::endl; 88 | failed++; 89 | } 90 | 91 | swap1.swap(swap2); 92 | 93 | if (swap1 != swap4 || swap2 != swap3 || swap1 == swap2) 94 | { 95 | outStream << "FAIL - swap didn't swap" << std::endl; 96 | failed++; 97 | } 98 | 99 | { 100 | std::unordered_map m = {{s1, 1}, {s2, 2}}; 101 | auto it1 = m.find(s1); 102 | auto it2 = m.find(s2); 103 | if(!( it1 != m.end() && it1->first == s1 && it1->second == 1 && it2 != m.end() && it2->first == s2 && it2->second == 2)) 104 | { 105 | outStream << "FAIL - map/hash failed!" << std::endl; 106 | failed++; 107 | } 108 | auto it3 = m.find(s3); 109 | if(it3 != m.end()) 110 | { 111 | outStream << "FAIL - map/hash failed!" << std::endl; 112 | failed++; 113 | } 114 | } 115 | std::array bytes = 116 | {{ 117 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 118 | 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xdd 119 | }}; 120 | xg::Guid guidFromBytes(bytes); 121 | xg::Guid guidFromString("0102030405060708090a0b0c0d0e0fdd"); 122 | if (guidFromBytes != guidFromString) 123 | { 124 | outStream << "FAIL - String/bytes make different guids" << std::endl; 125 | failed++; 126 | } 127 | 128 | if(!std::equal(guidFromBytes.bytes().begin(), guidFromBytes.bytes().end(), bytes.begin())) 129 | { 130 | outStream << "FAIL - array returned from bytes() is wrong" << std::endl; 131 | failed++; 132 | } 133 | 134 | /************************************************************************* 135 | * ERROR HANDLING 136 | *************************************************************************/ 137 | 138 | xg::Guid empty; 139 | xg::Guid twoTooFew("7bcd757f-5b10-4f9b-af69-1a1f226f3b"); 140 | if (twoTooFew != empty || twoTooFew.isValid()) 141 | { 142 | outStream << "FAIL - Guid from two too few chars" << std::endl; 143 | failed++; 144 | } 145 | 146 | xg::Guid oneTooFew("16d1bd03-09a5-47d3-944b-5e326fd52d2"); 147 | if (oneTooFew != empty || oneTooFew.isValid()) 148 | { 149 | outStream << "FAIL - Guid from one too few chars" << std::endl; 150 | failed++; 151 | } 152 | 153 | xg::Guid twoTooMany("7bcd757f-5b10-4f9b-af69-1a1f226f3beeff"); 154 | if (twoTooMany != empty || twoTooMany.isValid()) 155 | { 156 | outStream << "FAIL - Guid from two too many chars" << std::endl; 157 | failed++; 158 | } 159 | 160 | xg::Guid oneTooMany("16d1bd03-09a5-47d3-944b-5e326fd52d27a"); 161 | if (oneTooMany != empty || oneTooMany.isValid()) 162 | { 163 | outStream << "FAIL - Guid from one too many chars" << std::endl; 164 | failed++; 165 | } 166 | 167 | xg::Guid badString("!!bad-guid-string!!"); 168 | if (badString != empty || badString.isValid()) 169 | { 170 | outStream << "FAIL - Guid from bad string" << std::endl; 171 | failed++; 172 | } 173 | 174 | if (failed == 0) 175 | { 176 | outStream << "All tests passed!" << std::endl; 177 | return 0; 178 | } 179 | else 180 | { 181 | outStream << failed << " tests failed." << std::endl; 182 | return 1; 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /test/Test.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | int test(std::ostream &outStream); 8 | -------------------------------------------------------------------------------- /test/TestMain.cpp: -------------------------------------------------------------------------------- 1 | #include "Test.hpp" 2 | #include 3 | 4 | int main() 5 | { 6 | return test(std::cout); 7 | } 8 | --------------------------------------------------------------------------------