Commit 98f9af8e authored by TGIshib's avatar TGIshib

Merge remote-tracking branch 'refs/remotes/google/master' into key

# Conflicts:
#	src/idl_gen_general.cpp
parents 1a18122e 481d332e
# ------------------- Debianization ---------------------
if (UNIX)
# Set build environment
SET(CPACK_GENERATOR "TGZ;DEB")
SET(CPACK_SOURCE_TGZ "ON")
# Common package information
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY
"FlatBuffers is an efficient cross platform serialization library for C++, with support for Java, C# and Go. It was created at Google specifically for game development and other performance-critical applications.")
SET(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/google/flatbuffers")
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Vitaly Isaev <vitalyisaev2@gmail.com>")
# Derive package version from git
EXECUTE_PROCESS(
COMMAND date +%Y%m%d
OUTPUT_VARIABLE DATE
OUTPUT_STRIP_TRAILING_WHITESPACE
)
EXECUTE_PROCESS(
COMMAND git describe
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_DESCRIBE_DIRTY
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${GIT_DESCRIBE_DIRTY}")
string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${GIT_DESCRIBE_DIRTY}")
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${GIT_DESCRIBE_DIRTY}")
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.[0-9]+\\-([0-9]+).*" "\\1" VERSION_COMMIT "${GIT_DESCRIBE_DIRTY}")
SET(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})
SET(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR})
SET(CPACK_PACKAGE_VERSION_PATCH ${VERSION_PATCH})
SET(CPACK_PACKAGE_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_COMMIT}")
SET(CPACK_DEBIAN_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}")
# Derive architecture
IF(NOT CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
FIND_PROGRAM(DPKG_CMD dpkg)
IF(NOT DPKG_CMD)
MESSAGE(STATUS "Can not find dpkg in your path, default to i386.")
SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE i386)
ENDIF(NOT DPKG_CMD)
EXECUTE_PROCESS(COMMAND "${DPKG_CMD}" --print-architecture
OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE
OUTPUT_STRIP_TRAILING_WHITESPACE
)
ENDIF(NOT CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
# Package name
SET(CPACK_DEBIAN_PACKAGE_NAME "flatbuffers")
SET(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE.txt)
SET(CPACK_PACKAGE_FILE_NAME
"${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_DEBIAN_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
endif(UNIX)
INCLUDE(CPack)
...@@ -44,6 +44,7 @@ set(FlatBuffers_Compiler_SRCS ...@@ -44,6 +44,7 @@ set(FlatBuffers_Compiler_SRCS
src/idl_gen_fbs.cpp src/idl_gen_fbs.cpp
src/idl_gen_grpc.cpp src/idl_gen_grpc.cpp
src/flatc.cpp src/flatc.cpp
grpc/src/compiler/schema_interface.h
grpc/src/compiler/cpp_generator.h grpc/src/compiler/cpp_generator.h
grpc/src/compiler/cpp_generator.cc grpc/src/compiler/cpp_generator.cc
) )
...@@ -222,3 +223,7 @@ if(FLATBUFFERS_BUILD_TESTS) ...@@ -222,3 +223,7 @@ if(FLATBUFFERS_BUILD_TESTS)
endif() endif()
include(CMake/BuildFlatBuffers.cmake) include(CMake/BuildFlatBuffers.cmake)
if(FLATBUFFERS_PACKAGE_DEBIAN)
include(CMake/PackageDebian.cmake)
endif()
...@@ -761,7 +761,7 @@ INPUT = "FlatBuffers.md" \ ...@@ -761,7 +761,7 @@ INPUT = "FlatBuffers.md" \
"WhitePaper.md" \ "WhitePaper.md" \
"Internals.md" \ "Internals.md" \
"Grammar.md" \ "Grammar.md" \
"CONTRIBUTING.md" \ "../../CONTRIBUTING.md" \
"Tutorial.md" \ "Tutorial.md" \
"GoApi.md" \ "GoApi.md" \
"groups" \ "groups" \
......
...@@ -67,7 +67,8 @@ grpc::string FilenameIdentifier(const grpc::string &filename) { ...@@ -67,7 +67,8 @@ grpc::string FilenameIdentifier(const grpc::string &filename) {
template<class T, size_t N> template<class T, size_t N>
T *array_end(T (&array)[N]) { return array + N; } T *array_end(T (&array)[N]) { return array + N; }
void PrintIncludes(Printer *printer, const std::vector<grpc::string>& headers, const Parameters &params) { void PrintIncludes(grpc_generator::Printer *printer,
const std::vector<grpc::string>& headers, const Parameters &params) {
std::map<grpc::string, grpc::string> vars; std::map<grpc::string, grpc::string> vars;
vars["l"] = params.use_system_headers ? '<' : '"'; vars["l"] = params.use_system_headers ? '<' : '"';
...@@ -86,7 +87,7 @@ void PrintIncludes(Printer *printer, const std::vector<grpc::string>& headers, c ...@@ -86,7 +87,7 @@ void PrintIncludes(Printer *printer, const std::vector<grpc::string>& headers, c
} }
} }
grpc::string GetHeaderPrologue(File *file, const Parameters & /*params*/) { grpc::string GetHeaderPrologue(grpc_generator::File *file, const Parameters & /*params*/) {
grpc::string output; grpc::string output;
{ {
// Scope the output stream so it closes and finalizes output to the string. // Scope the output stream so it closes and finalizes output to the string.
...@@ -111,7 +112,7 @@ grpc::string GetHeaderPrologue(File *file, const Parameters & /*params*/) { ...@@ -111,7 +112,7 @@ grpc::string GetHeaderPrologue(File *file, const Parameters & /*params*/) {
return output; return output;
} }
grpc::string GetHeaderIncludes(File *file, grpc::string GetHeaderIncludes(grpc_generator::File *file,
const Parameters &params) { const Parameters &params) {
grpc::string output; grpc::string output;
{ {
...@@ -154,7 +155,7 @@ grpc::string GetHeaderIncludes(File *file, ...@@ -154,7 +155,7 @@ grpc::string GetHeaderIncludes(File *file,
} }
void PrintHeaderClientMethodInterfaces( void PrintHeaderClientMethodInterfaces(
Printer *printer, const Method *method, grpc_generator::Printer *printer, const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars, bool is_public) { std::map<grpc::string, grpc::string> *vars, bool is_public) {
(*vars)["Method"] = method->name(); (*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name(); (*vars)["Request"] = method->input_type_name();
...@@ -303,8 +304,8 @@ void PrintHeaderClientMethodInterfaces( ...@@ -303,8 +304,8 @@ void PrintHeaderClientMethodInterfaces(
} }
} }
void PrintHeaderClientMethod(Printer *printer, void PrintHeaderClientMethod(grpc_generator::Printer *printer,
const Method *method, const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars, std::map<grpc::string, grpc::string> *vars,
bool is_public) { bool is_public) {
(*vars)["Method"] = method->name(); (*vars)["Method"] = method->name();
...@@ -445,13 +446,13 @@ void PrintHeaderClientMethod(Printer *printer, ...@@ -445,13 +446,13 @@ void PrintHeaderClientMethod(Printer *printer,
} }
} }
void PrintHeaderClientMethodData(Printer *printer, const Method *method, void PrintHeaderClientMethodData(grpc_generator::Printer *printer, const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars) { std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name(); (*vars)["Method"] = method->name();
printer->Print(*vars, "const ::grpc::RpcMethod rpcmethod_$Method$_;\n"); printer->Print(*vars, "const ::grpc::RpcMethod rpcmethod_$Method$_;\n");
} }
void PrintHeaderServerMethodSync(Printer *printer, const Method *method, void PrintHeaderServerMethodSync(grpc_generator::Printer *printer, const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars) { std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name(); (*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name(); (*vars)["Request"] = method->input_type_name();
...@@ -483,8 +484,8 @@ void PrintHeaderServerMethodSync(Printer *printer, const Method *method, ...@@ -483,8 +484,8 @@ void PrintHeaderServerMethodSync(Printer *printer, const Method *method,
} }
void PrintHeaderServerMethodAsync( void PrintHeaderServerMethodAsync(
Printer *printer, grpc_generator::Printer *printer,
const Method *method, const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars) { std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name(); (*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name(); (*vars)["Request"] = method->input_type_name();
...@@ -599,8 +600,8 @@ void PrintHeaderServerMethodAsync( ...@@ -599,8 +600,8 @@ void PrintHeaderServerMethodAsync(
} }
void PrintHeaderServerMethodGeneric( void PrintHeaderServerMethodGeneric(
Printer *printer, grpc_generator::Printer *printer,
const Method *method, const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars) { std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name(); (*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name(); (*vars)["Request"] = method->input_type_name();
...@@ -669,8 +670,8 @@ void PrintHeaderServerMethodGeneric( ...@@ -669,8 +670,8 @@ void PrintHeaderServerMethodGeneric(
printer->Print(*vars, "};\n"); printer->Print(*vars, "};\n");
} }
void PrintHeaderService(Printer *printer, void PrintHeaderService(grpc_generator::Printer *printer,
const Service *service, const grpc_generator::Service *service,
std::map<grpc::string, grpc::string> *vars) { std::map<grpc::string, grpc::string> *vars) {
(*vars)["Service"] = service->name(); (*vars)["Service"] = service->name();
...@@ -764,7 +765,7 @@ void PrintHeaderService(Printer *printer, ...@@ -764,7 +765,7 @@ void PrintHeaderService(Printer *printer,
printer->Print("};\n"); printer->Print("};\n");
} }
grpc::string GetHeaderServices(File *file, grpc::string GetHeaderServices(grpc_generator::File *file,
const Parameters &params) { const Parameters &params) {
grpc::string output; grpc::string output;
{ {
...@@ -795,7 +796,7 @@ grpc::string GetHeaderServices(File *file, ...@@ -795,7 +796,7 @@ grpc::string GetHeaderServices(File *file,
return output; return output;
} }
grpc::string GetHeaderEpilogue(File *file, const Parameters & /*params*/) { grpc::string GetHeaderEpilogue(grpc_generator::File *file, const Parameters & /*params*/) {
grpc::string output; grpc::string output;
{ {
// Scope the output stream so it closes and finalizes output to the string. // Scope the output stream so it closes and finalizes output to the string.
...@@ -821,7 +822,7 @@ grpc::string GetHeaderEpilogue(File *file, const Parameters & /*params*/) { ...@@ -821,7 +822,7 @@ grpc::string GetHeaderEpilogue(File *file, const Parameters & /*params*/) {
return output; return output;
} }
grpc::string GetSourcePrologue(File *file, const Parameters & /*params*/) { grpc::string GetSourcePrologue(grpc_generator::File *file, const Parameters & /*params*/) {
grpc::string output; grpc::string output;
{ {
// Scope the output stream so it closes and finalizes output to the string. // Scope the output stream so it closes and finalizes output to the string.
...@@ -845,7 +846,7 @@ grpc::string GetSourcePrologue(File *file, const Parameters & /*params*/) { ...@@ -845,7 +846,7 @@ grpc::string GetSourcePrologue(File *file, const Parameters & /*params*/) {
return output; return output;
} }
grpc::string GetSourceIncludes(File *file, grpc::string GetSourceIncludes(grpc_generator::File *file,
const Parameters &params) { const Parameters &params) {
grpc::string output; grpc::string output;
{ {
...@@ -880,8 +881,8 @@ grpc::string GetSourceIncludes(File *file, ...@@ -880,8 +881,8 @@ grpc::string GetSourceIncludes(File *file,
return output; return output;
} }
void PrintSourceClientMethod(Printer *printer, void PrintSourceClientMethod(grpc_generator::Printer *printer,
const Method *method, const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars) { std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name(); (*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name(); (*vars)["Request"] = method->input_type_name();
...@@ -981,8 +982,8 @@ void PrintSourceClientMethod(Printer *printer, ...@@ -981,8 +982,8 @@ void PrintSourceClientMethod(Printer *printer,
} }
} }
void PrintSourceServerMethod(Printer *printer, void PrintSourceServerMethod(grpc_generator::Printer *printer,
const Method *method, const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars) { std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name(); (*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name(); (*vars)["Request"] = method->input_type_name();
...@@ -1040,8 +1041,8 @@ void PrintSourceServerMethod(Printer *printer, ...@@ -1040,8 +1041,8 @@ void PrintSourceServerMethod(Printer *printer,
} }
} }
void PrintSourceService(Printer *printer, void PrintSourceService(grpc_generator::Printer *printer,
const Service *service, const grpc_generator::Service *service,
std::map<grpc::string, grpc::string> *vars) { std::map<grpc::string, grpc::string> *vars) {
(*vars)["Service"] = service->name(); (*vars)["Service"] = service->name();
...@@ -1153,7 +1154,7 @@ void PrintSourceService(Printer *printer, ...@@ -1153,7 +1154,7 @@ void PrintSourceService(Printer *printer,
} }
} }
grpc::string GetSourceServices(File *file, grpc::string GetSourceServices(grpc_generator::File *file,
const Parameters &params) { const Parameters &params) {
grpc::string output; grpc::string output;
{ {
...@@ -1182,7 +1183,7 @@ grpc::string GetSourceServices(File *file, ...@@ -1182,7 +1183,7 @@ grpc::string GetSourceServices(File *file,
return output; return output;
} }
grpc::string GetSourceEpilogue(File *file, const Parameters & /*params*/) { grpc::string GetSourceEpilogue(grpc_generator::File *file, const Parameters & /*params*/) {
grpc::string temp; grpc::string temp;
if (!file->package().empty()) { if (!file->package().empty()) {
......
...@@ -41,16 +41,7 @@ ...@@ -41,16 +41,7 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#ifndef GRPC_CUSTOM_STRING #include "src/compiler/schema_interface.h"
#include <string>
#define GRPC_CUSTOM_STRING std::string
#endif
namespace grpc {
typedef GRPC_CUSTOM_STRING string;
} // namespace grpc
namespace grpc_cpp_generator { namespace grpc_cpp_generator {
...@@ -64,83 +55,29 @@ struct Parameters { ...@@ -64,83 +55,29 @@ struct Parameters {
grpc::string grpc_search_path; grpc::string grpc_search_path;
}; };
// An abstract interface representing a method.
struct Method {
virtual ~Method() {}
virtual grpc::string name() const = 0;
virtual grpc::string input_type_name() const = 0;
virtual grpc::string output_type_name() const = 0;
virtual bool NoStreaming() const = 0;
virtual bool ClientOnlyStreaming() const = 0;
virtual bool ServerOnlyStreaming() const = 0;
virtual bool BidiStreaming() const = 0;
};
// An abstract interface representing a service.
struct Service {
virtual ~Service() {}
virtual grpc::string name() const = 0;
virtual int method_count() const = 0;
virtual std::unique_ptr<const Method> method(int i) const = 0;
};
struct Printer {
virtual ~Printer() {}
virtual void Print(const std::map<grpc::string, grpc::string> &vars,
const char *template_string) = 0;
virtual void Print(const char *string) = 0;
virtual void Indent() = 0;
virtual void Outdent() = 0;
};
// An interface that allows the source generated to be output using various
// libraries/idls/serializers.
struct File {
virtual ~File() {}
virtual grpc::string filename() const = 0;
virtual grpc::string filename_without_ext() const = 0;
virtual grpc::string message_header_ext() const = 0;
virtual grpc::string service_header_ext() const = 0;
virtual grpc::string package() const = 0;
virtual std::vector<grpc::string> package_parts() const = 0;
virtual grpc::string additional_headers() const = 0;
virtual int service_count() const = 0;
virtual std::unique_ptr<const Service> service(int i) const = 0;
virtual std::unique_ptr<Printer> CreatePrinter(grpc::string *str) const = 0;
};
// Return the prologue of the generated header file. // Return the prologue of the generated header file.
grpc::string GetHeaderPrologue(File *file, const Parameters &params); grpc::string GetHeaderPrologue(grpc_generator::File *file, const Parameters &params);
// Return the includes needed for generated header file. // Return the includes needed for generated header file.
grpc::string GetHeaderIncludes(File *file, const Parameters &params); grpc::string GetHeaderIncludes(grpc_generator::File *file, const Parameters &params);
// Return the includes needed for generated source file. // Return the includes needed for generated source file.
grpc::string GetSourceIncludes(File *file, const Parameters &params); grpc::string GetSourceIncludes(grpc_generator::File *file, const Parameters &params);
// Return the epilogue of the generated header file. // Return the epilogue of the generated header file.
grpc::string GetHeaderEpilogue(File *file, const Parameters &params); grpc::string GetHeaderEpilogue(grpc_generator::File *file, const Parameters &params);
// Return the prologue of the generated source file. // Return the prologue of the generated source file.
grpc::string GetSourcePrologue(File *file, const Parameters &params); grpc::string GetSourcePrologue(grpc_generator::File *file, const Parameters &params);
// Return the services for generated header file. // Return the services for generated header file.
grpc::string GetHeaderServices(File *file, const Parameters &params); grpc::string GetHeaderServices(grpc_generator::File *file, const Parameters &params);
// Return the services for generated source file. // Return the services for generated source file.
grpc::string GetSourceServices(File *file, const Parameters &params); grpc::string GetSourceServices(grpc_generator::File *file, const Parameters &params);
// Return the epilogue of the generated source file. // Return the epilogue of the generated source file.
grpc::string GetSourceEpilogue(File *file, const Parameters &params); grpc::string GetSourceEpilogue(grpc_generator::File *file, const Parameters &params);
} // namespace grpc_cpp_generator } // namespace grpc_cpp_generator
......
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
#define GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
#include <memory>
#include <vector>
#ifndef GRPC_CUSTOM_STRING
#include <string>
#define GRPC_CUSTOM_STRING std::string
#endif
namespace grpc {
typedef GRPC_CUSTOM_STRING string;
} // namespace grpc
namespace grpc_generator {
// An abstract interface representing a method.
struct Method {
virtual ~Method() {}
virtual grpc::string name() const = 0;
virtual grpc::string input_type_name() const = 0;
virtual grpc::string output_type_name() const = 0;
virtual bool NoStreaming() const = 0;
virtual bool ClientOnlyStreaming() const = 0;
virtual bool ServerOnlyStreaming() const = 0;
virtual bool BidiStreaming() const = 0;
};
// An abstract interface representing a service.
struct Service {
virtual ~Service() {}
virtual grpc::string name() const = 0;
virtual int method_count() const = 0;
virtual std::unique_ptr<const Method> method(int i) const = 0;
};
struct Printer {
virtual ~Printer() {}
virtual void Print(const std::map<grpc::string, grpc::string> &vars,
const char *template_string) = 0;
virtual void Print(const char *string) = 0;
virtual void Indent() = 0;
virtual void Outdent() = 0;
};
// An interface that allows the source generated to be output using various
// libraries/idls/serializers.
struct File {
virtual ~File() {}
virtual grpc::string filename() const = 0;
virtual grpc::string filename_without_ext() const = 0;
virtual grpc::string message_header_ext() const = 0;
virtual grpc::string service_header_ext() const = 0;
virtual grpc::string package() const = 0;
virtual std::vector<grpc::string> package_parts() const = 0;
virtual grpc::string additional_headers() const = 0;
virtual int service_count() const = 0;
virtual std::unique_ptr<const Service> service(int i) const = 0;
virtual std::unique_ptr<Printer> CreatePrinter(grpc::string *str) const = 0;
};
} // namespace grpc_generator
#endif // GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
...@@ -1436,11 +1436,6 @@ class Struct FLATBUFFERS_FINAL_CLASS { ...@@ -1436,11 +1436,6 @@ class Struct FLATBUFFERS_FINAL_CLASS {
return ReadScalar<T>(&data_[o]); return ReadScalar<T>(&data_[o]);
} }
template<typename T> T GetPointer(uoffset_t o) const {
auto p = &data_[o];
return reinterpret_cast<T>(p + ReadScalar<uoffset_t>(p));
}
template<typename T> T GetStruct(uoffset_t o) const { template<typename T> T GetStruct(uoffset_t o) const {
return reinterpret_cast<T>(&data_[o]); return reinterpret_cast<T>(&data_[o]);
} }
......
...@@ -596,7 +596,9 @@ extern void GenComment(const std::vector<std::string> &dc, ...@@ -596,7 +596,9 @@ extern void GenComment(const std::vector<std::string> &dc,
// if it is less than 0, no linefeeds will be generated either. // if it is less than 0, no linefeeds will be generated either.
// See idl_gen_text.cpp. // See idl_gen_text.cpp.
// strict_json adds "quotes" around field names if true. // strict_json adds "quotes" around field names if true.
extern void GenerateText(const Parser &parser, // If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8
// byte arrays in String values), returns false.
extern bool GenerateText(const Parser &parser,
const void *flatbuffer, const void *flatbuffer,
std::string *text); std::string *text);
extern bool GenerateTextFile(const Parser &parser, extern bool GenerateTextFile(const Parser &parser,
......
...@@ -367,6 +367,28 @@ public class FlatBufferBuilder { ...@@ -367,6 +367,28 @@ public class FlatBufferBuilder {
} }
/// @endcond /// @endcond
/**
* Create a new array/vector and return a ByteBuffer to be filled later.
* Call {@link #endVector} after this method to get an offset to the beginning
* of vector.
*
* @param elem_size the size of each element in bytes.
* @param num_elems number of elements in the vector.
* @param alignment byte alignment.
* @return ByteBuffer with position and limit set to the space allocated for the array.
*/
public ByteBuffer createUnintializedVector(int elem_size, int num_elems, int alignment) {
int length = elem_size * num_elems;
startVector(elem_size, num_elems, alignment);
bb.position(space -= length);
// Slice and limit the copy vector to point to the 'array'
ByteBuffer copy = bb.slice().order(ByteOrder.LITTLE_ENDIAN);
copy.limit(length);
return copy;
}
/** /**
* Create a vector of tables. * Create a vector of tables.
* *
...@@ -438,6 +460,20 @@ public class FlatBufferBuilder { ...@@ -438,6 +460,20 @@ public class FlatBufferBuilder {
return endVector(); return endVector();
} }
/**
* Create a byte array in the buffer.
*
* @param arr A source array with data
* @return The offset in the buffer where the encoded array starts.
*/
public int createByteVector(byte[] arr) {
int length = arr.length;
startVector(1, length, 1);
bb.position(space -= length);
bb.put(arr);
return endVector();
}
/// @cond FLATBUFFERS_INTERNAL /// @cond FLATBUFFERS_INTERNAL
/** /**
* Should not be accessing the final buffer before it is finished. * Should not be accessing the final buffer before it is finished.
......
...@@ -37,6 +37,12 @@ public class Table { ...@@ -37,6 +37,12 @@ public class Table {
return Charset.forName("UTF-8").newDecoder(); return Charset.forName("UTF-8").newDecoder();
} }
}; };
public final static ThreadLocal<Charset> UTF8_CHARSET = new ThreadLocal<Charset>() {
@Override
protected Charset initialValue() {
return Charset.forName("UTF-8");
}
};
private final static ThreadLocal<CharBuffer> CHAR_BUFFER = new ThreadLocal<CharBuffer>(); private final static ThreadLocal<CharBuffer> CHAR_BUFFER = new ThreadLocal<CharBuffer>();
/** Used to hold the position of the `bb` buffer. */ /** Used to hold the position of the `bb` buffer. */
protected int bb_pos; protected int bb_pos;
...@@ -75,7 +81,7 @@ public class Table { ...@@ -75,7 +81,7 @@ public class Table {
protected int __indirect(int offset) { protected int __indirect(int offset) {
return offset + bb.getInt(offset); return offset + bb.getInt(offset);
} }
protected static int __indirect(int offset, ByteBuffer bb) { protected static int __indirect(int offset, ByteBuffer bb) {
return offset + bb.getInt(offset); return offset + bb.getInt(offset);
} }
...@@ -197,17 +203,21 @@ public class Table { ...@@ -197,17 +203,21 @@ public class Table {
} }
return true; return true;
} }
/** /**
* Sort tables by the key. * Sort tables by the key.
* *
* @param offsets An 'int' indexes of the tables into the bb. * @param offsets An 'int' indexes of the tables into the bb.
* @param bb A {@code ByteBuffer} to get the tables. * @param bb A {@code ByteBuffer} to get the tables.
*/ */
protected void sortTables(int[] offsets, ByteBuffer bb) { protected void sortTables(int[] offsets, final ByteBuffer bb) {
Integer[] off = new Integer[offsets.length]; Integer[] off = new Integer[offsets.length];
for (int i = 0; i < offsets.length; i++) off[i] = offsets[i]; for (int i = 0; i < offsets.length; i++) off[i] = offsets[i];
Arrays.sort(off, (Integer o1, Integer o2) -> keysCompare(o1, o2, bb)); java.util.Arrays.sort(off, new java.util.Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
return keysCompare(o1, o2, bb);
}
});
for (int i = 0; i < offsets.length; i++) offsets[i] = off[i]; for (int i = 0; i < offsets.length; i++) offsets[i] = off[i];
} }
...@@ -219,7 +229,7 @@ public class Table { ...@@ -219,7 +229,7 @@ public class Table {
* @param bb A {@code ByteBuffer} to get the keys. * @param bb A {@code ByteBuffer} to get the keys.
*/ */
protected int keysCompare(Integer o1, Integer o2, ByteBuffer bb) { return 0; } protected int keysCompare(Integer o1, Integer o2, ByteBuffer bb) { return 0; }
/** /**
* Compare two strings in the buffer. * Compare two strings in the buffer.
* *
...@@ -242,7 +252,7 @@ public class Table { ...@@ -242,7 +252,7 @@ public class Table {
} }
return len_1 - len_2; return len_1 - len_2;
} }
/** /**
* Compare string from the buffer with the 'String' object. * Compare string from the buffer with the 'String' object.
* *
......
...@@ -14,7 +14,20 @@ ...@@ -14,7 +14,20 @@
* limitations under the License. * limitations under the License.
*/ */
//#define UNSAFE_BYTEBUFFER // uncomment this line to use faster ByteBuffer // There are 2 #defines that have an impact on performance of this ByteBuffer implementation
//
// UNSAFE_BYTEBUFFER
// This will use unsafe code to manipulate the underlying byte array. This
// can yield a reasonable performance increase.
//
// BYTEBUFFER_NO_BOUNDS_CHECK
// This will disable the bounds check asserts to the byte array. This can
// yield a small performance gain in normal code..
//
// Using UNSAFE_BYTEBUFFER and BYTEBUFFER_NO_BOUNDS_CHECK together can yield a
// performance gain of ~15% for some operations, however doing so is potentially
// dangerous. Do so at your own risk!
//
using System; using System;
...@@ -22,9 +35,6 @@ namespace FlatBuffers ...@@ -22,9 +35,6 @@ namespace FlatBuffers
{ {
/// <summary> /// <summary>
/// Class to mimic Java's ByteBuffer which is used heavily in Flatbuffers. /// Class to mimic Java's ByteBuffer which is used heavily in Flatbuffers.
/// If your execution environment allows unsafe code, you should enable
/// unsafe code in your project and #define UNSAFE_BYTEBUFFER to use a
/// MUCH faster version of ByteBuffer.
/// </summary> /// </summary>
public class ByteBuffer public class ByteBuffer
{ {
...@@ -126,11 +136,14 @@ namespace FlatBuffers ...@@ -126,11 +136,14 @@ namespace FlatBuffers
} }
#endif // !UNSAFE_BYTEBUFFER #endif // !UNSAFE_BYTEBUFFER
private void AssertOffsetAndLength(int offset, int length) private void AssertOffsetAndLength(int offset, int length)
{ {
#if !BYTEBUFFER_NO_BOUNDS_CHECK
if (offset < 0 || if (offset < 0 ||
offset > _buffer.Length - length) offset > _buffer.Length - length)
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
#endif
} }
public void PutSbyte(int offset, sbyte value) public void PutSbyte(int offset, sbyte value)
...@@ -200,7 +213,6 @@ namespace FlatBuffers ...@@ -200,7 +213,6 @@ namespace FlatBuffers
public unsafe void PutUlong(int offset, ulong value) public unsafe void PutUlong(int offset, ulong value)
{ {
AssertOffsetAndLength(offset, sizeof(ulong)); AssertOffsetAndLength(offset, sizeof(ulong));
fixed (byte* ptr = _buffer) fixed (byte* ptr = _buffer)
{ {
*(ulong*)(ptr + offset) = BitConverter.IsLittleEndian *(ulong*)(ptr + offset) = BitConverter.IsLittleEndian
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.google.flatbuffers</groupId> <groupId>com.google.flatbuffers</groupId>
<artifactId>flatbuffers-java</artifactId> <artifactId>flatbuffers-java</artifactId>
<version>1.3.0-SNAPSHOT</version> <version>1.4.0-SNAPSHOT</version>
<packaging>bundle</packaging> <packaging>bundle</packaging>
<name>FlatBuffers Java API</name> <name>FlatBuffers Java API</name>
<description> <description>
......
...@@ -46,7 +46,10 @@ int main(int /*argc*/, const char * /*argv*/[]) { ...@@ -46,7 +46,10 @@ int main(int /*argc*/, const char * /*argv*/[]) {
// to ensure it is correct, we now generate text back from the binary, // to ensure it is correct, we now generate text back from the binary,
// and compare the two: // and compare the two:
std::string jsongen; std::string jsongen;
GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen); if (!GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen)) {
printf("Couldn't serialize parsed data to JSON!\n");
return 1;
}
if (jsongen != jsonfile) { if (jsongen != jsonfile) {
printf("%s----------------\n%s", jsongen.c_str(), jsonfile.c_str()); printf("%s----------------\n%s", jsongen.c_str(), jsonfile.c_str());
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#include "flatbuffers/util.h" #include "flatbuffers/util.h"
#include <limits> #include <limits>
#define FLATC_VERSION "1.3.0 (" __DATE__ ")" #define FLATC_VERSION "1.4.0 (" __DATE__ ")"
static void Error(const std::string &err, bool usage = false, static void Error(const std::string &err, bool usage = false,
bool show_exe_name = true); bool show_exe_name = true);
...@@ -243,7 +243,7 @@ int main(int argc, const char *argv[]) { ...@@ -243,7 +243,7 @@ int main(int argc, const char *argv[]) {
goto found; goto found;
} }
} }
Error("unknown commandline argument" + arg, true); Error("unknown commandline argument: " + arg, true);
found:; found:;
} }
} else { } else {
......
...@@ -333,15 +333,15 @@ class CppGenerator : public BaseGenerator { ...@@ -333,15 +333,15 @@ class CppGenerator : public BaseGenerator {
return (opts.scoped_enums ? "enum class " : "enum ") + enum_def.name; return (opts.scoped_enums ? "enum class " : "enum ") + enum_def.name;
} }
static std::string GenEnumVal(const EnumDef &enum_def, static std::string GenEnumValDecl(const EnumDef &enum_def,
const std::string &enum_val, const std::string &enum_val,
const IDLOptions &opts) { const IDLOptions &opts) {
return opts.prefixed_enums ? enum_def.name + "_" + enum_val : enum_val; return opts.prefixed_enums ? enum_def.name + "_" + enum_val : enum_val;
} }
static std::string GetEnumVal(const EnumDef &enum_def, static std::string GetEnumValUse(const EnumDef &enum_def,
const EnumVal &enum_val, const EnumVal &enum_val,
const IDLOptions &opts) { const IDLOptions &opts) {
if (opts.scoped_enums) { if (opts.scoped_enums) {
return enum_def.name + "::" + enum_val.name; return enum_def.name + "::" + enum_val.name;
} else if (opts.prefixed_enums) { } else if (opts.prefixed_enums) {
...@@ -396,7 +396,7 @@ class CppGenerator : public BaseGenerator { ...@@ -396,7 +396,7 @@ class CppGenerator : public BaseGenerator {
++it) { ++it) {
auto &ev = **it; auto &ev = **it;
GenComment(ev.doc_comment, code_ptr, nullptr, " "); GenComment(ev.doc_comment, code_ptr, nullptr, " ");
code += " " + GenEnumVal(enum_def, ev.name, parser_.opts) + " = "; code += " " + GenEnumValDecl(enum_def, ev.name, parser_.opts) + " = ";
code += NumToString(ev.value) + ",\n"; code += NumToString(ev.value) + ",\n";
minv = !minv || minv->value > ev.value ? &ev : minv; minv = !minv || minv->value > ev.value ? &ev : minv;
maxv = !maxv || maxv->value < ev.value ? &ev : maxv; maxv = !maxv || maxv->value < ev.value ? &ev : maxv;
...@@ -406,15 +406,15 @@ class CppGenerator : public BaseGenerator { ...@@ -406,15 +406,15 @@ class CppGenerator : public BaseGenerator {
assert(minv && maxv); assert(minv && maxv);
if (enum_def.attributes.Lookup("bit_flags")) { if (enum_def.attributes.Lookup("bit_flags")) {
if (minv->value != 0) // If the user didn't defined NONE value if (minv->value != 0) // If the user didn't defined NONE value
code += " " + GenEnumVal(enum_def, "NONE", parser_.opts) + " = 0,\n"; code += " " + GenEnumValDecl(enum_def, "NONE", parser_.opts) + " = 0,\n";
if (maxv->value != anyv) // If the user didn't defined ANY value if (maxv->value != anyv) // If the user didn't defined ANY value
code += " " + GenEnumVal(enum_def, "ANY", parser_.opts) + " = " + code += " " + GenEnumValDecl(enum_def, "ANY", parser_.opts) + " = " +
NumToString(anyv) + "\n"; NumToString(anyv) + "\n";
} else { // MIN & MAX are useless for bit_flags } else { // MIN & MAX are useless for bit_flags
code += " " + GenEnumVal(enum_def, "MIN", parser_.opts) + " = "; code += " " + GenEnumValDecl(enum_def, "MIN", parser_.opts) + " = ";
code += GenEnumVal(enum_def, minv->name, parser_.opts) + ",\n"; code += GenEnumValDecl(enum_def, minv->name, parser_.opts) + ",\n";
code += " " + GenEnumVal(enum_def, "MAX", parser_.opts) + " = "; code += " " + GenEnumValDecl(enum_def, "MAX", parser_.opts) + " = ";
code += GenEnumVal(enum_def, maxv->name, parser_.opts) + "\n"; code += GenEnumValDecl(enum_def, maxv->name, parser_.opts) + "\n";
} }
} }
code += "};\n"; code += "};\n";
...@@ -429,7 +429,7 @@ class CppGenerator : public BaseGenerator { ...@@ -429,7 +429,7 @@ class CppGenerator : public BaseGenerator {
code += " " + enum_def.name + " type;\n\n"; code += " " + enum_def.name + " type;\n\n";
code += " flatbuffers::NativeTable *table;\n"; code += " flatbuffers::NativeTable *table;\n";
code += " " + enum_def.name + "Union() : type("; code += " " + enum_def.name + "Union() : type(";
code += GenEnumVal(enum_def, "NONE", parser_.opts); code += GetEnumValUse(enum_def, *enum_def.vals.Lookup("NONE"), parser_.opts);
code += "), table(nullptr) {}\n"; code += "), table(nullptr) {}\n";
code += " " + enum_def.name + "Union(const "; code += " " + enum_def.name + "Union(const ";
code += enum_def.name + "Union &);\n"; code += enum_def.name + "Union &);\n";
...@@ -445,7 +445,7 @@ class CppGenerator : public BaseGenerator { ...@@ -445,7 +445,7 @@ class CppGenerator : public BaseGenerator {
auto native_name = NativeName(WrapInNameSpace(*ev.struct_def)); auto native_name = NativeName(WrapInNameSpace(*ev.struct_def));
code += " " + native_name + " *As"; code += " " + native_name + " *As";
code += ev.name + "() { return type == "; code += ev.name + "() { return type == ";
code += GetEnumVal(enum_def, ev, parser_.opts); code += GetEnumValUse(enum_def, ev, parser_.opts);
code += " ? reinterpret_cast<" + native_name; code += " ? reinterpret_cast<" + native_name;
code += " *>(table) : nullptr; }\n"; code += " *>(table) : nullptr; }\n";
} }
...@@ -478,7 +478,7 @@ class CppGenerator : public BaseGenerator { ...@@ -478,7 +478,7 @@ class CppGenerator : public BaseGenerator {
code += "()[static_cast<int>(e)"; code += "()[static_cast<int>(e)";
if (enum_def.vals.vec.front()->value) { if (enum_def.vals.vec.front()->value) {
code += " - static_cast<int>("; code += " - static_cast<int>(";
code += GetEnumVal(enum_def, *enum_def.vals.vec.front(), parser_.opts) + code += GetEnumValUse(enum_def, *enum_def.vals.vec.front(), parser_.opts) +
")"; ")";
} }
code += "]; }\n\n"; code += "]; }\n\n";
...@@ -500,7 +500,7 @@ class CppGenerator : public BaseGenerator { ...@@ -500,7 +500,7 @@ class CppGenerator : public BaseGenerator {
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
++it) { ++it) {
auto &ev = **it; auto &ev = **it;
code += " case " + GetEnumVal(enum_def, ev, parser_.opts); code += " case " + GetEnumValUse(enum_def, ev, parser_.opts);
if (!ev.value) { if (!ev.value) {
code += ": return true;\n"; // "NONE" enum value. code += ": return true;\n"; // "NONE" enum value.
} else { } else {
...@@ -518,7 +518,7 @@ class CppGenerator : public BaseGenerator { ...@@ -518,7 +518,7 @@ class CppGenerator : public BaseGenerator {
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
++it) { ++it) {
auto &ev = **it; auto &ev = **it;
code += " case " + GetEnumVal(enum_def, ev, parser_.opts); code += " case " + GetEnumValUse(enum_def, ev, parser_.opts);
if (!ev.value) { if (!ev.value) {
code += ": return nullptr;\n"; // "NONE" enum value. code += ": return nullptr;\n"; // "NONE" enum value.
} else { } else {
...@@ -533,7 +533,7 @@ class CppGenerator : public BaseGenerator { ...@@ -533,7 +533,7 @@ class CppGenerator : public BaseGenerator {
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
++it) { ++it) {
auto &ev = **it; auto &ev = **it;
code += " case " + GetEnumVal(enum_def, ev, parser_.opts); code += " case " + GetEnumValUse(enum_def, ev, parser_.opts);
if (!ev.value) { if (!ev.value) {
code += ": return 0;\n"; // "NONE" enum value. code += ": return 0;\n"; // "NONE" enum value.
} else { } else {
...@@ -553,7 +553,7 @@ class CppGenerator : public BaseGenerator { ...@@ -553,7 +553,7 @@ class CppGenerator : public BaseGenerator {
++it) { ++it) {
auto &ev = **it; auto &ev = **it;
if (ev.value) { if (ev.value) {
code += " case " + GenEnumVal(enum_def, ev.name, parser_.opts); code += " case " + GetEnumValUse(enum_def, ev, parser_.opts);
code += ": delete reinterpret_cast<"; code += ": delete reinterpret_cast<";
code += NativeName(WrapInNameSpace(*ev.struct_def)); code += NativeName(WrapInNameSpace(*ev.struct_def));
code += " *>(table); break;\n"; code += " *>(table); break;\n";
...@@ -613,7 +613,7 @@ class CppGenerator : public BaseGenerator { ...@@ -613,7 +613,7 @@ class CppGenerator : public BaseGenerator {
if (ev) { if (ev) {
code += WrapInNameSpace( code += WrapInNameSpace(
field.value.type.enum_def->defined_namespace, field.value.type.enum_def->defined_namespace,
GetEnumVal(*field.value.type.enum_def, *ev, parser_.opts)); GetEnumValUse(*field.value.type.enum_def, *ev, parser_.opts));
} else { } else {
code += GenUnderlyingCast(field, true, field.value.constant); code += GenUnderlyingCast(field, true, field.value.constant);
} }
......
...@@ -237,7 +237,7 @@ class GeneralGenerator : public BaseGenerator { ...@@ -237,7 +237,7 @@ class GeneralGenerator : public BaseGenerator {
// Save out the generated code for a single class while adding // Save out the generated code for a single class while adding
// declaration boilerplate. // declaration boilerplate.
bool SaveType(const std::string &defname, const Namespace &ns, bool SaveType(const std::string &defname, const Namespace &ns,
const std::string &classcode, bool needs_includes) { const std::string &classcode, bool needs_includes) {
if (!classcode.length()) return true; if (!classcode.length()) return true;
std::string code; std::string code;
...@@ -684,8 +684,7 @@ std::string GenOffsetGetter(flatbuffers::FieldDef *key_field, const char *num = ...@@ -684,8 +684,7 @@ std::string GenOffsetGetter(flatbuffers::FieldDef *key_field, const char *num =
key_offset += num; key_offset += num;
key_offset += (lang_.language == IDLOptions::kCSharp ? key_offset += (lang_.language == IDLOptions::kCSharp ?
".Value, builder.DataBuffer)" : ", _bb)"); ".Value, builder.DataBuffer)" : ", _bb)");
} } else {
else {
key_offset += GenByteBufferLength("bb"); key_offset += GenByteBufferLength("bb");
key_offset += " - tableOffset, bb)"; key_offset += " - tableOffset, bb)";
} }
...@@ -694,23 +693,21 @@ std::string GenOffsetGetter(flatbuffers::FieldDef *key_field, const char *num = ...@@ -694,23 +693,21 @@ std::string GenOffsetGetter(flatbuffers::FieldDef *key_field, const char *num =
std::string GenLookupKeyGetter(flatbuffers::FieldDef *key_field) { std::string GenLookupKeyGetter(flatbuffers::FieldDef *key_field) {
std::string key_getter = " "; std::string key_getter = " ";
key_getter += "tableOffset = __indirect(vectorLocation + 4 * (start + middle)"; key_getter += "int tableOffset = __indirect(vectorLocation + 4 * (start + middle)";
key_getter += ", bb);\n "; key_getter += ", bb);\n ";
if (key_field->value.type.base_type == BASE_TYPE_STRING) { if (key_field->value.type.base_type == BASE_TYPE_STRING) {
key_getter += "comp = " + FunctionStart('C') + "ompareStrings("; key_getter += "int comp = " + FunctionStart('C') + "ompareStrings(";
key_getter += GenOffsetGetter(key_field); key_getter += GenOffsetGetter(key_field);
key_getter += ", byteKey, bb);\n"; key_getter += ", byteKey, bb);\n";
} } else {
else {
auto get_val = GenGetter(key_field->value.type) + auto get_val = GenGetter(key_field->value.type) +
"(" + GenOffsetGetter(key_field) + ")"; "(" + GenOffsetGetter(key_field) + ")";
if (lang_.language == IDLOptions::kCSharp) { if (lang_.language == IDLOptions::kCSharp) {
key_getter += "comp = " + get_val + ".CompareTo(key);\n"; key_getter += "int comp = " + get_val + ".CompateTo(key);\n";
} } else {
else {
key_getter += GenTypeGet(key_field->value.type) + " val = "; key_getter += GenTypeGet(key_field->value.type) + " val = ";
key_getter += get_val + ";\n"; key_getter += get_val + ";\n";
key_getter += " comp = val > key ? 1 : val < key ? -1 : 0;\n"; key_getter += " int comp = val > key ? 1 : val < key ? -1 : 0;\n";
} }
} }
return key_getter; return key_getter;
...@@ -1215,8 +1212,7 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) { ...@@ -1215,8 +1212,7 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
code += "); }\n"; code += "); }\n";
} }
} }
if (struct_def.has_key && (lang_.language == IDLOptions::kJava || if (struct_def.has_key) {
lang_.language == IDLOptions::kCSharp)) {
if (lang_.language == IDLOptions::kJava) { if (lang_.language == IDLOptions::kJava) {
code += "\n @Override\n protected int keysCompare("; code += "\n @Override\n protected int keysCompare(";
code += "Integer o1, Integer o2, ByteBuffer _bb) {"; code += "Integer o1, Integer o2, ByteBuffer _bb) {";
...@@ -1238,32 +1234,31 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) { ...@@ -1238,32 +1234,31 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
code += "ookupByKey(" + GenVectorOffsetType(); code += "ookupByKey(" + GenVectorOffsetType();
code += " vectorOffset, " + GenTypeGet(key_field->value.type); code += " vectorOffset, " + GenTypeGet(key_field->value.type);
code += " key, ByteBuffer bb) {\n"; code += " key, ByteBuffer bb) {\n";
if (key_field->value.type.base_type == BASE_TYPE_STRING) { code += " byte[] byteKey = ";
code += " byte[] byteKey = "; if (lang_.language == IDLOptions::kJava)
if (lang_.language == IDLOptions::kJava) code += "key.getBytes(Table.UTF8_CHARSET.get());\n";
code += "key.getBytes(java.nio.charset.StandardCharsets.UTF_8);\n"; else
else code += "System.Text.Encoding.UTF8.GetBytes(key);\n";
code += "System.Text.Encoding.UTF8.GetBytes(key);\n";
}
code += " int vectorLocation = " + GenByteBufferLength("bb"); code += " int vectorLocation = " + GenByteBufferLength("bb");
code += " - vectorOffset"; code += " - vectorOffset";
if (lang_.language == IDLOptions::kCSharp) code += ".Value"; if (lang_.language == IDLOptions::kCSharp) code += ".Value";
code += ";\n int span = "; code += ";\n int span = ";
code += "bb." + FunctionStart('G') + "etInt(vectorLocation), "; code += "bb." + FunctionStart('G') + "etInt(vectorLocation);\n";
code += "middle, start = 0, comp, tableOffset; \n"; code += " int start = 0;\n";
code += " vectorLocation += 4;\n"; code += " vectorLocation += 4;\n";
code += " while (span != 0) {\n"; code += " while (span != 0) {\n";
code += " middle = span / 2;\n"; code += " int middle = span / 2;\n";
code += GenLookupKeyGetter(key_field); code += GenLookupKeyGetter(key_field);
code += " if (comp > 0) span = middle;\n"; code += " if (comp > 0) {\n";
code += " else if (comp < 0) {\n"; code += " span = middle;\n";
code += " } else if (comp < 0) {\n";
code += " middle++;\n"; code += " middle++;\n";
code += " start += middle;\n"; code += " start += middle;\n";
code += " span -= middle;\n"; code += " span -= middle;\n";
code += " }\n"; code += " } else {\n";
code += " else return new " + struct_def.name; code += " return new " + struct_def.name;
code += "().__init(tableOffset, bb);\n"; code += "().__init(tableOffset, bb);\n";
code += " }\n"; code += " }\n }\n";
code += " return null;\n"; code += " return null;\n";
code += " }\n"; code += " }\n";
} }
......
...@@ -288,9 +288,6 @@ static void GetMemberOfVectorOfStruct(const StructDef &struct_def, ...@@ -288,9 +288,6 @@ static void GetMemberOfVectorOfStruct(const StructDef &struct_def,
if (!(vectortype.struct_def->fixed)) { if (!(vectortype.struct_def->fixed)) {
code += "\t\tx = rcv._tab.Indirect(x)\n"; code += "\t\tx = rcv._tab.Indirect(x)\n";
} }
code += "\t\tif obj == nil {\n";
code += "\t\t\tobj = new(" + TypeName(field) + ")\n";
code += "\t\t}\n";
code += "\t\tobj.Init(rcv._tab.Bytes, x)\n"; code += "\t\tobj.Init(rcv._tab.Bytes, x)\n";
code += "\t\treturn true\n\t}\n"; code += "\t\treturn true\n\t}\n";
code += "\treturn false\n"; code += "\treturn false\n";
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
namespace flatbuffers { namespace flatbuffers {
class FlatBufMethod : public grpc_cpp_generator::Method { class FlatBufMethod : public grpc_generator::Method {
public: public:
enum Streaming { kNone, kClient, kServer, kBiDi }; enum Streaming { kNone, kClient, kServer, kBiDi };
...@@ -62,7 +62,7 @@ class FlatBufMethod : public grpc_cpp_generator::Method { ...@@ -62,7 +62,7 @@ class FlatBufMethod : public grpc_cpp_generator::Method {
Streaming streaming_; Streaming streaming_;
}; };
class FlatBufService : public grpc_cpp_generator::Service { class FlatBufService : public grpc_generator::Service {
public: public:
FlatBufService(const ServiceDef *service) : service_(service) {} FlatBufService(const ServiceDef *service) : service_(service) {}
...@@ -72,8 +72,8 @@ class FlatBufService : public grpc_cpp_generator::Service { ...@@ -72,8 +72,8 @@ class FlatBufService : public grpc_cpp_generator::Service {
return static_cast<int>(service_->calls.vec.size()); return static_cast<int>(service_->calls.vec.size());
}; };
std::unique_ptr<const grpc_cpp_generator::Method> method(int i) const { std::unique_ptr<const grpc_generator::Method> method(int i) const {
return std::unique_ptr<const grpc_cpp_generator::Method>( return std::unique_ptr<const grpc_generator::Method>(
new FlatBufMethod(service_->calls.vec[i])); new FlatBufMethod(service_->calls.vec[i]));
}; };
...@@ -81,7 +81,7 @@ class FlatBufService : public grpc_cpp_generator::Service { ...@@ -81,7 +81,7 @@ class FlatBufService : public grpc_cpp_generator::Service {
const ServiceDef *service_; const ServiceDef *service_;
}; };
class FlatBufPrinter : public grpc_cpp_generator::Printer { class FlatBufPrinter : public grpc_generator::Printer {
public: public:
FlatBufPrinter(std::string *str) FlatBufPrinter(std::string *str)
: str_(str), escape_char_('$'), indent_(0) {} : str_(str), escape_char_('$'), indent_(0) {}
...@@ -133,7 +133,7 @@ class FlatBufPrinter : public grpc_cpp_generator::Printer { ...@@ -133,7 +133,7 @@ class FlatBufPrinter : public grpc_cpp_generator::Printer {
int indent_; int indent_;
}; };
class FlatBufFile : public grpc_cpp_generator::File { class FlatBufFile : public grpc_generator::File {
public: public:
FlatBufFile(const Parser &parser, const std::string &file_name) FlatBufFile(const Parser &parser, const std::string &file_name)
: parser_(parser), file_name_(file_name) {} : parser_(parser), file_name_(file_name) {}
...@@ -163,13 +163,13 @@ class FlatBufFile : public grpc_cpp_generator::File { ...@@ -163,13 +163,13 @@ class FlatBufFile : public grpc_cpp_generator::File {
return static_cast<int>(parser_.services_.vec.size()); return static_cast<int>(parser_.services_.vec.size());
}; };
std::unique_ptr<const grpc_cpp_generator::Service> service(int i) const { std::unique_ptr<const grpc_generator::Service> service(int i) const {
return std::unique_ptr<const grpc_cpp_generator::Service> ( return std::unique_ptr<const grpc_generator::Service> (
new FlatBufService(parser_.services_.vec[i])); new FlatBufService(parser_.services_.vec[i]));
} }
std::unique_ptr<grpc_cpp_generator::Printer> CreatePrinter(std::string *str) const { std::unique_ptr<grpc_generator::Printer> CreatePrinter(std::string *str) const {
return std::unique_ptr<grpc_cpp_generator::Printer>( return std::unique_ptr<grpc_generator::Printer>(
new FlatBufPrinter(str)); new FlatBufPrinter(str));
} }
......
This diff is collapsed.
...@@ -40,6 +40,7 @@ namespace FlatBuffers.Test ...@@ -40,6 +40,7 @@ namespace FlatBuffers.Test
Assert.AreEqual((byte)99, buffer[0]); Assert.AreEqual((byte)99, buffer[0]);
} }
#if !BYTEBUFFER_NO_BOUNDS_CHECK
[FlatBuffersTestMethod] [FlatBuffersTestMethod]
public void ByteBuffer_PutByteCannotPutAtOffsetPastLength() public void ByteBuffer_PutByteCannotPutAtOffsetPastLength()
{ {
...@@ -47,6 +48,7 @@ namespace FlatBuffers.Test ...@@ -47,6 +48,7 @@ namespace FlatBuffers.Test
var uut = new ByteBuffer(buffer); var uut = new ByteBuffer(buffer);
Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutByte(1, 99)); Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutByte(1, 99));
} }
#endif
[FlatBuffersTestMethod] [FlatBuffersTestMethod]
public void ByteBuffer_PutShortPopulatesBufferCorrectly() public void ByteBuffer_PutShortPopulatesBufferCorrectly()
...@@ -60,6 +62,7 @@ namespace FlatBuffers.Test ...@@ -60,6 +62,7 @@ namespace FlatBuffers.Test
Assert.AreEqual((byte)0, buffer[1]); Assert.AreEqual((byte)0, buffer[1]);
} }
#if !BYTEBUFFER_NO_BOUNDS_CHECK
[FlatBuffersTestMethod] [FlatBuffersTestMethod]
public void ByteBuffer_PutShortCannotPutAtOffsetPastLength() public void ByteBuffer_PutShortCannotPutAtOffsetPastLength()
{ {
...@@ -67,7 +70,9 @@ namespace FlatBuffers.Test ...@@ -67,7 +70,9 @@ namespace FlatBuffers.Test
var uut = new ByteBuffer(buffer); var uut = new ByteBuffer(buffer);
Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutShort(2, 99)); Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutShort(2, 99));
} }
#endif
#if !BYTEBUFFER_NO_BOUNDS_CHECK
[FlatBuffersTestMethod] [FlatBuffersTestMethod]
public void ByteBuffer_PutShortChecksLength() public void ByteBuffer_PutShortChecksLength()
{ {
...@@ -83,6 +88,7 @@ namespace FlatBuffers.Test ...@@ -83,6 +88,7 @@ namespace FlatBuffers.Test
var uut = new ByteBuffer(buffer); var uut = new ByteBuffer(buffer);
Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutShort(1, 99)); Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutShort(1, 99));
} }
#endif
[FlatBuffersTestMethod] [FlatBuffersTestMethod]
public void ByteBuffer_PutIntPopulatesBufferCorrectly() public void ByteBuffer_PutIntPopulatesBufferCorrectly()
...@@ -98,6 +104,7 @@ namespace FlatBuffers.Test ...@@ -98,6 +104,7 @@ namespace FlatBuffers.Test
Assert.AreEqual(0x0A, buffer[3]); Assert.AreEqual(0x0A, buffer[3]);
} }
#if !BYTEBUFFER_NO_BOUNDS_CHECK
[FlatBuffersTestMethod] [FlatBuffersTestMethod]
public void ByteBuffer_PutIntCannotPutAtOffsetPastLength() public void ByteBuffer_PutIntCannotPutAtOffsetPastLength()
{ {
...@@ -121,6 +128,7 @@ namespace FlatBuffers.Test ...@@ -121,6 +128,7 @@ namespace FlatBuffers.Test
var uut = new ByteBuffer(buffer); var uut = new ByteBuffer(buffer);
Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutInt(2, 0x0A0B0C0D)); Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutInt(2, 0x0A0B0C0D));
} }
#endif
[FlatBuffersTestMethod] [FlatBuffersTestMethod]
public void ByteBuffer_PutLongPopulatesBufferCorrectly() public void ByteBuffer_PutLongPopulatesBufferCorrectly()
...@@ -140,6 +148,7 @@ namespace FlatBuffers.Test ...@@ -140,6 +148,7 @@ namespace FlatBuffers.Test
Assert.AreEqual(0x01, buffer[7]); Assert.AreEqual(0x01, buffer[7]);
} }
#if !BYTEBUFFER_NO_BOUNDS_CHECK
[FlatBuffersTestMethod] [FlatBuffersTestMethod]
public void ByteBuffer_PutLongCannotPutAtOffsetPastLength() public void ByteBuffer_PutLongCannotPutAtOffsetPastLength()
{ {
...@@ -163,6 +172,7 @@ namespace FlatBuffers.Test ...@@ -163,6 +172,7 @@ namespace FlatBuffers.Test
var uut = new ByteBuffer(buffer); var uut = new ByteBuffer(buffer);
Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutLong(2, 0x010203040A0B0C0D)); Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutLong(2, 0x010203040A0B0C0D));
} }
#endif
[FlatBuffersTestMethod] [FlatBuffersTestMethod]
public void ByteBuffer_GetByteReturnsCorrectData() public void ByteBuffer_GetByteReturnsCorrectData()
...@@ -173,6 +183,7 @@ namespace FlatBuffers.Test ...@@ -173,6 +183,7 @@ namespace FlatBuffers.Test
Assert.AreEqual((byte)99, uut.Get(0)); Assert.AreEqual((byte)99, uut.Get(0));
} }
#if !BYTEBUFFER_NO_BOUNDS_CHECK
[FlatBuffersTestMethod] [FlatBuffersTestMethod]
public void ByteBuffer_GetByteChecksOffset() public void ByteBuffer_GetByteChecksOffset()
{ {
...@@ -180,6 +191,7 @@ namespace FlatBuffers.Test ...@@ -180,6 +191,7 @@ namespace FlatBuffers.Test
var uut = new ByteBuffer(buffer); var uut = new ByteBuffer(buffer);
Assert.Throws<ArgumentOutOfRangeException>(()=>uut.Get(1)); Assert.Throws<ArgumentOutOfRangeException>(()=>uut.Get(1));
} }
#endif
[FlatBuffersTestMethod] [FlatBuffersTestMethod]
public void ByteBuffer_GetShortReturnsCorrectData() public void ByteBuffer_GetShortReturnsCorrectData()
...@@ -191,6 +203,7 @@ namespace FlatBuffers.Test ...@@ -191,6 +203,7 @@ namespace FlatBuffers.Test
Assert.AreEqual(1, uut.GetShort(0)); Assert.AreEqual(1, uut.GetShort(0));
} }
#if !BYTEBUFFER_NO_BOUNDS_CHECK
[FlatBuffersTestMethod] [FlatBuffersTestMethod]
public void ByteBuffer_GetShortChecksOffset() public void ByteBuffer_GetShortChecksOffset()
{ {
...@@ -206,6 +219,7 @@ namespace FlatBuffers.Test ...@@ -206,6 +219,7 @@ namespace FlatBuffers.Test
var uut = new ByteBuffer(buffer); var uut = new ByteBuffer(buffer);
Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetShort(1)); Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetShort(1));
} }
#endif
[FlatBuffersTestMethod] [FlatBuffersTestMethod]
public void ByteBuffer_GetIntReturnsCorrectData() public void ByteBuffer_GetIntReturnsCorrectData()
...@@ -219,6 +233,7 @@ namespace FlatBuffers.Test ...@@ -219,6 +233,7 @@ namespace FlatBuffers.Test
Assert.AreEqual(0x0A0B0C0D, uut.GetInt(0)); Assert.AreEqual(0x0A0B0C0D, uut.GetInt(0));
} }
#if !BYTEBUFFER_NO_BOUNDS_CHECK
[FlatBuffersTestMethod] [FlatBuffersTestMethod]
public void ByteBuffer_GetIntChecksOffset() public void ByteBuffer_GetIntChecksOffset()
{ {
...@@ -234,6 +249,7 @@ namespace FlatBuffers.Test ...@@ -234,6 +249,7 @@ namespace FlatBuffers.Test
var uut = new ByteBuffer(buffer); var uut = new ByteBuffer(buffer);
Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetInt(0)); Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetInt(0));
} }
#endif
[FlatBuffersTestMethod] [FlatBuffersTestMethod]
public void ByteBuffer_GetLongReturnsCorrectData() public void ByteBuffer_GetLongReturnsCorrectData()
...@@ -251,6 +267,7 @@ namespace FlatBuffers.Test ...@@ -251,6 +267,7 @@ namespace FlatBuffers.Test
Assert.AreEqual(0x010203040A0B0C0D, uut.GetLong(0)); Assert.AreEqual(0x010203040A0B0C0D, uut.GetLong(0));
} }
#if !BYTEBUFFER_NO_BOUNDS_CHECK
[FlatBuffersTestMethod] [FlatBuffersTestMethod]
public void ByteBuffer_GetLongChecksOffset() public void ByteBuffer_GetLongChecksOffset()
{ {
...@@ -266,6 +283,7 @@ namespace FlatBuffers.Test ...@@ -266,6 +283,7 @@ namespace FlatBuffers.Test
var uut = new ByteBuffer(buffer); var uut = new ByteBuffer(buffer);
Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetLong(0)); Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetLong(0));
} }
#endif
[FlatBuffersTestMethod] [FlatBuffersTestMethod]
public void ByteBuffer_ReverseBytesUshort() public void ByteBuffer_ReverseBytesUshort()
......
...@@ -185,6 +185,10 @@ class JavaTest { ...@@ -185,6 +185,10 @@ class JavaTest {
TestNestedFlatBuffer(); TestNestedFlatBuffer();
TestCreateByteVector();
TestCreateUninitializedVector();
System.out.println("FlatBuffers test: completed successfully"); System.out.println("FlatBuffers test: completed successfully");
} }
...@@ -305,6 +309,44 @@ class JavaTest { ...@@ -305,6 +309,44 @@ class JavaTest {
TestEq(nestedMonsterName, nestedMonster.name()); TestEq(nestedMonsterName, nestedMonster.name());
} }
static void TestCreateByteVector() {
FlatBufferBuilder fbb = new FlatBufferBuilder(16);
int str = fbb.createString("MyMonster");
byte[] inventory = new byte[] { 0, 1, 2, 3, 4 };
int vec = fbb.createByteVector(inventory);
Monster.startMonster(fbb);
Monster.addInventory(fbb, vec);
Monster.addName(fbb, str);
int monster1 = Monster.endMonster(fbb);
Monster.finishMonsterBuffer(fbb, monster1);
Monster monsterObject = Monster.getRootAsMonster(fbb.dataBuffer());
TestEq(monsterObject.inventory(1), (int)inventory[1]);
TestEq(monsterObject.inventoryLength(), inventory.length);
TestEq(ByteBuffer.wrap(inventory), monsterObject.inventoryAsByteBuffer());
}
static void TestCreateUninitializedVector() {
FlatBufferBuilder fbb = new FlatBufferBuilder(16);
int str = fbb.createString("MyMonster");
byte[] inventory = new byte[] { 0, 1, 2, 3, 4 };
ByteBuffer bb = fbb.createUnintializedVector(1, inventory.length, 1);
for (byte i:inventory) {
bb.put(i);
}
int vec = fbb.endVector();
Monster.startMonster(fbb);
Monster.addInventory(fbb, vec);
Monster.addName(fbb, str);
int monster1 = Monster.endMonster(fbb);
Monster.finishMonsterBuffer(fbb, monster1);
Monster monsterObject = Monster.getRootAsMonster(fbb.dataBuffer());
TestEq(monsterObject.inventory(1), (int)inventory[1]);
TestEq(monsterObject.inventoryLength(), inventory.length);
TestEq(ByteBuffer.wrap(inventory), monsterObject.inventoryAsByteBuffer());
}
static <T> void TestEq(T a, T b) { static <T> void TestEq(T a, T b) {
if (!a.equals(b)) { if (!a.equals(b)) {
System.out.println("" + a.getClass().getName() + " " + b.getClass().getName()); System.out.println("" + a.getClass().getName() + " " + b.getClass().getName());
......
...@@ -129,7 +129,7 @@ public sealed class Monster : Table { ...@@ -129,7 +129,7 @@ public sealed class Monster : Table {
return new Offset<Monster>(o); return new Offset<Monster>(o);
} }
public static void FinishMonsterBuffer(FlatBufferBuilder builder, Offset<Monster> offset) { builder.Finish(offset.Value, "MONS"); } public static void FinishMonsterBuffer(FlatBufferBuilder builder, Offset<Monster> offset) { builder.Finish(offset.Value, "MONS"); }
public static VectorOffset CreateMySortedVectorOfTables(FlatBufferBuilder builder, Offset<Monster>[] offsets) { public static VectorOffset CreateMySortedVectorOfTables(FlatBufferBuilder builder, Offset<Monster>[] offsets) {
Array.Sort(offsets, (Offset<Monster> o1, Offset<Monster> o2) => CompareStrings(__offset(10, o1.Value, builder.DataBuffer), __offset(10, o2.Value, builder.DataBuffer), builder.DataBuffer)); Array.Sort(offsets, (Offset<Monster> o1, Offset<Monster> o2) => CompareStrings(__offset(10, o1.Value, builder.DataBuffer), __offset(10, o2.Value, builder.DataBuffer), builder.DataBuffer));
return builder.CreateVectorOfTables(offsets); return builder.CreateVectorOfTables(offsets);
...@@ -138,19 +138,22 @@ public sealed class Monster : Table { ...@@ -138,19 +138,22 @@ public sealed class Monster : Table {
public static Monster LookupByKey(VectorOffset vectorOffset, string key, ByteBuffer bb) { public static Monster LookupByKey(VectorOffset vectorOffset, string key, ByteBuffer bb) {
byte[] byteKey = System.Text.Encoding.UTF8.GetBytes(key); byte[] byteKey = System.Text.Encoding.UTF8.GetBytes(key);
int vectorLocation = bb.Length - vectorOffset.Value; int vectorLocation = bb.Length - vectorOffset.Value;
int span = bb.GetInt(vectorLocation), middle, start = 0, comp, tableOffset; int span = bb.GetInt(vectorLocation);
int start = 0;
vectorLocation += 4; vectorLocation += 4;
while (span != 0) { while (span != 0) {
int middle = span / 2; int middle = span / 2;
tableOffset = __indirect(vectorLocation + 4 * (start + middle), bb); int tableOffset = __indirect(vectorLocation + 4 * (start + middle), bb);
comp = CompareStrings(__offset(10, bb.Length - tableOffset, bb), byteKey, bb); int comp = CompareStrings(__offset(10, bb.Length - tableOffset, bb), byteKey, bb);
if (comp > 0) span = middle; if (comp > 0) {
else if (comp < 0) { span = middle;
} else if (comp < 0) {
middle++; middle++;
start += middle; start += middle;
span -= middle; span -= middle;
} else {
return new Monster().__init(tableOffset, bb);
} }
else return new Monster().__init(tableOffset, bb);
} }
return null; return null;
} }
......
...@@ -131,9 +131,6 @@ func (rcv *Monster) Test4(obj *Test, j int) bool { ...@@ -131,9 +131,6 @@ func (rcv *Monster) Test4(obj *Test, j int) bool {
if o != 0 { if o != 0 {
x := rcv._tab.Vector(o) x := rcv._tab.Vector(o)
x += flatbuffers.UOffsetT(j) * 4 x += flatbuffers.UOffsetT(j) * 4
if obj == nil {
obj = new(Test)
}
obj.Init(rcv._tab.Bytes, x) obj.Init(rcv._tab.Bytes, x)
return true return true
} }
...@@ -173,9 +170,6 @@ func (rcv *Monster) Testarrayoftables(obj *Monster, j int) bool { ...@@ -173,9 +170,6 @@ func (rcv *Monster) Testarrayoftables(obj *Monster, j int) bool {
x := rcv._tab.Vector(o) x := rcv._tab.Vector(o)
x += flatbuffers.UOffsetT(j) * 4 x += flatbuffers.UOffsetT(j) * 4
x = rcv._tab.Indirect(x) x = rcv._tab.Indirect(x)
if obj == nil {
obj = new(Monster)
}
obj.Init(rcv._tab.Bytes, x) obj.Init(rcv._tab.Bytes, x)
return true return true
} }
......
...@@ -140,21 +140,24 @@ public final class Monster extends Table { ...@@ -140,21 +140,24 @@ public final class Monster extends Table {
protected int keysCompare(Integer o1, Integer o2, ByteBuffer _bb) { return compareStrings(__offset(10, o1, _bb), __offset(10, o2, _bb), _bb); } protected int keysCompare(Integer o1, Integer o2, ByteBuffer _bb) { return compareStrings(__offset(10, o1, _bb), __offset(10, o2, _bb), _bb); }
public static Monster lookupByKey(int vectorOffset, String key, ByteBuffer bb) { public static Monster lookupByKey(int vectorOffset, String key, ByteBuffer bb) {
byte[] byteKey = key.getBytes(StandardCharsets.UTF_8); byte[] byteKey = key.getBytes(Table.UTF8_CHARSET.get());
int vectorLocation = bb.array().length - vectorOffset.Value; int vectorLocation = bb.array().length - vectorOffset;
int span = bb.getInt(vectorLocation), middle, start = 0, comp, tableOffset; int span = bb.getInt(vectorLocation);
int start = 0;
vectorLocation += 4; vectorLocation += 4;
while (span != 0) { while (span != 0) {
int middle = span / 2; int middle = span / 2;
tableOffset = __indirect(vectorLocation + 4 * (start + middle), bb); int tableOffset = __indirect(vectorLocation + 4 * (start + middle), bb);
comp = compareStrings(__offset(10, bb.array().length - tableOffset, bb), byteKey, bb); int comp = compareStrings(__offset(10, bb.array().length - tableOffset, bb), byteKey, bb);
if (comp > 0) span = middle; if (comp > 0) {
else if (comp < 0) { span = middle;
} else if (comp < 0) {
middle++; middle++;
start += middle; start += middle;
span -= middle; span -= middle;
} else {
return new Monster().__init(tableOffset, bb);
} }
else return new Monster().__init(tableOffset, bb);
} }
return null; return null;
} }
......
...@@ -410,7 +410,8 @@ void ParseAndGenerateTextTest() { ...@@ -410,7 +410,8 @@ void ParseAndGenerateTextTest() {
// to ensure it is correct, we now generate text back from the binary, // to ensure it is correct, we now generate text back from the binary,
// and compare the two: // and compare the two:
std::string jsongen; std::string jsongen;
GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen); auto result = GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
TEST_EQ(result, true);
if (jsongen != jsonfile) { if (jsongen != jsonfile) {
printf("%s----------------\n%s", jsongen.c_str(), jsonfile.c_str()); printf("%s----------------\n%s", jsongen.c_str(), jsonfile.c_str());
...@@ -827,7 +828,8 @@ void FuzzTest2() { ...@@ -827,7 +828,8 @@ void FuzzTest2() {
std::string jsongen; std::string jsongen;
parser.opts.indent_step = 0; parser.opts.indent_step = 0;
GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen); auto result = GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
TEST_EQ(result, true);
if (jsongen != json) { if (jsongen != json) {
// These strings are larger than a megabyte, so we show the bytes around // These strings are larger than a megabyte, so we show the bytes around
...@@ -987,7 +989,8 @@ void UnicodeTest() { ...@@ -987,7 +989,8 @@ void UnicodeTest() {
true); true);
std::string jsongen; std::string jsongen;
parser.opts.indent_step = -1; parser.opts.indent_step = -1;
GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen); auto result = GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
TEST_EQ(result, true);
TEST_EQ(jsongen, TEST_EQ(jsongen,
std::string( std::string(
"{F: \"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC" "{F: \"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
...@@ -1003,13 +1006,31 @@ void UnicodeTestAllowNonUTF8() { ...@@ -1003,13 +1006,31 @@ void UnicodeTestAllowNonUTF8() {
"\\u5225\\u30B5\\u30A4\\u30C8\\x01\\x80\\u0080\\uD83D\\uDE0E\" }"), true); "\\u5225\\u30B5\\u30A4\\u30C8\\x01\\x80\\u0080\\uD83D\\uDE0E\" }"), true);
std::string jsongen; std::string jsongen;
parser.opts.indent_step = -1; parser.opts.indent_step = -1;
GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen); auto result = GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
TEST_EQ(result, true);
TEST_EQ(jsongen, TEST_EQ(jsongen,
std::string( std::string(
"{F: \"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC" "{F: \"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
"\\u5225\\u30B5\\u30A4\\u30C8\\u0001\\x80\\u0080\\uD83D\\uDE0E\"}")); "\\u5225\\u30B5\\u30A4\\u30C8\\u0001\\x80\\u0080\\uD83D\\uDE0E\"}"));
} }
void UnicodeTestGenerateTextFailsOnNonUTF8() {
flatbuffers::Parser parser;
// Allow non-UTF-8 initially to model what happens when we load a binary flatbuffer from disk
// which contains non-UTF-8 strings.
parser.opts.allow_non_utf8 = true;
TEST_EQ(parser.Parse("table T { F:string; }"
"root_type T;"
"{ F:\"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
"\\u5225\\u30B5\\u30A4\\u30C8\\x01\\x80\\u0080\\uD83D\\uDE0E\" }"), true);
std::string jsongen;
parser.opts.indent_step = -1;
// Now, disallow non-UTF-8 (the default behavior) so GenerateText indicates failure.
parser.opts.allow_non_utf8 = false;
auto result = GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
TEST_EQ(result, false);
}
void UnicodeSurrogatesTest() { void UnicodeSurrogatesTest() {
flatbuffers::Parser parser; flatbuffers::Parser parser;
...@@ -1157,7 +1178,8 @@ void UnknownFieldsTest() { ...@@ -1157,7 +1178,8 @@ void UnknownFieldsTest() {
std::string jsongen; std::string jsongen;
parser.opts.indent_step = -1; parser.opts.indent_step = -1;
GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen); auto result = GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
TEST_EQ(result, true);
TEST_EQ(jsongen == "{str: \"test\",i: 10}", true); TEST_EQ(jsongen == "{str: \"test\",i: 10}", true);
} }
...@@ -1222,6 +1244,7 @@ int main(int /*argc*/, const char * /*argv*/[]) { ...@@ -1222,6 +1244,7 @@ int main(int /*argc*/, const char * /*argv*/[]) {
IntegerOutOfRangeTest(); IntegerOutOfRangeTest();
UnicodeTest(); UnicodeTest();
UnicodeTestAllowNonUTF8(); UnicodeTestAllowNonUTF8();
UnicodeTestGenerateTextFailsOnNonUTF8();
UnicodeSurrogatesTest(); UnicodeSurrogatesTest();
UnicodeInvalidSurrogatesTest(); UnicodeInvalidSurrogatesTest();
InvalidUTF8Test(); InvalidUTF8Test();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment