JODA  0.13.1 (59b41972)
JSON On-Demand Analysis
ViewLayer.h
Go to the documentation of this file.
1 //
2 // Created by Nico on 27/08/2019.
3 //
4 
5 #ifndef JODA_VIEWLAYER_H
6 #define JODA_VIEWLAYER_H
7 
8 #include <glog/logging.h>
9 #include <joda/config/config.h>
10 #include <joda/misc/RJFwd.h>
11 #include <rapidjson/stringbuffer.h>
12 #include <algorithm>
13 #include <mutex>
14 #include <unordered_map>
15 #include <variant>
16 #include <optional>
17 #include "ObjectIterator.h"
18 #include "ViewCursor.h"
19 #include "ViewStructure.h"
20 #include "VirtualObject.h"
21 
22 class ViewLayer {
23  public:
24  ViewLayer(const RJValue *doc, const std::vector<std::string> *viewPaths,
25  ViewLayer *previousLayer, ViewStructure *struc);
26 
27  ViewLayer(const ViewLayer &other) = delete;
28  ViewLayer &operator=(const ViewLayer &other) = delete;
29 
30  ViewLayer(ViewLayer &&other) = delete;
31  ViewLayer &operator=(ViewLayer &&other) = delete;
32 
33  private:
34  const RJValue *doc;
35  std::vector<std::string> const *viewPaths;
36  ViewLayer *previousLayer;
37  std::string prefix = "";
38  std::unordered_map<std::string, VirtualObject> objects;
39  typedef typename std::unique_ptr<ViewCursor> Cursor;
40  Cursor cursor;
41 
42  bool pathOverwritten(const std::string &path) const;
43  ViewStructure *struc;
44 
45  /*
46  * Accepts
47  */
48  public:
49 
50  void updateDoc(const RJValue *doc);
51  void setPrefix(const std::string &prefix);
52 
53  bool pointerIsOverwritten(const std::string &ptr) const;
54  const VirtualObject *getVO(const std::string &ptr) const;
55 
56  template <typename Handler>
57  bool Accept(Handler &handler) {
58  lock();
59  getCursor(prefix);
60  auto res = Accept(handler, prefix);
61  unlock();
62  return res;
63  }
64 
65  template <typename Handler>
66  bool operator()(Handler &handler) {
67  return Accept(handler);
68  }
69 
70  RJValue const *Get(const RJPointer &ptr);
71 
72  std::variant<const RJValue, std::optional<const RJValue *>,
73  const VirtualObject *>
74  getPointerIfExists(const std::string &ptr, RJMemoryPoolAlloc &alloc) const {
75  auto obj = objects.find(ptr);
76  if (obj != objects.end()) {
77  return &obj->second;
78  }
79  auto *v = RJPointer(ptr.c_str()).Get(*doc);
80  if (pathOverwritten(ptr)) {
81  return v;
82  } else {
83  // It exists, but is not overwritten => shared
84  if (v != nullptr) return std::nullopt;
85  // It doesn't exist here, check below
86  if (previousLayer != nullptr)
87  return previousLayer->getPointerIfExists(ptr, alloc);
88  // If no below to check, return nullptr, meaning it is really not here
89  return std::optional<const RJValue *>(nullptr);
90  }
91  };
92 
93  template <typename Handler>
94  bool Accept(Handler &handler, const std::string &ptr) {
95  auto obj = objects.find(ptr);
96  if (obj != objects.end()) {
97  return obj->second.Accept(handler);
98  }
99 
100  if (cursor == nullptr) return true;
101  if (cursor->isShared(ptr)) {
102  return AcceptShared(handler, ptr);
103  } else {
104  auto *val = cursor->getVal();
105  if (val == nullptr) {
106  if (previousLayer == nullptr) return handler.Null();
107  return previousLayer->Accept(handler, ptr);
108  } else {
109  return val->Accept(handler);
110  }
111  }
112  }
113 
114  private:
115  void lock();
116  void unlock();
117  std::mutex mut;
118  RJValue const *Get(const RJPointer &ptr, const std::string &ptrStr);
119 
120  void getCursor(const std::string &ptr);
121 
122  template <typename Handler>
123  bool AcceptShared(Handler &handler, const std::string &curr) {
124  auto members = GetMembers(curr);
125  auto baseAttPath = curr + "/";
126  auto baseAttSize = baseAttPath.size();
127  if (RAPIDJSON_UNLIKELY(!handler.StartObject())) return false;
128 
129  VirtualObject obj(struc);
130  auto vos_enabled =
131  config::enable_views_vo && previousLayer != nullptr && struc != nullptr;
132 
133  if (vos_enabled) {
134  obj.reserve(members.size());
135  }
136  for (const auto &member : members) {
137  if (RAPIDJSON_UNLIKELY(
138  !handler.Key(member.name.c_str(), member.name.size(), true)))
139  return false;
140  if (member.val != nullptr) {
141  if (vos_enabled)
142  obj.addMember(struc->getOrAdd(member.name), member.val);
143  if (RAPIDJSON_UNLIKELY(!member.val->Accept(handler))) return false;
144  } else {
145  cursor->followAtt(member.name);
146  baseAttPath.erase(baseAttSize);
147  baseAttPath.append(member.name);
148  if (!Accept(handler, baseAttPath)) {
149  return false;
150  }
151  if (vos_enabled) {
152  DCHECK(objects.count(baseAttPath) > 0);
153  obj.addMember(struc->getOrAdd(member.name), &objects[baseAttPath]);
154  }
155  cursor->unfollow();
156  }
157  }
158 
159  if (vos_enabled) objects[curr] = std::move(obj);
160 
161  return handler.EndObject(members.size());
162  }
163 
164  std::vector<ViewCursor::ViewObjectMember> GetMembers(
165  const std::string &currPath);
166 };
167 
168 #endif // JODA_VIEWLAYER_H
rapidjson::MemoryPoolAllocator< RJBaseAlloc > RJMemoryPoolAlloc
Definition: RJFwd.h:26
rapidjson::GenericPointer< RJValue, RJBaseAlloc > RJPointer
Definition: RJFwd.h:30
rapidjson::GenericValue< RJChar, RJMemoryPoolAlloc > RJValue
Definition: RJFwd.h:29
Definition: ViewLayer.h:22
const VirtualObject * getVO(const std::string &ptr) const
Definition: ViewLayer.cpp:84
void setPrefix(const std::string &prefix)
Definition: ViewLayer.cpp:68
std::variant< const RJValue, std::optional< const RJValue * >, const VirtualObject * > getPointerIfExists(const std::string &ptr, RJMemoryPoolAlloc &alloc) const
Definition: ViewLayer.h:74
bool Accept(Handler &handler)
Definition: ViewLayer.h:57
ViewLayer(ViewLayer &&other)=delete
bool operator()(Handler &handler)
Definition: ViewLayer.h:66
void updateDoc(const RJValue *doc)
Definition: ViewLayer.cpp:80
RJValue const * Get(const RJPointer &ptr)
Definition: ViewLayer.cpp:51
ViewLayer & operator=(ViewLayer &&other)=delete
ViewLayer & operator=(const ViewLayer &other)=delete
bool Accept(Handler &handler, const std::string &ptr)
Definition: ViewLayer.h:94
ViewLayer(const RJValue *doc, const std::vector< std::string > *viewPaths, ViewLayer *previousLayer, ViewStructure *struc)
Definition: ViewLayer.cpp:19
bool pointerIsOverwritten(const std::string &ptr) const
Definition: ViewLayer.cpp:72
ViewLayer(const ViewLayer &other)=delete
Definition: ViewStructure.h:14
ID getOrAdd(const KEY &key)
Definition: ViewStructure.cpp:9
std::pair< size_t, size_t > reserve(size_t size)
Definition: ViewStructure.cpp:41
Definition: VirtualObject.h:13
static bool enable_views_vo
Definition: config.h:83