1 // [AsmJit]
2 // Machine Code Generation for C++.
3 //
4 // [License]
5 // Zlib - See LICENSE.md file in the package.
6 
7 #ifndef _ASMJIT_CORE_SMALLSTRING_H
8 #define _ASMJIT_CORE_SMALLSTRING_H
9 
10 #include "../core/globals.h"
11 #include "../core/zone.h"
12 
13 ASMJIT_BEGIN_NAMESPACE
14 
15 //! \addtogroup asmjit_zone
16 //! \{
17 
18 // ============================================================================
19 // [asmjit::ZoneStringBase]
20 // ============================================================================
21 
22 struct ZoneStringBase {
23   union {
24     struct {
25       uint32_t _size;
26       char _embedded[sizeof(void*) * 2 - 4];
27     };
28     struct {
29       void* _dummy;
30       char* _external;
31     };
32   };
33 
resetZoneStringBase34   inline void reset() noexcept {
35     _dummy = nullptr;
36     _external = nullptr;
37   }
38 
setDataZoneStringBase39   Error setData(Zone* zone, uint32_t maxEmbeddedSize, const char* str, size_t size) noexcept {
40     if (size == SIZE_MAX)
41       size = strlen(str);
42 
43     if (size <= maxEmbeddedSize) {
44       memcpy(_embedded, str, size);
45       _embedded[size] = '\0';
46     }
47     else {
48       char* external = static_cast<char*>(zone->dup(str, size, true));
49       if (ASMJIT_UNLIKELY(!external))
50         return DebugUtils::errored(kErrorOutOfMemory);
51       _external = external;
52     }
53 
54     _size = uint32_t(size);
55     return kErrorOk;
56   }
57 };
58 
59 // ============================================================================
60 // [asmjit::ZoneString<N>]
61 // ============================================================================
62 
63 //! Small string is a template that helps to create strings that can be either
64 //! statically allocated if they are small, or externally allocated in case
65 //! their size exceeds the limit. The `N` represents the size of the whole
66 //! `ZoneString` structure, based on that size the maximum size of the internal
67 //! buffer is determined.
68 template<size_t N>
69 class ZoneString {
70 public:
71   static constexpr uint32_t kWholeSize =
72     (N > sizeof(ZoneStringBase)) ? uint32_t(N) : uint32_t(sizeof(ZoneStringBase));
73   static constexpr uint32_t kMaxEmbeddedSize = kWholeSize - 5;
74 
75   union {
76     ZoneStringBase _base;
77     char _wholeData[kWholeSize];
78   };
79 
80   //! \name Construction & Destruction
81   //! \{
82 
ZoneString()83   inline ZoneString() noexcept { reset(); }
reset()84   inline void reset() noexcept { _base.reset(); }
85 
86   //! \}
87 
88   //! \name Accessors
89   //! \{
90 
data()91   inline const char* data() const noexcept { return _base._size <= kMaxEmbeddedSize ? _base._embedded : _base._external; }
empty()92   inline bool empty() const noexcept { return _base._size == 0; }
size()93   inline uint32_t size() const noexcept { return _base._size; }
94 
isEmbedded()95   inline bool isEmbedded() const noexcept { return _base._size <= kMaxEmbeddedSize; }
96 
setData(Zone * zone,const char * data,size_t size)97   inline Error setData(Zone* zone, const char* data, size_t size) noexcept {
98     return _base.setData(zone, kMaxEmbeddedSize, data, size);
99   }
100 
101   //! \}
102 };
103 
104 //! \}
105 
106 ASMJIT_END_NAMESPACE
107 
108 #endif // _ASMJIT_CORE_SMALLSTRING_H
109