From 1a27c7017a0ad947e3520718d9b66a71a14afa2e Mon Sep 17 00:00:00 2001 From: Lawrence Chan Date: Mon, 20 Mar 2017 19:36:27 -0500 Subject: [PATCH] C++: Add default value handling to mutation/SetField code (#4230) * Add default value handling to mutation/SetField code * Shorten reflection SetField impl * Modify impl to work with C++03 * Add more mutation tests * Fail SetField if non-scalar * Add IsScalar/IsInteger/IsFloat for reflection::BaseType * Use new IsScalar/IsInteger/IsFloat in reflection SetField * Assume scalar is either int or float --- include/flatbuffers/flatbuffers.h | 4 +- include/flatbuffers/reflection.h | 40 ++++++++++++++++-- samples/monster_generated.h | 10 ++--- src/idl_gen_cpp.cpp | 5 ++- tests/monster_test.bfbs | Bin 3944 -> 3904 bytes tests/monster_test_generated.h | 38 ++++++++--------- .../namespace_test1_generated.h | 2 +- .../namespace_test2_generated.h | 2 +- tests/test.cpp | 13 ++++++ 9 files changed, 81 insertions(+), 33 deletions(-) diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index ea78aeeea..048167c55 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -1646,9 +1646,9 @@ class Table { return field_offset ? reinterpret_cast

(p) : nullptr; } - template bool SetField(voffset_t field, T val) { + template bool SetField(voffset_t field, T val, T def) { auto field_offset = GetOptionalFieldOffset(field); - if (!field_offset) return false; + if (!field_offset) return val == def; WriteScalar(data_ + field_offset, val); return true; } diff --git a/include/flatbuffers/reflection.h b/include/flatbuffers/reflection.h index 6d8608a68..aab9f2088 100644 --- a/include/flatbuffers/reflection.h +++ b/include/flatbuffers/reflection.h @@ -30,6 +30,15 @@ namespace flatbuffers { // ------------------------- GETTERS ------------------------- +inline bool IsScalar (reflection::BaseType t) { return t >= reflection::UType && + t <= reflection::Double; } +inline bool IsInteger(reflection::BaseType t) { return t >= reflection::UType && + t <= reflection::ULong; } +inline bool IsFloat (reflection::BaseType t) { return t == reflection::Float || + t == reflection::Double; } +inline bool IsLong (reflection::BaseType t) { return t == reflection::Long || + t == reflection::ULong; } + // Size of a basic type, don't use with structs. inline size_t GetTypeSize(reflection::BaseType base_type) { // This needs to correspond to the BaseType enum. @@ -58,6 +67,18 @@ inline const Table *GetAnyRoot(const uint8_t *flatbuf) { return GetRoot(flatbuf); } +// Get a field's default, if you know it's an integer, and its exact type. +template T GetFieldDefaultI(const reflection::Field &field) { + assert(sizeof(T) == GetTypeSize(field.type()->base_type())); + return static_cast(field.default_integer()); +} + +// Get a field's default, if you know it's floating point and its exact type. +template T GetFieldDefaultF(const reflection::Field &field) { + assert(sizeof(T) == GetTypeSize(field.type()->base_type())); + return static_cast(field.default_real()); +} + // Get a field, if you know it's an integer, and its exact type. template T GetFieldI(const Table &table, const reflection::Field &field) { @@ -242,8 +263,19 @@ template T *GetAnyFieldAddressOf(const Struct &st, // Set any scalar field, if you know its exact type. template bool SetField(Table *table, const reflection::Field &field, T val) { - assert(sizeof(T) == GetTypeSize(field.type()->base_type())); - return table->SetField(field.offset(), val); + reflection::BaseType type = field.type()->base_type(); + if (!IsScalar(type)) { + return false; + } + assert(sizeof(T) == GetTypeSize(type)); + T def; + if (IsInteger(type)) { + def = GetFieldDefaultI(field); + } else { + assert(IsFloat(type)); + def = GetFieldDefaultF(field); + } + return table->SetField(field.offset(), val, def); } // Raw helper functions used below: set any value in memory as a 64bit int, a @@ -258,7 +290,7 @@ void SetAnyValueS(reflection::BaseType type, uint8_t *data, const char *val); inline bool SetAnyFieldI(Table *table, const reflection::Field &field, int64_t val) { auto field_ptr = table->GetAddressOf(field.offset()); - if (!field_ptr) return false; + if (!field_ptr) return val == GetFieldDefaultI(field); SetAnyValueI(field.type()->base_type(), field_ptr, val); return true; } @@ -267,7 +299,7 @@ inline bool SetAnyFieldI(Table *table, const reflection::Field &field, inline bool SetAnyFieldF(Table *table, const reflection::Field &field, double val) { auto field_ptr = table->GetAddressOf(field.offset()); - if (!field_ptr) return false; + if (!field_ptr) return val == GetFieldDefaultF(field); SetAnyValueF(field.type()->base_type(), field_ptr, val); return true; } diff --git a/samples/monster_generated.h b/samples/monster_generated.h index 48ca9818d..464fc1768 100644 --- a/samples/monster_generated.h +++ b/samples/monster_generated.h @@ -183,13 +183,13 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { return GetField(VT_MANA, 150); } bool mutate_mana(int16_t _mana) { - return SetField(VT_MANA, _mana); + return SetField(VT_MANA, _mana, 150); } int16_t hp() const { return GetField(VT_HP, 100); } bool mutate_hp(int16_t _hp) { - return SetField(VT_HP, _hp); + return SetField(VT_HP, _hp, 100); } const flatbuffers::String *name() const { return GetPointer(VT_NAME); @@ -207,7 +207,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { return static_cast(GetField(VT_COLOR, 2)); } bool mutate_color(Color _color) { - return SetField(VT_COLOR, static_cast(_color)); + return SetField(VT_COLOR, static_cast(_color), 2); } const flatbuffers::Vector> *weapons() const { return GetPointer> *>(VT_WEAPONS); @@ -219,7 +219,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { return static_cast(GetField(VT_EQUIPPED_TYPE, 0)); } bool mutate_equipped_type(Equipment _equipped_type) { - return SetField(VT_EQUIPPED_TYPE, static_cast(_equipped_type)); + return SetField(VT_EQUIPPED_TYPE, static_cast(_equipped_type), 0); } const void *equipped() const { return GetPointer(VT_EQUIPPED); @@ -375,7 +375,7 @@ struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { return GetField(VT_DAMAGE, 0); } bool mutate_damage(int16_t _damage) { - return SetField(VT_DAMAGE, _damage); + return SetField(VT_DAMAGE, _damage, 0); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 19172aa93..857287596 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -1162,14 +1162,17 @@ class CppGenerator : public BaseGenerator { if (parser_.opts.mutable_buffer) { if (is_scalar) { + const auto type = GenTypeWire(field.value.type, "", false); + code_.SetValue("SET_FN", "SetField<" + type + ">"); code_.SetValue("OFFSET_NAME", offset_str); code_.SetValue("FIELD_TYPE", GenTypeBasic(field.value.type, true)); code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, false, "_" + field.name)); + code_.SetValue("DEFAULT_VALUE", GenDefaultConstant(field)); code_ += " bool mutate_{{FIELD_NAME}}({{FIELD_TYPE}} " "_{{FIELD_NAME}}) {"; - code_ += " return SetField({{OFFSET_NAME}}, {{FIELD_VALUE}});"; + code_ += " return {{SET_FN}}({{OFFSET_NAME}}, {{FIELD_VALUE}}, {{DEFAULT_VALUE}});"; code_ += " }"; } else { auto type = GenTypeGet(field.value.type, " ", "", " *", true); diff --git a/tests/monster_test.bfbs b/tests/monster_test.bfbs index 449921cc83be89e24aaf697a5f4f67c742550e76..21f3c0008fc9a5632ea6aa2c6667f93251da08eb 100644 GIT binary patch literal 3904 zcmai1-D_M$6hE7!`RX=F)7Zu|%54cDl(4j$5K0k=(S8Uv6;opoG2HCl?XKLtciFvL zn<64oiWKRClu|^bi1bOsr#|#Siin6v@ehzv`Xog}@T;ww_4hk-XLGY8IB<4m?wsHG znsa7mM@3}r$lL-tv_2V@4(XP(49E~>f?tvSpr=63fv&ZQbfLeB{?lHO_qU0Bn--~T z70Cne8K@oW#7w6|9)LP9K7L|eb#Sd529Q6jdb%*87XG58*pGpxLDV@2I=*t$Eqj^6 zXWeqe_cG4}D@NumtbGJJ1)`mq-x>{c&}iCsjYfmtzlV*~YuhdijLfB2W_Ia#7}O%K zij`iCK^oS zR@d#-MuV{-&7YV*j82ZhW@08lHU{*eB?ixien?~0FCYCZhVW2j;lp+}{b5{R^72@x*ObK70hL90^x+_A7PJQx z`*9*FdewRC>O#fMd6^^Cu>5?G^XqvSrLrCLtHzg}HJf^&fz}&4IHKJ#a?wQ~=)a90 zV{jF;6Vwtvy9M$D*6za5{Sa2{6dA<^rP1fn-$j2J{cBivK<7af2>lVf?*KQ6{uBam z9yEsUKj7OnP#W_I7=0P^1-^fc{x13#&==9ahjn!7$pQ3^8#taxZYLk+>SZs8+^7@= zPA)8Sa>zl+Fg=}c`3)}@0dxJ2Mq?Be!e~37F%WAdLSDMns=E>vYEiWmoX(1T@`yRn zhbj=c1Ke&oq&ViwFbHlct}rEX5$l*D<3(6MBiKFije;DIY2C9;4CH^Az=({1mnTSv z$|csc0j!8TE;H-o1s8Vz`fyLrEJAB+K;QT0nhlpQ9!3@={p9{8{9F!0zlKk8@o)7L zQ5N|IxLuN6hue6O%%#MKhG8wS@y+{|B% z#$%G%6jz_hHue2ta9WZ9a6>Y=DXx~lje{4ec!bDxjCaVsbvPTBq<`dn-Qd)}I~Wh* zbV>S`#99A{yJB$a-_8e(#&#Ls6leV-?zX|HfAhc%AUikJ7yCzCCwS4Re-|+Bm%WN( zjxzr!ko(6C$53VrzwY-9jQfzG)I)v;M8nDNl`9dh44HqZ^7~U5v)u<~n>?u)*3Sfp z`ASScT)yDD(Q>^|(2GIt|Eu|hsuvlDtTe2mK3gBmVK4B?)O9n~g`u`Z%(tQfY#gY| z=2cv;5ib%Zat3vWD(EMW&e3-&<$dgw>wZ-7OM&M^VTiMj-~Rvnh>E3}^JdBS9WTf` z^@>vp92~*UY1mtJ;VF(9J$qMSCvQM&C*#s$r#V;f{Sodjd#=pjjOoEiOC0Sb&erra zPU$pGgD&i#CLw&&O#@E=TsI<^j3a&J9-xypt!ceZIF*mV--VNo{H^=E6s=S|e4jBG zyUp@0?CgXH%g@*|mu#b*x%fh@8f^3a?8AHuBA<*0^Qsh_!ND9>SKv{%`eyDT#DnIe z@f_qk%KEHn4Nr&l90Ws(uLRbfJzHPIn06JaCG3*VG?EcxPaB<~4d!I+RzC7F_t;me zrLbDkG#Bz70GT$TySZiu&wJW36x)$Xwd?*ES&R`K2yizO|Dn;ZcL(o-HfSS{wK-3w zxN%R571Y1MFsx`J;>1>Ws@s@VQFa5DpZ5NvwW~6p*7{)d z%$tRHT&YqCYm(I(m40H`=73|2DVuSb1nmH|yayI=;i?Ssz6F{FvGqY7eWotPnz~HB z)B`5yO=B0YLpcOq`eW@PKkYh$hsiy|r)Mc+G8D^HAi>&9Oz3%12IE@F>0Ydw zaf&)7K(yNd9RzLQ-=deBf@Q|HW9W(d8FUMD8N~JoGPl4s>nrz|zOojl&|lJemuBtm z!@NVY%g9Ue<5?hI8vbT2y^47|EVc4&EGeJ)+G+T?EEh1gai?#zm-}}PlrenzM)@4$ zR7l#r#}?C%~BNj3H&P9|yJM%1M~J;nSZO=9y_W?^$oO-nO+p zrvKc#{UCcDlFQ^5ANV{sS*!L8k!CFU+B5Gg{)3|YVSWE$(98+SWF1h)201}LRIiWq zq}?Vr&HD{YakKT>wk|j6^D^iwtw~LH%tm07`8N=Q<1Vc=&wZfp%opNaJwwg;Xzm9M z0aga#+1kGf?jGN`+#~vAFUovdT?kCPciS!nv7lY2mUlOWo) P@&A;UgL(~rb`tGBDj=Xf literal 3944 zcmai1O=w(29RF`VHoM8@qisxM8|Af>5K0Mc5<)2wYPBCqn~I4Qq$IxVzU@AF``)tq zc1J{)xpC zfnN)qDptCc4|32Bsw=yPp$tq}YsAkxwQ$a*ta*FMbKZ2r(qX?|#!5FZ9nfFnX;%rF zE9Eh!UyQ6gG; zqYjLnX_R-!t2;(luF+QRi`&_W|3|Bi<70IITAF=~jj@NiyzUgRPOG_ts{@MH7)D7u zK7Xj}$Wjh@Fy1>rP5n=XC8s)zNX}L4yfc2J8kAr0^IpB+K!=R-l-89tQ0M0ADcciC zgZB;0(J$o9J*MA>v1R*~qZ7m`1o?W|@k2Xw1K-LAW&Sx}A+4DPRurzKz|PFL)e#ysYx4Y{2E0gIBmn&LvPbgwuLA3ZC@|XLx}vet5tg?DAvNN z>z|nrxeDBNInaVTg?T`FV2;8SCozz1h#gO8hj5-brrQ8kxVm2~^qi*-x@8Wszmnt! z*+f|X!S7j_R&|CpF%SI@w%>oeBYO}-)t)qY!o^xg^k;vIqG4oE(htQylpos2C+3Hx zAnFL`8^6Tu13$Tm_02NY zf@^48HjXp)5tn`xMVn-_1$R~BGI5--kGL7&1`zdR{O)R8R~%>TBd!5lzwB(mJ&$=T zx3LN_?hH8hU%`AIvM*VSrXQ>Q{VD9pHZe}Q65{HRAA#wW=UZf4|BINu4(2^&_#mfH z^z3k{UM#8$M25gO2Wd%pSDNww73Q(yJ7vl`g83etj}I|k2Jt+j6ev8$yoarF-3wjM z^&Kk=0@OXu{eL|ROK#12*Y!Nh@e5YHV!6JB5^J4-?5YjTQTk9@Mb6`%fTVs5#pG49 zeuTW>cyR7PPu`Bnczut1jCCi0({%^9QPia@D%u#v#F~1=3Z6rC=|Wv#EvJ0iZO-@< z#!J9vP-T+7e4uKbDiw+!V?hodW4;S7g5>_4swN0Sy%y`maHZnF@9TArQ8i81xim!V z!W36n=a^fjH8f9kCsXHq^U@u{d?%ttT+-f*vRB_-u(yMG=lTs?K0$Rw>B6^{@dsZE zls$|U)lz&}yoTY+pm^=4VOl>{?2OWr=ZC)L+CC6Z%l%S*^c1FU6{h4DpbT z+aN8j1J1X4wG1|ONTu2ltz-^d(!6>p&&U0ZPQAa{Al3MR`V_bjYqvD6lW{LqxDdZ5 zTH}#|HgSFzW4t)r`KLP5oz$aj`!?rhRBm^)%KVNIT(mGG-K9h9@dudN{?_Iq&OPLKmY~YhY@ML^> z7q2&+qtr6VW4E@gmwt5%s3+=-N@@!K=~dcifsB3ROWRI^cur~jZFHZ3Hn8=Slb@8Q zkkJXW&Fi0_{IYWNT1(Of_zY5w9 z+93Y411lyk^&1fr&8Brufosx-*VS3n`Yi!(zAFq;_c^TS^G3YUiB&VB>@@XLI_Ya0 z*2KR)7!kgKiA}}^Q?ma3XTBFF#@8O#K*qmJ=^gSyOZ^)^=D^0^FK_tu8a|HD{st09 BliUCR diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h index 61e909840..ea7f4c3bd 100644 --- a/tests/monster_test_generated.h +++ b/tests/monster_test_generated.h @@ -312,7 +312,7 @@ struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Ta return static_cast(GetField(VT_COLOR, 2)); } bool mutate_color(Color _color) { - return SetField(VT_COLOR, static_cast(_color)); + return SetField(VT_COLOR, static_cast(_color), 2); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && @@ -380,13 +380,13 @@ struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { return GetField(VT_VAL, 0); } bool mutate_val(int64_t _val) { - return SetField(VT_VAL, _val); + return SetField(VT_VAL, _val, 0); } uint16_t count() const { return GetField(VT_COUNT, 0); } bool mutate_count(uint16_t _count) { - return SetField(VT_COUNT, _count); + return SetField(VT_COUNT, _count, 0); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && @@ -542,13 +542,13 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { return GetField(VT_MANA, 150); } bool mutate_mana(int16_t _mana) { - return SetField(VT_MANA, _mana); + return SetField(VT_MANA, _mana, 150); } int16_t hp() const { return GetField(VT_HP, 100); } bool mutate_hp(int16_t _hp) { - return SetField(VT_HP, _hp); + return SetField(VT_HP, _hp, 100); } const flatbuffers::String *name() const { return GetPointer(VT_NAME); @@ -572,13 +572,13 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { return static_cast(GetField(VT_COLOR, 8)); } bool mutate_color(Color _color) { - return SetField(VT_COLOR, static_cast(_color)); + return SetField(VT_COLOR, static_cast(_color), 8); } Any test_type() const { return static_cast(GetField(VT_TEST_TYPE, 0)); } bool mutate_test_type(Any _test_type) { - return SetField(VT_TEST_TYPE, static_cast(_test_type)); + return SetField(VT_TEST_TYPE, static_cast(_test_type), 0); } const void *test() const { return GetPointer(VT_TEST); @@ -642,55 +642,55 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { return GetField(VT_TESTBOOL, 0) != 0; } bool mutate_testbool(bool _testbool) { - return SetField(VT_TESTBOOL, static_cast(_testbool)); + return SetField(VT_TESTBOOL, static_cast(_testbool), 0); } int32_t testhashs32_fnv1() const { return GetField(VT_TESTHASHS32_FNV1, 0); } bool mutate_testhashs32_fnv1(int32_t _testhashs32_fnv1) { - return SetField(VT_TESTHASHS32_FNV1, _testhashs32_fnv1); + return SetField(VT_TESTHASHS32_FNV1, _testhashs32_fnv1, 0); } uint32_t testhashu32_fnv1() const { return GetField(VT_TESTHASHU32_FNV1, 0); } bool mutate_testhashu32_fnv1(uint32_t _testhashu32_fnv1) { - return SetField(VT_TESTHASHU32_FNV1, _testhashu32_fnv1); + return SetField(VT_TESTHASHU32_FNV1, _testhashu32_fnv1, 0); } int64_t testhashs64_fnv1() const { return GetField(VT_TESTHASHS64_FNV1, 0); } bool mutate_testhashs64_fnv1(int64_t _testhashs64_fnv1) { - return SetField(VT_TESTHASHS64_FNV1, _testhashs64_fnv1); + return SetField(VT_TESTHASHS64_FNV1, _testhashs64_fnv1, 0); } uint64_t testhashu64_fnv1() const { return GetField(VT_TESTHASHU64_FNV1, 0); } bool mutate_testhashu64_fnv1(uint64_t _testhashu64_fnv1) { - return SetField(VT_TESTHASHU64_FNV1, _testhashu64_fnv1); + return SetField(VT_TESTHASHU64_FNV1, _testhashu64_fnv1, 0); } int32_t testhashs32_fnv1a() const { return GetField(VT_TESTHASHS32_FNV1A, 0); } bool mutate_testhashs32_fnv1a(int32_t _testhashs32_fnv1a) { - return SetField(VT_TESTHASHS32_FNV1A, _testhashs32_fnv1a); + return SetField(VT_TESTHASHS32_FNV1A, _testhashs32_fnv1a, 0); } uint32_t testhashu32_fnv1a() const { return GetField(VT_TESTHASHU32_FNV1A, 0); } bool mutate_testhashu32_fnv1a(uint32_t _testhashu32_fnv1a) { - return SetField(VT_TESTHASHU32_FNV1A, _testhashu32_fnv1a); + return SetField(VT_TESTHASHU32_FNV1A, _testhashu32_fnv1a, 0); } int64_t testhashs64_fnv1a() const { return GetField(VT_TESTHASHS64_FNV1A, 0); } bool mutate_testhashs64_fnv1a(int64_t _testhashs64_fnv1a) { - return SetField(VT_TESTHASHS64_FNV1A, _testhashs64_fnv1a); + return SetField(VT_TESTHASHS64_FNV1A, _testhashs64_fnv1a, 0); } uint64_t testhashu64_fnv1a() const { return GetField(VT_TESTHASHU64_FNV1A, 0); } bool mutate_testhashu64_fnv1a(uint64_t _testhashu64_fnv1a) { - return SetField(VT_TESTHASHU64_FNV1A, _testhashu64_fnv1a); + return SetField(VT_TESTHASHU64_FNV1A, _testhashu64_fnv1a, 0); } const flatbuffers::Vector *testarrayofbools() const { return GetPointer *>(VT_TESTARRAYOFBOOLS); @@ -702,19 +702,19 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { return GetField(VT_TESTF, 3.14159f); } bool mutate_testf(float _testf) { - return SetField(VT_TESTF, _testf); + return SetField(VT_TESTF, _testf, 3.14159f); } float testf2() const { return GetField(VT_TESTF2, 3.0f); } bool mutate_testf2(float _testf2) { - return SetField(VT_TESTF2, _testf2); + return SetField(VT_TESTF2, _testf2, 3.0f); } float testf3() const { return GetField(VT_TESTF3, 0.0f); } bool mutate_testf3(float _testf3) { - return SetField(VT_TESTF3, _testf3); + return SetField(VT_TESTF3, _testf3, 0.0f); } const flatbuffers::Vector> *testarrayofstring2() const { return GetPointer> *>(VT_TESTARRAYOFSTRING2); diff --git a/tests/namespace_test/namespace_test1_generated.h b/tests/namespace_test/namespace_test1_generated.h index 9c8c28a73..2a71fbcad 100644 --- a/tests/namespace_test/namespace_test1_generated.h +++ b/tests/namespace_test/namespace_test1_generated.h @@ -75,7 +75,7 @@ struct TableInNestedNS FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { return GetField(VT_FOO, 0); } bool mutate_foo(int32_t _foo) { - return SetField(VT_FOO, _foo); + return SetField(VT_FOO, _foo, 0); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && diff --git a/tests/namespace_test/namespace_test2_generated.h b/tests/namespace_test/namespace_test2_generated.h index 15971ba18..4e2a622c9 100644 --- a/tests/namespace_test/namespace_test2_generated.h +++ b/tests/namespace_test/namespace_test2_generated.h @@ -40,7 +40,7 @@ struct TableInFirstNS FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { return static_cast(GetField(VT_FOO_ENUM, 0)); } bool mutate_foo_enum(NamespaceA::NamespaceB::EnumInNestedNS _foo_enum) { - return SetField(VT_FOO_ENUM, static_cast(_foo_enum)); + return SetField(VT_FOO_ENUM, static_cast(_foo_enum), 0); } const NamespaceA::NamespaceB::StructInNestedNS *foo_struct() const { return GetStruct(VT_FOO_STRUCT); diff --git a/tests/test.cpp b/tests/test.cpp index f74e9a8b8..4e031b6dd 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -285,10 +285,23 @@ void MutateFlatBuffersTest(uint8_t *flatbuf, std::size_t length) { auto hp_ok = monster->mutate_hp(10); TEST_EQ(hp_ok, true); // Field was present. TEST_EQ(monster->hp(), 10); + // Mutate to default value + auto hp_ok_default = monster->mutate_hp(100); + TEST_EQ(hp_ok_default, true); // Field was present. + TEST_EQ(monster->hp(), 100); + // Test that mutate to default above keeps field valid for further mutations + auto hp_ok_2 = monster->mutate_hp(20); + TEST_EQ(hp_ok_2, true); + TEST_EQ(monster->hp(), 20); monster->mutate_hp(80); + // Monster originally at 150 mana (default value) + auto mana_default_ok = monster->mutate_mana(150); // Mutate to default value. + TEST_EQ(mana_default_ok, true); // Mutation should succeed, because default value. + TEST_EQ(monster->mana(), 150); auto mana_ok = monster->mutate_mana(10); TEST_EQ(mana_ok, false); // Field was NOT present, because default value. + TEST_EQ(monster->mana(), 150); // Mutate structs. auto pos = monster->mutable_pos();