1#include "taichi/util/str.h"
2
3#include <sstream>
4
5#include "taichi/inc/constants.h"
6
7namespace taichi::lang {
8
9std::string c_quoted(std::string const &str) {
10 // https://zh.cppreference.com/w/cpp/language/escape
11 std::stringstream ss;
12 ss << '"';
13 for (auto const &c : str) {
14 switch (c) {
15#define REG_ESC(x, y) \
16 case x: \
17 ss << "\\" y; \
18 break;
19 REG_ESC('\n', "n");
20 REG_ESC('\a', "a");
21 REG_ESC('\b', "b");
22 REG_ESC('\v', "v");
23 REG_ESC('\t', "t");
24 REG_ESC('\f', "f");
25 REG_ESC('\'', "'");
26 REG_ESC('\"', "\"");
27 REG_ESC('\\', "\\");
28 default:
29 ss << c;
30 }
31 }
32#undef REG_ESC
33 ss << '"';
34 return ss.str();
35}
36
37std::string format_error_message(const std::string &error_message_template,
38 const std::function<uint64(int)> &fetcher) {
39 std::string error_message_formatted;
40 int argument_id = 0;
41 for (int i = 0; i < (int)error_message_template.size(); i++) {
42 if (error_message_template[i] != '%') {
43 error_message_formatted += error_message_template[i];
44 } else {
45 const auto dtype = error_message_template[i + 1];
46 const auto argument = fetcher(argument_id);
47 if (dtype == 'd') {
48 error_message_formatted += fmt::format(
49 "{}", taichi_union_cast_with_different_sizes<int32>(argument));
50 } else if (dtype == 'f') {
51 error_message_formatted += fmt::format(
52 "{}", taichi_union_cast_with_different_sizes<float32>(argument));
53 } else {
54 TI_ERROR("Data type identifier %{} is not supported", dtype);
55 }
56 argument_id += 1;
57 i++; // skip the dtype char
58 }
59 }
60 return error_message_formatted;
61}
62
63} // namespace taichi::lang
64