OpenShot Library | libopenshot-audio  0.2.0
juce_JSON.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  The code included in this file is provided under the terms of the ISC license
11  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12  To use, copy, modify, and/or distribute this software for any purpose with or
13  without fee is hereby granted provided that the above copyright notice and
14  this permission notice appear in all copies.
15 
16  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18  DISCLAIMED.
19 
20  ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
26 struct JSONParser
27 {
28  static Result parseObjectOrArray (String::CharPointerType t, var& result)
29  {
30  t = t.findEndOfWhitespace();
31 
32  switch (t.getAndAdvance())
33  {
34  case 0: result = var(); return Result::ok();
35  case '{': return parseObject (t, result);
36  case '[': return parseArray (t, result);
37  }
38 
39  return createFail ("Expected '{' or '['", &t);
40  }
41 
42  static Result parseString (const juce_wchar quoteChar, String::CharPointerType& t, var& result)
43  {
44  MemoryOutputStream buffer (256);
45 
46  for (;;)
47  {
48  auto c = t.getAndAdvance();
49 
50  if (c == quoteChar)
51  break;
52 
53  if (c == '\\')
54  {
55  c = t.getAndAdvance();
56 
57  switch (c)
58  {
59  case '"':
60  case '\'':
61  case '\\':
62  case '/': break;
63 
64  case 'a': c = '\a'; break;
65  case 'b': c = '\b'; break;
66  case 'f': c = '\f'; break;
67  case 'n': c = '\n'; break;
68  case 'r': c = '\r'; break;
69  case 't': c = '\t'; break;
70 
71  case 'u':
72  {
73  c = 0;
74 
75  for (int i = 4; --i >= 0;)
76  {
78 
79  if (digitValue < 0)
80  return createFail ("Syntax error in unicode escape sequence");
81 
82  c = (juce_wchar) ((c << 4) + static_cast<juce_wchar> (digitValue));
83  }
84 
85  break;
86  }
87  }
88  }
89 
90  if (c == 0)
91  return createFail ("Unexpected end-of-input in string constant");
92 
93  buffer.appendUTF8Char (c);
94  }
95 
96  result = buffer.toUTF8();
97  return Result::ok();
98  }
99 
100  static Result parseAny (String::CharPointerType& t, var& result)
101  {
102  t = t.findEndOfWhitespace();
103  auto t2 = t;
104 
105  switch (t2.getAndAdvance())
106  {
107  case '{': t = t2; return parseObject (t, result);
108  case '[': t = t2; return parseArray (t, result);
109  case '"': t = t2; return parseString ('"', t, result);
110  case '\'': t = t2; return parseString ('\'', t, result);
111 
112  case '-':
113  t2 = t2.findEndOfWhitespace();
114  if (! CharacterFunctions::isDigit (*t2))
115  break;
116 
117  t = t2;
118  return parseNumber (t, result, true);
119 
120  case '0': case '1': case '2': case '3': case '4':
121  case '5': case '6': case '7': case '8': case '9':
122  return parseNumber (t, result, false);
123 
124  case 't': // "true"
125  if (t2.getAndAdvance() == 'r' && t2.getAndAdvance() == 'u' && t2.getAndAdvance() == 'e')
126  {
127  t = t2;
128  result = var (true);
129  return Result::ok();
130  }
131  break;
132 
133  case 'f': // "false"
134  if (t2.getAndAdvance() == 'a' && t2.getAndAdvance() == 'l'
135  && t2.getAndAdvance() == 's' && t2.getAndAdvance() == 'e')
136  {
137  t = t2;
138  result = var (false);
139  return Result::ok();
140  }
141  break;
142 
143  case 'n': // "null"
144  if (t2.getAndAdvance() == 'u' && t2.getAndAdvance() == 'l' && t2.getAndAdvance() == 'l')
145  {
146  t = t2;
147  result = var();
148  return Result::ok();
149  }
150  break;
151 
152  default:
153  break;
154  }
155 
156  return createFail ("Syntax error", &t);
157  }
158 
159 private:
160  static Result createFail (const char* const message, const String::CharPointerType* location = nullptr)
161  {
162  String m (message);
163  if (location != nullptr)
164  m << ": \"" << String (*location, 20) << '"';
165 
166  return Result::fail (m);
167  }
168 
169  static Result parseNumber (String::CharPointerType& t, var& result, const bool isNegative)
170  {
171  auto oldT = t;
172 
173  int64 intValue = t.getAndAdvance() - '0';
174  jassert (intValue >= 0 && intValue < 10);
175 
176  for (;;)
177  {
178  auto previousChar = t;
179  auto c = t.getAndAdvance();
180  auto digit = ((int) c) - '0';
181 
182  if (isPositiveAndBelow (digit, 10))
183  {
184  intValue = intValue * 10 + digit;
185  continue;
186  }
187 
188  if (c == 'e' || c == 'E' || c == '.')
189  {
190  t = oldT;
191  auto asDouble = CharacterFunctions::readDoubleValue (t);
192  result = isNegative ? -asDouble : asDouble;
193  return Result::ok();
194  }
195 
197  || c == ',' || c == '}' || c == ']' || c == 0)
198  {
199  t = previousChar;
200  break;
201  }
202 
203  return createFail ("Syntax error in number", &oldT);
204  }
205 
206  auto correctedValue = isNegative ? -intValue : intValue;
207 
208  if ((intValue >> 31) != 0)
209  result = correctedValue;
210  else
211  result = (int) correctedValue;
212 
213  return Result::ok();
214  }
215 
216  static Result parseObject (String::CharPointerType& t, var& result)
217  {
218  auto resultObject = new DynamicObject();
219  result = resultObject;
220  auto& resultProperties = resultObject->getProperties();
221 
222  for (;;)
223  {
224  t = t.findEndOfWhitespace();
225 
226  auto oldT = t;
227  auto c = t.getAndAdvance();
228 
229  if (c == '}')
230  break;
231 
232  if (c == 0)
233  return createFail ("Unexpected end-of-input in object declaration");
234 
235  if (c == '"')
236  {
237  var propertyNameVar;
238  auto r = parseString ('"', t, propertyNameVar);
239 
240  if (r.failed())
241  return r;
242 
243  const Identifier propertyName (propertyNameVar.toString());
244 
245  if (propertyName.isValid())
246  {
247  t = t.findEndOfWhitespace();
248  oldT = t;
249 
250  auto c2 = t.getAndAdvance();
251 
252  if (c2 != ':')
253  return createFail ("Expected ':', but found", &oldT);
254 
255  resultProperties.set (propertyName, var());
256  var* propertyValue = resultProperties.getVarPointer (propertyName);
257 
258  auto r2 = parseAny (t, *propertyValue);
259 
260  if (r2.failed())
261  return r2;
262 
263  t = t.findEndOfWhitespace();
264  oldT = t;
265 
266  auto nextChar = t.getAndAdvance();
267 
268  if (nextChar == ',')
269  continue;
270 
271  if (nextChar == '}')
272  break;
273  }
274  }
275 
276  return createFail ("Expected object member declaration, but found", &oldT);
277  }
278 
279  return Result::ok();
280  }
281 
282  static Result parseArray (String::CharPointerType& t, var& result)
283  {
284  result = var (Array<var>());
285  auto* destArray = result.getArray();
286 
287  for (;;)
288  {
289  t = t.findEndOfWhitespace();
290 
291  auto oldT = t;
292  auto c = t.getAndAdvance();
293 
294  if (c == ']')
295  break;
296 
297  if (c == 0)
298  return createFail ("Unexpected end-of-input in array declaration");
299 
300  t = oldT;
301  destArray->add (var());
302  auto r = parseAny (t, destArray->getReference (destArray->size() - 1));
303 
304  if (r.failed())
305  return r;
306 
307  t = t.findEndOfWhitespace();
308  oldT = t;
309 
310  auto nextChar = t.getAndAdvance();
311 
312  if (nextChar == ',')
313  continue;
314 
315  if (nextChar == ']')
316  break;
317 
318  return createFail ("Expected object array item, but found", &oldT);
319  }
320 
321  return Result::ok();
322  }
323 };
324 
325 //==============================================================================
327 {
328  static void write (OutputStream& out, const var& v,
329  int indentLevel, bool allOnOneLine, int maximumDecimalPlaces)
330  {
331  if (v.isString())
332  {
333  out << '"';
334  writeString (out, v.toString().getCharPointer());
335  out << '"';
336  }
337  else if (v.isVoid())
338  {
339  out << "null";
340  }
341  else if (v.isUndefined())
342  {
343  out << "undefined";
344  }
345  else if (v.isBool())
346  {
347  out << (static_cast<bool> (v) ? "true" : "false");
348  }
349  else if (v.isDouble())
350  {
351  auto d = static_cast<double> (v);
352 
353  if (juce_isfinite (d))
354  {
355  out << serialiseDouble (d);
356  }
357  else
358  {
359  out << "null";
360  }
361  }
362  else if (v.isArray())
363  {
364  writeArray (out, *v.getArray(), indentLevel, allOnOneLine, maximumDecimalPlaces);
365  }
366  else if (v.isObject())
367  {
368  if (auto* object = v.getDynamicObject())
369  object->writeAsJSON (out, indentLevel, allOnOneLine, maximumDecimalPlaces);
370  else
371  jassertfalse; // Only DynamicObjects can be converted to JSON!
372  }
373  else
374  {
375  // Can't convert these other types of object to JSON!
376  jassert (! (v.isMethod() || v.isBinaryData()));
377 
378  out << v.toString();
379  }
380  }
381 
382  static void writeEscapedChar (OutputStream& out, const unsigned short value)
383  {
384  out << "\\u" << String::toHexString ((int) value).paddedLeft ('0', 4);
385  }
386 
387  static void writeString (OutputStream& out, String::CharPointerType t)
388  {
389  for (;;)
390  {
391  auto c = t.getAndAdvance();
392 
393  switch (c)
394  {
395  case 0: return;
396 
397  case '\"': out << "\\\""; break;
398  case '\\': out << "\\\\"; break;
399  case '\a': out << "\\a"; break;
400  case '\b': out << "\\b"; break;
401  case '\f': out << "\\f"; break;
402  case '\t': out << "\\t"; break;
403  case '\r': out << "\\r"; break;
404  case '\n': out << "\\n"; break;
405 
406  default:
407  if (c >= 32 && c < 127)
408  {
409  out << (char) c;
410  }
411  else
412  {
414  {
415  CharPointer_UTF16::CharType chars[2];
416  CharPointer_UTF16 utf16 (chars);
417  utf16.write (c);
418 
419  for (int i = 0; i < 2; ++i)
420  writeEscapedChar (out, (unsigned short) chars[i]);
421  }
422  else
423  {
424  writeEscapedChar (out, (unsigned short) c);
425  }
426  }
427 
428  break;
429  }
430  }
431  }
432 
433  static void writeSpaces (OutputStream& out, int numSpaces)
434  {
435  out.writeRepeatedByte (' ', (size_t) numSpaces);
436  }
437 
438  static void writeArray (OutputStream& out, const Array<var>& array,
439  int indentLevel, bool allOnOneLine, int maximumDecimalPlaces)
440  {
441  out << '[';
442 
443  if (! array.isEmpty())
444  {
445  if (! allOnOneLine)
446  out << newLine;
447 
448  for (int i = 0; i < array.size(); ++i)
449  {
450  if (! allOnOneLine)
451  writeSpaces (out, indentLevel + indentSize);
452 
453  write (out, array.getReference(i), indentLevel + indentSize, allOnOneLine, maximumDecimalPlaces);
454 
455  if (i < array.size() - 1)
456  {
457  if (allOnOneLine)
458  out << ", ";
459  else
460  out << ',' << newLine;
461  }
462  else if (! allOnOneLine)
463  out << newLine;
464  }
465 
466  if (! allOnOneLine)
467  writeSpaces (out, indentLevel);
468  }
469 
470  out << ']';
471  }
472 
473  enum { indentSize = 2 };
474 };
475 
476 //==============================================================================
477 var JSON::parse (const String& text)
478 {
479  var result;
480 
481  if (! parse (text, result))
482  result = var();
483 
484  return result;
485 }
486 
488 {
489  var result;
490 
491  if (! JSONParser::parseAny (text.text, result))
492  result = var();
493 
494  return result;
495 }
496 
498 {
499  return parse (input.readEntireStreamAsString());
500 }
501 
502 var JSON::parse (const File& file)
503 {
504  return parse (file.loadFileAsString());
505 }
506 
507 Result JSON::parse (const String& text, var& result)
508 {
509  return JSONParser::parseObjectOrArray (text.getCharPointer(), result);
510 }
511 
512 String JSON::toString (const var& data, const bool allOnOneLine, int maximumDecimalPlaces)
513 {
514  MemoryOutputStream mo (1024);
515  JSONFormatter::write (mo, data, 0, allOnOneLine, maximumDecimalPlaces);
516  return mo.toUTF8();
517 }
518 
519 void JSON::writeToStream (OutputStream& output, const var& data, const bool allOnOneLine, int maximumDecimalPlaces)
520 {
521  JSONFormatter::write (output, data, 0, allOnOneLine, maximumDecimalPlaces);
522 }
523 
525 {
527  JSONFormatter::writeString (mo, s.text);
528  return mo.toString();
529 }
530 
532 {
533  auto quote = t.getAndAdvance();
534 
535  if (quote == '"' || quote == '\'')
536  return JSONParser::parseString (quote, t, result);
537 
538  return Result::fail ("Not a quoted string!");
539 }
540 
541 //==============================================================================
542 //==============================================================================
543 #if JUCE_UNIT_TESTS
544 
545 class JSONTests : public UnitTest
546 {
547 public:
548  JSONTests() : UnitTest ("JSON", "JSON") {}
549 
550  static String createRandomWideCharString (Random& r)
551  {
552  juce_wchar buffer[40] = { 0 };
553 
554  for (int i = 0; i < numElementsInArray (buffer) - 1; ++i)
555  {
556  if (r.nextBool())
557  {
558  do
559  {
560  buffer[i] = (juce_wchar) (1 + r.nextInt (0x10ffff - 1));
561  }
562  while (! CharPointer_UTF16::canRepresent (buffer[i]));
563  }
564  else
565  buffer[i] = (juce_wchar) (1 + r.nextInt (0xff));
566  }
567 
568  return CharPointer_UTF32 (buffer);
569  }
570 
571  static String createRandomIdentifier (Random& r)
572  {
573  char buffer[30] = { 0 };
574 
575  for (int i = 0; i < numElementsInArray (buffer) - 1; ++i)
576  {
577  static const char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-:";
578  buffer[i] = chars [r.nextInt (sizeof (chars) - 1)];
579  }
580 
581  return CharPointer_ASCII (buffer);
582  }
583 
584  // Creates a random double that can be easily stringified, to avoid
585  // false failures when decimal places are rounded or truncated slightly
586  static var createRandomDouble (Random& r)
587  {
588  return var ((r.nextDouble() * 1000.0) + 0.1);
589  }
590 
591  static var createRandomVar (Random& r, int depth)
592  {
593  switch (r.nextInt (depth > 3 ? 6 : 8))
594  {
595  case 0: return {};
596  case 1: return r.nextInt();
597  case 2: return r.nextInt64();
598  case 3: return r.nextBool();
599  case 4: return createRandomDouble (r);
600  case 5: return createRandomWideCharString (r);
601 
602  case 6:
603  {
604  var v (createRandomVar (r, depth + 1));
605 
606  for (int i = 1 + r.nextInt (30); --i >= 0;)
607  v.append (createRandomVar (r, depth + 1));
608 
609  return v;
610  }
611 
612  case 7:
613  {
614  DynamicObject* o = new DynamicObject();
615 
616  for (int i = r.nextInt (30); --i >= 0;)
617  o->setProperty (createRandomIdentifier (r), createRandomVar (r, depth + 1));
618 
619  return o;
620  }
621 
622  default:
623  return {};
624  }
625  }
626 
627  void runTest() override
628  {
629  {
630  beginTest ("JSON");
631 
632  Random r = getRandom();
633 
634  expect (JSON::parse (String()) == var());
635  expect (JSON::parse ("{}").isObject());
636  expect (JSON::parse ("[]").isArray());
637  expect (JSON::parse ("[ 1234 ]")[0].isInt());
638  expect (JSON::parse ("[ 12345678901234 ]")[0].isInt64());
639  expect (JSON::parse ("[ 1.123e3 ]")[0].isDouble());
640  expect (JSON::parse ("[ -1234]")[0].isInt());
641  expect (JSON::parse ("[-12345678901234]")[0].isInt64());
642  expect (JSON::parse ("[-1.123e3]")[0].isDouble());
643 
644  for (int i = 100; --i >= 0;)
645  {
646  var v;
647 
648  if (i > 0)
649  v = createRandomVar (r, 0);
650 
651  const bool oneLine = r.nextBool();
652  String asString (JSON::toString (v, oneLine));
653  var parsed = JSON::parse ("[" + asString + "]")[0];
654  String parsedString (JSON::toString (parsed, oneLine));
655  expect (asString.isNotEmpty() && parsedString == asString);
656  }
657  }
658 
659  {
660  beginTest ("Float formatting");
661 
662  std::map<double, String> tests;
663  tests[1] = "1.0";
664  tests[1.1] = "1.1";
665  tests[1.01] = "1.01";
666  tests[0.76378] = "0.76378";
667  tests[-10] = "-10.0";
668  tests[10.01] = "10.01";
669  tests[0.0123] = "0.0123";
670  tests[-3.7e-27] = "-3.7e-27";
671  tests[1e+40] = "1.0e40";
672  tests[-12345678901234567.0] = "-1.234567890123457e16";
673  tests[192000] = "192000.0";
674  tests[1234567] = "1.234567e6";
675  tests[0.00006] = "0.00006";
676  tests[0.000006] = "6.0e-6";
677 
678  for (auto& test : tests)
679  expectEquals (JSON::toString (test.first), test.second);
680  }
681  }
682 };
683 
684 static JSONTests JSONUnitTests;
685 
686 #endif
687 
688 } // namespace juce
juce::File::loadFileAsString
String loadFileAsString() const
Reads a file into memory as a string.
Definition: juce_File.cpp:530
juce::CharPointer_UTF16::getBytesRequiredFor
static size_t getBytesRequiredFor(juce_wchar charToWrite) noexcept
Returns the number of bytes that would be needed to represent the given unicode character in this enc...
Definition: juce_CharPointer_UTF16.h:252
juce::StringRef
A simple class for holding temporary references to a string literal or String.
Definition: juce_StringRef.h:65
juce::CharacterFunctions::getHexDigitValue
static int getHexDigitValue(juce_wchar digit) noexcept
Returns 0 to 16 for '0' to 'F", or -1 for characters that aren't a legal hex digit.
Definition: juce_CharacterFunctions.cpp:117
juce::JSONParser
Definition: juce_JSON.cpp:26
juce::Result
Represents the 'success' or 'failure' of an operation, and holds an associated error message to descr...
Definition: juce_Result.h:60
juce::Array::size
int size() const noexcept
Returns the current number of elements in the array.
Definition: juce_Array.h:219
juce::MemoryOutputStream
Writes data to an internal memory buffer, which grows as required.
Definition: juce_MemoryOutputStream.h:39
juce::InputStream
The base class for streams that read data.
Definition: juce_InputStream.h:40
juce::String::getCharPointer
CharPointerType getCharPointer() const noexcept
Returns the character pointer currently being used to store this string.
Definition: juce_String.h:1200
juce::DynamicObject
Represents a dynamically implemented object.
Definition: juce_DynamicObject.h:43
juce::Array
Holds a resizable array of primitive or copy-by-value objects.
Definition: juce_Array.h:59
juce::String::toHexString
static String toHexString(IntegerType number)
Returns a string representing this numeric value in hexadecimal.
Definition: juce_String.h:1055
juce::CharPointer_UTF16
Wraps a pointer to a null-terminated UTF-16 character string, and provides various methods to operate...
Definition: juce_CharPointer_UTF16.h:38
juce::CharacterFunctions::readDoubleValue
static double readDoubleValue(CharPointerType &text) noexcept
Parses a character string to read a floating-point number.
Definition: juce_CharacterFunctions.h:151
juce::StringRef::text
String::CharPointerType text
The text that is referenced.
Definition: juce_StringRef.h:126
juce::CharPointer_UTF16::canRepresent
static bool canRepresent(juce_wchar character) noexcept
Returns true if the given unicode character can be represented in this encoding.
Definition: juce_CharPointer_UTF16.h:434
juce::OutputStream
The base class for streams that write data to some kind of destination.
Definition: juce_OutputStream.h:41
juce::File
Represents a local file or directory.
Definition: juce_File.h:44
juce::Identifier::isValid
bool isValid() const noexcept
Returns true if this Identifier is not null.
Definition: juce_Identifier.h:118
juce::MemoryOutputStream::toUTF8
String toUTF8() const
Returns a String created from the (UTF8) data that has been written to the stream.
Definition: juce_MemoryOutputStream.cpp:189
juce::JSON::parse
static Result parse(const String &text, var &parsedResult)
Parses a string of JSON-formatted text, and returns a result code containing any parse errors.
Definition: juce_JSON.cpp:507
juce::CharPointer_UTF8::findEndOfWhitespace
CharPointer_UTF8 findEndOfWhitespace() const noexcept
Returns the first non-whitespace character in the string.
Definition: juce_CharPointer_UTF8.h:488
juce::var
A variant class, that can be used to hold a range of primitive values.
Definition: juce_Variant.h:45
juce::OutputStream::writeRepeatedByte
virtual bool writeRepeatedByte(uint8 byte, size_t numTimesToRepeat)
Writes a byte to the output stream a given number of times.
Definition: juce_OutputStream.cpp:77
juce::JSON::toString
static String toString(const var &objectToFormat, bool allOnOneLine=false, int maximumDecimalPlaces=15)
Returns a string which contains a JSON-formatted representation of the var object.
Definition: juce_JSON.cpp:512
juce::CharacterFunctions::isDigit
static bool isDigit(char character) noexcept
Checks whether a character is a digit.
Definition: juce_CharacterFunctions.cpp:74
juce::var::getArray
Array< var > * getArray() const noexcept
If this variant holds an array, this provides access to it.
Definition: juce_Variant.cpp:507
juce::JSON::parseQuotedString
static Result parseQuotedString(String::CharPointerType &text, var &result)
Parses a quoted string-literal in JSON format, returning the un-escaped result in the result paramete...
Definition: juce_JSON.cpp:531
juce::InputStream::readEntireStreamAsString
virtual String readEntireStreamAsString()
Tries to read the whole stream and turn it into a string.
Definition: juce_InputStream.cpp:209
juce::Identifier
Represents a string identifier, designed for accessing properties by name.
Definition: juce_Identifier.h:42
juce::String::paddedLeft
String paddedLeft(juce_wchar padCharacter, int minimumLength) const
Returns a copy of this string with the specified character repeatedly added to its beginning until th...
Definition: juce_String.cpp:1167
juce::JSON::escapeString
static String escapeString(StringRef)
Returns a version of a string with any extended characters escaped.
Definition: juce_JSON.cpp:524
juce::MemoryOutputStream::toString
String toString() const
Attempts to detect the encoding of the data and convert it to a string.
Definition: juce_MemoryOutputStream.cpp:195
juce::CharPointer_UTF8
Wraps a pointer to a null-terminated UTF-8 character string, and provides various methods to operate ...
Definition: juce_CharPointer_UTF8.h:38
juce::UnitTest
This is a base class for classes that perform a unit test.
Definition: juce_UnitTest.h:73
juce::CharacterFunctions::isWhitespace
static bool isWhitespace(char character) noexcept
Checks whether a character is whitespace.
Definition: juce_CharacterFunctions.cpp:64
juce::CharPointer_UTF16::write
void write(juce_wchar charToWrite) noexcept
Writes a unicode character to this string, and advances this pointer to point to the next position.
Definition: juce_CharPointer_UTF16.h:185
juce::String
The JUCE String class!
Definition: juce_String.h:42
juce::JSON::writeToStream
static void writeToStream(OutputStream &output, const var &objectToFormat, bool allOnOneLine=false, int maximumDecimalPlaces=15)
Writes a JSON-formatted representation of the var object to the given stream.
Definition: juce_JSON.cpp:519
juce::Result::ok
static Result ok() noexcept
Creates and returns a 'successful' result.
Definition: juce_Result.h:65
juce::JSONFormatter
Definition: juce_JSON.cpp:326
juce::CharPointer_UTF8::getAndAdvance
juce_wchar getAndAdvance() noexcept
Returns the character that this pointer is currently pointing to, and then advances the pointer to po...
Definition: juce_CharPointer_UTF8.h:151
juce::JSON::fromString
static var fromString(StringRef)
Parses a string that was created with the toString() method.
Definition: juce_JSON.cpp:487
juce::Array::getReference
ElementType & getReference(int index) const noexcept
Returns a direct reference to one of the elements in the array, without checking the index passed in.
Definition: juce_Array.h:271
juce::MemoryOutputStream::appendUTF8Char
bool appendUTF8Char(juce_wchar character)
Appends the utf-8 bytes for a unicode character.
Definition: juce_MemoryOutputStream.cpp:132
juce::Result::fail
static Result fail(const String &errorMessage) noexcept
Creates a 'failure' result.
Definition: juce_Result.cpp:65
juce::Array::isEmpty
bool isEmpty() const noexcept
Returns true if the array is empty, false otherwise.
Definition: juce_Array.h:226