diff options
41 files changed, 1445 insertions, 1246 deletions
@@ -72,3 +72,9 @@ Testing/Temporary .project net/**/obj node_modules/ +android/.externalNativeBuild/ +android/.gradle/ +android/build/ +samples/android/.externalNativeBuild/ +samples/android/.gradle/ +samples/android/build/ diff --git a/.travis.yml b/.travis.yml index bee81694..297c406b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,31 +1,58 @@ -language: cpp - -os: -- linux -- osx - -compiler: - - gcc - #- clang - env: - matrix: - - BUILD_TYPE=Debug BIICODE=false - - BUILD_TYPE=Release BIICODE=false - # biicode .deb files no longer available. - # - BUILD_TYPE=Release BIICODE=true - # - BUILD_TYPE=Debug BIICODE=true global: + # Set at the root level as this is ignored when set under matrix.env. - GCC_VERSION="4.9" +matrix: + include: + - language: cpp + os: + - linux + - osx + + compiler: + - gcc + #- clang + + env: + matrix: + - BUILD_TYPE=Debug BIICODE=false + - BUILD_TYPE=Release BIICODE=false + # biicode .deb files no longer available. + # - BUILD_TYPE=Release BIICODE=true + # - BUILD_TYPE=Debug BIICODE=true + + before_install: + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq; fi + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq g++-$GCC_VERSION; fi + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq gcc-$GCC_VERSION; fi + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which g++-$GCC_VERSION) /usr/bin/g++; fi + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi + + script: + - if [ "$BIICODE" == "false" ]; then cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE . && make && make test; fi + - if [ "$BIICODE" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then ./biicode/support/bii-travis.sh $BUILD_TYPE; fi -before_install: -- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi -- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq; fi -- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq g++-$GCC_VERSION; fi -- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq gcc-$GCC_VERSION; fi -- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which g++-$GCC_VERSION) /usr/bin/g++; fi -- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi - -script: -- if [ "$BIICODE" == "false" ]; then cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE . && make && make test; fi -- if [ "$BIICODE" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then ./biicode/support/bii-travis.sh $BUILD_TYPE; fi + - language: android + sudo: true + android: + components: + - tools + - platform-tools + - build-tools-25.0.2 + - android-25 + - extra-android-m2repository + compiler: + - gcc + before_install: + - git clone https://github.com/urho3d/android-ndk.git $HOME/android-ndk-root + - export ANDROID_NDK_HOME=$HOME/android-ndk-root + # Setup environment for Linux build which is required to build the sample. + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq; fi + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq g++-$GCC_VERSION; fi + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq gcc-$GCC_VERSION; fi + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which g++-$GCC_VERSION) /usr/bin/g++; fi + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi + script: + - for build_gradle in $(git ls-files | grep build.gradle); do ( cd "$(dirname "${build_gradle}")" && ./gradlew build ); done diff --git a/CMakeLists.txt b/CMakeLists.txt index 53d453bb..e8353252 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ set(FlatBuffers_Library_SRCS include/flatbuffers/util.h include/flatbuffers/reflection.h include/flatbuffers/reflection_generated.h + include/flatbuffers/stl_emulation.h include/flatbuffers/flexbuffers.h include/flatbuffers/registry.h src/code_generators.cpp @@ -198,6 +199,7 @@ function(compile_flatbuffers_schema_to_cpp SRC_FBS) OUTPUT ${GEN_HEADER} COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -c --no-includes --gen-mutable --gen-object-api -o "${SRC_FBS_DIR}" + --cpp-ptr-type flatbuffers::unique_ptr # Used to test with C++98 STLs -I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test" "${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}" DEPENDS flatc) diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index a15f547b..846fd13c 100755 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -17,17 +17,14 @@ --> <!-- BEGIN_INCLUDE(manifest) --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.FlatBufferTest" - android:versionCode="1" - android:versionName="1.0"> + package="com.example.FlatBufferTest"> <uses-feature android:glEsVersion="0x00020000"></uses-feature> - <!-- This is the platform API where NativeActivity was introduced. --> - <uses-sdk android:minSdkVersion="9" /> <!-- This .apk has no Java code itself, so set hasCode to false. --> - <application android:label="@string/app_name" android:hasCode="false"> - + <application android:label="@string/app_name" + android:hasCode="false" + android:allowBackup="false"> <!-- Our activity is the built-in NativeActivity framework class. This will take care of integrating with our NDK code. --> <activity android:name="android.app.NativeActivity" diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 00000000..73e4188c --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,108 @@ +// Copyright (c) 2017 Google, Inc. +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.0' + } +} + +allprojects { + repositories { + jcenter() + } +} + +apply plugin: 'com.android.application' + +android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + + sourceSets { + main { + manifest.srcFile 'AndroidManifest.xml' + res.srcDirs = ['res'] + } + } + + externalNativeBuild { + ndkBuild { + path "jni/Android.mk" + } + } + + defaultConfig { + applicationId 'com.example.FlatBufferTest' + // This is the platform API where NativeActivity was introduced. + minSdkVersion 9 + targetSdkVersion 25 + versionCode 1 + versionName "1.0" + + buildTypes { + release { + minifyEnabled false + } + } + + externalNativeBuild { + ndkBuild { + targets "FlatBufferTest" + arguments "-j" + Runtime.getRuntime().availableProcessors() + abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86", "x86_64" + } + } + } + + lintOptions { + abortOnError false + } + + // Build with each STL variant. + productFlavors { + stlport { + applicationIdSuffix ".stlport" + versionNameSuffix "-stlport" + externalNativeBuild { + ndkBuild { + arguments "APP_STL=stlport_static" + } + } + } + gnustl { + applicationIdSuffix ".gnustl" + versionNameSuffix "-gnustl" + externalNativeBuild { + ndkBuild { + arguments "APP_STL=gnustl_static" + } + } + } + libcpp { + applicationIdSuffix ".libcpp" + versionNameSuffix "-libcpp" + externalNativeBuild { + ndkBuild { + arguments "APP_STL=c++_static" + } + } + } + } +} diff --git a/android/build_apk.sh b/android/build_apk.sh deleted file mode 100755 index 1b9f4a45..00000000 --- a/android/build_apk.sh +++ /dev/null @@ -1,511 +0,0 @@ -#!/bin/bash -eu -# -# Copyright (c) 2013 Google, Inc. -# -# This software is provided 'as-is', without any express or implied -# warranty. In no event will the authors be held liable for any damages -# arising from the use of this software. -# Permission is granted to anyone to use this software for any purpose, -# including commercial applications, and to alter it and redistribute it -# freely, subject to the following restrictions: -# 1. The origin of this software must not be misrepresented; you must not -# claim that you wrote the original software. If you use this software -# in a product, an acknowledgment in the product documentation would be -# appreciated but is not required. -# 2. Altered source versions must be plainly marked as such, and must not be -# misrepresented as being the original software. -# 3. This notice may not be removed or altered from any source distribution. -# -# Build, deploy, debug / execute a native Android package based upon -# NativeActivity. - -declare -r script_directory=$(dirname $0) -declare -r android_root=${script_directory}/../../../../../../ -declare -r script_name=$(basename $0) -declare -r android_manifest=AndroidManifest.xml -declare -r os_name=$(uname -s) - -# Minimum Android target version supported by this project. -: ${BUILDAPK_ANDROID_TARGET_MINVERSION:=10} -# Directory containing the Android SDK -# (http://developer.android.com/sdk/index.html). -: ${ANDROID_SDK_HOME:=} -# Directory containing the Android NDK -# (http://developer.android.com/tools/sdk/ndk/index.html). -: ${NDK_HOME:=} - -# Display script help and exit. -usage() { - echo " -Build the Android package in the current directory and deploy it to a -connected device. - -Usage: ${script_name} \\ - [ADB_DEVICE=serial_number] [BUILD=0] [DEPLOY=0] [RUN_DEBUGGER=1] \ - [LAUNCH=0] [SWIG_BIN=swig_binary_directory] [SWIG_LIB=swig_include_directory] [ndk-build arguments ...] - -ADB_DEVICE=serial_number: - serial_number specifies the device to deploy the built apk to if multiple - Android devices are connected to the host. -BUILD=0: - Disables the build of the package. -DEPLOY=0: - Disables the deployment of the built apk to the Android device. -RUN_DEBUGGER=1: - Launches the application in gdb after it has been deployed. To debug in - gdb, NDK_DEBUG=1 must also be specified on the command line to build a - debug apk. -LAUNCH=0: - Disable the launch of the apk on the Android device. -SWIG_BIN=swig_binary_directory: - The directory where the SWIG binary lives. No need to set this if SWIG is - installed and point to from your PATH variable. -SWIG_LIB=swig_include_directory: - The directory where SWIG shared include files are, usually obtainable from - commandline with \"swig -swiglib\". No need to set this if SWIG is installed - and point to from your PATH variable. -ndk-build arguments...: - Additional arguments for ndk-build. See ndk-build -h for more information. -" >&2 - exit 1 -} - -# Get the number of CPU cores present on the host. -get_number_of_cores() { - case ${os_name} in - Darwin) - sysctl hw.ncpu | awk '{ print $2 }' - ;; - CYGWIN*|Linux) - awk '/^processor/ { n=$3 } END { print n + 1 }' /proc/cpuinfo - ;; - *) - echo 1 - ;; - esac -} - -# Get the package name from an AndroidManifest.xml file. -get_package_name_from_manifest() { - xmllint --xpath 'string(/manifest/@package)' "${1}" -} - -# Get the library name from an AndroidManifest.xml file. -get_library_name_from_manifest() { - echo "\ -setns android=http://schemas.android.com/apk/res/android -xpath string(/manifest/application/activity\ -[@android:name=\"android.app.NativeActivity\"]/meta-data\ -[@android:name=\"android.app.lib_name\"]/@android:value)" | - xmllint --shell "${1}" | awk '/Object is a string/ { print $NF }' -} - -# Get the number of Android devices connected to the system. -get_number_of_devices_connected() { - adb devices -l | \ - awk '/^..*$/ { if (p) { print $0 } } - /List of devices attached/ { p = 1 }' | \ - wc -l - return ${PIPESTATUS[0]} -} - -# Kill a process and its' children. This is provided for cygwin which -# doesn't ship with pkill. -kill_process_group() { - local parent_pid="${1}" - local child_pid= - for child_pid in $(ps -f | \ - awk '{ if ($3 == '"${parent_pid}"') { print $2 } }'); do - kill_process_group "${child_pid}" - done - kill "${parent_pid}" 2>/dev/null -} - -# Find and run "adb". -adb() { - local adb_path= - for path in "$(which adb 2>/dev/null)" \ - "${ANDROID_SDK_HOME}/sdk/platform-tools/adb" \ - "${android_root}/prebuilts/sdk/platform-tools/adb"; do - if [[ -e "${path}" ]]; then - adb_path="${path}" - break - fi - done - if [[ "${adb_path}" == "" ]]; then - echo -e "Unable to find adb." \ - "\nAdd the Android ADT sdk/platform-tools directory to the" \ - "PATH." >&2 - exit 1 - fi - "${adb_path}" "$@" -} - -# Find and run "android". -android() { - local android_executable=android - if echo "${os_name}" | grep -q CYGWIN; then - android_executable=android.bat - fi - local android_path= - for path in "$(which ${android_executable})" \ - "${ANDROID_SDK_HOME}/sdk/tools/${android_executable}" \ - "${android_root}/prebuilts/sdk/tools/${android_executable}"; do - if [[ -e "${path}" ]]; then - android_path="${path}" - break - fi - done - if [[ "${android_path}" == "" ]]; then - echo -e "Unable to find android tool." \ - "\nAdd the Android ADT sdk/tools directory to the PATH." >&2 - exit 1 - fi - # Make sure ant is installed. - if [[ "$(which ant)" == "" ]]; then - echo -e "Unable to find ant." \ - "\nPlease install ant and add to the PATH." >&2 - exit 1 - fi - - "${android_path}" "$@" -} - -# Find and run "ndk-build" -ndkbuild() { - local ndkbuild_path= - for path in "$(which ndk-build 2>/dev/null)" \ - "${NDK_HOME}/ndk-build" \ - "${android_root}/prebuilts/ndk/current/ndk-build"; do - if [[ -e "${path}" ]]; then - ndkbuild_path="${path}" - break - fi - done - if [[ "${ndkbuild_path}" == "" ]]; then - echo -e "Unable to find ndk-build." \ - "\nAdd the Android NDK directory to the PATH." >&2 - exit 1 - fi - "${ndkbuild_path}" "$@" -} - -# Get file modification time of $1 in seconds since the epoch. -stat_mtime() { - local filename="${1}" - case ${os_name} in - Darwin) stat -f%m "${filename}" 2>/dev/null || echo 0 ;; - *) stat -c%Y "${filename}" 2>/dev/null || echo 0 ;; - esac -} - -# Build the native (C/C++) build targets in the current directory. -build_native_targets() { - # Save the list of output modules in the install directory so that it's - # possible to restore their timestamps after the build is complete. This - # works around a bug in ndk/build/core/setup-app.mk which results in the - # unconditional execution of the clean-installed-binaries rule. - restore_libraries="$(find libs -type f 2>/dev/null | \ - sed -E 's@^libs/(.*)@\1@')" - - # Build native code. - ndkbuild -j$(get_number_of_cores) "$@" - - # Restore installed libraries. - # Obviously this is a nasty hack (along with ${restore_libraries} above) as - # it assumes it knows where the NDK will be placing output files. - ( - IFS=$'\n' - for libpath in ${restore_libraries}; do - source_library="obj/local/${libpath}" - target_library="libs/${libpath}" - if [[ -e "${source_library}" ]]; then - cp -a "${source_library}" "${target_library}" - fi - done - ) -} - -# Select the oldest installed android build target that is at least as new as -# BUILDAPK_ANDROID_TARGET_MINVERSION. If a suitable build target isn't found, -# this function prints an error message and exits with an error. -select_android_build_target() { - local -r android_targets_installed=$( \ - android list targets | \ - awk -F'"' '/^id:.*android/ { print $2 }') - local android_build_target= - for android_target in $(echo "${android_targets_installed}" | \ - awk -F- '{ print $2 }' | sort -n); do - local isNumber='^[0-9]+$' - # skip preview API releases e.g. 'android-L' - if [[ $android_target =~ $isNumber ]]; then - if [[ $((android_target)) -ge \ - $((BUILDAPK_ANDROID_TARGET_MINVERSION)) ]]; then - android_build_target="android-${android_target}" - break - fi - # else - # The API version is a letter, so skip it. - fi - done - if [[ "${android_build_target}" == "" ]]; then - echo -e \ - "Found installed Android targets:" \ - "$(echo ${android_targets_installed} | sed 's/ /\n /g;s/^/\n /;')" \ - "\nAndroid SDK platform" \ - "android-$((BUILDAPK_ANDROID_TARGET_MINVERSION))" \ - "must be installed to build this project." \ - "\nUse the \"android\" application to install API" \ - "$((BUILDAPK_ANDROID_TARGET_MINVERSION)) or newer." >&2 - exit 1 - fi - echo "${android_build_target}" -} - -# Sign unsigned apk $1 and write the result to $2 with key store file $3 and -# password $4. -# If a key store file $3 and password $4 aren't specified, a temporary -# (60 day) key is generated and used to sign the package. -sign_apk() { - local unsigned_apk="${1}" - local signed_apk="${2}" - if [[ $(stat_mtime "${unsigned_apk}") -gt \ - $(stat_mtime "${signed_apk}") ]]; then - local -r key_alias=$(basename ${signed_apk} .apk) - local keystore="${3}" - local key_password="${4}" - [[ "${keystore}" == "" ]] && keystore="${unsigned_apk}.keystore" - [[ "${key_password}" == "" ]] && \ - key_password="${key_alias}123456" - if [[ ! -e ${keystore} ]]; then - keytool -genkey -v -dname "cn=, ou=${key_alias}, o=fpl" \ - -storepass ${key_password} \ - -keypass ${key_password} -keystore ${keystore} \ - -alias ${key_alias} -keyalg RSA -keysize 2048 -validity 60 - fi - cp "${unsigned_apk}" "${signed_apk}" - jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 \ - -keystore ${keystore} -storepass ${key_password} \ - -keypass ${key_password} "${signed_apk}" ${key_alias} - fi -} - -# Build the apk $1 for package filename $2 in the current directory using the -# ant build target $3. -build_apk() { - local -r output_apk="${1}" - local -r package_filename="${2}" - local -r ant_target="${3}" - # Get the list of installed android targets and select the oldest target - # that is at least as new as BUILDAPK_ANDROID_TARGET_MINVERSION. - local -r android_build_target=$(select_android_build_target) - [[ "${android_build_target}" == "" ]] && exit 1 - echo "Building ${output_apk} for target ${android_build_target}" >&2 - - # Create / update build.xml and local.properties files. - if [[ $(stat_mtime "${android_manifest}") -gt \ - $(stat_mtime build.xml) ]]; then - android update project --target "${android_build_target}" \ - -n ${package_filename} --path . - fi - - # Use ant to build the apk. - ant -quiet ${ant_target} - - # Sign release apks with a temporary key as these packages will not be - # redistributed. - local unsigned_apk="bin/${package_filename}-${ant_target}-unsigned.apk" - if [[ "${ant_target}" == "release" ]]; then - sign_apk "${unsigned_apk}" "${output_apk}" "" "" - fi -} - -# Uninstall package $1 and install apk $2 on device $3 where $3 is "-s device" -# or an empty string. If $3 is an empty string adb will fail when multiple -# devices are connected to the host system. -install_apk() { - local -r uninstall_package_name="${1}" - local -r install_apk="${2}" - local -r adb_device="${3}" - # Uninstall the package if it's already installed. - adb ${adb_device} uninstall "${uninstall_package_name}" 1>&2 > /dev/null || \ - true # no error check - - # Install the apk. - # NOTE: The following works around adb not returning an error code when - # it fails to install an apk. - echo "Install ${install_apk}" >&2 - local -r adb_install_result=$(adb ${adb_device} install "${install_apk}") - echo "${adb_install_result}" - if echo "${adb_install_result}" | grep -qF 'Failure ['; then - exit 1 - fi -} - -# Launch previously installed package $1 on device $2. -# If $2 is an empty string adb will fail when multiple devices are connected -# to the host system. -launch_package() { - ( - # Determine the SDK version of Android on the device. - local -r android_sdk_version=$( - adb ${adb_device} shell cat system/build.prop | \ - awk -F= '/ro.build.version.sdk/ { - v=$2; sub(/[ \r\n]/, "", v); print v - }') - - # Clear logs from previous runs. - # Note that logcat does not just 'tail' the logs, it dumps the entire log - # history. - adb ${adb_device} logcat -c - - local finished_msg='Displayed '"${package_name}" - local timeout_msg='Activity destroy timeout.*'"${package_name}" - # Maximum time to wait before stopping log monitoring. 0 = infinity. - local launch_timeout=0 - # If this is a Gingerbread device, kill log monitoring after 10 seconds. - if [[ $((android_sdk_version)) -le 10 ]]; then - launch_timeout=10 - fi - # Display logcat in the background. - # Stop displaying the log when the app launch / execution completes or the - # logcat - ( - adb ${adb_device} logcat | \ - awk " - { - print \$0 - } - - /ActivityManager.*: ${finished_msg}/ { - exit 0 - } - - /ActivityManager.*: ${timeout_msg}/ { - exit 0 - }" & - adb_logcat_pid=$!; - if [[ $((launch_timeout)) -gt 0 ]]; then - sleep $((launch_timeout)); - kill ${adb_logcat_pid}; - else - wait ${adb_logcat_pid}; - fi - ) & - logcat_pid=$! - # Kill adb logcat if this shell exits. - trap "kill_process_group ${logcat_pid}" SIGINT SIGTERM EXIT - - # If the SDK is newer than 10, "am" supports stopping an activity. - adb_stop_activity= - if [[ $((android_sdk_version)) -gt 10 ]]; then - adb_stop_activity=-S - fi - - # Launch the activity and wait for it to complete. - adb ${adb_device} shell am start ${adb_stop_activity} -n \ - ${package_name}/android.app.NativeActivity - - wait "${logcat_pid}" - ) -} - -# See usage(). -main() { - # Parse arguments for this script. - local adb_device= - local ant_target=release - local disable_deploy=0 - local disable_build=0 - local run_debugger=0 - local launch=1 - local build_package=1 - for opt; do - case ${opt} in - # NDK_DEBUG=0 tells ndk-build to build this as debuggable but to not - # modify the underlying code whereas NDK_DEBUG=1 also builds as debuggable - # but does modify the code - NDK_DEBUG=1) ant_target=debug ;; - NDK_DEBUG=0) ant_target=debug ;; - ADB_DEVICE*) adb_device="$(\ - echo "${opt}" | sed -E 's/^ADB_DEVICE=([^ ]+)$/-s \1/;t;s/.*//')" ;; - BUILD=0) disable_build=1 ;; - DEPLOY=0) disable_deploy=1 ;; - RUN_DEBUGGER=1) run_debugger=1 ;; - LAUNCH=0) launch=0 ;; - clean) build_package=0 disable_deploy=1 launch=0 ;; - -h|--help|help) usage ;; - esac - done - - # If a target device hasn't been specified and multiple devices are connected - # to the host machine, display an error. - local -r devices_connected=$(get_number_of_devices_connected) - if [[ "${adb_device}" == "" && $((devices_connected)) -gt 1 && \ - ($((disable_deploy)) -eq 0 || $((launch)) -ne 0 || \ - $((run_debugger)) -ne 0) ]]; then - if [[ $((disable_deploy)) -ne 0 ]]; then - echo "Deployment enabled, disable using DEPLOY=0" >&2 - fi - if [[ $((launch)) -ne 0 ]]; then - echo "Launch enabled." >&2 - fi - if [[ $((disable_deploy)) -eq 0 ]]; then - echo "Deployment enabled." >&2 - fi - if [[ $((run_debugger)) -ne 0 ]]; then - echo "Debugger launch enabled." >&2 - fi - echo " -Multiple Android devices are connected to this host. Either disable deployment -and execution of the built .apk using: - \"${script_name} DEPLOY=0 LAUNCH=0\" - -or specify a device to deploy to using: - \"${script_name} ADB_DEVICE=\${device_serial}\". - -The Android devices connected to this machine are: -$(adb devices -l) -" >&2 - exit 1 - fi - - if [[ $((disable_build)) -eq 0 ]]; then - # Build the native target. - build_native_targets "$@" - fi - - # Get the package name from the manifest. - local -r package_name=$(get_package_name_from_manifest "${android_manifest}") - if [[ "${package_name}" == "" ]]; then - echo -e "No package name specified in ${android_manifest},"\ - "skipping apk build, deploy" - "\nand launch steps." >&2 - exit 0 - fi - local -r package_basename=${package_name/*./} - local package_filename=$(get_library_name_from_manifest ${android_manifest}) - [[ "${package_filename}" == "" ]] && package_filename="${package_basename}" - - # Output apk name. - local -r output_apk="bin/${package_filename}-${ant_target}.apk" - - if [[ $((disable_build)) -eq 0 && $((build_package)) -eq 1 ]]; then - # Build the apk. - build_apk "${output_apk}" "${package_filename}" "${ant_target}" - fi - - # Deploy to the device. - if [[ $((disable_deploy)) -eq 0 ]]; then - install_apk "${package_name}" "${output_apk}" "${adb_device}" - fi - - if [[ "${ant_target}" == "debug" && $((run_debugger)) -eq 1 ]]; then - # Start debugging. - ndk-gdb ${adb_device} --start - elif [[ $((launch)) -eq 1 ]]; then - launch_package "${package_name}" "${adb_device}" - fi -} - -main "$@" diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar Binary files differnew file mode 100644 index 00000000..b4163b81 --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.jar diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..1e1168cf --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Jun 19 11:54:59 PDT 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-all.zip diff --git a/android/gradlew b/android/gradlew new file mode 100755 index 00000000..cccdd3d5 --- /dev/null +++ b/android/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/android/gradlew.bat b/android/gradlew.bat new file mode 100644 index 00000000..f9553162 --- /dev/null +++ b/android/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 0269dd3f..aec561a9 100755 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -39,6 +39,7 @@ LOCAL_SRC_FILES := src/idl_parser.cpp \ src/util.cpp \ src/code_generators.cpp LOCAL_STATIC_LIBRARIES := flatbuffers +LOCAL_ARM_MODE := arm include $(BUILD_STATIC_LIBRARY) # FlatBuffers test @@ -48,7 +49,7 @@ LOCAL_SRC_FILES := android/jni/main.cpp \ tests/test.cpp \ src/idl_gen_fbs.cpp \ src/idl_gen_general.cpp -LOCAL_LDLIBS := -llog -landroid +LOCAL_LDLIBS := -llog -landroid -latomic LOCAL_STATIC_LIBRARIES := android_native_app_glue flatbuffers_extra LOCAL_ARM_MODE := arm include $(BUILD_SHARED_LIBRARY) diff --git a/android/jni/Application.mk b/android/jni/Application.mk index 2fc9c737..ca9e8004 100755 --- a/android/jni/Application.mk +++ b/android/jni/Application.mk @@ -13,10 +13,8 @@ # 2. Altered source versions must be plainly marked as such, and must not be # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. -APP_PLATFORM := android-10 +APP_PLATFORM := android-9 APP_PROJECT_PATH := $(call my-dir)/.. -APP_STL := gnustl_static - +APP_STL ?= stlport_static APP_ABI := armeabi-v7a - APP_CPPFLAGS += -std=c++11 diff --git a/include/flatbuffers/base.h b/include/flatbuffers/base.h index 38127f0f..497a2a96 100644 --- a/include/flatbuffers/base.h +++ b/include/flatbuffers/base.h @@ -29,6 +29,8 @@ #include <functional> #endif +#include "flatbuffers/stl_emulation.h" + /// @cond FLATBUFFERS_INTERNAL #if __cplusplus <= 199711L && \ (!defined(_MSC_VER) || _MSC_VER < 1600) && \ @@ -173,5 +175,5 @@ inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) { return ((~buf_size) + 1) & (scalar_size - 1); } -} +} // namespace flatbuffers #endif // FLATBUFFERS_BASE_H_ diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index 9216cf4d..25a54798 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -816,10 +816,8 @@ class FlatBufferBuilder void PopBytes(size_t amount) { buf_.pop(amount); } template<typename T> void AssertScalarT() { - #ifndef FLATBUFFERS_CPP98_STL // The code assumes power of 2 sizes and endian-swap-ability. - static_assert(std::is_scalar<T>::value, "T must be a scalar type"); - #endif + static_assert(flatbuffers::is_scalar<T>::value, "T must be a scalar type"); } // Write a single aligned scalar to the buffer @@ -1182,6 +1180,22 @@ class FlatBufferBuilder } #endif + /// @brief Serialize values returned by a function into a FlatBuffer `vector`. + /// This is a convenience function that takes care of iteration for you. + /// @tparam T The data type of the `std::vector` elements. + /// @param f A function that takes the current iteration 0..vector_size-1, + /// and the state parameter returning any type that you can construct a + /// FlatBuffers vector out of. + /// @param state State passed to f. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template <typename T, typename F, typename S> Offset<Vector<T>> CreateVector( + size_t vector_size, F f, S *state) { + std::vector<T> elems(vector_size); + for (size_t i = 0; i < vector_size; i++) elems[i] = f(i, state); + return CreateVector(elems); + } + /// @brief Serialize a `std::vector<std::string>` into a FlatBuffer `vector`. /// This is a convenience function for a common case. /// @param v A const reference to the `std::vector` to serialize into the @@ -1226,7 +1240,6 @@ class FlatBufferBuilder return CreateVectorOfStructs<T>(vv.data(), vv.size()); } - #ifndef FLATBUFFERS_CPP98_STL /// @brief Serialize an array of structs into a FlatBuffer `vector`. /// @tparam T The data type of the struct array elements. @@ -1238,16 +1251,34 @@ class FlatBufferBuilder /// accessors. template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs( size_t vector_size, const std::function<void(size_t i, T *)> &filler) { - StartVector(vector_size * sizeof(T) / AlignOf<T>(), AlignOf<T>()); - T *structs = reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T))); + T* structs = StartVectorOfStructs<T>(vector_size); for (size_t i = 0; i < vector_size; i++) { filler(i, structs); structs++; } - return Offset<Vector<const T *>>(EndVector(vector_size)); + return EndVectorOfStructs<T>(vector_size); } #endif + /// @brief Serialize an array of structs into a FlatBuffer `vector`. + /// @tparam T The data type of the struct array elements. + /// @param[in] f A function that takes the current iteration 0..vector_size-1, + /// a pointer to the struct that must be filled and the state argument. + /// @param[in] state Arbitrary state to pass to f. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + /// This is mostly useful when flatbuffers are generated with mutation + /// accessors. + template <typename T, typename F, typename S> Offset<Vector<const T *>> + CreateVectorOfStructs(size_t vector_size, F f, S *state) { + T* structs = StartVectorOfStructs<T>(vector_size); + for (size_t i = 0; i < vector_size; i++) { + f(i, structs, state); + structs++; + } + return EndVectorOfStructs<T>(vector_size); + } + /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`. /// @tparam T The data type of the `std::vector` struct elements. /// @param[in]] v A const reference to the `std::vector` of structs to @@ -1508,6 +1539,21 @@ class FlatBufferBuilder // For use with CreateSharedString. Instantiated on first use only. typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap; StringOffsetMap *string_pool; + + private: + // Allocates space for a vector of structures. + // Must be completed with EndVectorOfStructs(). + template<typename T> const T* StartVectorOfStructs(size_t vector_size) { + StartVector(vector_size * sizeof(T) / AlignOf<T>(), AlignOf<T>()); + return reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T))); + } + + // End the vector of structues in the flatbuffers. + // Vector should have previously be started with StartVectorOfStructs(). + template<typename T> Offset<Vector<const T *>> EndVectorOfStructs( + size_t vector_size) { + return Offset<Vector<const T *>>(EndVector(vector_size)); + } }; /// @} diff --git a/include/flatbuffers/flexbuffers.h b/include/flatbuffers/flexbuffers.h index 67f82b94..15360375 100644 --- a/include/flatbuffers/flexbuffers.h +++ b/include/flatbuffers/flexbuffers.h @@ -18,6 +18,8 @@ #define FLATBUFFERS_FLEXBUFFERS_H_ #include <map> +// Used to select STL variant. +#include "flatbuffers/base.h" // We use the basic binary writing functions from the regular FlatBuffers. #include "flatbuffers/util.h" @@ -743,7 +745,7 @@ inline Reference GetRoot(const uint8_t *buffer, size_t size) { } inline Reference GetRoot(const std::vector<uint8_t> &buffer) { - return GetRoot(buffer.data(), buffer.size()); + return GetRoot(flatbuffers::vector_data(buffer), buffer.size()); } // Flags that configure how the Builder behaves. @@ -913,7 +915,7 @@ class Builder FLATBUFFERS_FINAL_CLASS { return CreateBlob(data, len, 0, TYPE_BLOB); } size_t Blob(const std::vector<uint8_t> &v) { - return CreateBlob(v.data(), v.size(), 0, TYPE_BLOB); + return CreateBlob(flatbuffers::vector_data(v), v.size(), 0, TYPE_BLOB); } // TODO(wvo): support all the FlexBuffer types (like flexbuffers::String), @@ -957,11 +959,15 @@ class Builder FLATBUFFERS_FINAL_CLASS { // step automatically when appliccable, and encourage people to write in // sorted fashion. // std::sort is typically already a lot faster on sorted data though. - auto dict = reinterpret_cast<TwoValue *>(stack_.data() + start); + auto dict = + reinterpret_cast<TwoValue *>(flatbuffers::vector_data(stack_) + + start); std::sort(dict, dict + len, [&](const TwoValue &a, const TwoValue &b) -> bool { - auto as = reinterpret_cast<const char *>(buf_.data() + a.key.u_); - auto bs = reinterpret_cast<const char *>(buf_.data() + b.key.u_); + auto as = reinterpret_cast<const char *>( + flatbuffers::vector_data(buf_) + a.key.u_); + auto bs = reinterpret_cast<const char *>( + flatbuffers::vector_data(buf_) + b.key.u_); auto comp = strcmp(as, bs); // If this assertion hits, you've added two keys with the same value to // this map. @@ -986,13 +992,25 @@ class Builder FLATBUFFERS_FINAL_CLASS { f(); return EndVector(start, false, false); } + template <typename F, typename T> size_t Vector(F f, T &state) { + auto start = StartVector(); + f(state); + return EndVector(start, false, false); + } template<typename F> size_t Vector(const char *key, F f) { auto start = StartVector(key); f(); return EndVector(start, false, false); } + template <typename F, typename T> size_t Vector(const char *key, F f, + T &state) { + auto start = StartVector(key); + f(state); + return EndVector(start, false, false); + } + template<typename T> void Vector(const T *elems, size_t len) { - if (std::is_scalar<T>::value) { + if (flatbuffers::is_scalar<T>::value) { // This path should be a lot quicker and use less space. ScalarVector(elems, len, false); } else { @@ -1007,7 +1025,7 @@ class Builder FLATBUFFERS_FINAL_CLASS { Vector(elems, len); } template<typename T> void Vector(const std::vector<T> &vec) { - Vector(vec.data(), vec.size()); + Vector(flatbuffers::vector_data(vec), vec.size()); } template<typename F> size_t TypedVector(F f) { @@ -1015,18 +1033,29 @@ class Builder FLATBUFFERS_FINAL_CLASS { f(); return EndVector(start, true, false); } + template <typename F, typename T> size_t TypedVector(F f, T &state) { + auto start = StartVector(); + f(state); + return EndVector(start, true, false); + } template<typename F> size_t TypedVector(const char *key, F f) { auto start = StartVector(key); f(); return EndVector(start, true, false); } + template <typename F, typename T> size_t TypedVector(const char *key, F f, + T &state) { + auto start = StartVector(key); + f(state); + return EndVector(start, true, false); + } template<typename T> size_t FixedTypedVector(const T *elems, size_t len) { // We only support a few fixed vector lengths. Anything bigger use a // regular typed vector. assert(len >= 2 && len <= 4); // And only scalar values. - assert(std::is_scalar<T>::value); + assert(flatbuffers::is_scalar<T>::value); return ScalarVector(elems, len, true); } @@ -1041,11 +1070,22 @@ class Builder FLATBUFFERS_FINAL_CLASS { f(); return EndMap(start); } + template <typename F, typename T> size_t Map(F f, T &state) { + auto start = StartMap(); + f(state); + return EndMap(start); + } template<typename F> size_t Map(const char *key, F f) { auto start = StartMap(key); f(); return EndMap(start); } + template <typename F, typename T> size_t Map(const char *key, F f, + T &state) { + auto start = StartMap(key); + f(state); + return EndMap(start); + } template<typename T> void Map(const std::map<std::string, T> &map) { auto start = StartMap(); for (auto it = map.begin(); it != map.end(); ++it) @@ -1174,10 +1214,10 @@ class Builder FLATBUFFERS_FINAL_CLASS { } template<typename T> static Type GetScalarType() { - assert(std::is_scalar<T>::value); - return std::is_floating_point<T>::value + assert(flatbuffers::is_scalar<T>::value); + return flatbuffers::is_floating_point<T>::value ? TYPE_FLOAT - : (std::is_unsigned<T>::value ? TYPE_UINT : TYPE_INT); + : (flatbuffers::is_unsigned<T>::value ? TYPE_UINT : TYPE_INT); } struct Value { @@ -1364,9 +1404,11 @@ class Builder FLATBUFFERS_FINAL_CLASS { struct KeyOffsetCompare { KeyOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {} - bool operator() (size_t a, size_t b) const { - auto stra = reinterpret_cast<const char *>(buf_->data() + a); - auto strb = reinterpret_cast<const char *>(buf_->data() + b); + bool operator()(size_t a, size_t b) const { + auto stra = + reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + a); + auto strb = + reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + b); return strcmp(stra, strb) < 0; } const std::vector<uint8_t> *buf_; @@ -1375,9 +1417,11 @@ class Builder FLATBUFFERS_FINAL_CLASS { typedef std::pair<size_t, size_t> StringOffset; struct StringOffsetCompare { StringOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {} - bool operator() (const StringOffset &a, const StringOffset &b) const { - auto stra = reinterpret_cast<const char *>(buf_->data() + a.first); - auto strb = reinterpret_cast<const char *>(buf_->data() + b.first); + bool operator()(const StringOffset &a, const StringOffset &b) const { + auto stra = reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + + a.first); + auto strb = reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + + b.first); return strncmp(stra, strb, std::min(a.second, b.second) + 1) < 0; } const std::vector<uint8_t> *buf_; diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index 4e27e30c..0f500243 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -20,13 +20,17 @@ #include <map> #include <stack> #include <memory> -#include <functional> +#include "flatbuffers/base.h" #include "flatbuffers/flatbuffers.h" #include "flatbuffers/hash.h" #include "flatbuffers/reflection.h" #include "flatbuffers/flexbuffers.h" +#if !defined(FLATBUFFERS_CPP98_STL) + #include <functional> +#endif // !defined(FLATBUFFERS_CPP98_STL) + // This file defines the data types representing a parsed IDL (Interface // Definition Language) / schema file. @@ -164,7 +168,7 @@ template<typename T> class SymbolTable { } bool Add(const std::string &name, T *e) { - vec.emplace_back(e); + vector_emplace_back(&vec, e); auto it = dict.find(name); if (it != dict.end()) return true; dict[name] = e; @@ -571,15 +575,32 @@ private: FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field, size_t parent_fieldn, const StructDef *parent_struct_def); + #if defined(FLATBUFFERS_CPP98_STL) + typedef CheckedError (*ParseTableDelimitersBody)( + const std::string &name, size_t &fieldn, const StructDef *struct_def, + void *state); + #else + typedef std::function<CheckedError(const std::string&, size_t&, + const StructDef*, void*)> + ParseTableDelimitersBody; + #endif // defined(FLATBUFFERS_CPP98_STL) FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn, const StructDef *struct_def, - const std::function<CheckedError(const std::string &name)> &body); + ParseTableDelimitersBody body, + void *state); FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def, std::string *value, uoffset_t *ovalue); void SerializeStruct(const StructDef &struct_def, const Value &val); void AddVector(bool sortbysize, int count); - FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(size_t &count, - const std::function<CheckedError()> &body); + #if defined(FLATBUFFERS_CPP98_STL) + typedef CheckedError (*ParseVectorDelimitersBody)(size_t &count, + void *state); + #else + typedef std::function<CheckedError(size_t&, void*)> + ParseVectorDelimitersBody; + #endif // defined(FLATBUFFERS_CPP98_STL) + FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters( + size_t &count, ParseVectorDelimitersBody body, void *state); FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue); FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes); FLATBUFFERS_CHECKED_ERROR TryTypedValue(int dtoken, bool check, Value &e, diff --git a/include/flatbuffers/reflection.h b/include/flatbuffers/reflection.h index aab9f208..ad5c4562 100644 --- a/include/flatbuffers/reflection.h +++ b/include/flatbuffers/reflection.h @@ -361,12 +361,13 @@ template<typename T, typename U> class pointer_inside_vector { public: pointer_inside_vector(T *ptr, std::vector<U> &vec) : offset_(reinterpret_cast<uint8_t *>(ptr) - - reinterpret_cast<uint8_t *>(vec.data())), + reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec))), vec_(vec) {} T *operator*() const { return reinterpret_cast<T *>( - reinterpret_cast<uint8_t *>(vec_.data()) + offset_); + reinterpret_cast<uint8_t *>( + flatbuffers::vector_data(vec_)) + offset_); } T *operator->() const { return operator*(); @@ -418,7 +419,6 @@ uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize, uoffset_t elem_size, std::vector<uint8_t> *flatbuf, const reflection::Object *root_table = nullptr); -#ifndef FLATBUFFERS_CPP98_STL template <typename T> void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val, const Vector<T> *vec, std::vector<uint8_t> *flatbuf, @@ -432,7 +432,7 @@ void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val, // Set new elements to "val". for (int i = 0; i < delta_elem; i++) { auto loc = newelems + i * sizeof(T); - auto is_scalar = std::is_scalar<T>::value; + auto is_scalar = flatbuffers::is_scalar<T>::value; if (is_scalar) { WriteScalar(loc, val); } else { // struct @@ -440,7 +440,6 @@ void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val, } } } -#endif // Adds any new data (in the form of a new FlatBuffer) to an existing // FlatBuffer. This can be used when any of the above methods are not diff --git a/include/flatbuffers/registry.h b/include/flatbuffers/registry.h index 9a227682..35771c18 100644 --- a/include/flatbuffers/registry.h +++ b/include/flatbuffers/registry.h @@ -107,7 +107,7 @@ class Registry { } // Parse schema. parser->opts = opts_; - if (!parser->Parse(schematext.c_str(), include_paths_.data(), + if (!parser->Parse(schematext.c_str(), vector_data(include_paths_), schema.path_.c_str())) { lasterror_ = parser->error_; return false; diff --git a/include/flatbuffers/stl_emulation.h b/include/flatbuffers/stl_emulation.h new file mode 100644 index 00000000..7906648b --- /dev/null +++ b/include/flatbuffers/stl_emulation.h @@ -0,0 +1,215 @@ +/* + * Copyright 2017 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_STL_EMULATION_H_ +#define FLATBUFFERS_STL_EMULATION_H_ + +#include <string> +#include <type_traits> +#include <vector> + +#if defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL) + #define FLATBUFFERS_CPP98_STL +#endif // defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL) + +#if defined(FLATBUFFERS_CPP98_STL) + #include <cctype> +#endif // defined(FLATBUFFERS_CPP98_STL) + +// This header provides backwards compatibility for C++98 STLs like stlport. +namespace flatbuffers { + +// Retrieve ::back() from a string in a way that is compatible with pre C++11 +// STLs (e.g stlport). +inline char string_back(const std::string &value) { + return value[value.length() - 1]; +} + +// Helper method that retrieves ::data() from a vector in a way that is +// compatible with pre C++11 STLs (e.g stlport). +template <typename T> inline T *vector_data(std::vector<T> &vector) { + return &(vector[0]); +} + +template <typename T> inline const T *vector_data( + const std::vector<T> &vector) { + return &(vector[0]); +} + +template <typename T, typename V> +inline void vector_emplace_back(std::vector<T> *vector, V &&data) { + #if defined(FLATBUFFERS_CPP98_STL) + vector->push_back(data); + #else + vector->emplace_back(std::forward<V>(data)); + #endif // defined(FLATBUFFERS_CPP98_STL) +} + +#ifndef FLATBUFFERS_CPP98_STL + #if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */) + template <typename T> + using numeric_limits = std::numeric_limits<T>; + #else + template <typename T> class numeric_limits : + public std::numeric_limits<T> {}; + #endif // !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */) +#else + template <typename T> class numeric_limits : + public std::numeric_limits<T> {}; + + template <> class numeric_limits<unsigned long long> { + public: + static unsigned long long min() { return 0ULL; } + static unsigned long long max() { return ~0ULL; } + }; + + template <> class numeric_limits<long long> { + public: + static long long min() { + return static_cast<long long>(1ULL << ((sizeof(long long) << 3) - 1)); + } + static long long max() { + return static_cast<long long>( + (1ULL << ((sizeof(long long) << 3) - 1)) - 1); + } + }; +#endif // FLATBUFFERS_CPP98_STL + +#if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */) + #ifndef FLATBUFFERS_CPP98_STL + template <typename T> using is_scalar = std::is_scalar<T>; + template <typename T> using is_floating_point = std::is_floating_point<T>; + template <typename T> using is_unsigned = std::is_unsigned<T>; + #else + // Map C++ TR1 templates defined by stlport. + template <typename T> using is_scalar = std::tr1::is_scalar<T>; + template <typename T> using is_floating_point = + std::tr1::is_floating_point<T>; + template <typename T> using is_unsigned = std::tr1::is_unsigned<T>; + #endif // !FLATBUFFERS_CPP98_STL +#else + // MSVC 2010 doesn't support C++11 aliases. + template <typename T> struct is_scalar : public std::is_scalar<T> {}; + template <typename T> struct is_floating_point : + public std::is_floating_point<T> {}; + template <typename T> struct is_unsigned : public std::is_unsigned<T> {}; +#endif // !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */) + +#ifndef FLATBUFFERS_CPP98_STL + #if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */) + template <class T> using unique_ptr = std::unique_ptr<T>; + #else + // MSVC 2010 doesn't support C++11 aliases. + // We're manually "aliasing" the class here as we want to bring unique_ptr + // into the flatbuffers namespace. We have unique_ptr in the flatbuffers + // namespace we have a completely independent implemenation (see below) + // for C++98 STL implementations. + template <class T> class unique_ptr : public std::unique_ptr<T> { + public: + unique_ptr() {} + explicit unique_ptr(T* p) : std::unique_ptr<T>(p) {} + unique_ptr(std::unique_ptr<T>&& u) { *this = std::move(u); } + unique_ptr(unique_ptr&& u) { *this = std::move(u); } + unique_ptr& operator=(std::unique_ptr<T>&& u) { + std::unique_ptr<T>::reset(u.release()); + return *this; + } + unique_ptr& operator=(unique_ptr&& u) { + std::unique_ptr<T>::reset(u.release()); + return *this; + } + unique_ptr& operator=(T* p) { + return std::unique_ptr<T>::operator=(p); + } + }; + #endif // !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */) +#else + // Very limited implementation of unique_ptr. + // This is provided simply to allow the C++ code generated from the default + // settings to function in C++98 environments with no modifications. + template <class T> class unique_ptr { + public: + typedef T element_type; + + unique_ptr() : ptr_(nullptr) {} + explicit unique_ptr(T* p) : ptr_(p) {} + unique_ptr(unique_ptr&& u) : ptr_(nullptr) { reset(u.release()); } + unique_ptr(const unique_ptr& u) : ptr_(nullptr) { + reset(const_cast<unique_ptr*>(&u)->release()); + } + ~unique_ptr() { reset(); } + + unique_ptr& operator=(const unique_ptr& u) { + reset(const_cast<unique_ptr*>(&u)->release()); + return *this; + } + + unique_ptr& operator=(unique_ptr&& u) { + reset(u.release()); + return *this; + } + + unique_ptr& operator=(T* p) { + reset(p); + return *this; + } + + const T& operator*() const { return ptr_; } + T* operator->() const { return ptr_; } + T* get() const noexcept { return ptr_; } + explicit operator bool() const { return ptr_ != nullptr; } + + // modifiers + T* release() { + T* value = ptr_; + ptr_ = nullptr; + return value; + } + + void reset(T* p = nullptr) { + T* value = ptr_; + ptr_ = p; + if (value) delete value; + } + + void swap(unique_ptr& u) { + T* temp_ptr = ptr_; + ptr_ = u.ptr_; + u.ptr_ = temp_ptr; + } + + private: + T* ptr_; + }; + + template <class T> bool operator==(const unique_ptr<T>& x, + const unique_ptr<T>& y) { + return x.get() == y.get(); + } + + template <class T, class D> bool operator==(const unique_ptr<T>& x, + const D* y) { + return static_cast<D*>(x.get()) == y; + } + + template <class T> bool operator==(const unique_ptr<T>& x, intptr_t y) { + return reinterpret_cast<intptr_t>(x.get()) == y; + } +#endif // !FLATBUFFERS_CPP98_STL + +} // namespace flatbuffers + +#endif // FLATBUFFERS_STL_EMULATION_H_ diff --git a/include/flatbuffers/util.h b/include/flatbuffers/util.h index ee62b86d..6b7b7bc3 100644 --- a/include/flatbuffers/util.h +++ b/include/flatbuffers/util.h @@ -60,6 +60,20 @@ template<> inline std::string NumToString<signed char>(signed char t) { template<> inline std::string NumToString<unsigned char>(unsigned char t) { return NumToString(static_cast<int>(t)); } +#if defined(FLATBUFFERS_CPP98_STL) + template <> inline std::string NumToString<long long>(long long t) { + char buf[21]; // (log((1 << 63) - 1) / log(10)) + 2 + snprintf(buf, sizeof(buf), "%lld", t); + return std::string(buf); + } + + template <> inline std::string NumToString<unsigned long long>( + unsigned long long t) { + char buf[22]; // (log((1 << 63) - 1) / log(10)) + 1 + snprintf(buf, sizeof(buf), "%llu", t); + return std::string(buf); + } +#endif // defined(FLATBUFFERS_CPP98_STL) // Special versions for floats/doubles. template<> inline std::string NumToString<double>(double t) { @@ -202,9 +216,10 @@ inline std::string ConCatPathFileName(const std::string &path, const std::string &filename) { std::string filepath = path; if (filepath.length()) { - if (filepath.back() == kPathSeparatorWindows) { - filepath.back() = kPathSeparator; - } else if (filepath.back() != kPathSeparator) { + char filepath_last_character = string_back(filepath); + if (filepath_last_character == kPathSeparatorWindows) { + filepath_last_character = kPathSeparator; + } else if (filepath_last_character != kPathSeparator) { filepath += kPathSeparator; } } diff --git a/samples/android/AndroidManifest.xml b/samples/android/AndroidManifest.xml index 0fa3dcfc..352e0fad 100755 --- a/samples/android/AndroidManifest.xml +++ b/samples/android/AndroidManifest.xml @@ -17,17 +17,14 @@ --> <!-- BEGIN_INCLUDE(manifest) --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.samples.FlatBufferSample" - android:versionCode="1" - android:versionName="1.0"> + package="com.samples.FlatBufferSample"> <uses-feature android:glEsVersion="0x00020000"></uses-feature> - <!-- This is the platform API where NativeActivity was introduced. --> - <uses-sdk android:minSdkVersion="9" /> <!-- This .apk has no Java code itself, so set hasCode to false. --> - <application android:label="@string/app_name" android:hasCode="false"> - + <application android:label="@string/app_name" + android:hasCode="false" + android:allowBackup="false"> <!-- Our activity is the built-in NativeActivity framework class. This will take care of integrating with our NDK code. --> <activity android:name="android.app.NativeActivity" diff --git a/samples/android/build.gradle b/samples/android/build.gradle new file mode 100644 index 00000000..e6af6d6f --- /dev/null +++ b/samples/android/build.gradle @@ -0,0 +1,108 @@ +// Copyright (c) 2017 Google, Inc. +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.0' + } +} + +allprojects { + repositories { + jcenter() + } +} + +apply plugin: 'com.android.application' + +android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + + sourceSets { + main { + manifest.srcFile 'AndroidManifest.xml' + res.srcDirs = ['res'] + } + } + + externalNativeBuild { + ndkBuild { + path "jni/Android.mk" + } + } + + defaultConfig { + applicationId 'com.samples.FlatBufferSample' + // This is the platform API where NativeActivity was introduced. + minSdkVersion 9 + targetSdkVersion 25 + versionCode 1 + versionName "1.0" + + buildTypes { + release { + minifyEnabled false + } + } + + externalNativeBuild { + ndkBuild { + targets "FlatBufferSample" + arguments "-j" + Runtime.getRuntime().availableProcessors() + abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86", "x86_64" + } + } + } + + lintOptions { + abortOnError false + } + + // Build with each STL variant. + productFlavors { + stlport { + applicationIdSuffix ".stlport" + versionNameSuffix "-stlport" + externalNativeBuild { + ndkBuild { + arguments "APP_STL=stlport_static" + } + } + } + gnustl { + applicationIdSuffix ".gnustl" + versionNameSuffix "-gnustl" + externalNativeBuild { + ndkBuild { + arguments "APP_STL=gnustl_static" + } + } + } + libcpp { + applicationIdSuffix ".libcpp" + versionNameSuffix "-libcpp" + externalNativeBuild { + ndkBuild { + arguments "APP_STL=c++_static" + } + } + } + } +} diff --git a/samples/android/build_apk.sh b/samples/android/build_apk.sh deleted file mode 100755 index 1b9f4a45..00000000 --- a/samples/android/build_apk.sh +++ /dev/null @@ -1,511 +0,0 @@ -#!/bin/bash -eu -# -# Copyright (c) 2013 Google, Inc. -# -# This software is provided 'as-is', without any express or implied -# warranty. In no event will the authors be held liable for any damages -# arising from the use of this software. -# Permission is granted to anyone to use this software for any purpose, -# including commercial applications, and to alter it and redistribute it -# freely, subject to the following restrictions: -# 1. The origin of this software must not be misrepresented; you must not -# claim that you wrote the original software. If you use this software -# in a product, an acknowledgment in the product documentation would be -# appreciated but is not required. -# 2. Altered source versions must be plainly marked as such, and must not be -# misrepresented as being the original software. -# 3. This notice may not be removed or altered from any source distribution. -# -# Build, deploy, debug / execute a native Android package based upon -# NativeActivity. - -declare -r script_directory=$(dirname $0) -declare -r android_root=${script_directory}/../../../../../../ -declare -r script_name=$(basename $0) -declare -r android_manifest=AndroidManifest.xml -declare -r os_name=$(uname -s) - -# Minimum Android target version supported by this project. -: ${BUILDAPK_ANDROID_TARGET_MINVERSION:=10} -# Directory containing the Android SDK -# (http://developer.android.com/sdk/index.html). -: ${ANDROID_SDK_HOME:=} -# Directory containing the Android NDK -# (http://developer.android.com/tools/sdk/ndk/index.html). -: ${NDK_HOME:=} - -# Display script help and exit. -usage() { - echo " -Build the Android package in the current directory and deploy it to a -connected device. - -Usage: ${script_name} \\ - [ADB_DEVICE=serial_number] [BUILD=0] [DEPLOY=0] [RUN_DEBUGGER=1] \ - [LAUNCH=0] [SWIG_BIN=swig_binary_directory] [SWIG_LIB=swig_include_directory] [ndk-build arguments ...] - -ADB_DEVICE=serial_number: - serial_number specifies the device to deploy the built apk to if multiple - Android devices are connected to the host. -BUILD=0: - Disables the build of the package. -DEPLOY=0: - Disables the deployment of the built apk to the Android device. -RUN_DEBUGGER=1: - Launches the application in gdb after it has been deployed. To debug in - gdb, NDK_DEBUG=1 must also be specified on the command line to build a - debug apk. -LAUNCH=0: - Disable the launch of the apk on the Android device. -SWIG_BIN=swig_binary_directory: - The directory where the SWIG binary lives. No need to set this if SWIG is - installed and point to from your PATH variable. -SWIG_LIB=swig_include_directory: - The directory where SWIG shared include files are, usually obtainable from - commandline with \"swig -swiglib\". No need to set this if SWIG is installed - and point to from your PATH variable. -ndk-build arguments...: - Additional arguments for ndk-build. See ndk-build -h for more information. -" >&2 - exit 1 -} - -# Get the number of CPU cores present on the host. -get_number_of_cores() { - case ${os_name} in - Darwin) - sysctl hw.ncpu | awk '{ print $2 }' - ;; - CYGWIN*|Linux) - awk '/^processor/ { n=$3 } END { print n + 1 }' /proc/cpuinfo - ;; - *) - echo 1 - ;; - esac -} - -# Get the package name from an AndroidManifest.xml file. -get_package_name_from_manifest() { - xmllint --xpath 'string(/manifest/@package)' "${1}" -} - -# Get the library name from an AndroidManifest.xml file. -get_library_name_from_manifest() { - echo "\ -setns android=http://schemas.android.com/apk/res/android -xpath string(/manifest/application/activity\ -[@android:name=\"android.app.NativeActivity\"]/meta-data\ -[@android:name=\"android.app.lib_name\"]/@android:value)" | - xmllint --shell "${1}" | awk '/Object is a string/ { print $NF }' -} - -# Get the number of Android devices connected to the system. -get_number_of_devices_connected() { - adb devices -l | \ - awk '/^..*$/ { if (p) { print $0 } } - /List of devices attached/ { p = 1 }' | \ - wc -l - return ${PIPESTATUS[0]} -} - -# Kill a process and its' children. This is provided for cygwin which -# doesn't ship with pkill. -kill_process_group() { - local parent_pid="${1}" - local child_pid= - for child_pid in $(ps -f | \ - awk '{ if ($3 == '"${parent_pid}"') { print $2 } }'); do - kill_process_group "${child_pid}" - done - kill "${parent_pid}" 2>/dev/null -} - -# Find and run "adb". -adb() { - local adb_path= - for path in "$(which adb 2>/dev/null)" \ - "${ANDROID_SDK_HOME}/sdk/platform-tools/adb" \ - "${android_root}/prebuilts/sdk/platform-tools/adb"; do - if [[ -e "${path}" ]]; then - adb_path="${path}" - break - fi - done - if [[ "${adb_path}" == "" ]]; then - echo -e "Unable to find adb." \ - "\nAdd the Android ADT sdk/platform-tools directory to the" \ - "PATH." >&2 - exit 1 - fi - "${adb_path}" "$@" -} - -# Find and run "android". -android() { - local android_executable=android - if echo "${os_name}" | grep -q CYGWIN; then - android_executable=android.bat - fi - local android_path= - for path in "$(which ${android_executable})" \ - "${ANDROID_SDK_HOME}/sdk/tools/${android_executable}" \ - "${android_root}/prebuilts/sdk/tools/${android_executable}"; do - if [[ -e "${path}" ]]; then - android_path="${path}" - break - fi - done - if [[ "${android_path}" == "" ]]; then - echo -e "Unable to find android tool." \ - "\nAdd the Android ADT sdk/tools directory to the PATH." >&2 - exit 1 - fi - # Make sure ant is installed. - if [[ "$(which ant)" == "" ]]; then - echo -e "Unable to find ant." \ - "\nPlease install ant and add to the PATH." >&2 - exit 1 - fi - - "${android_path}" "$@" -} - -# Find and run "ndk-build" -ndkbuild() { - local ndkbuild_path= - for path in "$(which ndk-build 2>/dev/null)" \ - "${NDK_HOME}/ndk-build" \ - "${android_root}/prebuilts/ndk/current/ndk-build"; do - if [[ -e "${path}" ]]; then - ndkbuild_path="${path}" - break - fi - done - if [[ "${ndkbuild_path}" == "" ]]; then - echo -e "Unable to find ndk-build." \ - "\nAdd the Android NDK directory to the PATH." >&2 - exit 1 - fi - "${ndkbuild_path}" "$@" -} - -# Get file modification time of $1 in seconds since the epoch. -stat_mtime() { - local filename="${1}" - case ${os_name} in - Darwin) stat -f%m "${filename}" 2>/dev/null || echo 0 ;; - *) stat -c%Y "${filename}" 2>/dev/null || echo 0 ;; - esac -} - -# Build the native (C/C++) build targets in the current directory. -build_native_targets() { - # Save the list of output modules in the install directory so that it's - # possible to restore their timestamps after the build is complete. This - # works around a bug in ndk/build/core/setup-app.mk which results in the - # unconditional execution of the clean-installed-binaries rule. - restore_libraries="$(find libs -type f 2>/dev/null | \ - sed -E 's@^libs/(.*)@\1@')" - - # Build native code. - ndkbuild -j$(get_number_of_cores) "$@" - - # Restore installed libraries. - # Obviously this is a nasty hack (along with ${restore_libraries} above) as - # it assumes it knows where the NDK will be placing output files. - ( - IFS=$'\n' - for libpath in ${restore_libraries}; do - source_library="obj/local/${libpath}" - target_library="libs/${libpath}" - if [[ -e "${source_library}" ]]; then - cp -a "${source_library}" "${target_library}" - fi - done - ) -} - -# Select the oldest installed android build target that is at least as new as -# BUILDAPK_ANDROID_TARGET_MINVERSION. If a suitable build target isn't found, -# this function prints an error message and exits with an error. -select_android_build_target() { - local -r android_targets_installed=$( \ - android list targets | \ - awk -F'"' '/^id:.*android/ { print $2 }') - local android_build_target= - for android_target in $(echo "${android_targets_installed}" | \ - awk -F- '{ print $2 }' | sort -n); do - local isNumber='^[0-9]+$' - # skip preview API releases e.g. 'android-L' - if [[ $android_target =~ $isNumber ]]; then - if [[ $((android_target)) -ge \ - $((BUILDAPK_ANDROID_TARGET_MINVERSION)) ]]; then - android_build_target="android-${android_target}" - break - fi - # else - # The API version is a letter, so skip it. - fi - done - if [[ "${android_build_target}" == "" ]]; then - echo -e \ - "Found installed Android targets:" \ - "$(echo ${android_targets_installed} | sed 's/ /\n /g;s/^/\n /;')" \ - "\nAndroid SDK platform" \ - "android-$((BUILDAPK_ANDROID_TARGET_MINVERSION))" \ - "must be installed to build this project." \ - "\nUse the \"android\" application to install API" \ - "$((BUILDAPK_ANDROID_TARGET_MINVERSION)) or newer." >&2 - exit 1 - fi - echo "${android_build_target}" -} - -# Sign unsigned apk $1 and write the result to $2 with key store file $3 and -# password $4. -# If a key store file $3 and password $4 aren't specified, a temporary -# (60 day) key is generated and used to sign the package. -sign_apk() { - local unsigned_apk="${1}" - local signed_apk="${2}" - if [[ $(stat_mtime "${unsigned_apk}") -gt \ - $(stat_mtime "${signed_apk}") ]]; then - local -r key_alias=$(basename ${signed_apk} .apk) - local keystore="${3}" - local key_password="${4}" - [[ "${keystore}" == "" ]] && keystore="${unsigned_apk}.keystore" - [[ "${key_password}" == "" ]] && \ - key_password="${key_alias}123456" - if [[ ! -e ${keystore} ]]; then - keytool -genkey -v -dname "cn=, ou=${key_alias}, o=fpl" \ - -storepass ${key_password} \ - -keypass ${key_password} -keystore ${keystore} \ - -alias ${key_alias} -keyalg RSA -keysize 2048 -validity 60 - fi - cp "${unsigned_apk}" "${signed_apk}" - jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 \ - -keystore ${keystore} -storepass ${key_password} \ - -keypass ${key_password} "${signed_apk}" ${key_alias} - fi -} - -# Build the apk $1 for package filename $2 in the current directory using the -# ant build target $3. -build_apk() { - local -r output_apk="${1}" - local -r package_filename="${2}" - local -r ant_target="${3}" - # Get the list of installed android targets and select the oldest target - # that is at least as new as BUILDAPK_ANDROID_TARGET_MINVERSION. - local -r android_build_target=$(select_android_build_target) - [[ "${android_build_target}" == "" ]] && exit 1 - echo "Building ${output_apk} for target ${android_build_target}" >&2 - - # Create / update build.xml and local.properties files. - if [[ $(stat_mtime "${android_manifest}") -gt \ - $(stat_mtime build.xml) ]]; then - android update project --target "${android_build_target}" \ - -n ${package_filename} --path . - fi - - # Use ant to build the apk. - ant -quiet ${ant_target} - - # Sign release apks with a temporary key as these packages will not be - # redistributed. - local unsigned_apk="bin/${package_filename}-${ant_target}-unsigned.apk" - if [[ "${ant_target}" == "release" ]]; then - sign_apk "${unsigned_apk}" "${output_apk}" "" "" - fi -} - -# Uninstall package $1 and install apk $2 on device $3 where $3 is "-s device" -# or an empty string. If $3 is an empty string adb will fail when multiple -# devices are connected to the host system. -install_apk() { - local -r uninstall_package_name="${1}" - local -r install_apk="${2}" - local -r adb_device="${3}" - # Uninstall the package if it's already installed. - adb ${adb_device} uninstall "${uninstall_package_name}" 1>&2 > /dev/null || \ - true # no error check - - # Install the apk. - # NOTE: The following works around adb not returning an error code when - # it fails to install an apk. - echo "Install ${install_apk}" >&2 - local -r adb_install_result=$(adb ${adb_device} install "${install_apk}") - echo "${adb_install_result}" - if echo "${adb_install_result}" | grep -qF 'Failure ['; then - exit 1 - fi -} - -# Launch previously installed package $1 on device $2. -# If $2 is an empty string adb will fail when multiple devices are connected -# to the host system. -launch_package() { - ( - # Determine the SDK version of Android on the device. - local -r android_sdk_version=$( - adb ${adb_device} shell cat system/build.prop | \ - awk -F= '/ro.build.version.sdk/ { - v=$2; sub(/[ \r\n]/, "", v); print v - }') - - # Clear logs from previous runs. - # Note that logcat does not just 'tail' the logs, it dumps the entire log - # history. - adb ${adb_device} logcat -c - - local finished_msg='Displayed '"${package_name}" - local timeout_msg='Activity destroy timeout.*'"${package_name}" - # Maximum time to wait before stopping log monitoring. 0 = infinity. - local launch_timeout=0 - # If this is a Gingerbread device, kill log monitoring after 10 seconds. - if [[ $((android_sdk_version)) -le 10 ]]; then - launch_timeout=10 - fi - # Display logcat in the background. - # Stop displaying the log when the app launch / execution completes or the - # logcat - ( - adb ${adb_device} logcat | \ - awk " - { - print \$0 - } - - /ActivityManager.*: ${finished_msg}/ { - exit 0 - } - - /ActivityManager.*: ${timeout_msg}/ { - exit 0 - }" & - adb_logcat_pid=$!; - if [[ $((launch_timeout)) -gt 0 ]]; then - sleep $((launch_timeout)); - kill ${adb_logcat_pid}; - else - wait ${adb_logcat_pid}; - fi - ) & - logcat_pid=$! - # Kill adb logcat if this shell exits. - trap "kill_process_group ${logcat_pid}" SIGINT SIGTERM EXIT - - # If the SDK is newer than 10, "am" supports stopping an activity. - adb_stop_activity= - if [[ $((android_sdk_version)) -gt 10 ]]; then - adb_stop_activity=-S - fi - - # Launch the activity and wait for it to complete. - adb ${adb_device} shell am start ${adb_stop_activity} -n \ - ${package_name}/android.app.NativeActivity - - wait "${logcat_pid}" - ) -} - -# See usage(). -main() { - # Parse arguments for this script. - local adb_device= - local ant_target=release - local disable_deploy=0 - local disable_build=0 - local run_debugger=0 - local launch=1 - local build_package=1 - for opt; do - case ${opt} in - # NDK_DEBUG=0 tells ndk-build to build this as debuggable but to not - # modify the underlying code whereas NDK_DEBUG=1 also builds as debuggable - # but does modify the code - NDK_DEBUG=1) ant_target=debug ;; - NDK_DEBUG=0) ant_target=debug ;; - ADB_DEVICE*) adb_device="$(\ - echo "${opt}" | sed -E 's/^ADB_DEVICE=([^ ]+)$/-s \1/;t;s/.*//')" ;; - BUILD=0) disable_build=1 ;; - DEPLOY=0) disable_deploy=1 ;; - RUN_DEBUGGER=1) run_debugger=1 ;; - LAUNCH=0) launch=0 ;; - clean) build_package=0 disable_deploy=1 launch=0 ;; - -h|--help|help) usage ;; - esac - done - - # If a target device hasn't been specified and multiple devices are connected - # to the host machine, display an error. - local -r devices_connected=$(get_number_of_devices_connected) - if [[ "${adb_device}" == "" && $((devices_connected)) -gt 1 && \ - ($((disable_deploy)) -eq 0 || $((launch)) -ne 0 || \ - $((run_debugger)) -ne 0) ]]; then - if [[ $((disable_deploy)) -ne 0 ]]; then - echo "Deployment enabled, disable using DEPLOY=0" >&2 - fi - if [[ $((launch)) -ne 0 ]]; then - echo "Launch enabled." >&2 - fi - if [[ $((disable_deploy)) -eq 0 ]]; then - echo "Deployment enabled." >&2 - fi - if [[ $((run_debugger)) -ne 0 ]]; then - echo "Debugger launch enabled." >&2 - fi - echo " -Multiple Android devices are connected to this host. Either disable deployment -and execution of the built .apk using: - \"${script_name} DEPLOY=0 LAUNCH=0\" - -or specify a device to deploy to using: - \"${script_name} ADB_DEVICE=\${device_serial}\". - -The Android devices connected to this machine are: -$(adb devices -l) -" >&2 - exit 1 - fi - - if [[ $((disable_build)) -eq 0 ]]; then - # Build the native target. - build_native_targets "$@" - fi - - # Get the package name from the manifest. - local -r package_name=$(get_package_name_from_manifest "${android_manifest}") - if [[ "${package_name}" == "" ]]; then - echo -e "No package name specified in ${android_manifest},"\ - "skipping apk build, deploy" - "\nand launch steps." >&2 - exit 0 - fi - local -r package_basename=${package_name/*./} - local package_filename=$(get_library_name_from_manifest ${android_manifest}) - [[ "${package_filename}" == "" ]] && package_filename="${package_basename}" - - # Output apk name. - local -r output_apk="bin/${package_filename}-${ant_target}.apk" - - if [[ $((disable_build)) -eq 0 && $((build_package)) -eq 1 ]]; then - # Build the apk. - build_apk "${output_apk}" "${package_filename}" "${ant_target}" - fi - - # Deploy to the device. - if [[ $((disable_deploy)) -eq 0 ]]; then - install_apk "${package_name}" "${output_apk}" "${adb_device}" - fi - - if [[ "${ant_target}" == "debug" && $((run_debugger)) -eq 1 ]]; then - # Start debugging. - ndk-gdb ${adb_device} --start - elif [[ $((launch)) -eq 1 ]]; then - launch_package "${package_name}" "${adb_device}" - fi -} - -main "$@" diff --git a/samples/android/gradle/wrapper/gradle-wrapper.jar b/samples/android/gradle/wrapper/gradle-wrapper.jar Binary files differnew file mode 100644 index 00000000..b4163b81 --- /dev/null +++ b/samples/android/gradle/wrapper/gradle-wrapper.jar diff --git a/samples/android/gradle/wrapper/gradle-wrapper.properties b/samples/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..1e1168cf --- /dev/null +++ b/samples/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Jun 19 11:54:59 PDT 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-all.zip diff --git a/samples/android/gradlew b/samples/android/gradlew new file mode 100755 index 00000000..cccdd3d5 --- /dev/null +++ b/samples/android/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/samples/android/gradlew.bat b/samples/android/gradlew.bat new file mode 100644 index 00000000..f9553162 --- /dev/null +++ b/samples/android/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/samples/android/jni/Android.mk b/samples/android/jni/Android.mk index 6f22d285..917c2f9e 100755 --- a/samples/android/jni/Android.mk +++ b/samples/android/jni/Android.mk @@ -38,7 +38,7 @@ $(info $(LOCAL_C_INCLUDES)) LOCAL_SRC_FILES := main.cpp LOCAL_CPPFLAGS := -std=c++11 -fexceptions -Wall -Wno-literal-suffix -LOCAL_LDLIBS := -llog -landroid +LOCAL_LDLIBS := -llog -landroid -latomic LOCAL_ARM_MODE := arm LOCAL_STATIC_LIBRARIES := android_native_app_glue flatbuffers diff --git a/samples/android/jni/Application.mk b/samples/android/jni/Application.mk index 2fc9c737..ca9e8004 100755 --- a/samples/android/jni/Application.mk +++ b/samples/android/jni/Application.mk @@ -13,10 +13,8 @@ # 2. Altered source versions must be plainly marked as such, and must not be # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. -APP_PLATFORM := android-10 +APP_PLATFORM := android-9 APP_PROJECT_PATH := $(call my-dir)/.. -APP_STL := gnustl_static - +APP_STL ?= stlport_static APP_ABI := armeabi-v7a - APP_CPPFLAGS += -std=c++11 diff --git a/samples/android_sample.sh b/samples/android_sample.sh index ead8fd80..53633aca 100755 --- a/samples/android_sample.sh +++ b/samples/android_sample.sh @@ -29,8 +29,7 @@ fi # Execute `build_apk.sh` to build and run the android app. cd android -./build_apk.sh +./gradlew build + + -# Cleanup the temporary files. -rm build.xml local.properties proguard-project.txt project.properties -rm -rf bin libs obj diff --git a/samples/monster_generated.h b/samples/monster_generated.h index f4bdbb34..9fca774d 100644 --- a/samples/monster_generated.h +++ b/samples/monster_generated.h @@ -103,6 +103,7 @@ struct EquipmentUnion { void Reset(); +#ifndef FLATBUFFERS_CPP98_STL template <typename T> void Set(T&& val) { Reset(); @@ -111,6 +112,7 @@ struct EquipmentUnion { value = new T(std::forward<T>(val)); } } +#endif // FLATBUFFERS_CPP98_STL static void *UnPack(const void *obj, Equipment type, const flatbuffers::resolver_function_t *resolver); flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher = nullptr) const; @@ -165,13 +167,13 @@ STRUCT_END(Vec3, 12); struct MonsterT : public flatbuffers::NativeTable { typedef Monster TableType; - std::unique_ptr<Vec3> pos; + flatbuffers::unique_ptr<Vec3> pos; int16_t mana; int16_t hp; std::string name; std::vector<uint8_t> inventory; Color color; - std::vector<std::unique_ptr<WeaponT>> weapons; + std::vector<flatbuffers::unique_ptr<WeaponT>> weapons; EquipmentUnion equipped; MonsterT() : mana(150), @@ -461,13 +463,13 @@ inline MonsterT *Monster::UnPack(const flatbuffers::resolver_function_t *_resolv inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function_t *_resolver) const { (void)_o; (void)_resolver; - { auto _e = pos(); if (_e) _o->pos = std::unique_ptr<Vec3>(new Vec3(*_e)); }; + { auto _e = pos(); if (_e) _o->pos = flatbuffers::unique_ptr<Vec3>(new Vec3(*_e)); }; { auto _e = mana(); _o->mana = _e; }; { auto _e = hp(); _o->hp = _e; }; { auto _e = name(); if (_e) _o->name = _e->str(); }; { auto _e = inventory(); if (_e) { _o->inventory.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->inventory[_i] = _e->Get(_i); } } }; { auto _e = color(); _o->color = _e; }; - { auto _e = weapons(); if (_e) { _o->weapons.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->weapons[_i] = std::unique_ptr<WeaponT>(_e->Get(_i)->UnPack(_resolver)); } } }; + { auto _e = weapons(); if (_e) { _o->weapons.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->weapons[_i] = flatbuffers::unique_ptr<WeaponT>(_e->Get(_i)->UnPack(_resolver)); } } }; { auto _e = equipped_type(); _o->equipped.type = _e; }; { auto _e = equipped(); if (_e) _o->equipped.value = EquipmentUnion::UnPack(_e, equipped_type(), _resolver); }; } @@ -479,13 +481,14 @@ inline flatbuffers::Offset<Monster> Monster::Pack(flatbuffers::FlatBufferBuilder inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *_rehasher) { (void)_rehasher; (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const MonsterT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; auto _pos = _o->pos ? _o->pos.get() : 0; auto _mana = _o->mana; auto _hp = _o->hp; auto _name = _o->name.size() ? _fbb.CreateString(_o->name) : 0; auto _inventory = _o->inventory.size() ? _fbb.CreateVector(_o->inventory) : 0; auto _color = _o->color; - auto _weapons = _o->weapons.size() ? _fbb.CreateVector<flatbuffers::Offset<Weapon>>(_o->weapons.size(), [&](size_t i) { return CreateWeapon(_fbb, _o->weapons[i].get(), _rehasher); }) : 0; + auto _weapons = _o->weapons.size() ? _fbb.CreateVector<flatbuffers::Offset<Weapon>> (_o->weapons.size(), [](size_t i, _VectorArgs *__va) { return CreateWeapon(*__va->__fbb, __va->__o->weapons[i].get(), __va->__rehasher); }, &_va ) : 0; auto _equipped_type = _o->equipped.type; auto _equipped = _o->equipped.Pack(_fbb); return MyGame::Sample::CreateMonster( @@ -521,6 +524,7 @@ inline flatbuffers::Offset<Weapon> Weapon::Pack(flatbuffers::FlatBufferBuilder & inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT *_o, const flatbuffers::rehasher_function_t *_rehasher) { (void)_rehasher; (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const WeaponT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; auto _name = _o->name.size() ? _fbb.CreateString(_o->name) : 0; auto _damage = _o->damage; return MyGame::Sample::CreateWeapon( @@ -616,10 +620,10 @@ inline void FinishMonsterBuffer( fbb.Finish(root); } -inline std::unique_ptr<MonsterT> UnPackMonster( +inline flatbuffers::unique_ptr<MonsterT> UnPackMonster( const void *buf, const flatbuffers::resolver_function_t *res = nullptr) { - return std::unique_ptr<MonsterT>(GetMonster(buf)->UnPack(res)); + return flatbuffers::unique_ptr<MonsterT>(GetMonster(buf)->UnPack(res)); } } // namespace Sample diff --git a/src/code_generators.cpp b/src/code_generators.cpp index 3126ce59..e0bee8ba 100644 --- a/src/code_generators.cpp +++ b/src/code_generators.cpp @@ -16,6 +16,7 @@ #include "flatbuffers/code_generators.h" #include <assert.h> +#include "flatbuffers/base.h" #include "flatbuffers/util.h" #if defined(_MSC_VER) @@ -58,7 +59,7 @@ void CodeWriter::operator+=(std::string text) { // Update the text to everything after the }}. text = text.substr(end + 2); } - if (!text.empty() && text.back() == '\\') { + if (!text.empty() && string_back(text) == '\\') { text.pop_back(); stream_ << text; } else { @@ -129,8 +130,8 @@ std::string BaseGenerator::GetNameSpace(const Definition &def) const { std::string qualified_name = qualifying_start_; for (auto it = ns->components.begin(); it != ns->components.end(); ++it) { qualified_name += *it; - if (std::next(it) != ns->components.end()) { - qualified_name += qualifying_separator_; + if ((it + 1) != ns->components.end()) { + qualified_name += qualifying_separator_; } } @@ -167,4 +168,3 @@ void GenComment(const std::vector<std::string> &dc, std::string *code_ptr, #if defined(_MSC_VER) #pragma warning(pop) #endif - diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 242c8d9b..56d10e62 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -722,6 +722,7 @@ class CppGenerator : public BaseGenerator { code_ += " void Reset();"; code_ += ""; if (!enum_def.uses_type_aliases) { + code_ += "#ifndef FLATBUFFERS_CPP98_STL"; code_ += " template <typename T>"; code_ += " void Set(T&& val) {"; code_ += " Reset();"; @@ -730,6 +731,7 @@ class CppGenerator : public BaseGenerator { code_ += " value = new T(std::forward<T>(val));"; code_ += " }"; code_ += " }"; + code_ += "#endif // FLATBUFFERS_CPP98_STL"; code_ += ""; } code_ += " " + UnionUnPackSignature(enum_def, true) + ";"; @@ -1802,11 +1804,13 @@ class CppGenerator : public BaseGenerator { code += "(" + value + ")"; } else { code += "_fbb.CreateVector<flatbuffers::Offset<"; - code += WrapInNameSpace(*vector_type.struct_def) + ">>"; - code += "(" + value + ".size(), [&](size_t i) {"; - code += " return Create" + vector_type.struct_def->name; - code += "(_fbb, " + value + "[i]" + GenPtrGet(field) + ", "; - code += "_rehasher); })"; + code += WrapInNameSpace(*vector_type.struct_def) + ">> "; + code += "(" + value + ".size(), "; + code += "[](size_t i, _VectorArgs *__va) { "; + code += "return Create" + vector_type.struct_def->name; + code += "(*__va->__fbb, __va->_" + value + "[i]" + + GenPtrGet(field) + ", "; + code += "__va->__rehasher); }, &_va )"; } break; } @@ -1815,16 +1819,19 @@ class CppGenerator : public BaseGenerator { break; } case BASE_TYPE_UNION: { - code += "_fbb.CreateVector<flatbuffers::Offset<void>>(" + value + - ".size(), [&](size_t i) { return " + value + - "[i].Pack(_fbb, _rehasher); })"; + code += "_fbb.CreateVector<flatbuffers::" + "Offset<void>>(" + value + + ".size(), [](size_t i, _VectorArgs *__va) { " + "return __va->_" + value + + "[i].Pack(*__va->__fbb, __va->__rehasher); }, &_va)"; break; } case BASE_TYPE_UTYPE: { value = StripUnionType(value); code += "_fbb.CreateVector<uint8_t>(" + value + - ".size(), [&](size_t i) { return static_cast<uint8_t>(" + value + - "[i].type); })"; + ".size(), [](size_t i, _VectorArgs *__va) { " + "return static_cast<uint8_t>(__va->_" + value + + "[i].type); }, &_va)"; break; } default: { @@ -1935,6 +1942,15 @@ class CppGenerator : public BaseGenerator { code_ += " (void)_rehasher;"; code_ += " (void)_o;"; + code_ += + " struct _VectorArgs " + "{ flatbuffers::FlatBufferBuilder *__fbb; " + "const " + + NativeName(struct_def.name, &struct_def) + + "* __o; " + "const flatbuffers::rehasher_function_t *__rehasher; } _va = { " + "&_fbb, _o, _rehasher}; (void)_va;"; + for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { auto &field = **it; diff --git a/src/idl_gen_general.cpp b/src/idl_gen_general.cpp index baeaddf6..fb5a822a 100644 --- a/src/idl_gen_general.cpp +++ b/src/idl_gen_general.cpp @@ -21,6 +21,10 @@ #include "flatbuffers/util.h" #include "flatbuffers/code_generators.h" +#if defined(FLATBUFFERS_CPP98_STL) + #include <cctype> +#endif // defined(FLATBUFFERS_CPP98_STL) + namespace flatbuffers { // Convert an underscore_based_indentifier in to camelCase. @@ -204,7 +208,7 @@ class GeneralGenerator : public BaseGenerator { std::string code; if (lang_.language == IDLOptions::kCSharp) { - code = "// <auto-generated>\n" + code = "// <auto-generated>\n" "// " + std::string(FlatBuffersGeneratedWarning()) + "\n" "// </auto-generated>\n\n"; } else { diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index a7468d55..af3f93e3 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -106,8 +106,8 @@ CheckedError Parser::CheckInRange(int64_t val, int64_t min, int64_t max) { template<typename T> inline CheckedError atot(const char *s, Parser &parser, T *val) { int64_t i = StringToInt(s); - const int64_t min = std::numeric_limits<T>::min(); - const int64_t max = std::numeric_limits<T>::max(); + const int64_t min = flatbuffers::numeric_limits<T>::min(); + const int64_t max = flatbuffers::numeric_limits<T>::max(); ECHECK(parser.CheckInRange(i, min, max)); *val = (T)i; return NoError(); @@ -870,7 +870,8 @@ void Parser::SerializeStruct(const StructDef &struct_def, const Value &val) { CheckedError Parser::ParseTableDelimiters(size_t &fieldn, const StructDef *struct_def, - const std::function<CheckedError(const std::string &name)> &body) { + ParseTableDelimitersBody body, + void *state) { // We allow tables both as JSON object{ .. } with field names // or vector[..] with all fields in order char terminator = '}'; @@ -898,7 +899,7 @@ CheckedError Parser::ParseTableDelimiters(size_t &fieldn, } if (!opts.protobuf_ascii_alike || !(Is('{') || Is('['))) EXPECT(':'); } - ECHECK(body(name)); + ECHECK(body(name, fieldn, struct_def, state)); if (Is(terminator)) break; ECHECK(ParseComma()); } @@ -911,52 +912,56 @@ CheckedError Parser::ParseTableDelimiters(size_t &fieldn, CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, uoffset_t *ovalue) { - size_t fieldn = 0; - auto err = ParseTableDelimiters(fieldn, &struct_def, - [&](const std::string &name) -> CheckedError { + size_t fieldn_outer = 0; + auto err = ParseTableDelimiters(fieldn_outer, &struct_def, + [](const std::string &name, size_t &fieldn, + const StructDef *struct_def_inner, + void *state) -> CheckedError { + Parser *parser = static_cast<Parser *>(state); if (name == "$schema") { - EXPECT(kTokenStringConstant); + ECHECK(parser->Expect(kTokenStringConstant)); return NoError(); } - auto field = struct_def.fields.Lookup(name); + auto field = struct_def_inner->fields.Lookup(name); if (!field) { - if (!opts.skip_unexpected_fields_in_json) { - return Error("unknown field: " + name); + if (!parser->opts.skip_unexpected_fields_in_json) { + return parser->Error("unknown field: " + name); } else { - ECHECK(SkipAnyJsonValue()); + ECHECK(parser->SkipAnyJsonValue()); } } else { - if (Is(kTokenNull)) { - NEXT(); // Ignore this field. + if (parser->Is(kTokenNull)) { + ECHECK(parser->Next()); // Ignore this field. } else { Value val = field->value; if (field->flexbuffer) { flexbuffers::Builder builder(1024, flexbuffers::BUILDER_FLAG_SHARE_ALL); - ECHECK(ParseFlexBufferValue(&builder)); + ECHECK(parser->ParseFlexBufferValue(&builder)); builder.Finish(); - auto off = builder_.CreateVector(builder.GetBuffer()); + auto off = parser->builder_.CreateVector(builder.GetBuffer()); val.constant = NumToString(off.o); } else { - ECHECK(ParseAnyValue(val, field, fieldn, &struct_def)); + ECHECK(parser->ParseAnyValue(val, field, fieldn, struct_def_inner)); } // Hardcoded insertion-sort with error-check. // If fields are specified in order, then this loop exits immediately. - auto elem = field_stack_.rbegin(); - for (; elem != field_stack_.rbegin() + fieldn; ++elem) { + auto elem = parser->field_stack_.rbegin(); + for (; elem != parser->field_stack_.rbegin() + fieldn; ++elem) { auto existing_field = elem->second; if (existing_field == field) - return Error("field set more than once: " + field->name); + return parser->Error("field set more than once: " + field->name); if (existing_field->value.offset < field->value.offset) break; } // Note: elem points to before the insertion point, thus .base() points // to the correct spot. - field_stack_.insert(elem.base(), std::make_pair(val, field)); + parser->field_stack_.insert(elem.base(), + std::make_pair(val, field)); fieldn++; } } return NoError(); - }); + }, this); ECHECK(err); // Check if all required fields are parsed. @@ -968,7 +973,7 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, continue; } bool found = false; - for (auto pf_it = field_stack_.end() - fieldn; + for (auto pf_it = field_stack_.end() - fieldn_outer; pf_it != field_stack_.end(); ++pf_it) { auto parsed_field = pf_it->second; @@ -982,7 +987,7 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, } } - if (struct_def.fixed && fieldn != struct_def.fields.vec.size()) + if (struct_def.fixed && fieldn_outer != struct_def.fields.vec.size()) return Error("struct: wrong number of initializers: " + struct_def.name); auto start = struct_def.fixed @@ -993,8 +998,9 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, size; size /= 2) { // Go through elements in reverse, since we're building the data backwards. - for (auto it = field_stack_.rbegin(); - it != field_stack_.rbegin() + fieldn; ++it) { + for (auto it = field_stack_.rbegin(); it != field_stack_.rbegin() + + fieldn_outer; + ++it) { auto &field_value = it->first; auto field = it->second; if (!struct_def.sortbysize || @@ -1035,7 +1041,7 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, } } } - for (size_t i = 0; i < fieldn; i++) field_stack_.pop_back(); + for (size_t i = 0; i < fieldn_outer; i++) field_stack_.pop_back(); if (struct_def.fixed) { builder_.ClearOffsets(); @@ -1058,11 +1064,12 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, } CheckedError Parser::ParseVectorDelimiters(size_t &count, - const std::function<CheckedError()> &body) { + ParseVectorDelimitersBody body, + void *state) { EXPECT('['); for (;;) { if ((!opts.strict_json || !count) && Is(']')) break; - ECHECK(body()); + ECHECK(body(count, state)); count++; if (Is(']')) break; ECHECK(ParseComma()); @@ -1073,13 +1080,18 @@ CheckedError Parser::ParseVectorDelimiters(size_t &count, CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue) { size_t count = 0; - auto err = ParseVectorDelimiters(count, [&]() -> CheckedError { + std::pair<Parser *, const Type &> parser_and_type_state(this, type); + auto err = ParseVectorDelimiters(count, + [](size_t &, void *state) -> CheckedError { + auto *parser_and_type = + static_cast<std::pair<Parser *, const Type &> *>(state); + auto *parser = parser_and_type->first; Value val; - val.type = type; - ECHECK(ParseAnyValue(val, nullptr, 0, nullptr)); - field_stack_.push_back(std::make_pair(val, nullptr)); + val.type = parser_and_type->second; + ECHECK(parser->ParseAnyValue(val, nullptr, 0, nullptr)); + parser->field_stack_.push_back(std::make_pair(val, nullptr)); return NoError(); - }); + }, &parser_and_type_state); ECHECK(err); builder_.StartVector(count * InlineSize(type) / InlineAlignment(type), @@ -1927,17 +1939,25 @@ CheckedError Parser::ParseTypeFromProtoType(Type *type) { CheckedError Parser::SkipAnyJsonValue() { switch (token_) { case '{': { - size_t fieldn = 0; - return ParseTableDelimiters(fieldn, nullptr, - [&](const std::string &) -> CheckedError { - ECHECK(SkipAnyJsonValue()); - fieldn++; - return NoError(); - }); + size_t fieldn_outer = 0; + return ParseTableDelimiters(fieldn_outer, nullptr, + [](const std::string &, + size_t &fieldn, const StructDef *, + void *state) -> CheckedError { + auto *parser = static_cast<Parser *>(state); + ECHECK(parser->SkipAnyJsonValue()); + fieldn++; + return NoError(); + }, + this); } case '[': { size_t count = 0; - return ParseVectorDelimiters(count, [&]() { return SkipAnyJsonValue(); }); + return ParseVectorDelimiters(count, [](size_t &, + void *state) -> CheckedError { + return static_cast<Parser *>(state)->SkipAnyJsonValue(); + }, + this); } case kTokenStringConstant: EXPECT(kTokenStringConstant); @@ -1957,15 +1977,25 @@ CheckedError Parser::SkipAnyJsonValue() { CheckedError Parser::ParseFlexBufferValue(flexbuffers::Builder *builder) { switch (token_) { case '{': { + std::pair<Parser *, flexbuffers::Builder *> parser_and_builder_state( + this, builder); auto start = builder->StartMap(); - size_t fieldn = 0; - auto err = ParseTableDelimiters(fieldn, nullptr, - [&](const std::string &name) -> CheckedError { - builder->Key(name); - ECHECK(ParseFlexBufferValue(builder)); - fieldn++; - return NoError(); - }); + size_t fieldn_outer = 0; + auto err = ParseTableDelimiters(fieldn_outer, nullptr, + [](const std::string &name, + size_t &fieldn, const StructDef *, + void *state) -> CheckedError { + auto *parser_and_builder = + static_cast<std::pair<Parser *, flexbuffers::Builder *> *>( + state); + auto *parser = parser_and_builder->first; + auto *current_builder = parser_and_builder->second; + current_builder->Key(name); + ECHECK(parser->ParseFlexBufferValue(current_builder)); + fieldn++; + return NoError(); + }, + &parser_and_builder_state); ECHECK(err); builder->EndMap(start); break; @@ -1973,9 +2003,17 @@ CheckedError Parser::ParseFlexBufferValue(flexbuffers::Builder *builder) { case '[':{ auto start = builder->StartVector(); size_t count = 0; - ECHECK(ParseVectorDelimiters(count, [&]() { - return ParseFlexBufferValue(builder); - })); + std::pair<Parser *, flexbuffers::Builder *> parser_and_builder_state( + this, builder); + ECHECK(ParseVectorDelimiters(count, [](size_t &, + void *state) -> CheckedError { + auto *parser_and_builder = + static_cast<std::pair<Parser *, flexbuffers::Builder *> *>( + state); + return parser_and_builder->first->ParseFlexBufferValue( + parser_and_builder->second); + }, + &parser_and_builder_state)); builder->EndVector(start, false, false); break; } @@ -2082,7 +2120,7 @@ CheckedError Parser::DoParse(const char *source, ECHECK(ParseProtoDecl()); } else if (Is(kTokenNativeInclude)) { NEXT(); - native_included_files_.emplace_back(attribute_); + vector_emplace_back(&native_included_files_, attribute_); EXPECT(kTokenStringConstant); } else if (Is(kTokenInclude) || (opts.proto_mode && @@ -2201,7 +2239,10 @@ std::set<std::string> Parser::GetIncludedFilesRecursive( to_process.pop_front(); included_files.insert(current); - auto new_files = files_included_per_file_.at(current); + // Workaround the lack of const accessor in C++98 maps. + auto &new_files = + (*const_cast<std::map<std::string, std::set<std::string>> *>( + &files_included_per_file_))[current]; for (auto it = new_files.begin(); it != new_files.end(); ++it) { if (included_files.find(*it) == included_files.end()) to_process.push_back(*it); diff --git a/src/reflection.cpp b/src/reflection.cpp index 96b3e4aa..2eee4616 100644 --- a/src/reflection.cpp +++ b/src/reflection.cpp @@ -165,15 +165,15 @@ class ResizeContext { ResizeContext(const reflection::Schema &schema, uoffset_t start, int delta, std::vector<uint8_t> *flatbuf, const reflection::Object *root_table = nullptr) - : schema_(schema), startptr_(flatbuf->data() + start), + : schema_(schema), startptr_(vector_data(*flatbuf) + start), delta_(delta), buf_(*flatbuf), dag_check_(flatbuf->size() / sizeof(uoffset_t), false) { auto mask = static_cast<int>(sizeof(largest_scalar_t) - 1); delta_ = (delta_ + mask) & ~mask; if (!delta_) return; // We can't shrink by less than largest_scalar_t. // Now change all the offsets by delta_. - auto root = GetAnyRoot(buf_.data()); - Straddle<uoffset_t, 1>(buf_.data(), root, buf_.data()); + auto root = GetAnyRoot(vector_data(buf_)); + Straddle<uoffset_t, 1>(vector_data(buf_), root, vector_data(buf_)); ResizeTable(root_table ? *root_table : *schema.root_table(), root); // We can now add or remove bytes at start. if (delta_ > 0) buf_.insert(buf_.begin() + start, delta_, 0); @@ -200,7 +200,7 @@ class ResizeContext { // will straddle and which won't. uint8_t &DagCheck(const void *offsetloc) { auto dag_idx = reinterpret_cast<const uoffset_t *>(offsetloc) - - reinterpret_cast<const uoffset_t *>(buf_.data()); + reinterpret_cast<const uoffset_t *>(vector_data(buf_)); return dag_check_[dag_idx]; } @@ -296,19 +296,19 @@ void SetString(const reflection::Schema &schema, const std::string &val, const reflection::Object *root_table) { auto delta = static_cast<int>(val.size()) - static_cast<int>(str->Length()); auto str_start = static_cast<uoffset_t>( - reinterpret_cast<const uint8_t *>(str) - flatbuf->data()); + reinterpret_cast<const uint8_t *>(str) - vector_data(*flatbuf)); auto start = str_start + static_cast<uoffset_t>(sizeof(uoffset_t)); if (delta) { // Clear the old string, since we don't want parts of it remaining. - memset(flatbuf->data() + start, 0, str->Length()); + memset(vector_data(*flatbuf) + start, 0, str->Length()); // Different size, we must expand (or contract). ResizeContext(schema, start, delta, flatbuf, root_table); // Set the new length. - WriteScalar(flatbuf->data() + str_start, + WriteScalar(vector_data(*flatbuf) + str_start, static_cast<uoffset_t>(val.size())); } // Copy new data. Safe because we created the right amount of space. - memcpy(flatbuf->data() + start, val.c_str(), val.size() + 1); + memcpy(vector_data(*flatbuf) + start, val.c_str(), val.size() + 1); } uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize, @@ -317,7 +317,8 @@ uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize, const reflection::Object *root_table) { auto delta_elem = static_cast<int>(newsize) - static_cast<int>(num_elems); auto delta_bytes = delta_elem * static_cast<int>(elem_size); - auto vec_start = reinterpret_cast<const uint8_t *>(vec) - flatbuf->data(); + auto vec_start = reinterpret_cast<const uint8_t *>(vec) - + vector_data(*flatbuf); auto start = static_cast<uoffset_t>(vec_start + sizeof(uoffset_t) + elem_size * num_elems); if (delta_bytes) { @@ -325,16 +326,16 @@ uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize, // Clear elements we're throwing away, since some might remain in the // buffer. auto size_clear = -delta_elem * elem_size; - memset(flatbuf->data() + start - size_clear, 0, size_clear); + memset(vector_data(*flatbuf) + start - size_clear, 0, size_clear); } ResizeContext(schema, start, delta_bytes, flatbuf, root_table); - WriteScalar(flatbuf->data() + vec_start, newsize); // Length field. + WriteScalar(vector_data(*flatbuf) + vec_start, newsize); // Length field. // Set new elements to 0.. this can be overwritten by the caller. if (delta_elem > 0) { - memset(flatbuf->data() + start, 0, delta_elem * elem_size); + memset(vector_data(*flatbuf) + start, 0, delta_elem * elem_size); } } - return flatbuf->data() + start; + return vector_data(*flatbuf) + start; } const uint8_t *AddFlatBuffer(std::vector<uint8_t> &flatbuf, @@ -349,7 +350,7 @@ const uint8_t *AddFlatBuffer(std::vector<uint8_t> &flatbuf, // Insert the entire FlatBuffer minus the root pointer. flatbuf.insert(flatbuf.end(), newbuf + sizeof(uoffset_t), newbuf + newlen); auto root_offset = ReadScalar<uoffset_t>(newbuf) - sizeof(uoffset_t); - return flatbuf.data() + insertion_point + root_offset; + return vector_data(flatbuf) + insertion_point + root_offset; } void CopyInline(FlatBufferBuilder &fbb, const reflection::Field &fielddef, diff --git a/tests/monster_test.bfbs b/tests/monster_test.bfbs Binary files differindex ea66514b..95f7c5e1 100644 --- a/tests/monster_test.bfbs +++ b/tests/monster_test.bfbs diff --git a/tests/monster_test.schema.json b/tests/monster_test.schema.json index 7c58f706..28bc11dd 100644 --- a/tests/monster_test.schema.json +++ b/tests/monster_test.schema.json @@ -18,6 +18,18 @@ "properties" : { } }, + "MyGame_OtherNameSpace_TableB" : { + "type" : "object", + "properties" : { + "a" : { "$ref" : "#/definitions/TableA" } + } + }, + "TableA" : { + "type" : "object", + "properties" : { + "b" : { "$ref" : "#/definitions/MyGame_OtherNameSpace_TableB" } + } + }, "MyGame_Example2_Monster" : { "type" : "object", "properties" : { diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h index 580ed57b..d61db621 100644 --- a/tests/monster_test_generated.h +++ b/tests/monster_test_generated.h @@ -137,6 +137,7 @@ struct AnyUnion { void Reset(); +#ifndef FLATBUFFERS_CPP98_STL template <typename T> void Set(T&& val) { Reset(); @@ -145,6 +146,7 @@ struct AnyUnion { value = new T(std::forward<T>(val)); } } +#endif // FLATBUFFERS_CPP98_STL static void *UnPack(const void *obj, Any type, const flatbuffers::resolver_function_t *resolver); flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher = nullptr) const; @@ -516,7 +518,7 @@ flatbuffers::Offset<Stat> CreateStat(flatbuffers::FlatBufferBuilder &_fbb, const struct MonsterT : public flatbuffers::NativeTable { typedef Monster TableType; - std::unique_ptr<Vec3> pos; + flatbuffers::unique_ptr<Vec3> pos; int16_t mana; int16_t hp; std::string name; @@ -525,10 +527,10 @@ struct MonsterT : public flatbuffers::NativeTable { AnyUnion test; std::vector<Test> test4; std::vector<std::string> testarrayofstring; - std::vector<std::unique_ptr<MonsterT>> testarrayoftables; - std::unique_ptr<MonsterT> enemy; + std::vector<flatbuffers::unique_ptr<MonsterT>> testarrayoftables; + flatbuffers::unique_ptr<MonsterT> enemy; std::vector<uint8_t> testnestedflatbuffer; - std::unique_ptr<StatT> testempty; + flatbuffers::unique_ptr<StatT> testempty; bool testbool; int32_t testhashs32_fnv1; uint32_t testhashu32_fnv1; @@ -1134,6 +1136,7 @@ inline flatbuffers::Offset<Monster> Monster::Pack(flatbuffers::FlatBufferBuilder inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *_rehasher) { (void)_rehasher; (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const MonsterT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; return MyGame::Example2::CreateMonster( _fbb); } @@ -1161,6 +1164,7 @@ inline flatbuffers::Offset<TestSimpleTableWithEnum> TestSimpleTableWithEnum::Pac inline flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(flatbuffers::FlatBufferBuilder &_fbb, const TestSimpleTableWithEnumT *_o, const flatbuffers::rehasher_function_t *_rehasher) { (void)_rehasher; (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const TestSimpleTableWithEnumT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; auto _color = _o->color; return MyGame::Example::CreateTestSimpleTableWithEnum( _fbb, @@ -1188,6 +1192,7 @@ inline flatbuffers::Offset<Stat> Stat::Pack(flatbuffers::FlatBufferBuilder &_fbb inline flatbuffers::Offset<Stat> CreateStat(flatbuffers::FlatBufferBuilder &_fbb, const StatT *_o, const flatbuffers::rehasher_function_t *_rehasher) { (void)_rehasher; (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const StatT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; auto _id = _o->id.size() ? _fbb.CreateString(_o->id) : 0; auto _val = _o->val; auto _count = _o->count; @@ -1207,7 +1212,7 @@ inline MonsterT *Monster::UnPack(const flatbuffers::resolver_function_t *_resolv inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function_t *_resolver) const { (void)_o; (void)_resolver; - { auto _e = pos(); if (_e) _o->pos = std::unique_ptr<Vec3>(new Vec3(*_e)); }; + { auto _e = pos(); if (_e) _o->pos = flatbuffers::unique_ptr<Vec3>(new Vec3(*_e)); }; { auto _e = mana(); _o->mana = _e; }; { auto _e = hp(); _o->hp = _e; }; { auto _e = name(); if (_e) _o->name = _e->str(); }; @@ -1217,10 +1222,10 @@ inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function { auto _e = test(); if (_e) _o->test.value = AnyUnion::UnPack(_e, test_type(), _resolver); }; { auto _e = test4(); if (_e) { _o->test4.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->test4[_i] = *_e->Get(_i); } } }; { auto _e = testarrayofstring(); if (_e) { _o->testarrayofstring.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofstring[_i] = _e->Get(_i)->str(); } } }; - { auto _e = testarrayoftables(); if (_e) { _o->testarrayoftables.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayoftables[_i] = std::unique_ptr<MonsterT>(_e->Get(_i)->UnPack(_resolver)); } } }; - { auto _e = enemy(); if (_e) _o->enemy = std::unique_ptr<MonsterT>(_e->UnPack(_resolver)); }; + { auto _e = testarrayoftables(); if (_e) { _o->testarrayoftables.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayoftables[_i] = flatbuffers::unique_ptr<MonsterT>(_e->Get(_i)->UnPack(_resolver)); } } }; + { auto _e = enemy(); if (_e) _o->enemy = flatbuffers::unique_ptr<MonsterT>(_e->UnPack(_resolver)); }; { auto _e = testnestedflatbuffer(); if (_e) { _o->testnestedflatbuffer.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testnestedflatbuffer[_i] = _e->Get(_i); } } }; - { auto _e = testempty(); if (_e) _o->testempty = std::unique_ptr<StatT>(_e->UnPack(_resolver)); }; + { auto _e = testempty(); if (_e) _o->testempty = flatbuffers::unique_ptr<StatT>(_e->UnPack(_resolver)); }; { auto _e = testbool(); _o->testbool = _e; }; { auto _e = testhashs32_fnv1(); _o->testhashs32_fnv1 = _e; }; { auto _e = testhashu32_fnv1(); _o->testhashu32_fnv1 = _e; }; @@ -1246,6 +1251,7 @@ inline flatbuffers::Offset<Monster> Monster::Pack(flatbuffers::FlatBufferBuilder inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *_rehasher) { (void)_rehasher; (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const MonsterT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; auto _pos = _o->pos ? _o->pos.get() : 0; auto _mana = _o->mana; auto _hp = _o->hp; @@ -1256,7 +1262,7 @@ inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder auto _test = _o->test.Pack(_fbb); auto _test4 = _o->test4.size() ? _fbb.CreateVectorOfStructs(_o->test4) : 0; auto _testarrayofstring = _o->testarrayofstring.size() ? _fbb.CreateVectorOfStrings(_o->testarrayofstring) : 0; - auto _testarrayoftables = _o->testarrayoftables.size() ? _fbb.CreateVector<flatbuffers::Offset<Monster>>(_o->testarrayoftables.size(), [&](size_t i) { return CreateMonster(_fbb, _o->testarrayoftables[i].get(), _rehasher); }) : 0; + auto _testarrayoftables = _o->testarrayoftables.size() ? _fbb.CreateVector<flatbuffers::Offset<Monster>> (_o->testarrayoftables.size(), [](size_t i, _VectorArgs *__va) { return CreateMonster(*__va->__fbb, __va->__o->testarrayoftables[i].get(), __va->__rehasher); }, &_va ) : 0; auto _enemy = _o->enemy ? CreateMonster(_fbb, _o->enemy.get(), _rehasher) : 0; auto _testnestedflatbuffer = _o->testnestedflatbuffer.size() ? _fbb.CreateVector(_o->testnestedflatbuffer) : 0; auto _testempty = _o->testempty ? CreateStat(_fbb, _o->testempty.get(), _rehasher) : 0; @@ -1452,10 +1458,10 @@ inline void FinishMonsterBuffer( fbb.Finish(root, MonsterIdentifier()); } -inline std::unique_ptr<MonsterT> UnPackMonster( +inline flatbuffers::unique_ptr<MonsterT> UnPackMonster( const void *buf, const flatbuffers::resolver_function_t *res = nullptr) { - return std::unique_ptr<MonsterT>(GetMonster(buf)->UnPack(res)); + return flatbuffers::unique_ptr<MonsterT>(GetMonster(buf)->UnPack(res)); } } // namespace Example diff --git a/tests/test.cpp b/tests/test.cpp index fa7fa6e1..576fcf29 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -121,12 +121,13 @@ flatbuffers::DetachedBuffer CreateFlatBufferTest(std::string &buffer) { mlocs[2] = mb3.Finish(); // Create an array of strings. Also test string pooling, and lambdas. - const char *names[] = { "bob", "fred", "bob", "fred" }; auto vecofstrings = builder.CreateVector<flatbuffers::Offset<flatbuffers::String>>(4, - [&](size_t i) { - return builder.CreateSharedString(names[i]); - }); + [](size_t i, flatbuffers::FlatBufferBuilder *b) + -> flatbuffers::Offset<flatbuffers::String> { + static const char *names[] = { "bob", "fred", "bob", "fred" }; + return b->CreateSharedString(names[i]); + }, &builder); // Creating vectors of strings in one convenient call. std::vector<std::string> names2; @@ -541,7 +542,7 @@ void ParseAndGenerateTextTest() { TEST_EQ(result, true); if (jsongen != jsonfile) { - printf("%s----------------\n%s", jsongen.c_str(), jsonfile.c_str()); + TEST_OUTPUT_LINE("%s----------------\n%s", jsongen.c_str(), jsonfile.c_str()); TEST_NOTNULL(NULL); } @@ -671,8 +672,8 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) { // Get the root. // This time we wrap the result from GetAnyRoot in a smartpointer that // will keep rroot valid as resizingbuf resizes. - auto rroot = flatbuffers::piv(flatbuffers::GetAnyRoot(resizingbuf.data()), - resizingbuf); + auto rroot = flatbuffers::piv(flatbuffers::GetAnyRoot( + flatbuffers::vector_data(resizingbuf)), resizingbuf); SetString(schema, "totally new string", GetFieldS(**rroot, name_field), &resizingbuf); // Here resizingbuf has changed, but rroot is still valid. @@ -718,12 +719,14 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) { TEST_EQ_STR(rtestarrayofstring->Get(2)->c_str(), "hank"); // Test integrity of all resize operations above. flatbuffers::Verifier resize_verifier( - reinterpret_cast<const uint8_t *>(resizingbuf.data()), + reinterpret_cast<const uint8_t *>( + flatbuffers::vector_data(resizingbuf)), resizingbuf.size()); TEST_EQ(VerifyMonsterBuffer(resize_verifier), true); // Test buffer is valid using reflection as well - TEST_EQ(flatbuffers::Verify(schema, *schema.root_table(), resizingbuf.data(), + TEST_EQ(flatbuffers::Verify(schema, *schema.root_table(), + flatbuffers::vector_data(resizingbuf), resizingbuf.size()), true); // As an additional test, also set it on the name field. @@ -778,7 +781,7 @@ void ParseProtoTest() { TEST_EQ(parser2.Parse(fbs.c_str(), nullptr), true); if (fbs != goldenfile) { - printf("%s----------------\n%s", fbs.c_str(), goldenfile.c_str()); + TEST_OUTPUT_LINE("%s----------------\n%s", fbs.c_str(), goldenfile.c_str()); TEST_NOTNULL(NULL); } } @@ -1039,17 +1042,17 @@ void FuzzTest2() { i -= std::min(static_cast<size_t>(10), i); // show some context; size_t end = std::min(len, i + 20); for (; i < end; i++) - printf("at %d: found \"%c\", expected \"%c\"\n", - static_cast<int>(i), jsongen[i], json[i]); + TEST_OUTPUT_LINE("at %d: found \"%c\", expected \"%c\"\n", + static_cast<int>(i), jsongen[i], json[i]); break; } } TEST_NOTNULL(NULL); } - printf("%dk schema tested with %dk of json\n", - static_cast<int>(schema.length() / 1024), - static_cast<int>(json.length() / 1024)); + TEST_OUTPUT_LINE("%dk schema tested with %dk of json\n", + static_cast<int>(schema.length() / 1024), + static_cast<int>(json.length() / 1024)); } // Test that parser errors are actually generated. @@ -1526,18 +1529,20 @@ void ConformTest() { flatbuffers::Parser parser; TEST_EQ(parser.Parse("table T { A:int; } enum E:byte { A }"), true); - auto test_conform = [&](const char *test, const char *expected_err) { + auto test_conform = [](flatbuffers::Parser &parser1, + const char *test, const char *expected_err) { flatbuffers::Parser parser2; TEST_EQ(parser2.Parse(test), true); - auto err = parser2.ConformTo(parser); + auto err = parser2.ConformTo(parser1); TEST_NOTNULL(strstr(err.c_str(), expected_err)); }; - test_conform("table T { A:byte; }", "types differ for field"); - test_conform("table T { B:int; A:int; }", "offsets differ for field"); - test_conform("table T { A:int = 1; }", "defaults differ for field"); - test_conform("table T { B:float; }", "field renamed to different type"); - test_conform("enum E:byte { B, A }", "values differ for enum"); + test_conform(parser, "table T { A:byte; }", "types differ for field"); + test_conform(parser, "table T { B:int; A:int; }", "offsets differ for field"); + test_conform(parser, "table T { A:int = 1; }", "defaults differ for field"); + test_conform(parser, "table T { B:float; }", + "field renamed to different type"); + test_conform(parser, "enum E:byte { B, A }", "values differ for enum"); } void ParseProtoBufAsciiTest() { @@ -1566,6 +1571,8 @@ void FlexBuffersTest() { // Write the equivalent of: // { vec: [ -100, "Fred", 4.0 ], bar: [ 1, 2, 3 ], foo: 100 } +#ifndef FLATBUFFERS_CPP98_STL + // It's possible to do this without std::function support as well. slb.Map([&]() { slb.Vector("vec", [&]() { slb += -100; // Equivalent to slb.Add(-100) or slb.Int(-100); @@ -1581,9 +1588,27 @@ void FlexBuffersTest() { }); }); slb.Finish(); +#else + // It's possible to do this without std::function support as well. + slb.Map([](flexbuffers::Builder& slb2) { + slb2.Vector("vec", [](flexbuffers::Builder& slb3) { + slb3 += -100; // Equivalent to slb.Add(-100) or slb.Int(-100); + slb3 += "Fred"; + slb3.IndirectFloat(4.0f); + }, slb2); + int ints[] = { 1, 2, 3 }; + slb2.Vector("bar", ints, 3); + slb2.FixedTypedVector("bar3", ints, 3); + slb2.Double("foo", 100); + slb2.Map("mymap", [](flexbuffers::Builder& slb3) { + slb3.String("foo", "Fred"); // Testing key and string reuse. + }, slb2); + }, slb); + slb.Finish(); +#endif // FLATBUFFERS_CPP98_STL for (size_t i = 0; i < slb.GetBuffer().size(); i++) - printf("%d ", slb.GetBuffer().data()[i]); + printf("%d ", flatbuffers::vector_data(slb.GetBuffer())[i]); printf("\n"); auto map = flexbuffers::GetRoot(slb.GetBuffer()).AsMap(); @@ -1641,7 +1666,11 @@ int main(int /*argc*/, const char * /*argv*/[]) { std::string rawbuf; auto flatbuf1 = CreateFlatBufferTest(rawbuf); +#if !defined(FLATBUFFERS_CPP98_STL) auto flatbuf = std::move(flatbuf1); // Test move assignment. +#else + auto &flatbuf = flatbuf1; +#endif // !defined(FLATBUFFERS_CPP98_STL) AccessFlatBufferTest(reinterpret_cast<const uint8_t *>(rawbuf.c_str()), rawbuf.length()); AccessFlatBufferTest(flatbuf.data(), flatbuf.size()); @@ -1692,4 +1721,3 @@ int main(int /*argc*/, const char * /*argv*/[]) { return 1; } } - diff --git a/tests/union_vector/union_vector_generated.h b/tests/union_vector/union_vector_generated.h index 98f96615..8758ad49 100644 --- a/tests/union_vector/union_vector_generated.h +++ b/tests/union_vector/union_vector_generated.h @@ -364,6 +364,7 @@ inline flatbuffers::Offset<Attacker> Attacker::Pack(flatbuffers::FlatBufferBuild inline flatbuffers::Offset<Attacker> CreateAttacker(flatbuffers::FlatBufferBuilder &_fbb, const AttackerT *_o, const flatbuffers::rehasher_function_t *_rehasher) { (void)_rehasher; (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const AttackerT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; auto _sword_attack_damage = _o->sword_attack_damage; return CreateAttacker( _fbb, @@ -392,10 +393,11 @@ inline flatbuffers::Offset<Movie> Movie::Pack(flatbuffers::FlatBufferBuilder &_f inline flatbuffers::Offset<Movie> CreateMovie(flatbuffers::FlatBufferBuilder &_fbb, const MovieT *_o, const flatbuffers::rehasher_function_t *_rehasher) { (void)_rehasher; (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const MovieT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; auto _main_character_type = _o->main_character.type; auto _main_character = _o->main_character.Pack(_fbb); - auto _characters_type = _o->characters.size() ? _fbb.CreateVector<uint8_t>(_o->characters.size(), [&](size_t i) { return static_cast<uint8_t>(_o->characters[i].type); }) : 0; - auto _characters = _o->characters.size() ? _fbb.CreateVector<flatbuffers::Offset<void>>(_o->characters.size(), [&](size_t i) { return _o->characters[i].Pack(_fbb, _rehasher); }) : 0; + auto _characters_type = _o->characters.size() ? _fbb.CreateVector<uint8_t>(_o->characters.size(), [](size_t i, _VectorArgs *__va) { return static_cast<uint8_t>(__va->__o->characters[i].type); }, &_va) : 0; + auto _characters = _o->characters.size() ? _fbb.CreateVector<flatbuffers::Offset<void>>(_o->characters.size(), [](size_t i, _VectorArgs *__va) { return __va->__o->characters[i].Pack(*__va->__fbb, __va->__rehasher); }, &_va) : 0; return CreateMovie( _fbb, _main_character_type, @@ -602,10 +604,10 @@ inline void FinishMovieBuffer( fbb.Finish(root, MovieIdentifier()); } -inline std::unique_ptr<MovieT> UnPackMovie( +inline flatbuffers::unique_ptr<MovieT> UnPackMovie( const void *buf, const flatbuffers::resolver_function_t *res = nullptr) { - return std::unique_ptr<MovieT>(GetMovie(buf)->UnPack(res)); + return flatbuffers::unique_ptr<MovieT>(GetMovie(buf)->UnPack(res)); } #endif // FLATBUFFERS_GENERATED_UNIONVECTOR_H_ |