File indexing completed on 2025-09-16 08:52:42
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include <algorithm>
0010 #include <iomanip>
0011 #include <sstream>
0012 #include <string>
0013 #include <string_view>
0014 #include <utility>
0015 #include <vector>
0016
0017 #include "corecel/OpaqueId.hh"
0018 #include "corecel/cont/Array.hh"
0019 #include "corecel/cont/Span.hh"
0020 #include "corecel/data/Collection.hh"
0021 #include "corecel/math/Quantity.hh"
0022
0023 #include "Join.hh"
0024
0025 #include "detail/ReprImpl.hh"
0026
0027 namespace celeritas
0028 {
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 template<class T>
0044 detail::Repr<T> repr(T const& obj, char const* name = nullptr)
0045 {
0046 return {obj, name};
0047 }
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 template<class T>
0059 struct ReprTraits
0060 {
0061 static void print_type(std::ostream& os, char const* name = nullptr)
0062 {
0063 detail::print_simple_type(os, "UNKNOWN", name);
0064 }
0065 static void init(std::ostream&) {}
0066 static void print_value(std::ostream& os, T const& value) { os << value; }
0067 };
0068
0069 template<>
0070 struct ReprTraits<float>
0071 {
0072 static void print_type(std::ostream& os, char const* name = nullptr)
0073 {
0074 detail::print_simple_type(os, "float", name);
0075 }
0076 static void init(std::ostream& os) { os.precision(7); }
0077 static void print_value(std::ostream& os, float value)
0078 {
0079 os << value << 'f';
0080 }
0081 };
0082
0083 template<>
0084 struct ReprTraits<double>
0085 {
0086 static void print_type(std::ostream& os, char const* name = nullptr)
0087 {
0088 detail::print_simple_type(os, "double", name);
0089 }
0090 static void init(std::ostream& os) { os.precision(14); }
0091 static void print_value(std::ostream& os, double value) { os << value; }
0092 };
0093
0094 template<>
0095 struct ReprTraits<char>
0096 {
0097 static void print_type(std::ostream& os, char const* name = nullptr)
0098 {
0099 detail::print_simple_type(os, "char", name);
0100 }
0101 static void init(std::ostream&) {}
0102 static void print_value(std::ostream& os, char value)
0103 {
0104 os << '\'';
0105 detail::repr_char(os, value);
0106 os << '\'';
0107 }
0108 };
0109
0110 template<>
0111 struct ReprTraits<unsigned char>
0112 {
0113 static void print_type(std::ostream& os, char const* name = nullptr)
0114 {
0115 detail::print_simple_type(os, "unsigned char", name);
0116 }
0117 static void init(std::ostream& os) { os << std::setfill('0') << std::hex; }
0118 static void print_value(std::ostream& os, unsigned char value)
0119 {
0120 os << "'\\x" << detail::char_to_hex_string(value) << '\'';
0121 }
0122 };
0123
0124 template<>
0125 struct ReprTraits<bool>
0126 {
0127 static void print_type(std::ostream& os, char const* name = nullptr)
0128 {
0129 detail::print_simple_type(os, "bool", name);
0130 }
0131 static void init(std::ostream& os) { os << std::boolalpha; }
0132 static void print_value(std::ostream& os, bool value) { os << value; }
0133 };
0134
0135 template<>
0136 struct ReprTraits<int>
0137 {
0138 static void print_type(std::ostream& os, char const* name = nullptr)
0139 {
0140 detail::print_simple_type(os, "int", name);
0141 }
0142 static void init(std::ostream&) {}
0143 static void print_value(std::ostream& os, int value) { os << value; }
0144 };
0145
0146 template<>
0147 struct ReprTraits<unsigned int>
0148 {
0149 static void print_type(std::ostream& os, char const* name = nullptr)
0150 {
0151 detail::print_simple_type(os, "unsigned int", name);
0152 }
0153 static void init(std::ostream&) {}
0154 static void print_value(std::ostream& os, unsigned int value)
0155 {
0156 os << value << 'u';
0157 }
0158 };
0159
0160 template<>
0161 struct ReprTraits<long>
0162 {
0163 static void print_type(std::ostream& os, char const* name = nullptr)
0164 {
0165 detail::print_simple_type(os, "long", name);
0166 }
0167 static void init(std::ostream&) {}
0168 static void print_value(std::ostream& os, long value)
0169 {
0170 os << value << 'l';
0171 }
0172 };
0173
0174 template<>
0175 struct ReprTraits<unsigned long>
0176 {
0177 static void print_type(std::ostream& os, char const* name = nullptr)
0178 {
0179 detail::print_simple_type(os, "unsigned long", name);
0180 }
0181 static void init(std::ostream&) {}
0182 static void print_value(std::ostream& os, unsigned long value)
0183 {
0184 os << value << "ul";
0185 }
0186 };
0187
0188 template<>
0189 struct ReprTraits<long long>
0190 {
0191 static void print_type(std::ostream& os, char const* name = nullptr)
0192 {
0193 detail::print_simple_type(os, "long long", name);
0194 }
0195 static void init(std::ostream&) {}
0196 static void print_value(std::ostream& os, long long value)
0197 {
0198 os << value << "ll";
0199 }
0200 };
0201
0202 template<>
0203 struct ReprTraits<unsigned long long>
0204 {
0205 static void print_type(std::ostream& os, char const* name = nullptr)
0206 {
0207 detail::print_simple_type(os, "unsigned long long", name);
0208 }
0209 static void init(std::ostream&) {}
0210 static void print_value(std::ostream& os, unsigned long long value)
0211 {
0212 os << value << "ull";
0213 }
0214 };
0215
0216 template<>
0217 struct ReprTraits<std::string_view>
0218 {
0219 static void print_type(std::ostream& os, char const* name = nullptr)
0220 {
0221 detail::print_simple_type(os, "std::string_view", name);
0222 }
0223
0224 static void init(std::ostream&) {}
0225 static void print_value(std::ostream& os, std::string_view value)
0226 {
0227 using ssize = std::streamsize;
0228 ssize width = os.width();
0229 os.width(
0230 std::max(width - static_cast<ssize>(value.size()) - 2, ssize{0}));
0231
0232 if (detail::all_printable(value)
0233 && (value.size() > 70
0234 || std::count(value.begin(), value.end(), '"') > 2))
0235 {
0236
0237 os << "R\"(" << value << ")\"";
0238 return;
0239 }
0240
0241 os << '"';
0242 for (char c : value)
0243 {
0244 if (c == '\"')
0245 {
0246 os << '\\';
0247 }
0248 detail::repr_char(os, c);
0249 }
0250 os << '"';
0251 }
0252 };
0253
0254 template<>
0255 struct ReprTraits<std::string>
0256 {
0257 using value_type = std::string::value_type;
0258
0259 static void print_type(std::ostream& os, char const* name = nullptr)
0260 {
0261 detail::print_simple_type(os, "std::string", name);
0262 }
0263
0264 static void init(std::ostream&) {}
0265 static void print_value(std::ostream& os, std::string const& value)
0266 {
0267 ReprTraits<std::string_view>::print_value(os, value);
0268 }
0269 };
0270
0271 template<>
0272 struct ReprTraits<char*>
0273 {
0274 using value_type = char;
0275
0276 static void print_type(std::ostream& os, char const* name = nullptr)
0277 {
0278 detail::print_simple_type(os, "char const*", name);
0279 }
0280
0281 static void init(std::ostream&) {}
0282
0283 static void print_value(std::ostream& os, char const* value)
0284 {
0285 if (value)
0286 {
0287 ReprTraits<std::string_view>::print_value(os, value);
0288 }
0289 else
0290 {
0291 os << "nullptr";
0292 }
0293 }
0294 };
0295
0296 template<std::size_t N>
0297 struct ReprTraits<char[N]> : ReprTraits<char*>
0298 {
0299 };
0300
0301 template<>
0302 struct ReprTraits<char const*> : ReprTraits<char*>
0303 {
0304 };
0305
0306
0307 template<class T1, class T2>
0308 struct ReprTraits<std::pair<T1, T2>>
0309 {
0310 using RT1 = ReprTraits<T1>;
0311 using RT2 = ReprTraits<T2>;
0312
0313 static void print_type(std::ostream& os, char const* name = nullptr)
0314 {
0315 os << "std::pair<";
0316 RT1::print_type(os);
0317 os << ',';
0318 RT2::print_type(os);
0319 os << '>';
0320 if (name)
0321 {
0322 os << ' ' << name;
0323 }
0324 }
0325
0326 static void init(std::ostream& os)
0327 {
0328 RT1::init(os);
0329 RT2::init(os);
0330 }
0331
0332 static void print_value(std::ostream& os, std::pair<T1, T2> const& value)
0333 {
0334 os << '{';
0335 RT1::print_value(os, value.first);
0336 os << ',';
0337 RT2::print_value(os, value.second);
0338 os << '}';
0339 }
0340 };
0341
0342
0343 template<class V, class S>
0344 struct ReprTraits<OpaqueId<V, S>>
0345 {
0346 using RT = ReprTraits<S>;
0347
0348 static void print_type(std::ostream& os, char const* name = nullptr)
0349 {
0350 os << "OpaqueID<?>";
0351 if (name)
0352 {
0353 os << ' ' << name;
0354 }
0355 }
0356
0357 static void init(std::ostream& os) { RT::init(os); }
0358
0359 static void print_value(std::ostream& os, OpaqueId<V, S> const& value)
0360 {
0361 os << '{';
0362 if (value)
0363 {
0364 RT::print_value(os, value.unchecked_get());
0365 }
0366 os << '}';
0367 }
0368 };
0369
0370
0371 template<class U, class V>
0372 struct ReprTraits<Quantity<U, V>>
0373 {
0374 using RT = ReprTraits<V>;
0375
0376 static void print_type(std::ostream& os, char const* name = nullptr)
0377 {
0378 os << "Quantity<?,?>";
0379 if (name)
0380 {
0381 os << ' ' << name;
0382 }
0383 }
0384
0385 static void init(std::ostream& os) { RT::init(os); }
0386
0387 static void print_value(std::ostream& os, Quantity<U, V> const& q)
0388 {
0389 os << '{';
0390 RT::print_value(os, q.value());
0391 os << '}';
0392 }
0393 };
0394
0395
0396
0397
0398 template<class Container>
0399 struct ContTraits
0400 {
0401 using size_type = typename Container::size_type;
0402 using value_type = std::decay_t<typename Container::value_type>;
0403 };
0404
0405 template<class T, std::size_t N>
0406 struct ContTraits<T[N]>
0407 {
0408 using size_type = std::size_t;
0409 using value_type = std::decay_t<T>;
0410 };
0411
0412
0413
0414
0415 template<class Container>
0416 struct ContainerReprTraits
0417 {
0418 using value_type = typename ContTraits<Container>::value_type;
0419 using RT = ReprTraits<value_type>;
0420
0421 static void init(std::ostream& os) { RT::init(os); }
0422
0423 static void print_value(std::ostream& os, Container const& data)
0424 {
0425 os << '{'
0426 << join_stream(
0427 std::begin(data), std::end(data), ", ", RT::print_value);
0428 if (std::size(data) > 8)
0429 {
0430
0431 os << ',';
0432 }
0433 os << '}';
0434 }
0435 };
0436
0437 template<class T, class A>
0438 struct ReprTraits<std::vector<T, A>>
0439 : public ContainerReprTraits<std::vector<T, A>>
0440 {
0441 using value_type = std::decay_t<T>;
0442
0443 static void print_type(std::ostream& os, char const* name = nullptr)
0444 {
0445 detail::print_container_type<value_type>(os, "std::vector", name);
0446 }
0447 };
0448
0449 template<class T, size_type N>
0450 struct ReprTraits<Array<T, N>> : public ContainerReprTraits<Array<T, N>>
0451 {
0452 using value_type = std::decay_t<T>;
0453
0454 static void print_type(std::ostream& os, char const* name = nullptr)
0455 {
0456 os << "Array<";
0457 ReprTraits<value_type>::print_type(os);
0458 os << ',' << N << '>';
0459 if (name)
0460 {
0461 os << ' ' << name;
0462 }
0463 }
0464 };
0465
0466 template<class T, std::size_t N>
0467 struct ReprTraits<T[N]> : public ContainerReprTraits<T[N]>
0468 {
0469 using value_type = std::decay_t<T>;
0470
0471 static void print_type(std::ostream& os, char const* name = nullptr)
0472 {
0473 os << "Array<";
0474 ReprTraits<value_type>::print_type(os);
0475 os << ',' << N << '>';
0476 if (name)
0477 {
0478 os << ' ' << name;
0479 }
0480 }
0481 };
0482
0483 template<class T, std::size_t N>
0484 struct ReprTraits<Span<T, N>> : public ContainerReprTraits<Span<T, N>>
0485 {
0486 using value_type = std::decay_t<T>;
0487
0488 static void print_type(std::ostream& os, char const* name = nullptr)
0489 {
0490 detail::print_container_type<value_type>(os, "Span", name);
0491 }
0492 };
0493
0494
0495 template<class T, Ownership W, class I>
0496 struct ReprTraits<Collection<T, W, MemSpace::host, I>>
0497 {
0498 using ContainerT = Collection<T, W, MemSpace::host, I>;
0499 using value_type = typename ContainerT::value_type;
0500 using RT = ReprTraits<value_type>;
0501
0502 static void init(std::ostream& os) { RT::init(os); }
0503
0504 static void print_value(std::ostream& os, ContainerT const& data)
0505 {
0506 auto view = data[typename ContainerT::AllItemsT{}];
0507 os << '{'
0508 << join_stream(
0509 std::begin(view), std::end(view), ", ", RT::print_value)
0510 << '}';
0511 }
0512
0513 static void print_type(std::ostream& os, char const* name = nullptr)
0514 {
0515 detail::print_container_type<value_type>(os, "Collection", name);
0516 }
0517 };
0518
0519
0520 template<class T, Ownership W, class I>
0521 struct ReprTraits<Collection<T, W, MemSpace::device, I>>
0522 {
0523 using ContainerT = Collection<T, W, MemSpace::device, I>;
0524 using value_type = typename ContainerT::value_type;
0525
0526 static void init(std::ostream&) {}
0527
0528 static void print_value(std::ostream& os, ContainerT const& data)
0529 {
0530 auto view = data[typename ContainerT::AllItemsT{}];
0531 os << "<device collection, size=" << data.size() << '>';
0532 }
0533
0534 static void print_type(std::ostream& os, char const* name = nullptr)
0535 {
0536 detail::print_container_type<value_type>(os, "Collection", name);
0537 }
0538 };
0539
0540
0541 }