rippled
STParsedJSON.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/basics/contract.h>
21 #include <ripple/basics/safe_cast.h>
22 #include <ripple/basics/StringUtilities.h>
23 #include <ripple/protocol/ErrorCodes.h>
24 #include <ripple/protocol/LedgerFormats.h>
25 #include <ripple/protocol/STAccount.h>
26 #include <ripple/protocol/STAmount.h>
27 #include <ripple/protocol/STArray.h>
28 #include <ripple/protocol/STBitString.h>
29 #include <ripple/protocol/STBlob.h>
30 #include <ripple/protocol/STVector256.h>
31 #include <ripple/protocol/STInteger.h>
32 #include <ripple/protocol/STParsedJSON.h>
33 #include <ripple/protocol/STPathSet.h>
34 #include <ripple/protocol/TER.h>
35 #include <ripple/protocol/TxFormats.h>
36 #include <ripple/protocol/UintTypes.h>
37 #include <ripple/protocol/impl/STVar.h>
38 #include <ripple/beast/core/LexicalCast.h>
39 #include <cassert>
40 #include <memory>
41 
42 namespace ripple {
43 
44 namespace STParsedJSONDetail
45 {
46 template <typename U, typename S>
47 constexpr
49 to_unsigned (S value)
50 {
51  if (value < 0 || std::numeric_limits<U>::max () < value)
52  Throw<std::runtime_error> ("Value out of range");
53  return static_cast<U> (value);
54 }
55 
56 template <typename U1, typename U2>
57 constexpr
59 to_unsigned (U2 value)
60 {
61  if (std::numeric_limits<U1>::max () < value)
62  Throw<std::runtime_error> ("Value out of range");
63  return static_cast<U1> (value);
64 }
65 
66 static std::string make_name (std::string const& object,
67  std::string const& field)
68 {
69  if (field.empty ())
70  return object;
71 
72  return object + "." + field;
73 }
74 
75 static Json::Value not_an_object (std::string const& object,
76  std::string const& field)
77 {
79  "Field '" + make_name (object, field) + "' is not a JSON object.");
80 }
81 
82 static Json::Value not_an_object (std::string const& object)
83 {
84  return not_an_object (object, "");
85 }
86 
87 static Json::Value not_an_array (std::string const& object)
88 {
90  "Field '" + object + "' is not a JSON array.");
91 }
92 
93 static Json::Value unknown_field (std::string const& object,
94  std::string const& field)
95 {
97  "Field '" + make_name (object, field) + "' is unknown.");
98 }
99 
100 static Json::Value out_of_range (std::string const& object,
101  std::string const& field)
102 {
104  "Field '" + make_name (object, field) + "' is out of range.");
105 }
106 
107 static Json::Value bad_type (std::string const& object,
108  std::string const& field)
109 {
111  "Field '" + make_name (object, field) + "' has bad type.");
112 }
113 
114 static Json::Value invalid_data (std::string const& object,
115  std::string const& field)
116 {
118  "Field '" + make_name (object, field) + "' has invalid data.");
119 }
120 
121 static Json::Value invalid_data (std::string const& object)
122 {
123  return invalid_data (object, "");
124 }
125 
126 static Json::Value array_expected (std::string const& object,
127  std::string const& field)
128 {
130  "Field '" + make_name (object, field) + "' must be a JSON array.");
131 }
132 
134  std::string const& field)
135 {
137  "Field '" + make_name (object, field) + "' must be a string.");
138 }
139 
140 static Json::Value too_deep (std::string const& object)
141 {
143  "Field '" + object + "' exceeds nesting depth limit.");
144 }
145 
147  unsigned int index)
148 {
150  "Field '" + object + "[" + std::to_string (index) +
151  "]' must be an object with a single key/object value.");
152 }
153 
154 static Json::Value template_mismatch (SField const& sField)
155 {
157  "Object '" + sField.getName () +
158  "' contents did not meet requirements for that type.");
159 }
160 
161 static Json::Value
163 {
165  "Item '" + item + "' at index " + std::to_string (index) +
166  " is not an object. Arrays may only contain objects.");
167 }
168 
169 // This function is used by parseObject to parse any JSON type that doesn't
170 // recurse. Everything represented here is a leaf-type.
171 static boost::optional<detail::STVar> parseLeaf (
172  std::string const& json_name,
173  std::string const& fieldName,
174  SField const* name,
175  Json::Value const& value,
176  Json::Value& error)
177 {
178  boost::optional <detail::STVar> ret;
179 
180  auto const& field = SField::getField (fieldName);
181 
182  if (field == sfInvalid)
183  {
184  error = unknown_field (json_name, fieldName);
185  return ret;
186  }
187 
188  switch (field.fieldType)
189  {
190  case STI_UINT8:
191  try
192  {
193  constexpr auto minValue = std::numeric_limits<std::uint8_t>::min();
194  constexpr auto maxValue = std::numeric_limits<std::uint8_t>::max();
195  if (value.isString ())
196  {
197  std::string const strValue = value.asString();
198 
199  if (!strValue.empty() &&
200  ((strValue[0] < '0') || (strValue[0] > '9')))
201  {
202  if (field == sfTransactionResult)
203  {
204  auto ter = transCode(strValue);
205 
206  if (!ter ||
207  TERtoInt (*ter) < minValue ||
208  TERtoInt (*ter) > maxValue)
209  {
210  error = out_of_range(json_name, fieldName);
211  return ret;
212  }
213 
214  ret = detail::make_stvar<STUInt8>(field,
215  static_cast<std::uint8_t>(TERtoInt (*ter)));
216  }
217  else
218  {
219  error = bad_type(json_name, fieldName);
220  return ret;
221  }
222  }
223  else
224  {
225  ret = detail::make_stvar <STUInt8>(field,
226  beast::lexicalCastThrow <std::uint8_t>(strValue));
227  }
228  }
229  else if (value.isInt ())
230  {
231  if (value.asInt () < minValue || value.asInt () > maxValue)
232  {
233  error = out_of_range (json_name, fieldName);
234  return ret;
235  }
236 
237  ret = detail::make_stvar <STUInt8> (field,
238  static_cast <std::uint8_t> (value.asInt ()));
239  }
240  else if (value.isUInt ())
241  {
242  if (value.asUInt () > maxValue)
243  {
244  error = out_of_range (json_name, fieldName);
245  return ret;
246  }
247 
248  ret = detail::make_stvar <STUInt8> (field,
249  static_cast <std::uint8_t> (value.asUInt ()));
250  }
251  else
252  {
253  error = bad_type (json_name, fieldName);
254  return ret;
255  }
256  }
257  catch (std::exception const&)
258  {
259  error = invalid_data (json_name, fieldName);
260  return ret;
261  }
262  break;
263 
264  case STI_UINT16:
265  try
266  {
267  if (value.isString ())
268  {
269  std::string const strValue = value.asString ();
270 
271  if (! strValue.empty () &&
272  ((strValue[0] < '0') || (strValue[0] > '9')))
273  {
274  if (field == sfTransactionType)
275  {
276  TxType const txType (TxFormats::getInstance().
277  findTypeByName (strValue));
278 
279  if (txType == ttINVALID)
280  Throw<std::runtime_error>(
281  "Invalid transaction format name");
282  ret = detail::make_stvar <STUInt16> (field,
283  static_cast <std::uint16_t> (txType));
284 
285  if (*name == sfGeneric)
286  name = &sfTransaction;
287  }
288  else if (field == sfLedgerEntryType)
289  {
290  LedgerEntryType const type (
292  findTypeByName (strValue));
293 
294  if (!(0u <= type &&
295  type <= std::min<unsigned>(
298  <LedgerEntryType>>::max())))
299  Throw<std::runtime_error>(
300  "Invalid ledger entry type: out of range");
301  ret = detail::make_stvar <STUInt16> (field,
302  static_cast <std::uint16_t> (type));
303 
304  if (*name == sfGeneric)
305  name = &sfLedgerEntry;
306  }
307  else
308  {
309  error = invalid_data (json_name, fieldName);
310  return ret;
311  }
312  }
313  else
314  {
315  ret = detail::make_stvar <STUInt16> (field,
316  beast::lexicalCastThrow <std::uint16_t> (strValue));
317  }
318  }
319  else if (value.isInt ())
320  {
321  ret = detail::make_stvar <STUInt16> (field,
322  to_unsigned <std::uint16_t> (value.asInt ()));
323  }
324  else if (value.isUInt ())
325  {
326  ret = detail::make_stvar <STUInt16> (field,
327  to_unsigned <std::uint16_t> (value.asUInt ()));
328  }
329  else
330  {
331  error = bad_type (json_name, fieldName);
332  return ret;
333  }
334  }
335  catch (std::exception const&)
336  {
337  error = invalid_data (json_name, fieldName);
338  return ret;
339  }
340 
341  break;
342 
343  case STI_UINT32:
344  try
345  {
346  if (value.isString ())
347  {
348  ret = detail::make_stvar <STUInt32> (field,
349  beast::lexicalCastThrow <std::uint32_t> (
350  value.asString ()));
351  }
352  else if (value.isInt ())
353  {
354  ret = detail::make_stvar <STUInt32> (field,
355  to_unsigned <std::uint32_t> (value.asInt ()));
356  }
357  else if (value.isUInt ())
358  {
359  ret = detail::make_stvar <STUInt32> (field,
360  safe_cast <std::uint32_t> (value.asUInt ()));
361  }
362  else
363  {
364  error = bad_type (json_name, fieldName);
365  return ret;
366  }
367  }
368  catch (std::exception const&)
369  {
370  error = invalid_data (json_name, fieldName);
371  return ret;
372  }
373 
374  break;
375 
376  case STI_UINT64:
377  try
378  {
379  if (value.isString ())
380  {
381  ret = detail::make_stvar <STUInt64> (field,
382  uintFromHex (value.asString ()));
383  }
384  else if (value.isInt ())
385  {
386  ret = detail::make_stvar <STUInt64> (field,
387  to_unsigned<std::uint64_t> (value.asInt ()));
388  }
389  else if (value.isUInt ())
390  {
391  ret = detail::make_stvar <STUInt64> (field,
392  safe_cast <std::uint64_t> (value.asUInt ()));
393  }
394  else
395  {
396  error = bad_type (json_name, fieldName);
397  return ret;
398  }
399  }
400  catch (std::exception const&)
401  {
402  error = invalid_data (json_name, fieldName);
403  return ret;
404  }
405 
406  break;
407 
408  case STI_HASH128:
409  try
410  {
411  if (value.isString ())
412  {
413  ret = detail::make_stvar <STHash128> (field, value.asString ());
414  }
415  else
416  {
417  error = bad_type (json_name, fieldName);
418  return ret;
419  }
420  }
421  catch (std::exception const&)
422  {
423  error = invalid_data (json_name, fieldName);
424  return ret;
425  }
426 
427  break;
428 
429  case STI_HASH160:
430  try
431  {
432  if (value.isString ())
433  {
434  ret = detail::make_stvar <STHash160> (field, value.asString ());
435  }
436  else
437  {
438  error = bad_type (json_name, fieldName);
439  return ret;
440  }
441  }
442  catch (std::exception const&)
443  {
444  error = invalid_data (json_name, fieldName);
445  return ret;
446  }
447 
448  break;
449 
450  case STI_HASH256:
451  try
452  {
453  if (value.isString ())
454  {
455  ret = detail::make_stvar <STHash256> (field, value.asString ());
456  }
457  else
458  {
459  error = bad_type (json_name, fieldName);
460  return ret;
461  }
462  }
463  catch (std::exception const&)
464  {
465  error = invalid_data (json_name, fieldName);
466  return ret;
467  }
468 
469  break;
470 
471  case STI_VL:
472  if (! value.isString ())
473  {
474  error = bad_type (json_name, fieldName);
475  return ret;
476  }
477 
478  try
479  {
480  if (auto vBlob = strUnHex(value.asString()))
481  {
482  ret = detail::make_stvar<STBlob>(
483  field, vBlob->data(), vBlob->size());
484  }
485  else
486  {
487  Throw<std::invalid_argument> ("invalid data");
488  }
489  }
490  catch (std::exception const&)
491  {
492  error = invalid_data (json_name, fieldName);
493  return ret;
494  }
495 
496  break;
497 
498  case STI_AMOUNT:
499  try
500  {
501  ret = detail::make_stvar <STAmount> (amountFromJson (field, value));
502  }
503  catch (std::exception const&)
504  {
505  error = invalid_data (json_name, fieldName);
506  return ret;
507  }
508 
509  break;
510 
511  case STI_VECTOR256:
512  if (! value.isArrayOrNull ())
513  {
514  error = array_expected (json_name, fieldName);
515  return ret;
516  }
517 
518  try
519  {
520  STVector256 tail (field);
521  for (Json::UInt i = 0; value.isValidIndex (i); ++i)
522  {
523  uint256 s;
524  s.SetHex (value[i].asString ());
525  tail.push_back (s);
526  }
527  ret = detail::make_stvar <STVector256> (std::move (tail));
528  }
529  catch (std::exception const&)
530  {
531  error = invalid_data (json_name, fieldName);
532  return ret;
533  }
534 
535  break;
536 
537  case STI_PATHSET:
538  if (!value.isArrayOrNull ())
539  {
540  error = array_expected (json_name, fieldName);
541  return ret;
542  }
543 
544  try
545  {
546  STPathSet tail (field);
547 
548  for (Json::UInt i = 0; value.isValidIndex (i); ++i)
549  {
550  STPath p;
551 
552  if (!value[i].isArrayOrNull ())
553  {
555  ss << fieldName << "[" << i << "]";
556  error = array_expected (json_name, ss.str ());
557  return ret;
558  }
559 
560  for (Json::UInt j = 0; value[i].isValidIndex (j); ++j)
561  {
563  ss << fieldName << "[" << i << "][" << j << "]";
564  std::string const element_name (
565  json_name + "." + ss.str());
566 
567  // each element in this path has some combination of
568  // account, currency, or issuer
569 
570  Json::Value pathEl = value[i][j];
571 
572  if (!pathEl.isObject())
573  {
574  error = not_an_object (element_name);
575  return ret;
576  }
577 
578  Json::Value const& account = pathEl["account"];
579  Json::Value const& currency = pathEl["currency"];
580  Json::Value const& issuer = pathEl["issuer"];
581  bool hasCurrency = false;
582  AccountID uAccount, uIssuer;
583  Currency uCurrency;
584 
585  if (account)
586  {
587  // human account id
588  if (! account.isString ())
589  {
590  error = string_expected (element_name, "account");
591  return ret;
592  }
593 
594  // If we have what looks like a 160-bit hex value, we
595  // set it, otherwise, we assume it's an AccountID
596  if (!uAccount.SetHexExact (account.asString ()))
597  {
598  auto const a = parseBase58<AccountID>(
599  account.asString());
600  if (! a)
601  {
602  error = invalid_data (element_name, "account");
603  return ret;
604  }
605  uAccount = *a;
606  }
607  }
608 
609  if (currency)
610  {
611  // human currency
612  if (!currency.isString ())
613  {
614  error = string_expected (element_name, "currency");
615  return ret;
616  }
617 
618  hasCurrency = true;
619 
620  if (!uCurrency.SetHexExact (currency.asString ()))
621  {
622  if (!to_currency (uCurrency, currency.asString ()))
623  {
624  error = invalid_data (element_name, "currency");
625  return ret;
626  }
627  }
628  }
629 
630  if (issuer)
631  {
632  // human account id
633  if (!issuer.isString ())
634  {
635  error = string_expected (element_name, "issuer");
636  return ret;
637  }
638 
639  if (!uIssuer.SetHexExact (issuer.asString ()))
640  {
641  auto const a = parseBase58<AccountID>(
642  issuer.asString());
643  if (! a)
644  {
645  error = invalid_data (element_name, "issuer");
646  return ret;
647  }
648  uIssuer = *a;
649  }
650  }
651 
652  p.emplace_back (uAccount, uCurrency, uIssuer, hasCurrency);
653  }
654 
655  tail.push_back (p);
656  }
657  ret = detail::make_stvar <STPathSet> (std::move (tail));
658  }
659  catch (std::exception const&)
660  {
661  error = invalid_data (json_name, fieldName);
662  return ret;
663  }
664 
665  break;
666 
667  case STI_ACCOUNT:
668  {
669  if (! value.isString ())
670  {
671  error = bad_type (json_name, fieldName);
672  return ret;
673  }
674 
675  std::string const strValue = value.asString ();
676 
677  try
678  {
679  // VFALCO This needs careful auditing
680  auto const account =
681  parseHexOrBase58<AccountID>(
682  strValue);
683  if (! account)
684  {
685  error = invalid_data (json_name, fieldName);
686  return ret;
687  }
688  ret = detail::make_stvar <STAccount>(
689  field, *account);
690  }
691  catch (std::exception const&)
692  {
693  error = invalid_data (json_name, fieldName);
694  return ret;
695  }
696  }
697  break;
698 
699  default:
700  error = bad_type (json_name, fieldName);
701  return ret;
702  }
703 
704  return ret;
705 }
706 
707 static const int maxDepth = 64;
708 
709 // Forward declaration since parseObject() and parseArray() call each other.
710 static boost::optional <detail::STVar> parseArray (
711  std::string const& json_name,
712  Json::Value const& json,
713  SField const& inName,
714  int depth,
715  Json::Value& error);
716 
717 
718 
719 static boost::optional <STObject> parseObject (
720  std::string const& json_name,
721  Json::Value const& json,
722  SField const& inName,
723  int depth,
724  Json::Value& error)
725 {
726  if (! json.isObjectOrNull ())
727  {
728  error = not_an_object (json_name);
729  return boost::none;
730  }
731 
732  if (depth > maxDepth)
733  {
734  error = too_deep (json_name);
735  return boost::none;
736  }
737 
738  try
739  {
740 
741  STObject data (inName);
742 
743  for (auto const& fieldName : json.getMemberNames ())
744  {
745  Json::Value const& value = json [fieldName];
746 
747  auto const& field = SField::getField (fieldName);
748 
749  if (field == sfInvalid)
750  {
751  error = unknown_field (json_name, fieldName);
752  return boost::none;
753  }
754 
755  switch (field.fieldType)
756  {
757 
758  // Object-style containers (which recurse).
759  case STI_OBJECT:
760  case STI_TRANSACTION:
761  case STI_LEDGERENTRY:
762  case STI_VALIDATION:
763  if (! value.isObject ())
764  {
765  error = not_an_object (json_name, fieldName);
766  return boost::none;
767  }
768 
769  try
770  {
771  auto ret = parseObject (json_name + "." + fieldName,
772  value, field, depth + 1, error);
773  if (! ret)
774  return boost::none;
775  data.emplace_back (std::move (*ret));
776  }
777  catch (std::exception const&)
778  {
779  error = invalid_data (json_name, fieldName);
780  return boost::none;
781  }
782 
783  break;
784 
785  // Array-style containers (which recurse).
786  case STI_ARRAY:
787  try
788  {
789  auto array = parseArray (json_name + "." + fieldName,
790  value, field, depth + 1, error);
791  if (array == boost::none)
792  return boost::none;
793  data.emplace_back (std::move (*array));
794  }
795  catch (std::exception const&)
796  {
797  error = invalid_data (json_name, fieldName);
798  return boost::none;
799  }
800 
801  break;
802 
803  // Everything else (types that don't recurse).
804  default:
805  {
806  auto leaf =
807  parseLeaf (json_name, fieldName, &inName, value, error);
808 
809  if (!leaf)
810  return boost::none;
811 
812  data.emplace_back (std::move (*leaf));
813  }
814 
815  break;
816  }
817  }
818 
819  // Some inner object types have templates. Attempt to apply that.
820  data.applyTemplateFromSField (inName); // May throw
821 
822  return data;
823  }
824  catch (STObject::FieldErr const&)
825  {
826  error = template_mismatch (inName);
827  }
828  catch (std::exception const&)
829  {
830  error = invalid_data (json_name);
831  }
832  return boost::none;
833 }
834 
835 static boost::optional <detail::STVar> parseArray (
836  std::string const& json_name,
837  Json::Value const& json,
838  SField const& inName,
839  int depth,
840  Json::Value& error)
841 {
842  if (! json.isArrayOrNull ())
843  {
844  error = not_an_array (json_name);
845  return boost::none;
846  }
847 
848  if (depth > maxDepth)
849  {
850  error = too_deep (json_name);
851  return boost::none;
852  }
853 
854  try
855  {
856  STArray tail (inName);
857 
858  for (Json::UInt i = 0; json.isValidIndex (i); ++i)
859  {
860  bool const isObjectOrNull (json[i].isObjectOrNull());
861  bool const singleKey (isObjectOrNull ? json[i].size() == 1 : true);
862 
863  if (!isObjectOrNull || !singleKey)
864  {
865  // null values are !singleKey
866  error = singleton_expected (json_name, i);
867  return boost::none;
868  }
869 
870  // TODO: There doesn't seem to be a nice way to get just the
871  // first/only key in an object without copying all keys into
872  // a vector
873  std::string const objectName (json[i].getMemberNames()[0]);;
874  auto const& nameField (SField::getField(objectName));
875 
876  if (nameField == sfInvalid)
877  {
878  error = unknown_field (json_name, objectName);
879  return boost::none;
880  }
881 
882  Json::Value const objectFields (json[i][objectName]);
883 
885  ss << json_name << "." <<
886  "[" << i << "]." << objectName;
887 
888  auto ret = parseObject (ss.str (), objectFields,
889  nameField, depth + 1, error);
890  if (! ret)
891  {
892  std::string errMsg = error["error_message"].asString ();
893  error["error_message"] = "Error at '" + ss.str () +
894  "'. " + errMsg;
895  return boost::none;
896  }
897 
898  if (ret->getFName().fieldType != STI_OBJECT)
899  {
900  error = non_object_in_array (ss.str(), i);
901  return boost::none;
902  }
903 
904  tail.push_back (std::move (*ret));
905  }
906 
907  return detail::make_stvar <STArray> (std::move (tail));
908  }
909  catch (std::exception const&)
910  {
911  error = invalid_data (json_name);
912  return boost::none;
913  }
914 }
915 
916 } // STParsedJSONDetail
917 
918 //------------------------------------------------------------------------------
919 
921  std::string const& name,
922  Json::Value const& json)
923 {
924  using namespace STParsedJSONDetail;
925  object = parseObject (name, json, sfGeneric, 0, error);
926 }
927 
928 //------------------------------------------------------------------------------
929 
931  std::string const& name,
932  Json::Value const& json)
933 {
934  using namespace STParsedJSONDetail;
935  auto arr = parseArray (name, json, sfGeneric, 0, error);
936  if (!arr)
937  array = boost::none;
938  else
939  {
940  auto p = dynamic_cast <STArray*> (&arr->get());
941  if (p == nullptr)
942  array = boost::none;
943  else
944  array = std::move (*p);
945  }
946 }
947 
948 
949 
950 } // ripple
Json::Value::isInt
bool isInt() const
Definition: json_value.cpp:1012
ripple::to_currency
bool to_currency(Currency &currency, std::string const &code)
Tries to convert a string to a Currency, returns true on success.
Definition: UintTypes.cpp:67
std::is_signed
ripple::STParsedJSONDetail::to_unsigned
constexpr std::enable_if_t< std::is_unsigned< U >::value &&std::is_signed< S >::value, U > to_unsigned(S value)
Definition: STParsedJSON.cpp:49
ripple::STParsedJSONDetail::maxDepth
static const int maxDepth
Definition: STParsedJSON.cpp:707
ripple::STParsedJSONDetail::singleton_expected
static Json::Value singleton_expected(std::string const &object, unsigned int index)
Definition: STParsedJSON.cpp:146
std::is_unsigned
Json::Value::isObject
bool isObject() const
Definition: json_value.cpp:1069
std::string
STL class.
ripple::ttINVALID
@ ttINVALID
Definition: TxFormats.h:35
ripple::rpcINVALID_PARAMS
@ rpcINVALID_PARAMS
Definition: ErrorCodes.h:85
Json::Value::isString
bool isString() const
Definition: json_value.cpp:1049
Json::Value::isValidIndex
bool isValidIndex(UInt index) const
Return true if index < size().
Definition: json_value.cpp:862
std::exception
STL class.
ripple::sfGeneric
const SField sfGeneric(access, 0)
Definition: SField.h:317
ripple::STParsedJSONDetail::template_mismatch
static Json::Value template_mismatch(SField const &sField)
Definition: STParsedJSON.cpp:154
ripple::sfLedgerEntryType
const SF_U16 sfLedgerEntryType(access, STI_UINT16, 1, "LedgerEntryType", SField::sMD_Never)
Definition: SField.h:330
ripple::uintFromHex
uint64_t uintFromHex(std::string const &strSrc)
Definition: StringUtilities.cpp:33
ripple::STParsedJSONDetail::bad_type
static Json::Value bad_type(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:107
Json::UInt
unsigned int UInt
Definition: json_forwards.h:28
ripple::STI_AMOUNT
@ STI_AMOUNT
Definition: SField.h:65
ripple::STI_UINT8
@ STI_UINT8
Definition: SField.h:73
ripple::STParsedJSONDetail::parseLeaf
static boost::optional< detail::STVar > parseLeaf(std::string const &json_name, std::string const &fieldName, SField const *name, Json::Value const &value, Json::Value &error)
Definition: STParsedJSON.cpp:171
ripple::STI_PATHSET
@ STI_PATHSET
Definition: SField.h:75
ripple::STVector256::push_back
void push_back(uint256 const &v)
Definition: STVector256.h:160
ripple::STI_VALIDATION
@ STI_VALIDATION
Definition: SField.h:82
ripple::STI_LEDGERENTRY
@ STI_LEDGERENTRY
Definition: SField.h:81
ripple::STParsedJSONDetail::non_object_in_array
static Json::Value non_object_in_array(std::string const &item, Json::UInt index)
Definition: STParsedJSON.cpp:162
std::stringstream
STL class.
ripple::STParsedJSONDetail::parseArray
static boost::optional< detail::STVar > parseArray(std::string const &json_name, Json::Value const &json, SField const &inName, int depth, Json::Value &error)
Definition: STParsedJSON.cpp:835
ripple::STArray::push_back
void push_back(STObject const &object)
Definition: STArray.h:95
ripple::STParsedJSONDetail::too_deep
static Json::Value too_deep(std::string const &object)
Definition: STParsedJSON.cpp:140
ripple::strUnHex
boost::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
Definition: StringUtilities.h:69
ripple::SField::getField
static const SField & getField(int fieldCode)
Definition: SField.cpp:269
ripple::STI_ACCOUNT
@ STI_ACCOUNT
Definition: SField.h:67
ripple::STI_ARRAY
@ STI_ARRAY
Definition: SField.h:70
ripple::TERtoInt
constexpr TERUnderlyingType TERtoInt(TELcodes v)
Definition: TER.h:289
ripple::STI_HASH160
@ STI_HASH160
Definition: SField.h:74
ripple::sfInvalid
const SField sfInvalid(access, -1)
Definition: SField.h:316
ripple::STPathSet
Definition: STPathSet.h:297
ripple::sfLedgerEntry
const SField sfLedgerEntry(access, STI_LEDGERENTRY, 257, "LedgerEntry")
Definition: SField.h:318
ripple::STParsedJSONObject::error
Json::Value error
On failure, an appropriate set of error values.
Definition: STParsedJSON.h:52
std::underlying_type_t
ripple::base_uint< 256 >
ripple::STObject::FieldErr
Definition: STObject.h:264
ripple::STParsedJSONDetail::out_of_range
static Json::Value out_of_range(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:100
ripple::TxFormats::getInstance
static TxFormats const & getInstance()
Definition: TxFormats.cpp:236
std::enable_if_t
Json::Value::isArrayOrNull
bool isArrayOrNull() const
Definition: json_value.cpp:1062
ripple::STArray
Definition: STArray.h:28
ripple::sfTransaction
const SField sfTransaction(access, STI_TRANSACTION, 257, "Transaction")
Definition: SField.h:319
std::to_string
T to_string(T... args)
ripple::STI_VL
@ STI_VL
Definition: SField.h:66
ripple::STI_UINT16
@ STI_UINT16
Definition: SField.h:60
ripple::STParsedJSONDetail::parseObject
static boost::optional< STObject > parseObject(std::string const &json_name, Json::Value const &json, SField const &inName, int depth, Json::Value &error)
Definition: STParsedJSON.cpp:719
ripple::sfTransactionType
const SF_U16 sfTransactionType(access, STI_UINT16, 2, "TransactionType")
Definition: SField.h:331
ripple::STI_HASH256
@ STI_HASH256
Definition: SField.h:64
ripple::base_uint::SetHex
bool SetHex(const char *psz, bool bStrict=false)
Parse a hex string into a base_uint The input can be:
Definition: base_uint.h:362
ripple::STPath::emplace_back
void emplace_back(Args &&... args)
Definition: STPathSet.h:233
ripple::amountFromJson
STAmount amountFromJson(SField const &name, Json::Value const &v)
Definition: STAmount.cpp:805
std::uint8_t
ripple::STI_VECTOR256
@ STI_VECTOR256
Definition: SField.h:76
ripple::base_uint::SetHexExact
bool SetHexExact(const char *psz)
Parse a hex string into a base_uint The string must contain exactly bytes * 2 hex characters and must...
Definition: base_uint.h:327
memory
ripple::LedgerFormats::getInstance
static LedgerFormats const & getInstance()
Definition: LedgerFormats.cpp:217
std::numeric_limits::min
T min(T... args)
ripple::TxType
TxType
Transaction type identifiers.
Definition: TxFormats.h:33
ripple::STI_UINT32
@ STI_UINT32
Definition: SField.h:61
ripple::STObject
Definition: STObject.h:51
ripple::STParsedJSONArray::STParsedJSONArray
STParsedJSONArray()=delete
Json::Value::getMemberNames
Members getMemberNames() const
Return a list of the member names.
Definition: json_value.cpp:979
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::SField
Identifies fields.
Definition: SField.h:112
ripple::LedgerEntryType
LedgerEntryType
Ledger entry types.
Definition: LedgerFormats.h:36
ripple::STI_UINT64
@ STI_UINT64
Definition: SField.h:62
ripple::transCode
boost::optional< TER > transCode(std::string const &token)
Definition: TER.cpp:200
ripple::SField::getName
std::string const & getName() const
Definition: SField.h:168
ripple::STParsedJSONDetail::not_an_object
static Json::Value not_an_object(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:75
ripple::STI_HASH128
@ STI_HASH128
Definition: SField.h:63
cassert
Json::Value::asUInt
UInt asUInt() const
Definition: json_value.cpp:555
Json::Value::isUInt
bool isUInt() const
Definition: json_value.cpp:1019
ripple::STParsedJSONDetail::make_name
static std::string make_name(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:66
ripple::sfTransactionResult
const SF_U8 sfTransactionResult(access, STI_UINT8, 3, "TransactionResult")
Definition: SField.h:326
ripple::STVector256
Definition: STVector256.h:29
ripple::STParsedJSONDetail::invalid_data
static Json::Value invalid_data(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:114
std::string::empty
T empty(T... args)
std::stringstream::str
T str(T... args)
Json::Value::asInt
Int asInt() const
Definition: json_value.cpp:516
ripple::STParsedJSONObject::STParsedJSONObject
STParsedJSONObject()=delete
ripple::STParsedJSONDetail::string_expected
static Json::Value string_expected(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:133
ripple::STI_OBJECT
@ STI_OBJECT
Definition: SField.h:69
std::numeric_limits::max
T max(T... args)
ripple::STPath
Definition: STPathSet.h:205
std::numeric_limits
Json::Value::isObjectOrNull
bool isObjectOrNull() const
Definition: json_value.cpp:1075
ripple::STParsedJSONDetail::array_expected
static Json::Value array_expected(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:126
ripple::RPC::make_error
Json::Value make_error(error_code_i code)
Returns a new json object that reflects the error code.
Definition: ErrorCodes.cpp:182
Json::Value
Represents a JSON value.
Definition: json_value.h:141
ripple::STParsedJSONDetail::not_an_array
static Json::Value not_an_array(std::string const &object)
Definition: STParsedJSON.cpp:87
ripple::STI_TRANSACTION
@ STI_TRANSACTION
Definition: SField.h:80
ripple::STParsedJSONDetail::unknown_field
static Json::Value unknown_field(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:93
Json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:482
ripple::STPathSet::push_back
void push_back(STPath const &e)
Definition: STPathSet.h:383