Merge pull request #4020 from albertofem/feature/allow_public_accessor_net

Allow access to underlying ByteBuffer in C#
diff --git a/.gitignore b/.gitignore
index e07fbae..79c70d0 100755
--- a/.gitignore
+++ b/.gitignore
@@ -64,3 +64,4 @@
 build/VS2010/FlatBuffers.sdf
 build/VS2010/FlatBuffers.opensdf
 build/VS2010/ipch/**/*.ipch
+*.so
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1af3d33..ad01c21 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,6 +12,9 @@
        ON)
 option(FLATBUFFERS_BUILD_FLATHASH "Enable the build of flathash" ON)
 option(FLATBUFFERS_BUILD_GRPCTEST "Enable the build of grpctest" OFF)
+option(FLATBUFFERS_BUILD_SHAREDLIB
+       "Enable the build of the flatbuffers shared library"
+       OFF)
 
 if(NOT FLATBUFFERS_BUILD_FLATC AND FLATBUFFERS_BUILD_TESTS)
     message(WARNING
@@ -164,6 +167,11 @@
   add_executable(flathash ${FlatHash_SRCS})
 endif()
 
+if(FLATBUFFERS_BUILD_SHAREDLIB)
+  add_library(flatbuffers_shared SHARED ${FlatBuffers_Library_SRCS})
+  set_target_properties(flatbuffers_shared PROPERTIES OUTPUT_NAME flatbuffers)
+endif()
+
 function(compile_flatbuffers_schema_to_cpp SRC_FBS)
   get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
   string(REGEX REPLACE "\\.fbs$" "_generated.h" GEN_HEADER ${SRC_FBS})
@@ -212,6 +220,9 @@
   if(FLATBUFFERS_BUILD_FLATC)
     install(TARGETS flatc DESTINATION bin)
   endif()
+  if(FLATBUFFERS_BUILD_SHAREDLIB)
+    install(TARGETS flatbuffers_shared DESTINATION lib)
+  endif()
 endif()
 
 if(FLATBUFFERS_BUILD_TESTS)
diff --git a/include/flatbuffers/util.h b/include/flatbuffers/util.h
index baf5bdd..c6755ab 100644
--- a/include/flatbuffers/util.h
+++ b/include/flatbuffers/util.h
@@ -95,20 +95,20 @@
 }
 
 // Portable implementation of strtoll().
-inline int64_t StringToInt(const char *str, int base = 10) {
+inline int64_t StringToInt(const char *str, char **endptr = nullptr, int base = 10) {
   #ifdef _MSC_VER
-    return _strtoi64(str, nullptr, base);
+    return _strtoi64(str, endptr, base);
   #else
-    return strtoll(str, nullptr, base);
+    return strtoll(str, endptr, base);
   #endif
 }
 
 // Portable implementation of strtoull().
-inline int64_t StringToUInt(const char *str, int base = 10) {
+inline int64_t StringToUInt(const char *str, char **endptr = nullptr, int base = 10) {
   #ifdef _MSC_VER
-    return _strtoui64(str, nullptr, base);
+    return _strtoui64(str, endptr, base);
   #else
-    return strtoull(str, nullptr, base);
+    return strtoull(str, endptr, base);
   #endif
 }
 
diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp
index d845b83..21cbed3 100644
--- a/src/idl_parser.cpp
+++ b/src/idl_parser.cpp
@@ -219,7 +219,7 @@
       return Error("escape code must be followed by " + NumToString(nibbles) +
                    " hex digits");
   std::string target(cursor_, cursor_ + nibbles);
-  *val = StringToUInt(target.c_str(), 16);
+  *val = StringToUInt(target.c_str(), nullptr, 16);
   cursor_ += nibbles;
   return NoError();
 }
@@ -447,7 +447,7 @@
               cursor_++;
               while (isxdigit(static_cast<unsigned char>(*cursor_))) cursor_++;
               attribute_.append(start + 2, cursor_);
-              attribute_ = NumToString(StringToUInt(attribute_.c_str(), 16));
+              attribute_ = NumToString(StringToUInt(attribute_.c_str(), nullptr, 16));
               token_ = kTokenIntegerConstant;
               return NoError();
           }
@@ -1093,10 +1093,15 @@
       NEXT();
     } else {  // Numeric constant in string.
       if (IsInteger(e.type.base_type)) {
-        // TODO(wvo): do we want to check for garbage after the number?
-        e.constant = NumToString(StringToInt(attribute_.c_str()));
+        char *end;
+        e.constant = NumToString(StringToInt(attribute_.c_str(), &end));
+        if (*end)
+          return Error("invalid integer: " + attribute_);
       } else if (IsFloat(e.type.base_type)) {
-        e.constant = NumToString(strtod(attribute_.c_str(), nullptr));
+        char *end;
+        e.constant = NumToString(strtod(attribute_.c_str(), &end));
+        if (*end)
+          return Error("invalid float: " + attribute_);
       } else {
         assert(0);  // Shouldn't happen, we covered all types.
         e.constant = "0";
diff --git a/tests/JavaTest.sh b/tests/JavaTest.sh
index 344bd1c..40e854b 100755
--- a/tests/JavaTest.sh
+++ b/tests/JavaTest.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 #
 # Copyright 2014 Google Inc. All rights reserved.
 #
@@ -16,14 +16,29 @@
 
 echo Compile then run the Java test.
 
+java -version
+
 testdir=$(readlink -fn `dirname $0`)
 thisdir=$(readlink -fn `pwd`)
 
+targetdir=${testdir}/target
+
 if [[ "$testdir" != "$thisdir" ]]; then
 	echo error: must be run from inside the ${testdir} directory
 	echo you ran it from ${thisdir}
 	exit 1
 fi
 
-javac -classpath ${testdir}/../java:${testdir}:${testdir}/namespace_test JavaTest.java
-java -classpath ${testdir}/../java:${testdir}:${testdir}/namespace_test JavaTest
+find .. -type f -name "*.class" -exec rm  {} \;
+
+if [[ -e "${targetdir}" ]]; then
+    echo "clean target"
+    rm -rf ${targetdir}
+fi
+
+mkdir ${targetdir}
+
+javac -d ${targetdir} -classpath ${testdir}/../java:${testdir}:${testdir}/namespace_test JavaTest.java
+java -classpath ${targetdir} JavaTest
+
+rm -rf ${targetdir}