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 
68 {
69 public:
70  CommonRefManager(const CommonRefManager&) = delete;
71  CommonRefManager& operator=(const CommonRefManager&) = delete;
72 
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;
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 
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
virtual int addRef() const =0
Increment reference counter.
static AtomicLong inc(AtomicLong *val)
Definition: plugin_tools.h:39
unsigned char bytes[16]
GUID bytes.
Definition: plugin_api.h:29
Definition: to_string.h:49
Base class for every interface, provided by plugin.
Definition: plugin_api.h:44
static AtomicLong dec(AtomicLong *val)
Definition: plugin_tools.h:49
CommonRefManager(nxpl::PluginInterface *objToWatch)
Definition: plugin_tools.h:77
GUID of plugin interface.
Definition: plugin_api.h:26
VMS dynamic plugin API (c++)
Definition: plugin_api.h:23
Definition: plugin_tools.h:178
Definition: plugin_tools.h:132
CommonRefManager(CommonRefManager *refCountingDelegate)
Definition: plugin_tools.h:88
int refCount(const nxpl::PluginInterface *object)
Definition: plugin_tools.h:158
Definition: plugin_tools.h:67
int addRef() const
Definition: plugin_tools.h:96
Definition: plugin_tools.h:26
int releaseRef() const
Definition: plugin_tools.h:107