@@ -89,6 +89,7 @@ StructMeta::StructMeta( const std::string & name, Fields fields, bool isStrict,
8989 else
9090 m_fieldnames = std::move ( fieldnames );
9191
92+ std::vector<StructFieldPtr> derivedFields; // easier to store this for pre-processing and only append derived fields to m_fields at the end
9293 for ( auto & derivedField : fields )
9394 {
9495 auto rv = m_fieldMap.emplace ( derivedField -> fieldname ().c_str (), derivedField );
@@ -117,28 +118,28 @@ StructMeta::StructMeta( const std::string & name, Fields fields, bool isStrict,
117118 rv.first -> second = derivedField; // field map
118119 }
119120 else
120- m_fields .push_back ( derivedField );
121+ derivedFields .push_back ( derivedField );
121122 }
122123
123124 size_t baseSize = m_base ? m_base -> size () : 0 ;
124125 size_t offset = baseSize;
125126 m_basePadding = 0 ;
126127
127128 // align to first field's alignment if there are derived fields remaining
128- if ( m_fields. size () > m_firstPartialField && ( offset % m_fields[ m_firstPartialField ] -> alignment () != 0 ) )
129- m_basePadding = m_fields[ m_firstPartialField ] -> alignment () - offset % m_fields[ m_firstPartialField ] -> alignment ();
129+ if ( !derivedFields. empty () && ( offset % derivedFields[ 0 ] -> alignment () != 0 ) )
130+ m_basePadding = derivedFields[ 0 ] -> alignment () - offset % derivedFields[ 0 ] -> alignment ();
130131
131132 offset += m_basePadding;
132- if ( m_fields. size () > m_firstPartialField )
133- CSP_ASSERT ( ( offset % m_fields[ m_firstPartialField ] -> alignment () ) == 0 );
133+ if ( !derivedFields. empty () )
134+ CSP_ASSERT ( ( offset % derivedFields[ 0 ] -> alignment () ) == 0 );
134135
135136 m_partialStart = offset;
136137 m_nativeStart = m_partialStart;
137138 m_firstNativePartialField = m_firstPartialField;
138139
139- for ( size_t idx = m_firstPartialField ; idx < m_fields .size (); ++idx )
140+ for ( size_t idx = 0 ; idx < derivedFields .size (); ++idx )
140141 {
141- auto & f = m_fields [ idx ];
142+ auto & f = derivedFields [ idx ];
142143 if ( offset % f -> alignment () != 0 )
143144 offset += f -> alignment () - offset % f -> alignment ();
144145
@@ -151,7 +152,7 @@ StructMeta::StructMeta( const std::string & name, Fields fields, bool isStrict,
151152 if ( !f -> isNative () )
152153 {
153154 m_nativeStart = offset;
154- m_firstNativePartialField = idx + 1 ;
155+ m_firstNativePartialField += 1 ;
155156 }
156157 }
157158
@@ -160,8 +161,8 @@ StructMeta::StructMeta( const std::string & name, Fields fields, bool isStrict,
160161 // setup masking bits for the remaining derived (partial) fields
161162 // note that this is done after the override dedup above so that overridden fields don't consume mask bits.
162163 // NOTE we can be more efficient by sticking masks into any potential alignment gaps, dont want to spend time on it
163- size_t optionalFieldCount = std::count_if ( m_fields .begin () + m_firstPartialField, m_fields .end (), []( const auto & f ) { return f -> isOptional (); } );
164- size_t partialFieldCount = m_fields .size () - m_firstPartialField ;
164+ size_t optionalFieldCount = std::count_if ( derivedFields .begin (), derivedFields .end (), []( const auto & f ) { return f -> isOptional (); } );
165+ size_t partialFieldCount = derivedFields .size ();
165166
166167 m_maskSize = partialFieldCount > 0 ? 1 + ( ( partialFieldCount + optionalFieldCount - 1 ) / 8 ) : 0 ;
167168 m_size = offset + m_maskSize;
@@ -177,9 +178,8 @@ StructMeta::StructMeta( const std::string & name, Fields fields, bool isStrict,
177178 // Set optional fields first so that their 2-bits never cross a byte boundary
178179 // Put both the set bits and none bits in the same vector to avoid fragmentation
179180 m_optionalFieldsBitMasks.resize ( 2 * m_maskSize );
180- for ( size_t i = m_firstPartialField; i < m_fields. size (); ++i )
181+ for ( auto & f : derivedFields )
181182 {
182- auto & f = m_fields[ i ];
183183 if ( f -> isOptional () )
184184 {
185185 f -> setMaskOffset ( maskLoc, maskBit );
@@ -193,9 +193,8 @@ StructMeta::StructMeta( const std::string & name, Fields fields, bool isStrict,
193193 }
194194 }
195195
196- for ( size_t i = m_firstPartialField; i < m_fields. size (); ++i )
196+ for ( auto & f : derivedFields )
197197 {
198- auto & f = m_fields[ i ];
199198 if ( !f -> isOptional () )
200199 {
201200 f -> setMaskOffset ( maskLoc, maskBit );
@@ -206,6 +205,9 @@ StructMeta::StructMeta( const std::string & name, Fields fields, bool isStrict,
206205 }
207206 }
208207 }
208+
209+ // append derived fields to m_fields after all processing is done
210+ m_fields.insert ( m_fields.end (), derivedFields.begin (), derivedFields.end () );
209211}
210212
211213StructMeta::~StructMeta ()
0 commit comments