UCommon
typeref.h
Go to the documentation of this file.
1 // Copyright (C) 2015 Cherokees of Idaho.
2 //
3 // This file is part of GNU uCommon C++.
4 //
5 // GNU uCommon C++ is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published
7 // by the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // GNU uCommon C++ is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
17 
28 #ifndef _UCOMMON_TYPEREF_H_
29 #define _UCOMMON_TYPEREF_H_
30 
31 #ifndef _UCOMMON_CPR_H_
32 #include <ucommon/cpr.h>
33 #endif
34 
35 #ifndef _UCOMMON_ATOMIC_H_
36 #include <ucommon/atomic.h>
37 #endif
38 
39 #ifndef _UCOMMON_PROTOCOLS_H_
40 #include <ucommon/protocols.h>
41 #endif
42 
43 #ifndef _UCOMMON_GENERICS_H_
44 #include <ucommon/generics.h>
45 #endif
46 
47 #ifndef _UCOMMON_OBJECT_H_
48 #include <ucommon/object.h>
49 #endif
50 
51 #ifndef _UCOMMON_THREAD_H_
52 #include <ucommon/thread.h>
53 #endif
54 
55 namespace ucommon {
56 
57 class TypeRelease;
58 class typeref_guard;
59 
68 class __EXPORT TypeRef
69 {
70 protected:
71  friend class ArrayRef;
72  friend class SharedRef;
73  friend class MapRef;
74  friend class TypeRelease;
75 
76  class Release;
77 
78 public:
86  class __EXPORT Counted : public __PROTOCOL ObjectProtocol
87  {
88  private:
89  __DELETE_COPY(Counted);
90 
91  protected:
92  friend class TypeRef;
93  friend class TypeRelease;
94 
95  union {
96  TypeRelease *autorelease;
97  Counted *linkrelease;
98  };
99 
100  mutable Atomic::counter count;
101  unsigned offset;
102  size_t size;
103 
112  explicit Counted(void *address, size_t size, TypeRelease *ar = NULL);
113 
119  virtual void dealloc(void);
120 
121  public:
126  inline bool is() const {
127  return (count.get() > 0);
128  }
129 
134  inline unsigned copies() const {
135  return ((unsigned)count.get());
136  }
137 
138  inline TypeRelease *getRelease() const {
139  return autorelease;
140  }
141 
148  void operator delete(void *address);
149 
154  void retain();
155 
160  void release();
161  };
162 
163 protected:
164  Counted *ref; // heap reference...
165 
170  TypeRef(Counted *object);
171 
177  TypeRef(const TypeRef& pointer);
178 
182  TypeRef();
183 
189  void set(Counted *object);
190 
194  void assign(const typeref_guard& ref);
195 
201  static caddr_t mem(caddr_t address);
202 
203 public:
208  virtual ~TypeRef();
209 
215  void set(const TypeRef& pointer);
216 
220  void clear(void);
221 
226  size_t size(void) const;
227 
232  unsigned copies() const;
233 
238  inline operator bool() const {
239  return ref != NULL;
240  }
241 
246  inline bool operator!() const {
247  return ref == NULL;
248  }
249 
259  inline static void put(TypeRef& target, Counted *object) {
260  target.set(object);
261  }
262 
263  bool is_released(void);
264 };
265 
266 class __EXPORT TypeRelease
267 {
268 public:
269  inline TypeRelease() {
270  delegate = nullptr;
271  }
272 
273  inline TypeRelease(TypeRelease *target) {
274  delegate = target;
275  }
276 
277  virtual unsigned purge();
278 
279  virtual caddr_t allocate(size_t size);
280 
281 protected:
282  friend class TypeRef::Counted;
283 
284  TypeRelease *delegate;
285 
286  void enlist(TypeRef::Counted **root, TypeRef::Counted *obj);
287 
288  TypeRef::Counted *delist(TypeRef::Counted **root);
289 
290  virtual void release(TypeRef::Counted *obj);
291 
292  void dealloc(TypeRef::Counted *obj);
293 
294  inline size_t size(TypeRef::Counted *obj) {
295  return obj->size;
296  }
297 };
298 
299 extern __EXPORT TypeRelease auto_release;
300 extern __EXPORT TypeRelease secure_release;
301 extern __EXPORT TypeRelease release_later;
302 
303 class __EXPORT typeref_guard : protected TypeRef
304 {
305 private:
306  friend class TypeRef;
307 
308  mutable Mutex sync;
309 
310 public:
311  inline typeref_guard() : TypeRef() {}
312 
313  inline typeref_guard(const typeref_guard& copy) : TypeRef(copy) {}
314 
315  inline typeref_guard(const TypeRef& pointer) : TypeRef(pointer) {}
316 
317  void set(const TypeRef& pointer);
318 
319  inline typeref_guard& operator=(const TypeRef& pointer) {
320  set(pointer);
321  return *this;
322  }
323 };
324 
325 template<typename T, TypeRelease& R = auto_release>
326 class typeref : public TypeRef
327 {
328 private:
329  class value : public Counted
330  {
331  private:
332  __DELETE_COPY(value);
333 
334  public:
335  T data;
336 
337  inline value(caddr_t mem, const T& object, TypeRelease *ar = &R) :
338  Counted(mem, sizeof(value), ar) {
339  data = object;
340  }
341  };
342 
343 public:
344  inline typeref() : TypeRef() {}
345 
346  inline typeref(const typeref_guard& global) : TypeRef() {
347  TypeRef::assign(global);
348  }
349 
350  inline typeref(const typeref& copy) : TypeRef(copy) {}
351 
352  inline typeref(const T& object, TypeRelease *ar = &R) : TypeRef() {
353  caddr_t p = R.allocate(sizeof(value));
354  TypeRef::set(new(mem(p)) value(p, object, ar));
355  }
356 
357  inline explicit typeref(Counted *object) : TypeRef(object) {}
358 
359  inline const T* operator->() const {
360  if(!ref)
361  return NULL;
362  value *v = polystatic_cast<value *>(ref);
363  return &(v->data);
364  }
365 
366  inline const T& operator*() const {
367  value *v = polystatic_cast<value*>(ref);
368  __THROW_DEREF(v);
369  return *(&(v->data));
370  }
371 
372  inline const T* operator()() const {
373  value *v = polystatic_cast<value*>(ref);
374  if(!v)
375  return nullptr;
376 
377  return &(v->data);
378  }
379 
380  inline operator const T&() const {
381  value *v = polystatic_cast<value*>(ref);
382  __THROW_DEREF(v);
383  return *(&(v->data));
384  }
385 
386  inline typeref& operator=(const typeref_guard& ptr) {
387  TypeRef::assign(ptr);
388  return *this;
389  }
390 
391  inline typeref& operator=(const typeref& ptr) {
392  TypeRef::set(ptr);
393  return *this;
394  }
395 
396  inline bool operator==(const typeref& ptr) const {
397  value *v1 = polystatic_cast<value*>(ref);
398  value *v2 = polystatic_cast<value*>(ptr.ref);
399  if(!v1 || !v2)
400  return false;
401  return v1->data == v2->data;
402  }
403 
404  inline bool operator==(const T& obj) const {
405  value *v = polystatic_cast<value *>(ref);
406  if(!v)
407  return false;
408  return v->data == obj;
409  }
410 
411  inline bool operator!=(const typeref& ptr) const {
412  return !(*this == ptr);
413  }
414 
415  inline bool operator!=(const T& obj) const {
416  return !(*this == obj);
417  }
418 
419  inline void set(T& object, TypeRelease *pool = &R) {
420  clear();
421  caddr_t p = R.allocate(sizeof(value));
422  TypeRef::set(new(mem(p)) value(p, object, pool));
423  }
424 
425  inline typeref& operator=(T& object) {
426  set(object);
427  return *this;
428  }
429 };
430 
431 // The specializations are done as simple template specializations so that the
432 // hard parts can be hard-coded rather than inline members. This means we do
433 // not pass the autorelease as a specialization here, but we can do a secondary
434 // template that does use releases with a lot less overhead.
435 
436 template<>
437 class __EXPORT typeref<const char *> : public TypeRef
438 {
439 public:
440  class value : public Counted
441  {
442  private:
443  __DELETE_COPY(value);
444 
445  protected:
446  friend class typeref;
447 
448  char mem[1];
449 
450  value(caddr_t addr, size_t size, const char *str, TypeRelease *ar = &auto_release);
451 
452  void destroy(void);
453 
454  public:
455  inline char *get() {
456  return &mem[0];
457  }
458 
459  inline size_t len() {
460  return strlen(mem);
461  }
462 
463  inline size_t max() {
464  return size;
465  }
466 
467  inline operator char *() {
468  return &mem[0];
469  }
470  };
471 
472  typeref();
473 
474  typeref(const typeref& copy);
475 
476  typeref(const char *str, TypeRelease *ar = &auto_release);
477 
478  typeref(size_t size, TypeRelease *ar = &auto_release);
479 
480  inline typeref(const typeref_guard& global) : TypeRef() {
481  TypeRef::assign(global);
482  }
483 
484  inline explicit typeref(Counted *object) : TypeRef(object) {}
485 
486  inline explicit typeref(value *value) : TypeRef(value) {}
487 
488  const char *operator*() const;
489 
490  inline operator const char *() const {
491  return operator*();
492  }
493 
494  size_t len() const;
495 
496  bool operator==(const typeref& ptr) const;
497 
498  bool operator==(const char *obj) const;
499 
500  bool operator==(value *chars) const;
501 
502  inline bool operator!=(const typeref& ptr) const {
503  return !(*this == ptr);
504  }
505 
506  inline bool operator!=(value *chars) const {
507  return !(*this == chars);
508  }
509 
510  inline bool operator!=(const char *obj) const {
511  return !(*this == obj);
512  }
513 
514  bool operator<(const typeref& ptr) const;
515 
516  inline bool operator>(const typeref& ptr) const {
517  return (ptr < *this);
518  }
519 
520  inline bool operator<=(const typeref& ptr) const {
521  return !(*this > ptr);
522  }
523 
524  inline bool operator>=(const typeref& ptr) const {
525  return !(*this < ptr);
526  }
527 
528  typeref& operator=(const typeref& objref);
529 
530  typeref& operator=(const char *str);
531 
532  typeref& operator=(value *chars);
533 
534  const typeref operator+(const char *str) const;
535 
536  const typeref operator+(const typeref& ptr) const;
537 
538  const char *operator()(ssize_t offset) const;
539 
540  void set(const char *str, TypeRelease *ar = &auto_release);
541 
542  void hex(const uint8_t *mem, size_t size, TypeRelease *ar = &auto_release);
543 
544  void b64(const uint8_t *mem, size_t size, TypeRelease *ar = &auto_release);
545 
546  void assign(value *chars);
547 
548  static void expand(value **handle, size_t size);
549 
550  static value *create(size_t size, TypeRelease *ar = &auto_release);
551 
552  static void destroy(value *bytes);
553 };
554 
555 template<>
556 class __EXPORT typeref<const uint8_t *> : public TypeRef
557 {
558 public:
559  class value : public Counted
560  {
561  private:
562  __DELETE_COPY(value);
563 
564  protected:
565  friend class typeref;
566 
567  uint8_t mem[1];
568 
569  value(caddr_t addr, size_t size, const uint8_t *data = nullptr, TypeRelease *ar = &auto_release);
570 
571  void destroy(void);
572 
573  public:
574  inline size_t max() {
575  return size;
576  }
577 
578  inline uint8_t *get() {
579  return &mem[0];
580  }
581 
582  inline operator uint8_t*() {
583  return &mem[0];
584  }
585  };
586 
587  typeref();
588 
589  typeref(const typeref& copy);
590 
591  typeref(uint8_t *str, size_t size, TypeRelease *ar = &auto_release);
592 
593  typeref(size_t size, TypeRelease *ar = &auto_release);
594 
595  typeref(bool mode, size_t bits, TypeRelease *ar = &auto_release);
596 
597  inline typeref(const typeref_guard& global) : TypeRef() {
598  TypeRef::assign(global);
599  }
600 
601  inline explicit typeref(Counted *object) : TypeRef(object) {}
602 
603  const uint8_t *operator*() const;
604 
605  inline operator const uint8_t *() const {
606  return operator*();
607  }
608 
609  typeref& operator=(const typeref& objref);
610 
611  typeref& operator=(value *bytes);
612 
613  bool operator==(const typeref& ptr) const;
614 
615  bool operator==(value *bytes) const;
616 
617  inline bool operator!=(const typeref& ptr) const {
618  return !(*this == ptr);
619  }
620 
621  inline bool operator!=(value *bytes) const {
622  return !(*this == bytes);
623  }
624 
625  const typeref operator+(const typeref& ptr) const;
626 
627  void set(const uint8_t *str, size_t size, TypeRelease *ar = &auto_release);
628 
629  size_t set(bool bit, size_t offset, size_t bits = 1);
630 
631  size_t hex(const char *str, bool ws = false, TypeRelease *ar = &auto_release);
632 
633  size_t b64(const char *str, bool ws = false, TypeRelease *ar = &auto_release);
634 
635  uint8_t *data(void);
636 
637  bool get(size_t offset);
638 
639  size_t count(size_t offset, size_t bits = 1);
640 
641  void assign(value *bytes);
642 
643  typeref<const char *> hex();
644 
645  typeref<const char *> b64();
646 
647  static value *create(size_t size, TypeRelease *ar = &auto_release);
648 
649  static void destroy(value *bytes);
650 };
651 
652 // convenience classes that roll up autorelease behavior for strings and
653 // byte arrays into templates.
654 
655 template<TypeRelease& R>
656 class stringref : public typeref<const char *>
657 {
658 public:
659  inline stringref() : typeref<const char *>() {}
660 
661  inline stringref(const stringref& copy) : typeref<const char *>(copy) {}
662 
663  inline stringref(const char *str) : typeref<const char *>(str, &R) {}
664 
665  inline stringref(size_t size) : typeref<const char *>(size, &R) {}
666 
667  inline explicit stringref(Counted *object) : typeref<const char *>(object) {}
668 
669  inline void set(const char *str) {
670  typeref<const char *>::set(str, &R);
671  }
672 
673  inline static value *create(size_t size) {
674  return typeref<const char *>::create(size, &R);
675  }
676 
677  inline static stringref promote(typeref<const char *>& str) {
678  stringref result = *str;
679  return result;
680  }
681 };
682 
683 template<TypeRelease& R>
684 class byteref : public typeref<const uint8_t *>
685 {
686 public:
687  inline byteref() : typeref<const uint8_t *>() {}
688 
689  inline byteref(uint8_t *str, size_t size) : typeref<const uint8_t *>(str, size, &R) {}
690 
691  inline byteref(size_t size) : typeref<const uint8_t *>(size, &R) {}
692 
693  inline byteref(bool mode, size_t bits) : typeref<const uint8_t *>(mode, bits, &R) {}
694 
695  inline explicit byteref(Counted *object) : typeref<const uint8_t *>(object) {}
696 
697  inline void set(const uint8_t *str, size_t size) {
698  typeref<const uint8_t *>::set(str, size, &R);
699  }
700 
701  inline size_t hex(const char *str, bool ws = false) {
702  return typeref<const uint8_t *>::hex(str, ws, &R);
703  }
704 
705  inline size_t b64(const char *str, bool ws = false) {
706  return typeref<const uint8_t *>::b64(str, ws, &R);
707  }
708 
709  inline stringref<R> hex() {
710  typeref<const char *> str = typeref<const uint8_t *>::hex();
711  stringref<R> result = *str;
712  return result;
713  }
714 
715  inline stringref<R> b64() {
716  typeref<const char *> str = typeref<const uint8_t *>::b64();
717  stringref<R> result = *str;
718  return result;
719  }
720 
721  inline static value *create(size_t size) {
722  return typeref<const uint8_t *>::create(size, &R);
723  }
724 
725  inline static byteref promote(typeref<const uint8_t *>& str) {
726  byteref result = *str;
727  return result;
728  }
729 };
730 
731 // a namespace for aliasing things we may typically use as a typeref
732 
733 namespace Type {
734  typedef int32_t Integer;
735  typedef double Real;
736  typedef const char *Chars;
737  typedef const uint8_t *Bytes;
738  typedef const uint8_t *Bools;
739 }
740 
741 typedef typeref<Type::Chars>::value *charvalues_t;
742 typedef typeref<Type::Bytes>::value *bytevalues_t;
743 typedef typeref<Type::Chars> stringref_t;
744 typedef typeref<Type::Bytes> byteref_t;
745 typedef typeref<Type::Bools> boolref_t;
746 
747 template<typename T>
748 inline typeref<T> typeref_cast(T x) {
749  return typeref<T>(x);
750 }
751 
752 } // namespace
753 
754 #endif
A common base class for all managed objects.
Definition: protocols.h:173
T &() max(T &o1, T &o2)
Convenience function to return max of two objects.
Definition: generics.h:445
static void put(TypeRef &target, Counted *object)
Special weak-public means to copy a container reference.
Definition: typeref.h:259
Create a linked list of auto-releasable objects.
Definition: memory.h:741
bool is() const
Is this object not empty?
Definition: typeref.h:126
void set(Counted *object)
Set our smart pointer to a specific heap container.
void assign(const typeref_guard &ref)
Assign from a guarded typeref.
Atomic counter class.
Definition: atomic.h:60
Heap base-class container for typeref objects.
Definition: typeref.h:86
A common object base class with auto-pointer support.
const struct sockaddr * addr(Socket::address &address)
A convenience function to convert a socket address list into a socket address.
Definition: socket.h:2089
Atomic pointers and locks.
Thread classes and sychronization objects.
void clear(void)
Manually release the current container.
TypeRef(Counted *object)
Create a smart pointer referencing an existing heap object.
Common namespace for all ucommon objects.
Definition: access.h:47
bool operator!() const
Check if we are currently not pointing to anything.
Definition: typeref.h:246
T copy(const T &src)
Convenience function to copy objects.
Definition: generics.h:395
Abstract interfaces and support.
unsigned copies() const
Number of retains (smart pointers) referencing us.
Definition: typeref.h:134
Generic templates for C++.
Runtime functions.
Smart pointer base class for auto-retained objects.
Definition: typeref.h:68
static caddr_t mem(caddr_t address)
Adjust memory pointer to atomic boundry.