diff --git a/.gitignore b/.gitignore index aedeb3cb2..bf6d665be 100755 --- a/.gitignore +++ b/.gitignore @@ -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 bee81694b..297c406b9 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 53d453bb1..e83532527 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 a15f547b7..846fd13cb 100755 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -17,17 +17,14 @@ --> + package="com.example.FlatBufferTest"> - - - - + &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 new file mode 100644 index 000000000..b4163b813 Binary files /dev/null and b/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..1e1168cf6 --- /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 000000000..cccdd3d51 --- /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 000000000..f9553162f --- /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 0269dd3f2..aec561a95 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 2fc9c7379..ca9e8004d 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 38127f0f4..497a2a964 100644 --- a/include/flatbuffers/base.h +++ b/include/flatbuffers/base.h @@ -29,6 +29,8 @@ #include #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 9216cf4d6..25a547986 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 void AssertScalarT() { - #ifndef FLATBUFFERS_CPP98_STL // The code assumes power of 2 sizes and endian-swap-ability. - static_assert(std::is_scalar::value, "T must be a scalar type"); - #endif + static_assert(flatbuffers::is_scalar::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 Offset> CreateVector( + size_t vector_size, F f, S *state) { + std::vector 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` 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(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 Offset> CreateVectorOfStructs( size_t vector_size, const std::function &filler) { - StartVector(vector_size * sizeof(T) / AlignOf(), AlignOf()); - T *structs = reinterpret_cast(buf_.make_space(vector_size * sizeof(T))); + T* structs = StartVectorOfStructs(vector_size); for (size_t i = 0; i < vector_size; i++) { filler(i, structs); structs++; } - return Offset>(EndVector(vector_size)); + return EndVectorOfStructs(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 Offset> + CreateVectorOfStructs(size_t vector_size, F f, S *state) { + T* structs = StartVectorOfStructs(vector_size); + for (size_t i = 0; i < vector_size; i++) { + f(i, structs, state); + structs++; + } + return EndVectorOfStructs(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, StringOffsetCompare> StringOffsetMap; StringOffsetMap *string_pool; + + private: + // Allocates space for a vector of structures. + // Must be completed with EndVectorOfStructs(). + template const T* StartVectorOfStructs(size_t vector_size) { + StartVector(vector_size * sizeof(T) / AlignOf(), AlignOf()); + return reinterpret_cast(buf_.make_space(vector_size * sizeof(T))); + } + + // End the vector of structues in the flatbuffers. + // Vector should have previously be started with StartVectorOfStructs(). + template Offset> EndVectorOfStructs( + size_t vector_size) { + return Offset>(EndVector(vector_size)); + } }; /// @} diff --git a/include/flatbuffers/flexbuffers.h b/include/flatbuffers/flexbuffers.h index 67f82b94c..153603755 100644 --- a/include/flatbuffers/flexbuffers.h +++ b/include/flatbuffers/flexbuffers.h @@ -18,6 +18,8 @@ #define FLATBUFFERS_FLEXBUFFERS_H_ #include +// 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 &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 &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(stack_.data() + start); + auto dict = + reinterpret_cast(flatbuffers::vector_data(stack_) + + start); std::sort(dict, dict + len, [&](const TwoValue &a, const TwoValue &b) -> bool { - auto as = reinterpret_cast(buf_.data() + a.key.u_); - auto bs = reinterpret_cast(buf_.data() + b.key.u_); + auto as = reinterpret_cast( + flatbuffers::vector_data(buf_) + a.key.u_); + auto bs = reinterpret_cast( + 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 size_t Vector(F f, T &state) { + auto start = StartVector(); + f(state); + return EndVector(start, false, false); + } template size_t Vector(const char *key, F f) { auto start = StartVector(key); f(); return EndVector(start, false, false); } + template size_t Vector(const char *key, F f, + T &state) { + auto start = StartVector(key); + f(state); + return EndVector(start, false, false); + } + template void Vector(const T *elems, size_t len) { - if (std::is_scalar::value) { + if (flatbuffers::is_scalar::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 void Vector(const std::vector &vec) { - Vector(vec.data(), vec.size()); + Vector(flatbuffers::vector_data(vec), vec.size()); } template size_t TypedVector(F f) { @@ -1015,18 +1033,29 @@ class Builder FLATBUFFERS_FINAL_CLASS { f(); return EndVector(start, true, false); } + template size_t TypedVector(F f, T &state) { + auto start = StartVector(); + f(state); + return EndVector(start, true, false); + } template size_t TypedVector(const char *key, F f) { auto start = StartVector(key); f(); return EndVector(start, true, false); } + template size_t TypedVector(const char *key, F f, + T &state) { + auto start = StartVector(key); + f(state); + return EndVector(start, true, false); + } template 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::value); + assert(flatbuffers::is_scalar::value); return ScalarVector(elems, len, true); } @@ -1041,11 +1070,22 @@ class Builder FLATBUFFERS_FINAL_CLASS { f(); return EndMap(start); } + template size_t Map(F f, T &state) { + auto start = StartMap(); + f(state); + return EndMap(start); + } template size_t Map(const char *key, F f) { auto start = StartMap(key); f(); return EndMap(start); } + template size_t Map(const char *key, F f, + T &state) { + auto start = StartMap(key); + f(state); + return EndMap(start); + } template void Map(const std::map &map) { auto start = StartMap(); for (auto it = map.begin(); it != map.end(); ++it) @@ -1174,10 +1214,10 @@ class Builder FLATBUFFERS_FINAL_CLASS { } template static Type GetScalarType() { - assert(std::is_scalar::value); - return std::is_floating_point::value + assert(flatbuffers::is_scalar::value); + return flatbuffers::is_floating_point::value ? TYPE_FLOAT - : (std::is_unsigned::value ? TYPE_UINT : TYPE_INT); + : (flatbuffers::is_unsigned::value ? TYPE_UINT : TYPE_INT); } struct Value { @@ -1364,9 +1404,11 @@ class Builder FLATBUFFERS_FINAL_CLASS { struct KeyOffsetCompare { KeyOffsetCompare(const std::vector &buf) : buf_(&buf) {} - bool operator() (size_t a, size_t b) const { - auto stra = reinterpret_cast(buf_->data() + a); - auto strb = reinterpret_cast(buf_->data() + b); + bool operator()(size_t a, size_t b) const { + auto stra = + reinterpret_cast(flatbuffers::vector_data(*buf_) + a); + auto strb = + reinterpret_cast(flatbuffers::vector_data(*buf_) + b); return strcmp(stra, strb) < 0; } const std::vector *buf_; @@ -1375,9 +1417,11 @@ class Builder FLATBUFFERS_FINAL_CLASS { typedef std::pair StringOffset; struct StringOffsetCompare { StringOffsetCompare(const std::vector &buf) : buf_(&buf) {} - bool operator() (const StringOffset &a, const StringOffset &b) const { - auto stra = reinterpret_cast(buf_->data() + a.first); - auto strb = reinterpret_cast(buf_->data() + b.first); + bool operator()(const StringOffset &a, const StringOffset &b) const { + auto stra = reinterpret_cast(flatbuffers::vector_data(*buf_) + + a.first); + auto strb = reinterpret_cast(flatbuffers::vector_data(*buf_) + + b.first); return strncmp(stra, strb, std::min(a.second, b.second) + 1) < 0; } const std::vector *buf_; diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index 4e27e30c4..0f500243d 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -20,13 +20,17 @@ #include #include #include -#include +#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 +#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 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 + ParseTableDelimitersBody; + #endif // defined(FLATBUFFERS_CPP98_STL) FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn, const StructDef *struct_def, - const std::function &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 &body); + #if defined(FLATBUFFERS_CPP98_STL) + typedef CheckedError (*ParseVectorDelimitersBody)(size_t &count, + void *state); + #else + typedef std::function + 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 *attributes); FLATBUFFERS_CHECKED_ERROR TryTypedValue(int dtoken, bool check, Value &e, diff --git a/include/flatbuffers/reflection.h b/include/flatbuffers/reflection.h index aab9f2088..ad5c45627 100644 --- a/include/flatbuffers/reflection.h +++ b/include/flatbuffers/reflection.h @@ -361,12 +361,13 @@ template class pointer_inside_vector { public: pointer_inside_vector(T *ptr, std::vector &vec) : offset_(reinterpret_cast(ptr) - - reinterpret_cast(vec.data())), + reinterpret_cast(flatbuffers::vector_data(vec))), vec_(vec) {} T *operator*() const { return reinterpret_cast( - reinterpret_cast(vec_.data()) + offset_); + reinterpret_cast( + 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 *flatbuf, const reflection::Object *root_table = nullptr); -#ifndef FLATBUFFERS_CPP98_STL template void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val, const Vector *vec, std::vector *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::value; + auto is_scalar = flatbuffers::is_scalar::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 9a227682d..35771c182 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 000000000..7906648ba --- /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 +#include +#include + +#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 +#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 inline T *vector_data(std::vector &vector) { + return &(vector[0]); +} + +template inline const T *vector_data( + const std::vector &vector) { + return &(vector[0]); +} + +template +inline void vector_emplace_back(std::vector *vector, V &&data) { + #if defined(FLATBUFFERS_CPP98_STL) + vector->push_back(data); + #else + vector->emplace_back(std::forward(data)); + #endif // defined(FLATBUFFERS_CPP98_STL) +} + +#ifndef FLATBUFFERS_CPP98_STL + #if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */) + template + using numeric_limits = std::numeric_limits; + #else + template class numeric_limits : + public std::numeric_limits {}; + #endif // !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */) +#else + template class numeric_limits : + public std::numeric_limits {}; + + template <> class numeric_limits { + public: + static unsigned long long min() { return 0ULL; } + static unsigned long long max() { return ~0ULL; } + }; + + template <> class numeric_limits { + public: + static long long min() { + return static_cast(1ULL << ((sizeof(long long) << 3) - 1)); + } + static long long max() { + return static_cast( + (1ULL << ((sizeof(long long) << 3) - 1)) - 1); + } + }; +#endif // FLATBUFFERS_CPP98_STL + +#if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */) + #ifndef FLATBUFFERS_CPP98_STL + template using is_scalar = std::is_scalar; + template using is_floating_point = std::is_floating_point; + template using is_unsigned = std::is_unsigned; + #else + // Map C++ TR1 templates defined by stlport. + template using is_scalar = std::tr1::is_scalar; + template using is_floating_point = + std::tr1::is_floating_point; + template using is_unsigned = std::tr1::is_unsigned; + #endif // !FLATBUFFERS_CPP98_STL +#else + // MSVC 2010 doesn't support C++11 aliases. + template struct is_scalar : public std::is_scalar {}; + template struct is_floating_point : + public std::is_floating_point {}; + template struct is_unsigned : public std::is_unsigned {}; +#endif // !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */) + +#ifndef FLATBUFFERS_CPP98_STL + #if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */) + template using unique_ptr = std::unique_ptr; + #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 unique_ptr : public std::unique_ptr { + public: + unique_ptr() {} + explicit unique_ptr(T* p) : std::unique_ptr(p) {} + unique_ptr(std::unique_ptr&& u) { *this = std::move(u); } + unique_ptr(unique_ptr&& u) { *this = std::move(u); } + unique_ptr& operator=(std::unique_ptr&& u) { + std::unique_ptr::reset(u.release()); + return *this; + } + unique_ptr& operator=(unique_ptr&& u) { + std::unique_ptr::reset(u.release()); + return *this; + } + unique_ptr& operator=(T* p) { + return std::unique_ptr::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 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(&u)->release()); + } + ~unique_ptr() { reset(); } + + unique_ptr& operator=(const unique_ptr& u) { + reset(const_cast(&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 bool operator==(const unique_ptr& x, + const unique_ptr& y) { + return x.get() == y.get(); + } + + template bool operator==(const unique_ptr& x, + const D* y) { + return static_cast(x.get()) == y; + } + + template bool operator==(const unique_ptr& x, intptr_t y) { + return reinterpret_cast(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 ee62b86d3..6b7b7bc3e 100644 --- a/include/flatbuffers/util.h +++ b/include/flatbuffers/util.h @@ -60,6 +60,20 @@ template<> inline std::string NumToString(signed char t) { template<> inline std::string NumToString(unsigned char t) { return NumToString(static_cast(t)); } +#if defined(FLATBUFFERS_CPP98_STL) + template <> inline std::string NumToString(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 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 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 0fa3dcfc0..352e0fade 100755 --- a/samples/android/AndroidManifest.xml +++ b/samples/android/AndroidManifest.xml @@ -17,17 +17,14 @@ --> + package="com.samples.FlatBufferSample"> - - - - + &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 new file mode 100644 index 000000000..b4163b813 Binary files /dev/null and b/samples/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/samples/android/gradle/wrapper/gradle-wrapper.properties b/samples/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..1e1168cf6 --- /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 000000000..cccdd3d51 --- /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 000000000..f9553162f --- /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 6f22d2852..917c2f9ee 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 2fc9c7379..ca9e8004d 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 ead8fd807..53633acad 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 f4bdbb341..9fca774da 100644 --- a/samples/monster_generated.h +++ b/samples/monster_generated.h @@ -103,6 +103,7 @@ struct EquipmentUnion { void Reset(); +#ifndef FLATBUFFERS_CPP98_STL template void Set(T&& val) { Reset(); @@ -111,6 +112,7 @@ struct EquipmentUnion { value = new T(std::forward(val)); } } +#endif // FLATBUFFERS_CPP98_STL static void *UnPack(const void *obj, Equipment type, const flatbuffers::resolver_function_t *resolver); flatbuffers::Offset 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 pos; + flatbuffers::unique_ptr pos; int16_t mana; int16_t hp; std::string name; std::vector inventory; Color color; - std::vector> weapons; + std::vector> 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(new Vec3(*_e)); }; + { auto _e = pos(); if (_e) _o->pos = flatbuffers::unique_ptr(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(_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(_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::Pack(flatbuffers::FlatBufferBuilder inline flatbuffers::Offset 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>(_o->weapons.size(), [&](size_t i) { return CreateWeapon(_fbb, _o->weapons[i].get(), _rehasher); }) : 0; + auto _weapons = _o->weapons.size() ? _fbb.CreateVector> (_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::Pack(flatbuffers::FlatBufferBuilder & inline flatbuffers::Offset 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 UnPackMonster( +inline flatbuffers::unique_ptr UnPackMonster( const void *buf, const flatbuffers::resolver_function_t *res = nullptr) { - return std::unique_ptr(GetMonster(buf)->UnPack(res)); + return flatbuffers::unique_ptr(GetMonster(buf)->UnPack(res)); } } // namespace Sample diff --git a/src/code_generators.cpp b/src/code_generators.cpp index 3126ce59d..e0bee8ba1 100644 --- a/src/code_generators.cpp +++ b/src/code_generators.cpp @@ -16,6 +16,7 @@ #include "flatbuffers/code_generators.h" #include +#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 &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 242c8d9bd..56d10e625 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 "; code_ += " void Set(T&& val) {"; code_ += " Reset();"; @@ -730,6 +731,7 @@ class CppGenerator : public BaseGenerator { code_ += " value = new T(std::forward(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>"; - 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>(" + value + - ".size(), [&](size_t i) { return " + value + - "[i].Pack(_fbb, _rehasher); })"; + code += "_fbb.CreateVector>(" + 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(" + value + - ".size(), [&](size_t i) { return static_cast(" + value + - "[i].type); })"; + ".size(), [](size_t i, _VectorArgs *__va) { " + "return static_cast(__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 baeaddf68..fb5a822ab 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 +#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 = "// \n" + code = "// \n" "// " + std::string(FlatBuffersGeneratedWarning()) + "\n" "// \n\n"; } else { diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index a7468d55b..af3f93e33 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 inline CheckedError atot(const char *s, Parser &parser, T *val) { int64_t i = StringToInt(s); - const int64_t min = std::numeric_limits::min(); - const int64_t max = std::numeric_limits::max(); + const int64_t min = flatbuffers::numeric_limits::min(); + const int64_t max = flatbuffers::numeric_limits::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 &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(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 &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_and_type_state(this, type); + auto err = ParseVectorDelimiters(count, + [](size_t &, void *state) -> CheckedError { + auto *parser_and_type = + static_cast *>(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(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(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_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 *>( + 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_and_builder_state( + this, builder); + ECHECK(ParseVectorDelimiters(count, [](size_t &, + void *state) -> CheckedError { + auto *parser_and_builder = + static_cast *>( + 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 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> *>( + &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 96b3e4aa1..2eee46162 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 *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(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(buf_.data(), root, buf_.data()); + auto root = GetAnyRoot(vector_data(buf_)); + Straddle(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(offsetloc) - - reinterpret_cast(buf_.data()); + reinterpret_cast(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(val.size()) - static_cast(str->Length()); auto str_start = static_cast( - reinterpret_cast(str) - flatbuf->data()); + reinterpret_cast(str) - vector_data(*flatbuf)); auto start = str_start + static_cast(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(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(newsize) - static_cast(num_elems); auto delta_bytes = delta_elem * static_cast(elem_size); - auto vec_start = reinterpret_cast(vec) - flatbuf->data(); + auto vec_start = reinterpret_cast(vec) - + vector_data(*flatbuf); auto start = static_cast(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 &flatbuf, @@ -349,7 +350,7 @@ const uint8_t *AddFlatBuffer(std::vector &flatbuf, // Insert the entire FlatBuffer minus the root pointer. flatbuf.insert(flatbuf.end(), newbuf + sizeof(uoffset_t), newbuf + newlen); auto root_offset = ReadScalar(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 index ea66514be..95f7c5e1c 100644 Binary files a/tests/monster_test.bfbs and b/tests/monster_test.bfbs differ diff --git a/tests/monster_test.schema.json b/tests/monster_test.schema.json index 7c58f7066..28bc11dd6 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 580ed57b4..d61db621f 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 void Set(T&& val) { Reset(); @@ -145,6 +146,7 @@ struct AnyUnion { value = new T(std::forward(val)); } } +#endif // FLATBUFFERS_CPP98_STL static void *UnPack(const void *obj, Any type, const flatbuffers::resolver_function_t *resolver); flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher = nullptr) const; @@ -516,7 +518,7 @@ flatbuffers::Offset CreateStat(flatbuffers::FlatBufferBuilder &_fbb, const struct MonsterT : public flatbuffers::NativeTable { typedef Monster TableType; - std::unique_ptr pos; + flatbuffers::unique_ptr pos; int16_t mana; int16_t hp; std::string name; @@ -525,10 +527,10 @@ struct MonsterT : public flatbuffers::NativeTable { AnyUnion test; std::vector test4; std::vector testarrayofstring; - std::vector> testarrayoftables; - std::unique_ptr enemy; + std::vector> testarrayoftables; + flatbuffers::unique_ptr enemy; std::vector testnestedflatbuffer; - std::unique_ptr testempty; + flatbuffers::unique_ptr testempty; bool testbool; int32_t testhashs32_fnv1; uint32_t testhashu32_fnv1; @@ -1134,6 +1136,7 @@ inline flatbuffers::Offset Monster::Pack(flatbuffers::FlatBufferBuilder inline flatbuffers::Offset 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::Pac inline flatbuffers::Offset 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::Pack(flatbuffers::FlatBufferBuilder &_fbb inline flatbuffers::Offset 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(new Vec3(*_e)); }; + { auto _e = pos(); if (_e) _o->pos = flatbuffers::unique_ptr(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(_e->Get(_i)->UnPack(_resolver)); } } }; - { auto _e = enemy(); if (_e) _o->enemy = std::unique_ptr(_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(_e->Get(_i)->UnPack(_resolver)); } } }; + { auto _e = enemy(); if (_e) _o->enemy = flatbuffers::unique_ptr(_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(_e->UnPack(_resolver)); }; + { auto _e = testempty(); if (_e) _o->testempty = flatbuffers::unique_ptr(_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::Pack(flatbuffers::FlatBufferBuilder inline flatbuffers::Offset 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 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>(_o->testarrayoftables.size(), [&](size_t i) { return CreateMonster(_fbb, _o->testarrayoftables[i].get(), _rehasher); }) : 0; + auto _testarrayoftables = _o->testarrayoftables.size() ? _fbb.CreateVector> (_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 UnPackMonster( +inline flatbuffers::unique_ptr UnPackMonster( const void *buf, const flatbuffers::resolver_function_t *res = nullptr) { - return std::unique_ptr(GetMonster(buf)->UnPack(res)); + return flatbuffers::unique_ptr(GetMonster(buf)->UnPack(res)); } } // namespace Example diff --git a/tests/test.cpp b/tests/test.cpp index fa7fa6e11..576fcf292 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>(4, - [&](size_t i) { - return builder.CreateSharedString(names[i]); - }); + [](size_t i, flatbuffers::FlatBufferBuilder *b) + -> flatbuffers::Offset { + static const char *names[] = { "bob", "fred", "bob", "fred" }; + return b->CreateSharedString(names[i]); + }, &builder); // Creating vectors of strings in one convenient call. std::vector 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(resizingbuf.data()), + reinterpret_cast( + 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(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(i), jsongen[i], json[i]); + TEST_OUTPUT_LINE("at %d: found \"%c\", expected \"%c\"\n", + static_cast(i), jsongen[i], json[i]); break; } } TEST_NOTNULL(NULL); } - printf("%dk schema tested with %dk of json\n", - static_cast(schema.length() / 1024), - static_cast(json.length() / 1024)); + TEST_OUTPUT_LINE("%dk schema tested with %dk of json\n", + static_cast(schema.length() / 1024), + static_cast(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(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 98f96615c..8758ad495 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::Pack(flatbuffers::FlatBufferBuild inline flatbuffers::Offset 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::Pack(flatbuffers::FlatBufferBuilder &_f inline flatbuffers::Offset 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(_o->characters.size(), [&](size_t i) { return static_cast(_o->characters[i].type); }) : 0; - auto _characters = _o->characters.size() ? _fbb.CreateVector>(_o->characters.size(), [&](size_t i) { return _o->characters[i].Pack(_fbb, _rehasher); }) : 0; + auto _characters_type = _o->characters.size() ? _fbb.CreateVector(_o->characters.size(), [](size_t i, _VectorArgs *__va) { return static_cast(__va->__o->characters[i].type); }, &_va) : 0; + auto _characters = _o->characters.size() ? _fbb.CreateVector>(_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 UnPackMovie( +inline flatbuffers::unique_ptr UnPackMovie( const void *buf, const flatbuffers::resolver_function_t *res = nullptr) { - return std::unique_ptr(GetMovie(buf)->UnPack(res)); + return flatbuffers::unique_ptr(GetMovie(buf)->UnPack(res)); } #endif // FLATBUFFERS_GENERATED_UNIONVECTOR_H_