File indexing completed on 2025-01-18 10:10:38
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef ROOT7_RDirectory
0017 #define ROOT7_RDirectory
0018
0019 #include "ROOT/RDirectoryEntry.hxx"
0020 #include "ROOT/RLogger.hxx"
0021
0022 #include <iterator>
0023 #include <memory>
0024 #include <type_traits>
0025 #include <unordered_map>
0026 #include <string>
0027 #include <string_view>
0028
0029 namespace ROOT {
0030 namespace Experimental {
0031
0032
0033 RLogChannel &IOLog();
0034
0035
0036
0037
0038 class RDirectoryUnknownKey: public std::exception {
0039 std::string fKeyName;
0040
0041 public:
0042 RDirectoryUnknownKey(std::string_view keyName): fKeyName(keyName) {}
0043 const char *what() const noexcept final { return fKeyName.c_str(); }
0044 };
0045
0046
0047
0048
0049
0050 class RDirectoryTypeMismatch: public std::exception {
0051 std::string fKeyName;
0052
0053 public:
0054 RDirectoryTypeMismatch(std::string_view keyName): fKeyName(keyName) {}
0055 const char *what() const noexcept final { return fKeyName.c_str(); }
0056 };
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073 class RDirectory {
0074
0075
0076
0077
0078 using ContentMap_t = std::unordered_map<std::string, Internal::RDirectoryEntry>;
0079
0080
0081 ContentMap_t fContent;
0082
0083 template <class T>
0084 struct ToContentType {
0085 using decaytype = typename std::decay<T>::type;
0086 using type =
0087 typename std::enable_if<!std::is_pointer<decaytype>::value && !std::is_member_pointer<decaytype>::value &&
0088 !std::is_void<decaytype>::value,
0089 decaytype>::type;
0090 };
0091 template <class T>
0092 using ToContentType_t = typename ToContentType<T>::type;
0093
0094 public:
0095
0096
0097
0098
0099
0100 template <class T, class... ARGS>
0101 std::shared_ptr<ToContentType_t<T>> Create(std::string_view name, ARGS &&... args)
0102 {
0103 auto ptr = std::make_shared<ToContentType_t<T>>(std::forward<ARGS>(args)...);
0104 Add(name, ptr);
0105 return ptr;
0106 }
0107
0108
0109
0110 Internal::RDirectoryEntry Find(std::string_view name) const
0111 {
0112 auto idx = fContent.find(std::string(name));
0113 if (idx == fContent.end())
0114 return nullptr;
0115 return idx->second;
0116 }
0117
0118
0119
0120
0121 enum class EFindStatus {
0122 kValidValue,
0123 kValidValueBase,
0124 kKeyNameNotFound,
0125 kTypeMismatch
0126 };
0127
0128
0129
0130
0131
0132
0133
0134
0135 template <class T>
0136 std::pair<Internal::RDirectoryEntry, EFindStatus> Find(std::string_view name) const
0137 {
0138 auto idx = fContent.find(std::string(name));
0139 if (idx == fContent.end())
0140 return {nullptr, EFindStatus::kKeyNameNotFound};
0141 if (idx->second.GetTypeInfo() == typeid(ToContentType_t<T>))
0142 return {idx->second, EFindStatus::kValidValue};
0143 if (idx->second.CastPointer<ToContentType_t<T>>())
0144 return {idx->second, EFindStatus::kValidValueBase};
0145 return {nullptr, EFindStatus::kTypeMismatch};
0146 }
0147
0148
0149
0150
0151
0152
0153
0154
0155 template <class T>
0156 std::shared_ptr<ToContentType_t<T>> Get(std::string_view name)
0157 {
0158 const auto &pair = Find<T>(name);
0159 const Internal::RDirectoryEntry &entry = pair.first;
0160 EFindStatus status = pair.second;
0161 switch (status) {
0162 case EFindStatus::kValidValue: return std::static_pointer_cast<ToContentType_t<T>>(entry.GetPointer());
0163 case EFindStatus::kValidValueBase: return entry.CastPointer<ToContentType_t<T>>();
0164 case EFindStatus::kTypeMismatch:
0165
0166 throw RDirectoryTypeMismatch(name);
0167 case EFindStatus::kKeyNameNotFound: throw RDirectoryUnknownKey(name);
0168 }
0169 return nullptr;
0170 }
0171
0172
0173
0174 template <class T>
0175 void Add(std::string_view name, const std::shared_ptr<T> &ptr)
0176 {
0177 Internal::RDirectoryEntry entry(ptr);
0178
0179 std::string sName(name);
0180 auto idx = fContent.find(sName);
0181 if (idx != fContent.end()) {
0182 R__LOG_WARNING(IOLog()) << "Replacing object with name \"" << name << "\"" << std::endl;
0183 idx->second.swap(entry);
0184 } else {
0185 fContent[sName].swap(entry);
0186 }
0187 }
0188
0189
0190 bool Remove(std::string_view name)
0191 {
0192 std::string sName(name);
0193 auto idx = fContent.find(sName);
0194 if (idx != fContent.end()) {
0195 fContent.erase(idx);
0196 return true;
0197 }
0198 return false;
0199 }
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210 static RDirectory &Heap();
0211 };
0212
0213 }
0214 }
0215
0216 #endif