diff options
author | Joshua Haberman <jhaberman@gmail.com> | 2018-11-15 10:14:36 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-15 10:14:36 -0800 |
commit | cb113bc8ccbf4357d4a3a43c8d1592d9f40bd70d (patch) | |
tree | 2275cab3e510d488354e341346b30928d142896b /upbc/message_layout.h | |
parent | d4e78f9fdff9ad14a0e8e3ad5d7d8379ee2124ef (diff) | |
parent | 9ce4a77f61c134bbed28bfd5be5cd7dc0e80f5e3 (diff) |
Merge pull request #134 from haberman/upbc-cpp
Added upb compiler written in C++ as a normal protoc plugin.
Diffstat (limited to 'upbc/message_layout.h')
-rw-r--r-- | upbc/message_layout.h | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/upbc/message_layout.h b/upbc/message_layout.h new file mode 100644 index 0000000..bdcc336 --- /dev/null +++ b/upbc/message_layout.h @@ -0,0 +1,104 @@ + +#ifndef UPBC_MESSAGE_LAYOUT_H +#define UPBC_MESSAGE_LAYOUT_H + +#include <unordered_map> +#include "absl/base/macros.h" +#include "google/protobuf/descriptor.h" + +namespace upbc { + +class MessageLayout { + public: + struct Size { + void Add(const Size& other) { + size32 += other.size32; + size64 += other.size64; + } + + void MaxFrom(const Size& other) { + size32 = std::max(size32, other.size32); + size64 = std::max(size64, other.size64); + } + + void AlignUp(const Size& align) { + size32 = Align(size32, align.size32); + size64 = Align(size64, align.size64); + } + + int64_t size32; + int64_t size64; + }; + + struct SizeAndAlign { + Size size; + Size align; + + void MaxFrom(const SizeAndAlign& other) { + size.MaxFrom(other.size); + align.MaxFrom(other.align); + } + }; + + MessageLayout(const google::protobuf::Descriptor* descriptor) { + ComputeLayout(descriptor); + } + + Size GetFieldOffset(const google::protobuf::FieldDescriptor* field) const { + return GetMapValue(field_offsets_, field); + } + + Size GetOneofCaseOffset( + const google::protobuf::OneofDescriptor* oneof) const { + return GetMapValue(oneof_case_offsets_, oneof); + } + + int GetHasbitIndex(const google::protobuf::FieldDescriptor* field) const { + return GetMapValue(hasbit_indexes_, field); + } + + Size message_size() const { return size_; } + + static bool HasHasbit(const google::protobuf::FieldDescriptor* field); + + private: + void ComputeLayout(const google::protobuf::Descriptor* descriptor); + void PlaceNonOneofFields(const google::protobuf::Descriptor* descriptor); + void PlaceOneofFields(const google::protobuf::Descriptor* descriptor); + Size Place(SizeAndAlign size_and_align); + + template <class K, class V> + static V GetMapValue(const std::unordered_map<K, V>& map, K key) { + auto iter = map.find(key); + if (iter == map.end()) { + fprintf(stderr, "No value for field.\n"); + abort(); + } + return iter->second; + } + + static bool IsPowerOfTwo(size_t val) { + return (val & (val - 1)) == 0; + } + + static size_t Align(size_t val, size_t align) { + ABSL_ASSERT(IsPowerOfTwo(align)); + return (val + align - 1) & ~(align - 1); + } + + static SizeAndAlign SizeOf(const google::protobuf::FieldDescriptor* field); + static int64_t FieldLayoutRank(const google::protobuf::FieldDescriptor* field); + + std::unordered_map<const google::protobuf::FieldDescriptor*, Size> + field_offsets_; + std::unordered_map<const google::protobuf::FieldDescriptor*, int> + hasbit_indexes_; + std::unordered_map<const google::protobuf::OneofDescriptor*, Size> + oneof_case_offsets_; + Size maxalign_; + Size size_; +}; + +} // namespace upbc + +#endif // UPBC_MESSAGE_LAYOUT_H |