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