string_concat.hpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // __ _____ _____ _____
  2. // __| | __| | | | JSON for Modern C++
  3. // | | |__ | | | | | | version 3.11.3
  4. // |_____|_____|_____|_|___| https://github.com/nlohmann/json
  5. //
  6. // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  7. // SPDX-License-Identifier: MIT
  8. #pragma once
  9. #include <cstring> // strlen
  10. #include <string> // string
  11. #include <utility> // forward
  12. #include <nlohmann/detail/meta/cpp_future.hpp>
  13. #include <nlohmann/detail/meta/detected.hpp>
  14. NLOHMANN_JSON_NAMESPACE_BEGIN
  15. namespace detail
  16. {
  17. inline std::size_t concat_length()
  18. {
  19. return 0;
  20. }
  21. template<typename... Args>
  22. inline std::size_t concat_length(const char* cstr, const Args& ... rest);
  23. template<typename StringType, typename... Args>
  24. inline std::size_t concat_length(const StringType& str, const Args& ... rest);
  25. template<typename... Args>
  26. inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
  27. {
  28. return 1 + concat_length(rest...);
  29. }
  30. template<typename... Args>
  31. inline std::size_t concat_length(const char* cstr, const Args& ... rest)
  32. {
  33. // cppcheck-suppress ignoredReturnValue
  34. return ::strlen(cstr) + concat_length(rest...);
  35. }
  36. template<typename StringType, typename... Args>
  37. inline std::size_t concat_length(const StringType& str, const Args& ... rest)
  38. {
  39. return str.size() + concat_length(rest...);
  40. }
  41. template<typename OutStringType>
  42. inline void concat_into(OutStringType& /*out*/)
  43. {}
  44. template<typename StringType, typename Arg>
  45. using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
  46. template<typename StringType, typename Arg>
  47. using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
  48. template<typename StringType, typename Arg>
  49. using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
  50. template<typename StringType, typename Arg>
  51. using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
  52. template<typename StringType, typename Arg>
  53. using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
  54. template<typename StringType, typename Arg>
  55. using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>;
  56. template<typename StringType, typename Arg>
  57. using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
  58. template<typename StringType, typename Arg>
  59. using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
  60. template < typename OutStringType, typename Arg, typename... Args,
  61. enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
  62. && detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 >
  63. inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
  64. template < typename OutStringType, typename Arg, typename... Args,
  65. enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
  66. && !detect_string_can_append_op<OutStringType, Arg>::value
  67. && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 >
  68. inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
  69. template < typename OutStringType, typename Arg, typename... Args,
  70. enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
  71. && !detect_string_can_append_op<OutStringType, Arg>::value
  72. && !detect_string_can_append_iter<OutStringType, Arg>::value
  73. && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 >
  74. inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
  75. template<typename OutStringType, typename Arg, typename... Args,
  76. enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
  77. inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
  78. {
  79. out.append(std::forward<Arg>(arg));
  80. concat_into(out, std::forward<Args>(rest)...);
  81. }
  82. template < typename OutStringType, typename Arg, typename... Args,
  83. enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
  84. && detect_string_can_append_op<OutStringType, Arg>::value, int > >
  85. inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
  86. {
  87. out += std::forward<Arg>(arg);
  88. concat_into(out, std::forward<Args>(rest)...);
  89. }
  90. template < typename OutStringType, typename Arg, typename... Args,
  91. enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
  92. && !detect_string_can_append_op<OutStringType, Arg>::value
  93. && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
  94. inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
  95. {
  96. out.append(arg.begin(), arg.end());
  97. concat_into(out, std::forward<Args>(rest)...);
  98. }
  99. template < typename OutStringType, typename Arg, typename... Args,
  100. enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
  101. && !detect_string_can_append_op<OutStringType, Arg>::value
  102. && !detect_string_can_append_iter<OutStringType, Arg>::value
  103. && detect_string_can_append_data<OutStringType, Arg>::value, int > >
  104. inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
  105. {
  106. out.append(arg.data(), arg.size());
  107. concat_into(out, std::forward<Args>(rest)...);
  108. }
  109. template<typename OutStringType = std::string, typename... Args>
  110. inline OutStringType concat(Args && ... args)
  111. {
  112. OutStringType str;
  113. str.reserve(concat_length(args...));
  114. concat_into(str, std::forward<Args>(args)...);
  115. return str;
  116. }
  117. } // namespace detail
  118. NLOHMANN_JSON_NAMESPACE_END