btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / kits / shared / JsonMessageWriter.cpp
blobae08ccd123b4592a416711a9e6da05519e2606fb
1 /*
2 * Copyright 2017, Andrew Lindesay <apl@lindesay.co.nz>
3 * Distributed under the terms of the MIT License.
4 */
7 #include "JsonMessageWriter.h"
10 namespace BPrivate {
12 /*! The class and sub-classes of it are used as a stack internal to the
13 BJsonMessageWriter class. As the JSON is parsed, the stack of these
14 internal listeners follows the stack of the JSON parsing in terms of
15 containers; arrays and objects.
18 class BStackedMessageEventListener : public BJsonEventListener {
19 public:
20 BStackedMessageEventListener(
21 BJsonMessageWriter* writer,
22 BStackedMessageEventListener* parent,
23 uint32 messageWhat);
24 BStackedMessageEventListener(
25 BJsonMessageWriter* writer,
26 BStackedMessageEventListener* parent,
27 BMessage* message);
28 ~BStackedMessageEventListener();
30 bool Handle(const BJsonEvent& event);
31 void HandleError(status_t status, int32 line,
32 const char* message);
33 void Complete();
35 void AddMessage(BMessage* value);
37 status_t ErrorStatus();
38 virtual const char* NextItemName() = 0;
40 BStackedMessageEventListener*
41 Parent();
43 protected:
44 void AddBool(bool value);
45 void AddNull();
46 void AddDouble(double value);
47 void AddString(const char* value);
49 virtual bool WillAdd();
50 virtual void DidAdd();
52 void SetStackedListenerOnWriter(
53 BStackedMessageEventListener*
54 stackedListener);
56 BJsonMessageWriter* fWriter;
57 bool fOwnsMessage;
58 BStackedMessageEventListener
59 *fParent;
60 BMessage* fMessage;
64 class BStackedArrayMessageEventListener : public BStackedMessageEventListener {
65 public:
66 BStackedArrayMessageEventListener(
67 BJsonMessageWriter* writer,
68 BStackedMessageEventListener* parent);
69 BStackedArrayMessageEventListener(
70 BJsonMessageWriter* writer,
71 BStackedMessageEventListener* parent,
72 BMessage* message);
73 ~BStackedArrayMessageEventListener();
75 bool Handle(const BJsonEvent& event);
77 const char* NextItemName();
79 protected:
80 void DidAdd();
82 private:
83 uint32 fCount;
84 BString fNextItemName;
89 class BStackedObjectMessageEventListener : public BStackedMessageEventListener {
90 public:
91 BStackedObjectMessageEventListener(
92 BJsonMessageWriter* writer,
93 BStackedMessageEventListener* parent);
94 BStackedObjectMessageEventListener(
95 BJsonMessageWriter* writer,
96 BStackedMessageEventListener* parent,
97 BMessage* message);
98 ~BStackedObjectMessageEventListener();
100 bool Handle(const BJsonEvent& event);
102 const char* NextItemName();
104 protected:
105 bool WillAdd();
106 void DidAdd();
107 private:
108 BString fNextItemName;
111 } // namespace BPrivate
113 using BPrivate::BStackedMessageEventListener;
114 using BPrivate::BStackedArrayMessageEventListener;
115 using BPrivate::BStackedObjectMessageEventListener;
118 // #pragma mark - BStackedMessageEventListener
121 BStackedMessageEventListener::BStackedMessageEventListener(
122 BJsonMessageWriter* writer,
123 BStackedMessageEventListener* parent,
124 uint32 messageWhat)
126 fWriter = writer;
127 fParent = parent;
128 fOwnsMessage = true;
129 fMessage = new BMessage(messageWhat);
133 BStackedMessageEventListener::BStackedMessageEventListener(
134 BJsonMessageWriter* writer,
135 BStackedMessageEventListener* parent,
136 BMessage* message)
138 fWriter = writer;
139 fParent = parent;
140 fOwnsMessage = false;
141 fMessage = message;
145 BStackedMessageEventListener::~BStackedMessageEventListener()
147 if (fOwnsMessage)
148 delete fMessage;
152 bool
153 BStackedMessageEventListener::Handle(const BJsonEvent& event)
155 if (fWriter->ErrorStatus() != B_OK)
156 return false;
158 switch (event.EventType()) {
160 case B_JSON_NUMBER:
161 AddDouble(event.ContentDouble());
162 break;
164 case B_JSON_STRING:
165 AddString(event.Content());
166 break;
168 case B_JSON_TRUE:
169 AddBool(true);
170 break;
172 case B_JSON_FALSE:
173 AddBool(false);
174 break;
176 case B_JSON_NULL:
177 AddNull();
178 break;
180 case B_JSON_OBJECT_START:
182 SetStackedListenerOnWriter(new BStackedObjectMessageEventListener(
183 fWriter, this));
184 break;
187 case B_JSON_ARRAY_START:
189 SetStackedListenerOnWriter(new BStackedArrayMessageEventListener(
190 fWriter, this));
191 break;
194 default:
196 HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE,
197 "unexpected type of json item to add to container");
198 return false;
202 return ErrorStatus() == B_OK;
206 void
207 BStackedMessageEventListener::HandleError(status_t status, int32 line,
208 const char* message)
210 fWriter->HandleError(status, line, message);
214 void
215 BStackedMessageEventListener::Complete()
217 // illegal state.
218 HandleError(JSON_EVENT_LISTENER_ANY_LINE, B_NOT_ALLOWED,
219 "Complete() called on stacked message listener");
223 void
224 BStackedMessageEventListener::AddMessage(BMessage* message)
226 if (WillAdd()) {
227 fMessage->AddMessage(NextItemName(), message);
228 DidAdd();
233 status_t
234 BStackedMessageEventListener::ErrorStatus()
236 return fWriter->ErrorStatus();
240 BStackedMessageEventListener*
241 BStackedMessageEventListener::Parent()
243 return fParent;
247 void
248 BStackedMessageEventListener::AddBool(bool value)
250 if (WillAdd()) {
251 fMessage->AddBool(NextItemName(), value);
252 DidAdd();
256 void
257 BStackedMessageEventListener::AddNull()
259 if (WillAdd()) {
260 fMessage->AddPointer(NextItemName(), (void*)NULL);
261 DidAdd();
265 void
266 BStackedMessageEventListener::AddDouble(double value)
268 if (WillAdd()) {
269 fMessage->AddDouble(NextItemName(), value);
270 DidAdd();
274 void
275 BStackedMessageEventListener::AddString(const char* value)
277 if (WillAdd()) {
278 fMessage->AddString(NextItemName(), value);
279 DidAdd();
284 bool
285 BStackedMessageEventListener::WillAdd()
287 return true;
291 void
292 BStackedMessageEventListener::DidAdd()
294 // noop - present for overriding
298 void
299 BStackedMessageEventListener::SetStackedListenerOnWriter(
300 BStackedMessageEventListener* stackedListener)
302 fWriter->SetStackedListener(stackedListener);
306 // #pragma mark - BStackedArrayMessageEventListener
309 BStackedArrayMessageEventListener::BStackedArrayMessageEventListener(
310 BJsonMessageWriter* writer,
311 BStackedMessageEventListener* parent)
313 BStackedMessageEventListener(writer, parent, B_JSON_MESSAGE_WHAT_ARRAY)
315 fCount = 0;
319 BStackedArrayMessageEventListener::BStackedArrayMessageEventListener(
320 BJsonMessageWriter* writer,
321 BStackedMessageEventListener* parent,
322 BMessage* message)
324 BStackedMessageEventListener(writer, parent, message)
326 message->what = B_JSON_MESSAGE_WHAT_ARRAY;
327 fCount = 0;
331 BStackedArrayMessageEventListener::~BStackedArrayMessageEventListener()
336 bool
337 BStackedArrayMessageEventListener::Handle(const BJsonEvent& event)
339 if (fWriter->ErrorStatus() != B_OK)
340 return false;
342 switch (event.EventType()) {
343 case B_JSON_ARRAY_END:
345 if (fParent != NULL)
346 fParent->AddMessage(fMessage);
347 SetStackedListenerOnWriter(fParent);
348 delete this;
349 break;
352 default:
353 return BStackedMessageEventListener::Handle(event);
356 return true;
360 const char*
361 BStackedArrayMessageEventListener::NextItemName()
363 fNextItemName.SetToFormat("%" B_PRIu32, fCount);
364 return fNextItemName.String();
368 void
369 BStackedArrayMessageEventListener::DidAdd()
371 BStackedMessageEventListener::DidAdd();
372 fCount++;
376 // #pragma mark - BStackedObjectMessageEventListener
379 BStackedObjectMessageEventListener::BStackedObjectMessageEventListener(
380 BJsonMessageWriter* writer,
381 BStackedMessageEventListener* parent)
383 BStackedMessageEventListener(writer, parent, B_JSON_MESSAGE_WHAT_OBJECT)
388 BStackedObjectMessageEventListener::BStackedObjectMessageEventListener(
389 BJsonMessageWriter* writer,
390 BStackedMessageEventListener* parent,
391 BMessage* message)
393 BStackedMessageEventListener(writer, parent, message)
395 message->what = B_JSON_MESSAGE_WHAT_OBJECT;
399 BStackedObjectMessageEventListener::~BStackedObjectMessageEventListener()
404 bool
405 BStackedObjectMessageEventListener::Handle(const BJsonEvent& event)
407 if (fWriter->ErrorStatus() != B_OK)
408 return false;
410 switch (event.EventType()) {
411 case B_JSON_OBJECT_END:
413 if (fParent != NULL)
414 fParent->AddMessage(fMessage);
415 SetStackedListenerOnWriter(fParent);
416 delete this;
417 break;
420 case B_JSON_OBJECT_NAME:
421 fNextItemName.SetTo(event.Content());
422 break;
424 default:
425 return BStackedMessageEventListener::Handle(event);
428 return true;
432 const char*
433 BStackedObjectMessageEventListener::NextItemName()
435 return fNextItemName.String();
439 bool
440 BStackedObjectMessageEventListener::WillAdd()
442 if (0 == fNextItemName.Length()) {
443 HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE,
444 "missing name for adding value into an object");
445 return false;
448 return true;
452 void
453 BStackedObjectMessageEventListener::DidAdd()
455 BStackedMessageEventListener::DidAdd();
456 fNextItemName.SetTo("", 0);
460 // #pragma mark - BJsonMessageWriter
463 BJsonMessageWriter::BJsonMessageWriter(BMessage& message)
465 fTopLevelMessage = &message;
466 fStackedListener = NULL;
470 BJsonMessageWriter::~BJsonMessageWriter()
472 BStackedMessageEventListener* listener = fStackedListener;
474 while (listener != NULL) {
475 BStackedMessageEventListener* nextListener = listener->Parent();
476 delete listener;
477 listener = nextListener;
480 fStackedListener = NULL;
484 bool
485 BJsonMessageWriter::Handle(const BJsonEvent& event)
487 if (fErrorStatus != B_OK)
488 return false;
490 if (fStackedListener != NULL)
491 return fStackedListener->Handle(event);
492 else {
493 switch(event.EventType()) {
494 case B_JSON_OBJECT_START:
496 SetStackedListener(new BStackedObjectMessageEventListener(
497 this, NULL, fTopLevelMessage));
498 break;
501 case B_JSON_ARRAY_START:
503 fTopLevelMessage->what = B_JSON_MESSAGE_WHAT_ARRAY;
504 SetStackedListener(new BStackedArrayMessageEventListener(
505 this, NULL, fTopLevelMessage));
506 break;
509 default:
511 HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE,
512 "a message object can only handle an object or an array"
513 "at the top level");
514 return false;
519 return true; // keep going
523 void
524 BJsonMessageWriter::Complete()
526 if (fStackedListener != NULL) {
527 HandleError(B_BAD_DATA, JSON_EVENT_LISTENER_ANY_LINE,
528 "unexpected end of input data processing structure");
533 void
534 BJsonMessageWriter::SetStackedListener(
535 BStackedMessageEventListener* listener)
537 fStackedListener = listener;