! * \brief Return a JSON-escaped version of the string (RFC 8259). * * Uses ``\\uXXXX`` for control characters, escapes ``\\/``, ``\\b``, ``\\f`` per the JSON spec. * Non-ASCII bytes are passed through as-is (valid UTF-8 is preserved). * * \param value The input string * \return The escaped string, quoted with double quotes */
| 834 | * \return The escaped string, quoted with double quotes |
| 835 | */ |
| 836 | inline String EscapeStringJSON(const String& value) { |
| 837 | std::ostringstream oss; |
| 838 | oss << '"'; |
| 839 | const char* data = value.data(); |
| 840 | const size_t size = value.size(); |
| 841 | for (size_t i = 0; i < size; ++i) { |
| 842 | switch (data[i]) { |
| 843 | /// \cond Doxygen_Suppress |
| 844 | #define TVM_FFI_ESCAPE_CHAR(pattern, val) \ |
| 845 | case pattern: \ |
| 846 | oss << (val); \ |
| 847 | break |
| 848 | TVM_FFI_ESCAPE_CHAR('\"', "\\\""); |
| 849 | TVM_FFI_ESCAPE_CHAR('\\', "\\\\"); |
| 850 | TVM_FFI_ESCAPE_CHAR('/', "\\/"); |
| 851 | TVM_FFI_ESCAPE_CHAR('\b', "\\b"); |
| 852 | TVM_FFI_ESCAPE_CHAR('\f', "\\f"); |
| 853 | TVM_FFI_ESCAPE_CHAR('\n', "\\n"); |
| 854 | TVM_FFI_ESCAPE_CHAR('\r', "\\r"); |
| 855 | TVM_FFI_ESCAPE_CHAR('\t', "\\t"); |
| 856 | #undef TVM_FFI_ESCAPE_CHAR |
| 857 | /// \endcond |
| 858 | default: { |
| 859 | uint8_t u8_val = static_cast<uint8_t>(data[i]); |
| 860 | // this is a control character, print as \uXXXX |
| 861 | if (u8_val < 0x20 || u8_val == 0x7f) { |
| 862 | char buffer[8]; |
| 863 | int size = TVM_FFI_SNPRINTF(buffer, sizeof(buffer), "\\u%04x", |
| 864 | static_cast<int32_t>(data[i]) & 0xff); |
| 865 | oss.write(buffer, size); |
| 866 | } else { |
| 867 | oss << data[i]; |
| 868 | } |
| 869 | break; |
| 870 | } |
| 871 | } |
| 872 | } |
| 873 | oss << '"'; |
| 874 | return String(oss.str()); |
| 875 | } |
| 876 | |
| 877 | /*! |
| 878 | * \brief Escape a string for JSON output. |