stub_analytics_plugin  1.6
Network Optix Video Analytics SDK
plugin_tools.h
Go to the documentation of this file.
1 #pragma once
2 
7 #if defined(_WIN32)
8  #include <Windows.h>
9  #undef min
10  #undef max
11 #endif
12 
13 #include <cstdlib>
14 #include <cstring>
15 #include <cerrno>
16 #include <sstream>
17 #include <iomanip>
18 #include <limits>
19 #include <type_traits>
20 
21 #include "plugin_api.h"
22 
23 // TODO: #mshevchenko: Split into GUID tools (e.g. nx::sdk::common::Guid) and ref-counting class
24 // (e.g. nx::sdk::common::Object), merging nx/mediaserver/sdk_support/utils.h with the latter.
25 namespace nxpt {
26 
37 template<class T>
38 class ScopedRef
39 {
40 public:
42  explicit ScopedRef(void* ptr): ScopedRef(static_cast<T*>(ptr), /*increaseRef*/ false) {}
43 
45  explicit ScopedRef(T* ptr = nullptr, bool increaseRef = true):
46  m_ptr(ptr)
47  {
48  // TODO: #dmishin get rid of this const mess when releaseRef becomes const
49  if (m_ptr && increaseRef)
50  const_cast<std::remove_const_t<T>*>(m_ptr)->addRef();
51  }
52 
53  ScopedRef(ScopedRef<T>&& right)
54  {
55  m_ptr = right.release();
56  }
57 
58  ScopedRef<T>& operator=(ScopedRef<T>&& right)
59  {
60  m_ptr = right.release();
61  return *this;
62  }
63 
64  ScopedRef(const ScopedRef<T>&) = delete;
65 
66  ScopedRef<T>& operator=(const ScopedRef<T>&) = delete;
67 
68  ~ScopedRef() { reset(); }
69 
70  operator bool() const { return m_ptr != nullptr; }
71 
73  T* get() { return m_ptr; }
74 
76  const T* get() const { return m_ptr; }
77 
78  T* operator->() { return m_ptr; }
79  const T* operator->() const { return m_ptr; }
80 
82  T* release()
83  {
84  T* ptrBak = m_ptr;
85  m_ptr = 0;
86  return ptrBak;
87  }
88 
93  void reset(T* ptr = nullptr)
94  {
95  if (m_ptr)
96  {
97  // TODO: #dmishin get rid of this const mess when releaseRef becomes const
98  const_cast<std::remove_const_t<T>*>(m_ptr)->releaseRef();
99  m_ptr = nullptr;
100  }
101 
102  take(ptr);
103  }
104 
105 private:
106  T* m_ptr;
107 
108  void take(T* ptr)
109  {
110  m_ptr = ptr;
111  if(m_ptr)
112  {
113  // TODO: #dmishin get rid of this const mess when releaseRef becomes const
114  const_cast<std::remove_const_t<T>*>(m_ptr)->addRef();
115  }
116  }
117 };
118 
119 namespace atomic {
120 
121 #ifdef _WIN32
122  typedef volatile LONG AtomicLong;
123 #elif __GNUC__
124  typedef volatile long AtomicLong;
125 #else
126  #error "Unsupported compiler is used."
127 #endif
128 
130 static AtomicLong inc(AtomicLong* val)
131 {
132  #ifdef _WIN32
133  return InterlockedIncrement(val);
134  #elif __GNUC__
135  return __sync_add_and_fetch(val, 1);
136  #endif
137 }
138 
140 static AtomicLong dec(AtomicLong* val)
141 {
142  #ifdef _WIN32
143  return InterlockedDecrement(val);
144  #elif __GNUC__
145  return __sync_sub_and_fetch(val, 1);
146  #endif
147 }
148 
149 } // namespace atomic
150 
159 {
160 public:
161  CommonRefManager(const CommonRefManager&) = delete;
162  CommonRefManager& operator=(const CommonRefManager&) = delete;
163 
169  m_refCount(1),
170  m_objToWatch(objToWatch),
171  m_refCountingDelegate(0)
172  {
173  }
174 
179  CommonRefManager(CommonRefManager* refCountingDelegate):
180  m_refCountingDelegate(refCountingDelegate)
181  {
182  }
183 
185  unsigned int addRef()
186  {
187  return m_refCountingDelegate
188  ? m_refCountingDelegate->addRef()
189  : atomic::inc(&m_refCount);
190  }
191 
196  unsigned int releaseRef()
197  {
198  if (m_refCountingDelegate)
199  return m_refCountingDelegate->releaseRef();
200 
201  unsigned int newRefCounter = atomic::dec(&m_refCount);
202  if (newRefCounter == 0)
203  delete m_objToWatch;
204  return newRefCounter;
205  }
206 
207  unsigned int refCount() const
208  {
209  if (m_refCountingDelegate)
210  return m_refCountingDelegate->refCount();
211  return m_refCount;
212  }
213 
214 private:
215  atomic::AtomicLong m_refCount;
216  nxpl::PluginInterface* m_objToWatch;
217  CommonRefManager* m_refCountingDelegate;
218 };
219 
220 template <typename T>
221 class CommonRefCounter: public T
222 {
223 public:
224  CommonRefCounter(const CommonRefCounter&) = delete;
225  CommonRefCounter& operator=(const CommonRefCounter&) = delete;
227  CommonRefCounter& operator=(CommonRefCounter&&) = delete;
228  virtual ~CommonRefCounter() = default;
229 
230  virtual unsigned int addRef() override { return m_refManager.addRef(); }
231  virtual unsigned int releaseRef() override { return m_refManager.releaseRef(); }
232 
233  unsigned int refCount() const { return m_refManager.refCount(); }
234 
235 protected:
236  CommonRefManager m_refManager;
237 
238  CommonRefCounter(): m_refManager(static_cast<T*>(this)) {}
239  CommonRefCounter(CommonRefManager* refManager): m_refManager(refManager) {}
240 };
241 
246 template<typename Interface>
247 unsigned int refCount(Interface* object)
248 {
249  if (const auto commonRefCounter = dynamic_cast<CommonRefCounter<Interface>*>(object))
250  return commonRefCounter->refCount();
251 
252  return 0;
253 }
254 
255 enum NxGuidFormatOption
256 {
257  uppercase = 0x1,
258  hyphens = 0x2,
259  braces = 0x4,
260  applyAll = uppercase | hyphens | braces
261 };
262 
264 {
265 public:
266  static nxpl::NX_GUID nullGuid()
267  {
268  return {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}};
269  }
270 
271  static nxpl::NX_GUID fromRawData(const char* data)
272  {
273  nxpl::NX_GUID result;
274  memcpy(result.bytes, data, sizeof(result.bytes));
275  return result;
276  }
277 
278  static nxpl::NX_GUID fromStdString(const std::string& guidStr)
279  {
280  static const auto kMinGuidStrSize = 32;
281  static const auto kGuidBytesNumber = 16;
282 
283  if (guidStr.size() < kMinGuidStrSize)
284  return NxGuidHelper::nullGuid();
285 
286  nxpl::NX_GUID guid;
287  int currentByteIndex = 0;
288  std::string currentByteString;
289  for (std::string::size_type i = 0; i < guidStr.size(); ++i)
290  {
291  if (guidStr[i] == '{' || guidStr[i] == '}' || guidStr[i] == '-'
292  || guidStr[i] == '\t' || guidStr[i] == '\n' || guidStr[i] == 'r'
293  || guidStr[i] == ' ')
294  {
295  continue;
296  }
297 
298  if (currentByteIndex >= kGuidBytesNumber)
299  return NxGuidHelper::nullGuid();
300 
301  currentByteString += guidStr[i];
302  if (currentByteString.size() == 2)
303  {
304  char* pEnd = nullptr;
305  errno = 0; //< Required before strtol().
306  const long v = std::strtol(currentByteString.c_str(), &pEnd, /*base*/ 16);
307  const bool hasError = v > std::numeric_limits<unsigned char>::max()
308  || v < std::numeric_limits<unsigned char>::min()
309  || errno != 0
310  || *pEnd != '\0';
311 
312  if (hasError)
313  return NxGuidHelper::nullGuid();
314 
315  guid.bytes[currentByteIndex] = (unsigned char) v;
316  ++currentByteIndex;
317  currentByteString.clear();
318  }
319  }
320 
321  if (currentByteIndex != kGuidBytesNumber)
322  return NxGuidHelper::nullGuid();
323 
324  return guid;
325  }
326 };
327 
328 static std::string toStdString(
329  const nxpl::NX_GUID& guid,
330  unsigned int format = NxGuidFormatOption::applyAll)
331 {
332  std::stringstream ss;
333  ss << std::hex << std::setfill('0');
334 
335  if (format & NxGuidFormatOption::braces)
336  ss << '{';
337 
338  if (format & NxGuidFormatOption::uppercase)
339  ss << std::uppercase;
340 
341  for (int i = 0; i < 4; ++i)
342  {
343  ss << std::setw(2);
344  ss << static_cast<unsigned int>(guid.bytes[i]);
345  }
346 
347  if (format & NxGuidFormatOption::hyphens)
348  ss << '-';
349 
350  for (int i = 0; i < 2; ++i)
351  {
352  ss << std::setw(2);
353  ss << static_cast<unsigned int>(guid.bytes[4 + i]);
354  }
355 
356  if (format & NxGuidFormatOption::hyphens)
357  ss << "-";
358 
359  for (int i = 0; i < 2; ++i)
360  {
361  ss << std::setw(2);
362  ss << static_cast<unsigned int>(guid.bytes[6 + i]);
363  }
364 
365  if (format & NxGuidFormatOption::hyphens)
366  ss << "-";
367 
368  for (int i = 0; i < 2; ++i)
369  {
370  ss << std::setw(2);
371  ss << static_cast<unsigned int>(guid.bytes[8 + i]);
372  }
373 
374  if (format & NxGuidFormatOption::hyphens)
375  ss << "-";
376 
377  for (int i = 0; i < 6; ++i)
378  {
379  ss << std::setw(2);
380  ss << static_cast<unsigned int>(guid.bytes[10 + i]);
381  }
382 
383  if (format & NxGuidFormatOption::braces)
384  ss << '}';
385 
386  return ss.str();
387 }
388 
389 } // namespace nxpt
390 
391 namespace nxpl {
392 
393 inline bool operator==(const nxpl::NX_GUID& id1, const nxpl::NX_GUID& id2)
394 {
395  return memcmp(id1.bytes, id2.bytes, sizeof(id1.bytes)) == 0;
396 }
397 
398 inline std::ostream& operator<<(std::ostream& os, const nxpl::NX_GUID& id)
399 {
400  return os << nxpt::toStdString(id);
401 }
402 
403 } // namespace nxpl
404 
405 namespace std {
406 
407 template<>
408 struct hash<nxpl::NX_GUID>
409 {
410  std::size_t operator()(const nxpl::NX_GUID& guid) const
411  {
412  std::size_t h;
413 
414  for (size_t i = 0; i < sizeof(guid.bytes); ++i)
415  h = (h + (324723947 + guid.bytes[i])) ^ 93485734985;
416 
417  return h;
418  }
419 };
420 
421 } // namespace std
static AtomicLong inc(AtomicLong *val)
Definition: plugin_tools.h:130
ScopedRef(T *ptr=nullptr, bool increaseRef=true)
Definition: plugin_tools.h:45
unsigned char bytes[16]
GUID bytes.
Definition: plugin_api.h:24
T * release()
Definition: plugin_tools.h:82
Definition: plugin_tools.h:405
Base class for every interface, provided by plugin.
Definition: plugin_api.h:38
static AtomicLong dec(AtomicLong *val)
Definition: plugin_tools.h:140
CommonRefManager(nxpl::PluginInterface *objToWatch)
Definition: plugin_tools.h:168
void reset(T *ptr=nullptr)
Definition: plugin_tools.h:93
GUID of plugin interface.
Definition: plugin_api.h:21
ScopedRef(void *ptr)
Definition: plugin_tools.h:42
unsigned int releaseRef()
Definition: plugin_tools.h:196
VMS dynamic plugin API (c++)
Definition: plugin_api.h:18
Definition: plugin_tools.h:263
Definition: plugin_tools.h:221
CommonRefManager(CommonRefManager *refCountingDelegate)
Definition: plugin_tools.h:179
Definition: plugin_tools.h:38
Definition: plugin_tools.h:158
Definition: plugin_tools.h:25
unsigned int addRef()
Definition: plugin_tools.h:185
unsigned int refCount(Interface *object)
Definition: plugin_tools.h:247