nx_server_plugin_sdk 1.0 Server Plugin SDK

plugin_tools.h
Go to the documentation of this file.
1 // Copyright 2018-present Network Optix, Inc. Licensed under MPL 2.0: www.mozilla.org/MPL/2.0/
2
3 #pragma once
4
9 // TODO: Remove this file when Storage and Camera SDKs are merged into Analytics SDK.
10
11 #if defined(_WIN32)
12 #define NOMINMAX //< Needed to prevent windows.h from defining macros min() and max().
13 #include <Windows.h>
14 #endif
15
16 #include <cerrno>
17 #include <cstdlib>
18 #include <cstring>
19 #include <iomanip>
20 #include <limits>
21 #include <sstream>
22 #include <type_traits>
23
24 #include "plugin_api.h"
25
26 namespace nxpt {
27
28 namespace atomic {
29
30 #ifdef _WIN32
31 typedef volatile LONG AtomicLong;
32 #elif __GNUC__
33 typedef volatile long AtomicLong;
34 #else
35 #error "Unsupported compiler is used."
36 #endif
37
39 static AtomicLong inc(AtomicLong* val)
40 {
41 #ifdef _WIN32
42 return InterlockedIncrement(val);
43 #elif __GNUC__
44 return __sync_add_and_fetch(val, 1);
45 #endif
46 }
47
49 static AtomicLong dec(AtomicLong* val)
50 {
51 #ifdef _WIN32
52 return InterlockedDecrement(val);
53 #elif __GNUC__
54 return __sync_sub_and_fetch(val, 1);
55 #endif
56 }
57
58 } // namespace atomic
59
67 class CommonRefManager
68 {
69 public:
70 CommonRefManager(const CommonRefManager&) = delete;
71 CommonRefManager& operator=(const CommonRefManager&) = delete;
72
77 CommonRefManager(nxpl::PluginInterface* objToWatch):
78 m_refCount(1),
79 m_objToWatch(objToWatch),
80 m_refCountingDelegate(nullptr)
81 {
82 }
83
88 CommonRefManager(CommonRefManager* refCountingDelegate):
89 m_refCount(0),
90 m_objToWatch(nullptr),
91 m_refCountingDelegate(refCountingDelegate)
92 {
93 }
94
96 int addRef() const
97 {
98 return m_refCountingDelegate
99 ? m_refCountingDelegate->addRef()
100 : atomic::inc(&m_refCount);
101 }
102
107 int releaseRef() const
108 {
109 if (m_refCountingDelegate)
110 return m_refCountingDelegate->releaseRef();
111
112 const int newRefCounter = atomic::dec(&m_refCount);
113 if (newRefCounter == 0)
114 delete m_objToWatch;
115 return newRefCounter;
116 }
117
118 int refCount() const
119 {
120 if (m_refCountingDelegate)
121 return m_refCountingDelegate->refCount();
122 return m_refCount;
123 }
124
125 private:
126 mutable atomic::AtomicLong m_refCount;
127 nxpl::PluginInterface* m_objToWatch;
128 CommonRefManager* m_refCountingDelegate;
129 };
130
131 template <typename T>
132 class CommonRefCounter: public T
133 {
134 public:
135 CommonRefCounter(const CommonRefCounter&) = delete;
136 CommonRefCounter& operator=(const CommonRefCounter&) = delete;
137 CommonRefCounter(CommonRefCounter&&) = delete;
138 CommonRefCounter& operator=(CommonRefCounter&&) = delete;
139 virtual ~CommonRefCounter() = default;
140
141 virtual int addRef() const override { return m_refManager.addRef(); }
142 virtual int releaseRef() const override { return m_refManager.releaseRef(); }
143
144 int refCount() const { return m_refManager.refCount(); }
145
146 protected:
147 CommonRefManager m_refManager;
148
149 CommonRefCounter(): m_refManager(static_cast<T*>(this)) {}
150 CommonRefCounter(CommonRefManager* refManager): m_refManager(refManager) {}
151 };
152
157 template<typename RefCountableInterface>
158 int refCount(const nxpl::PluginInterface* object)
159 {
160 if (object == nullptr)
161 return 0;
162
163 if (const auto commonRefCounter = dynamic_cast<CommonRefCounter<RefCountableInterface>*>(object))
164 return commonRefCounter->refCount();
165
166 (void) object->addRef();
167 return object->releaseRef();
168 }
169
170 enum NxGuidFormatOption
171 {
172 uppercase = 0x1,
173 hyphens = 0x2,
174 braces = 0x4,
175 applyAll = uppercase | hyphens | braces
176 };
177
178 class NxGuidHelper
179 {
180 public:
181 static nxpl::NX_GUID nullGuid()
182 {
183 return {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}};
184 }
185
186 static nxpl::NX_GUID fromRawData(const char* data)
187 {
188 nxpl::NX_GUID result;
189 memcpy(result.bytes, data, sizeof(result.bytes));
190 return result;
191 }
192
193 static nxpl::NX_GUID fromStdString(const std::string& guidStr)
194 {
195 static const auto kMinGuidStrSize = 32;
196 static const auto kGuidBytesNumber = 16;
197
198 if (guidStr.size() < kMinGuidStrSize)
199 return NxGuidHelper::nullGuid();
200
201 nxpl::NX_GUID guid;
202 int currentByteIndex = 0;
203 std::string currentByteString;
204 for (std::string::size_type i = 0; i < guidStr.size(); ++i)
205 {
206 if (guidStr[i] == '{' || guidStr[i] == '}' || guidStr[i] == '-'
207 || guidStr[i] == '\t' || guidStr[i] == '\n' || guidStr[i] == 'r'
208 || guidStr[i] == ' ')
209 {
210 continue;
211 }
212
213 if (currentByteIndex >= kGuidBytesNumber)
214 return NxGuidHelper::nullGuid();
215
216 currentByteString += guidStr[i];
217 if (currentByteString.size() == 2)
218 {
219 char* pEnd = nullptr;
220 errno = 0; //< Required before strtol().
221 const long v = std::strtol(currentByteString.c_str(), &pEnd, /*base*/ 16);
222 const bool hasError = v > std::numeric_limits<unsigned char>::max()
223 || v < std::numeric_limits<unsigned char>::min()
224 || errno != 0
225 || *pEnd != '\0';
226
227 if (hasError)
228 return NxGuidHelper::nullGuid();
229
230 guid.bytes[currentByteIndex] = (unsigned char) v;
231 ++currentByteIndex;
232 currentByteString.clear();
233 }
234 }
235
236 if (currentByteIndex != kGuidBytesNumber)
237 return NxGuidHelper::nullGuid();
238
239 return guid;
240 }
241 };
242
243 static std::string toStdString(
244 const nxpl::NX_GUID& guid,
245 unsigned int format = NxGuidFormatOption::applyAll)
246 {
247 std::stringstream ss;
248 ss << std::hex << std::setfill('0');
249
250 if (format & NxGuidFormatOption::braces)
251 ss << '{';
252
253 if (format & NxGuidFormatOption::uppercase)
254 ss << std::uppercase;
255
256 for (int i = 0; i < 4; ++i)
257 {
258 ss << std::setw(2);
259 ss << static_cast<unsigned int>(guid.bytes[i]);
260 }
261
262 if (format & NxGuidFormatOption::hyphens)
263 ss << '-';
264
265 for (int i = 0; i < 2; ++i)
266 {
267 ss << std::setw(2);
268 ss << static_cast<unsigned int>(guid.bytes[4 + i]);
269 }
270
271 if (format & NxGuidFormatOption::hyphens)
272 ss << "-";
273
274 for (int i = 0; i < 2; ++i)
275 {
276 ss << std::setw(2);
277 ss << static_cast<unsigned int>(guid.bytes[6 + i]);
278 }
279
280 if (format & NxGuidFormatOption::hyphens)
281 ss << "-";
282
283 for (int i = 0; i < 2; ++i)
284 {
285 ss << std::setw(2);
286 ss << static_cast<unsigned int>(guid.bytes[8 + i]);
287 }
288
289 if (format & NxGuidFormatOption::hyphens)
290 ss << "-";
291
292 for (int i = 0; i < 6; ++i)
293 {
294 ss << std::setw(2);
295 ss << static_cast<unsigned int>(guid.bytes[10 + i]);
296 }
297
298 if (format & NxGuidFormatOption::braces)
299 ss << '}';
300
301 return ss.str();
302 }
303
304 } // namespace nxpt
305
306 namespace nxpl {
307
308 inline bool operator==(const nxpl::NX_GUID& id1, const nxpl::NX_GUID& id2)
309 {
310 return memcmp(id1.bytes, id2.bytes, sizeof(id1.bytes)) == 0;
311 }
312
313 inline std::ostream& operator<<(std::ostream& os, const nxpl::NX_GUID& id)
314 {
315 return os << nxpt::toStdString(id);
316 }
317
318 } // namespace nxpl
319
320 namespace std {
321
322 template<>
323 struct hash<nxpl::NX_GUID>
324 {
325 std::size_t operator()(const nxpl::NX_GUID& guid) const
326 {
327 std::size_t h = 0;
328
329 for (size_t i = 0; i < sizeof(guid.bytes); ++i)
330 h = (h + (324'723'947ull + guid.bytes[i])) ^ 93'485'734'985ull;
331
332 return h;
333 }
334 };
335
336 } // namespace std
nxpl::PluginInterface::addRef
virtual int addRef() const =0
Increment reference counter.
nxpt::atomic::inc
static AtomicLong inc(AtomicLong *val)
Definition: plugin_tools.h:39
nxpl::NX_GUID::bytes
unsigned char bytes[16]
GUID bytes.
Definition: plugin_api.h:29
std
Definition: to_string.h:49
nxpl::PluginInterface
Base class for every interface, provided by plugin.
Definition: plugin_api.h:44
nxpt::atomic::dec
static AtomicLong dec(AtomicLong *val)
Definition: plugin_tools.h:49
nxpt::CommonRefManager::CommonRefManager
CommonRefManager(nxpl::PluginInterface *objToWatch)
Definition: plugin_tools.h:77
nxpl::NX_GUID
GUID of plugin interface.
Definition: plugin_api.h:26
nxpl
VMS dynamic plugin API (c++)
Definition: plugin_api.h:23
nxpt::NxGuidHelper
Definition: plugin_tools.h:178
nxpt::CommonRefCounter
Definition: plugin_tools.h:132
nxpt::CommonRefManager::CommonRefManager
CommonRefManager(CommonRefManager *refCountingDelegate)
Definition: plugin_tools.h:88
nxpt::refCount
int refCount(const nxpl::PluginInterface *object)
Definition: plugin_tools.h:158
nxpt::CommonRefManager
Definition: plugin_tools.h:67
nxpt::CommonRefManager::addRef
int addRef() const
Definition: plugin_tools.h:96
nxpt
Definition: plugin_tools.h:26
nxpt::CommonRefManager::releaseRef
int releaseRef() const
Definition: plugin_tools.h:107