google / flatbuffers

FlatBuffers: Memory Efficient Serialization Library
https://flatbuffers.dev/
Apache License 2.0
23.28k stars 3.25k forks source link

1.Gen JSON crash when the field not filled; 2. not print when the field value is 0, see #209 #236

Closed loachfish closed 9 years ago

loachfish commented 9 years ago

the commit-ecf5a6a does not solve the situation thar when the field value is 0.

My problem is that, I just modify the FILE:idl_gen_text.cppfunction; FUNCTION:GenStruct() LINE: if (struct_def.fixed || table->CheckField(fd.value.offset)) { to if (struct_def.fixed || table->CheckField(fd.value.offset) || true) { to ensure the value will be printed, while in this case it crashed.

the version i am using is git clone in 2015/01/12.

// test case, it can also test for #209 /Screen.fbs/ namespace hw.Screen;

enum LayOutType:ubyte { Full = 0, MasterSlave = 1 }

enum LayOutID:ubyte { MasterOrFullScreen = 0, Slave = 1 }

enum CursorCtrlType:ubyte { AddressingMode = 0, DestinationMode = 1 }

table NDBtnInfo { ID:ubyte; zoneID:ubyte; focusType:ubyte; specialBit:ubyte; x:ushort; y:ushort; w:ushort; h:ushort; upperBtnID:ubyte; lowerBtnID:ubyte; leftBtnID:ubyte; rightBtnID:ubyte; }

table NDTouchCoordinate{ layoutPattern:LayOutType; layoutID:LayOutID; overwriteFlag:bool; cursorControlType:CursorCtrlType;

btnCount:ubyte; 
btnInfo:[NDBtnInfo];

}

/_UTScreen.cpp/

include

include

include <sys/types.h>

include <sys/stat.h>

include

include

include

include

include "flatbuffers/flatbuffers.h"

include "flatbuffers/idl.h"

include "flatbuffers/util.h"

include "Screen_generated.h"

using namespace std; using namespace hw::Screen; using namespace flatbuffers;

ifndef NDEBUG

define NDEBUG

endif

int main(int argc, char* agrv[]) { std::vector orignal; orignal.push_back(0x00); orignal.push_back(0x01); orignal.push_back(0x00); orignal.push_back(0x01); orignal.push_back(0x00); orignal.push_back(0x00); orignal.push_back(0x00); orignal.push_back(0x00);

flatbuffers::FlatBufferBuilder fbb;
int index = 0;
unsigned char layoutPattern = orignal[index++];
unsigned char layoutID = orignal[index++];
unsigned char overwriteFlag = orignal[index++];
unsigned char cursorControlType = orignal[index++];
unsigned char btnCount = orignal[index++];
index += 3;

std::vector<flatbuffers::Offset<NDBtnInfo>> btnInfoList;
for (uint32_t i = 0; i < btnCount; ++i) {
    // as the btncnt is 0, do nothing;
}
NDTouchCoordinateBuilder mb(fbb);
mb.add_layoutPattern((LayOutType)layoutPattern);
mb.add_layoutID((LayOutID)layoutID);
mb.add_overwriteFlag(overwriteFlag);
mb.add_cursorControlType((CursorCtrlType)cursorControlType);
mb.add_btnCount(btnCount);

if (btnCount > 0) {
    // do nothing
    mb.add_btnInfo(fbb.CreateVector(btnInfoList));
}

fbb.Finish(mb.Finish());
//  fill flatbuffer's data to std::string
std::string fbs_str;
fbs_str.append((char*)fbb.GetBufferPointer(), fbb.GetSize());
printf("fbs str size[%d]\n", fbs_str.size());
for (int j = 0; j < fbs_str.size(); j++) {
    if ((j != 0) && (j % 8 == 0)) {
        printf("\n");
    }
    printf("0x%02x\t", fbs_str[j]);
}
printf("\n");

std::string filename("Screen.fbs");

// 1. load schemafile
std::string schemafile;
bool ok = flatbuffers::LoadFile(filename.c_str(), false, &schemafile);
if (!ok) {
    printf("couldn't load file.\n");
    return -1;
}

// 2. parse schema first, so we can use it to parse the data after
flatbuffers::Parser parser;
const char *include_directories[] = { nullptr, nullptr };
ok = parser.Parse(schemafile.c_str(), include_directories);
if (!ok) {
    printf("parse schema failed.\n");
    return -1;
}

// 3. set root table
std::string table("NDTouchCoordinate");
parser.SetRootType(table.c_str());

// 4. generate json string
// flatbuffers::GeneratorOptions()
flatbuffers::GeneratorOptions opts;
// opts.strict_json = true;

printf("+++++ GenerateText +++++\n");
std::string jsongen;
GenerateText(parser, fbs_str.c_str(), opts, &jsongen);

printf("json gen size[%d]:\n", jsongen.size());
printf("%s\n", jsongen.c_str());

return 0;

}

crash as signal 11 when gen struct about btnCount.

loachfish commented 9 years ago

maybe it was caused as that not fill the field btnInfo.

So the case is that when the vector is not filled, it will crash to gen?

loachfish commented 9 years ago

the function // Specialization of Print above for pointer types. template<> void Print<const void >(const void val, Type type, int indent, StructDef union_sd, const GeneratorOptions &opts, std::string _text); the val maybe nullptr, when the vector is not filled. when goto the function PrintVector, the pointer is nullptr.

So it add the condition: in the begine of function of Print if (val == nullptr) { return; }

it runs OK, but the output is like this: { layoutPattern: MasterSlave, layoutID: Slave, overwriteFlag: 1, cursorControlType: DestinationMode, btnCount: 0, btnInfo: }

loachfish commented 9 years ago

maybe we should fill the meta text when the val == nullptr, to ensure the format.

aardappel commented 9 years ago

are you using --defaults-json ? You adding || true does something similar to my commit, except it doesn't check that the field is scalar, which doesn't surprise me that it would crash.

loachfish commented 9 years ago

it works when add the options. flatbuffers::GeneratorOptions opts; opts.strict_json = true; opts.output_default_scalars_in_json = true; // key GenerateText(parser, fbs_str.c_str(), opts, &jsongen);

another syntax error when make in my env: flatbuffers/src/flathash.cpp:26:17: the enum items cannot end with a comma: enum OutputFormat { kDecimal, kHexadecimal, kHexadecimal0x, ///< };

Maybe it works well in some env, but it will affects the portability .

ghost commented 9 years ago

What compiler do you use, and what version?

loachfish commented 9 years ago

g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3

Ubuntu 12.04

ghost commented 9 years ago

fixed that issue: https://github.com/google/flatbuffers/commit/12ca3e054e257e06e2c6e35e8824d5ae569bce4b