FieldGroup is just a helper for OptimizePadding below. It holds a vector of fields that are grouped together because they have compatible alignment, and a preferred location in the final field ordering.
| 176 | // fields that are grouped together because they have compatible alignment, and |
| 177 | // a preferred location in the final field ordering. |
| 178 | class FieldGroup { |
| 179 | public: |
| 180 | FieldGroup() |
| 181 | : preferred_location_(0) {} |
| 182 | |
| 183 | // A group with a single field. |
| 184 | FieldGroup(float preferred_location, const FieldDescriptor* field) |
| 185 | : preferred_location_(preferred_location), |
| 186 | fields_(1, field) {} |
| 187 | |
| 188 | // Append the fields in 'other' to this group. |
| 189 | void Append(const FieldGroup& other) { |
| 190 | if (other.fields_.empty()) { |
| 191 | return; |
| 192 | } |
| 193 | // Preferred location is the average among all the fields, so we weight by |
| 194 | // the number of fields on each FieldGroup object. |
| 195 | preferred_location_ = |
| 196 | (preferred_location_ * fields_.size() + |
| 197 | (other.preferred_location_ * other.fields_.size())) / |
| 198 | (fields_.size() + other.fields_.size()); |
| 199 | fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end()); |
| 200 | } |
| 201 | |
| 202 | void SetPreferredLocation(float location) { preferred_location_ = location; } |
| 203 | const vector<const FieldDescriptor*>& fields() const { return fields_; } |
| 204 | |
| 205 | // FieldGroup objects sort by their preferred location. |
| 206 | bool operator<(const FieldGroup& other) const { |
| 207 | return preferred_location_ < other.preferred_location_; |
| 208 | } |
| 209 | |
| 210 | private: |
| 211 | // "preferred_location_" is an estimate of where this group should go in the |
| 212 | // final list of fields. We compute this by taking the average index of each |
| 213 | // field in this group in the original ordering of fields. This is very |
| 214 | // approximate, but should put this group close to where its member fields |
| 215 | // originally went. |
| 216 | float preferred_location_; |
| 217 | vector<const FieldDescriptor*> fields_; |
| 218 | // We rely on the default copy constructor and operator= so this type can be |
| 219 | // used in a vector. |
| 220 | }; |
| 221 | |
| 222 | // Reorder 'fields' so that if the fields are output into a c++ class in the new |
| 223 | // order, the alignment padding is minimized. We try to do this while keeping |