Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:52:42

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file corecel/io/Repr.hh
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  * Return a streamable object that prints out a C++-style.
0032  *
0033  * Example:
0034  * \code
0035   std::cout << repr(my_vec) << std::endl;
0036   \endcode
0037 
0038  * The 'name' argument defaults to null (just printing the value); if a string
0039  * is given a full variable declaration such as `std::string foo{"bar"}` will
0040  * be printed. If the name is empty, an anonymous value `std::string{"bar"}`
0041  * will be printed.
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  * Traits for writing an object for diagnostic or testing output.
0052  *
0053  * The "streamable" traits usually write so that the object can be injected
0054  * into test code.  The default tries to use whatever ostream operator is
0055  * available.
0056  * Other overrides are provided for collections, characters, and more?
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             // Print long literal strings or ones with many quotes on one line
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 //! Specialization for printing std::pairs
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 //! Specialization for OpaqueId
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 //! Specialization for Quantity
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 // CONTAINER TRAITS
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  * Get a string representation of a container of type T.
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             // Add a trailing ',' to long outputs to help clang-format
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 //! Print collection host data
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 //! Print placeholder for device data
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 }  // namespace celeritas