json.h (5289B)
1 /* GRAPHITE2 LICENSING 2 3 Copyright 2011, SIL International 4 All rights reserved. 5 6 This library is free software; you can redistribute it and/or modify 7 it under the terms of the GNU Lesser General Public License as published 8 by the Free Software Foundation; either version 2.1 of License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should also have received a copy of the GNU Lesser General Public 17 License along with this library in the file named "LICENSE". 18 If not, write to the Free Software Foundation, 51 Franklin Street, 19 Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 20 internet at http://www.fsf.org/licenses/lgpl.html. 21 22 Alternatively, the contents of this file may be used under the terms of the 23 Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public 24 License, as published by the Free Software Foundation, either version 2 25 of the License or (at your option) any later version. 26 */ 27 // JSON pretty printer for graphite font debug output logging. 28 // Created on: 15 Dec 2011 29 // Author: Tim Eves 30 31 #pragma once 32 33 #include "inc/Main.h" 34 #include <cassert> 35 #include <cstdio> 36 #include <cstdint> 37 #include "inc/List.h" 38 39 namespace graphite2 { 40 41 class json 42 { 43 // Prevent copying 44 json(const json &); 45 json & operator = (const json &); 46 47 typedef void (*_context_t)(json &); 48 49 FILE * const _stream; 50 char _contexts[128], // context stack 51 * _context, // current context (top of stack) 52 * _flatten; // if !0 points to context above which 53 // pretty printed output should occur. 54 Vector<void *> _env; 55 56 void context(const char current) throw(); 57 void indent(const int d=0) throw(); 58 void push_context(const char, const char) throw(); 59 void pop_context() throw(); 60 61 public: 62 class closer; 63 64 using string = const char *; 65 using number = double; 66 enum class integer : std::intmax_t {}; 67 enum class integer_u : std::uintmax_t {}; 68 using boolean = bool; 69 static const std::nullptr_t null; 70 71 void setenv(unsigned int index, void *val) { _env.reserve(index + 1); if (index >= _env.size()) _env.insert(_env.end(), _env.size() - index + 1, 0); _env[index] = val; } 72 void *getenv(unsigned int index) const { return _env[index]; } 73 const Vector<void *> &getenvs() const { return _env; } 74 75 static void flat(json &) throw(); 76 static void close(json &) throw(); 77 static void object(json &) throw(); 78 static void array(json &) throw(); 79 static void item(json &) throw(); 80 81 json(FILE * stream) throw(); 82 ~json() throw (); 83 84 FILE * stream() const throw(); 85 86 json & operator << (string) throw(); 87 json & operator << (number) throw(); 88 json & operator << (integer) throw(); 89 json & operator << (integer_u) throw(); 90 json & operator << (boolean) throw(); 91 json & operator << (std::nullptr_t) throw(); 92 json & operator << (_context_t) throw(); 93 94 operator bool() const throw(); 95 bool good() const throw(); 96 bool eof() const throw(); 97 98 CLASS_NEW_DELETE; 99 }; 100 101 class json::closer 102 { 103 // Prevent copying. 104 closer(const closer &); 105 closer & operator = (const closer &); 106 107 json * const _j; 108 public: 109 closer(json * const j) : _j(j) {} 110 ~closer() throw() { if (_j) *_j << close; } 111 }; 112 113 inline 114 json::json(FILE * s) throw() 115 : _stream(s), _context(_contexts), _flatten(0) 116 { 117 if (good()) 118 fflush(s); 119 } 120 121 122 inline 123 json::~json() throw () 124 { 125 while (_context > _contexts) pop_context(); 126 } 127 128 inline 129 FILE * json::stream() const throw() { return _stream; } 130 131 132 inline 133 json & json::operator << (json::_context_t ctxt) throw() 134 { 135 ctxt(*this); 136 return *this; 137 } 138 139 inline 140 json & operator << (json & j, signed char d) throw() { return j << json::integer(d); } 141 142 inline 143 json & operator << (json & j, unsigned char d) throw() { return j << json::integer_u(d); } 144 145 inline 146 json & operator << (json & j, short int d) throw() { return j << json::integer(d); } 147 148 inline 149 json & operator << (json & j, unsigned short int d) throw() { return j << json::integer_u(d); } 150 151 inline 152 json & operator << (json & j, int d) throw() { return j << json::integer(d); } 153 154 inline 155 json & operator << (json & j, unsigned int d) throw() { return j << json::integer_u(d); } 156 157 inline 158 json & operator << (json & j, long int d) throw() { return j << json::integer(d); } 159 160 inline 161 json & operator << (json & j, unsigned long int d) throw() { return j << json::integer_u(d); } 162 163 inline 164 json & operator << (json & j, long long int d) throw() { return j << json::integer(d); } 165 166 inline 167 json & operator << (json & j, unsigned long long int d) throw() { return j << json::integer_u(d); } 168 169 inline 170 json::operator bool() const throw() { return good(); } 171 172 inline 173 bool json::good() const throw() { return _stream && ferror(_stream) == 0; } 174 175 inline 176 bool json::eof() const throw() { return feof(_stream) != 0; } 177 178 } // namespace graphite2