json.hpp 5.25 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
// Copyright (c) 2012-2017 VideoStitch SAS
// Copyright (c) 2018 stitchEm

#pragma once

#include "libvideostitch/ptv.hpp"
#include "libvideostitch/status.hpp"

#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <utility>

namespace VideoStitch {
namespace Parse {

class JsonValue;

enum class ParseStatusCode {
  // generic states
  Ok,
  ErrorWithStatus,
  // custom parse states
  InvalidUBJson,
  NotUBJsonFormat,
};

typedef Result<ParseStatusCode> ParseStatus;
typedef Potential<JsonValue, DefaultDeleter<Ptv::Value>, ParseStatus> PotentialJsonValue;

/**
 * A map pointer class that preserves insertion order.
 * Right now it's implemented as a vector of pairs, so lookup is via linear search. It's OK because we expect json
 * objects to be small. It takes ownership of the objects being inserted.
 * TODO: add an index of top if this no longer holds changes.
 * Insertion just pushes at the back and removal makes a hole. The vectors are compacted every now and then.
 */
template <typename T>
class OrderedMap {
 public:
  OrderedMap();
  ~OrderedMap();

  void reverse();

  int size() const;

  std::pair<const std::string*, const T*> get(int i) const;
  std::pair<const std::string*, T*> get(int i);

  /**
   * Inserts given key/value pair. Fails if the key already exists.
   * @param key The key.
   * @param v The value. On successful insertion, ownership is transferred to the OrderedMap. Cannot be NULL.
   * @return false if the object already exists, true if the insertion succeeds.
   */
  bool put(const std::string& key, T* v);

  /**
   * Fetches a value (const).
   * @param key The key.
   * @return NULL if the key does not exist.
   */
  const T* get(const std::string& key) const;

  /**
   * Fetches a value. Ownership is retained.
   * @param key The key.
   * @return NULL if the key does not exist.
   */
  T* get(const std::string& key);

  /**
   * Removes an entry. The returned object must be deleted.
   * @param key The key.
   * @return NULL if the key does not exist.
   */
  T* remove(const std::string& key);

  /**
   * Clears the container.
   */
  void clear();

  /**
   * Compact/reindex.
   */
  void compact();

 private:
  std::vector<std::string> keys;
  std::vector<T*> values;
  int numHoles;
};

/**
 * A stream that reads from a string.
 */
class DataInputStream {
 public:
  /**
   * Input shall remain alive four our lifetime.
   * @param input Input data.
   */
  explicit DataInputStream(const std::string& data);

  /**
   * This mimicks the std::istream interface.
   * @{
   */
  int get();
  int peek();
  DataInputStream& read(char* s, size_t n);
  bool fail() const;
  /**
   *@}
   */

 private:
  const std::string& data;
  size_t pos;
};

/**
 * @brief A Json Value.
 */
class JsonValue : public Ptv::Value {
 public:
  /**
   * Creates a NULL value.
   */
  explicit JsonValue(void* v);

  /**
   * Creates a BOOL value.
   */
  explicit JsonValue(bool v);

  /**
   * Creates an INT value.
   */
  explicit JsonValue(int64_t v);
  explicit JsonValue(int v);

  /**
   * Creates a LIST of INT values
   */
  explicit JsonValue(const std::vector<int64_t>& v);

  /**
   * Creates an DOUBLE value.
   */
  explicit JsonValue(double v);

  /**
   * Creates a STRING value.
   */
  explicit JsonValue(const std::string& v);
  explicit JsonValue(const char* v);

  /**
   * Creates a LIST value.
   * @param v List of values. Takes ownership of v.
   */
  explicit JsonValue(std::vector<Ptv::Value*>* v);

  /**
   * Parse from an UBJson stream.
   * @param input Input stream.
   * StreamT can be either std::istream or DataStream.
   */
  template <class StreamT>
  static PotentialJsonValue parseUBJson(StreamT& input);

  /**
   * Creates an empty OBJECT value.
   */
  JsonValue();

  ~JsonValue();

  /**
   * Reverses the order of values within an object.
   */
  void reverse();

  Ptv::Value* clone() const override;
  Type getType() const override;
  bool asBool() const override;
  int64_t asInt() const override;
  double asDouble() const override;
  const std::string& asString() const override;
  const std::vector<Ptv::Value*>& asList() const override;

  void reset(Ptv::Value::Type t);
  void resetIfNotType(Ptv::Value::Type t);

  void asNil() override;
  bool& asBool() override;
  int64_t& asInt() override;
  double& asDouble() override;
  std::string& asString() override;
  std::vector<Ptv::Value*>& asList() override;
  Ptv::Value& asObject() override;

  void clear();

  const Ptv::Value* has(const std::string& key) const override;

  Ptv::Value* get(const std::string& key) override;

  Ptv::Value* remove(const std::string& key) override;

  int size() const override;

  std::pair<const std::string*, const Ptv::Value*> get(int i) const override;
  std::pair<const std::string*, Ptv::Value*> get(int i) override;

  Ptv::Value* push(const std::string& key, Ptv::Value* v) override;

  void printJson(std::ostream& os, int indent = 0) const override;
  std::string getJsonStr() const override;
  void printUBJson(std::ostream& os) const override;

 private:
  void printJsonCLocale(std::ostream& os, int indent) const;

  Ptv::Value::Type type;
  bool boolValue;
  int64_t intValue;
  double doubleValue;
  std::string stringValue;
  std::vector<Ptv::Value*> listValue;
  OrderedMap<Value> content;
};
}  // namespace Parse
}  // namespace VideoStitch