LCOV - code coverage report
Current view: top level - asmjit - moved_string.h (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 11 36 30.6 %
Date: 2026-11-05 10:19:06 Functions: 0 16 0.0 %

          Line data    Source code
       1             : #ifdef __PLUMED_HAS_ASMJIT
       2             : // This file is part of AsmJit project <https://asmjit.com>
       3             : //
       4             : // See asmjit.h or LICENSE.md for license and copyright information
       5             : // SPDX-License-Identifier: Zlib
       6             : 
       7             : #ifndef ASMJIT_CORE_STRING_H_INCLUDED
       8             : #define ASMJIT_CORE_STRING_H_INCLUDED
       9             : 
      10             : #include "support.h"
      11             : #include "zone.h"
      12             : 
      13             : ASMJIT_BEGIN_NAMESPACE
      14             : 
      15             : //! \addtogroup asmjit_utilities
      16             : //! \{
      17             : 
      18             : //! Format flags used by \ref String API.
      19             : enum class StringFormatFlags : uint32_t {
      20             :   //! No flags.
      21             :   kNone = 0x00000000u,
      22             :   //! Show sign.
      23             :   kShowSign = 0x00000001u,
      24             :   //! Show space.
      25             :   kShowSpace = 0x00000002u,
      26             :   //! Alternate form (use 0x when formatting HEX number).
      27             :   kAlternate = 0x00000004u,
      28             :   //! The input is signed.
      29             :   kSigned = 0x80000000u
      30             : };
      31           0 : ASMJIT_DEFINE_ENUM_FLAGS(StringFormatFlags)
      32             : 
      33             : //! Fixed string - only useful for strings that would never exceed `N - 1` characters; always null-terminated.
      34             : template<size_t N>
      35             : union FixedString {
      36             :   //! \name Constants
      37             :   //! \{
      38             : 
      39             :   // This cannot be constexpr as GCC 4.8 refuses constexpr members of unions.
      40             :   enum : uint32_t {
      41             :     kNumUInt32Words = uint32_t((N + sizeof(uint32_t) - 1) / sizeof(uint32_t))
      42             :   };
      43             : 
      44             :   //! \}
      45             : 
      46             :   //! \name Members
      47             :   //! \{
      48             : 
      49             :   char str[kNumUInt32Words * sizeof(uint32_t)];
      50             :   uint32_t u32[kNumUInt32Words];
      51             : 
      52             :   //! \}
      53             : 
      54             :   //! \name Utilities
      55             :   //! \{
      56             : 
      57             :   inline bool eq(const char* other) const noexcept {
      58         355 :     return strcmp(str, other) == 0;
      59             :   }
      60             : 
      61             :   //! \}
      62             : };
      63             : 
      64             : //! A simple non-reference counted string that uses small string optimization (SSO).
      65             : //!
      66             : //! This string has 3 allocation possibilities:
      67             : //!
      68             : //!   1. Small    - embedded buffer is used for up to `kSSOCapacity` characters. This should handle most small
      69             : //!                 strings and thus avoid dynamic memory allocation for most use-cases.
      70             : //!
      71             : //!   2. Large    - string that doesn't fit into an embedded buffer (or string that was truncated from a larger
      72             : //!                 buffer) and is owned by AsmJit. When you destroy the string AsmJit would automatically
      73             : //!                 release the large buffer.
      74             : //!
      75             : //!   3. External - like Large (2), however, the large buffer is not owned by AsmJit and won't be released when
      76             : //!                 the string is destroyed or reallocated. This is mostly useful for working with larger temporary
      77             : //!                 strings allocated on stack or with immutable strings.
      78             : class String {
      79             : public:
      80             :   ASMJIT_NONCOPYABLE(String)
      81             : 
      82             :   //! String operation.
      83             :   enum class ModifyOp : uint32_t {
      84             :     //! Assignment - a new content replaces the current one.
      85             :     kAssign = 0,
      86             :     //! Append - a new content is appended to the string.
      87             :     kAppend = 1
      88             :   };
      89             : 
      90             :   //! \cond INTERNAL
      91             :   enum : uint32_t {
      92             :     kLayoutSize = 32,
      93             :     kSSOCapacity = kLayoutSize - 2
      94             :   };
      95             : 
      96             :   //! String type.
      97             :   enum Type : uint8_t {
      98             :     //! Large string (owned by String).
      99             :     kTypeLarge = 0x1Fu,
     100             :     //! External string (zone allocated or not owned by String).
     101             :     kTypeExternal = 0x20u
     102             :   };
     103             : 
     104             :   union Raw {
     105             :     uint8_t u8[kLayoutSize];
     106             :     uint64_t u64[kLayoutSize / sizeof(uint64_t)];
     107             :     uintptr_t uptr[kLayoutSize / sizeof(uintptr_t)];
     108             :   };
     109             : 
     110             :   struct Small {
     111             :     uint8_t type;
     112             :     char data[kSSOCapacity + 1u];
     113             :   };
     114             : 
     115             :   struct Large {
     116             :     uint8_t type;
     117             :     uint8_t reserved[sizeof(uintptr_t) - 1];
     118             :     size_t size;
     119             :     size_t capacity;
     120             :     char* data;
     121             :   };
     122             : 
     123             :   union {
     124             :     uint8_t _type;
     125             :     Raw _raw;
     126             :     Small _small;
     127             :     Large _large;
     128             :   };
     129             :   //! \endcond
     130             : 
     131             :   //! \name Construction & Destruction
     132             :   //! \{
     133             : 
     134             :   //! Creates a default-initialized string if zero length.
     135             :   inline String() noexcept
     136      137460 :     : _small {} {}
     137             : 
     138             :   //! Creates a string that takes ownership of the content of the `other` string.
     139             :   inline String(String&& other) noexcept {
     140             :     _raw = other._raw;
     141             :     other._resetInternal();
     142             :   }
     143             : 
     144             :   inline ~String() noexcept {
     145      109968 :     reset();
     146           0 :   }
     147             : 
     148             :   //! Reset the string into a construction state.
     149             :   ASMJIT_API Error reset() noexcept;
     150             : 
     151             :   //! \}
     152             : 
     153             :   //! \name Overloaded Operators
     154             :   //! \{
     155             : 
     156             :   inline String& operator=(String&& other) noexcept {
     157             :     swap(other);
     158             :     other.reset();
     159             :     return *this;
     160             :   }
     161             : 
     162             :   inline bool operator==(const char* other) const noexcept { return  eq(other); }
     163             :   inline bool operator!=(const char* other) const noexcept { return !eq(other); }
     164             : 
     165             :   inline bool operator==(const String& other) const noexcept { return  eq(other); }
     166             :   inline bool operator!=(const String& other) const noexcept { return !eq(other); }
     167             : 
     168             :   //! \}
     169             : 
     170             :   //! \name Accessors
     171             :   //! \{
     172             : 
     173             :   inline bool isExternal() const noexcept { return _type == kTypeExternal; }
     174           0 :   inline bool isLargeOrExternal() const noexcept { return _type >= kTypeLarge; }
     175             : 
     176             :   //! Tests whether the string is empty.
     177             :   inline bool empty() const noexcept { return size() == 0; }
     178             :   //! Returns the size of the string.
     179           0 :   inline size_t size() const noexcept { return isLargeOrExternal() ? size_t(_large.size) : size_t(_type); }
     180             :   //! Returns the capacity of the string.
     181           0 :   inline size_t capacity() const noexcept { return isLargeOrExternal() ? _large.capacity : size_t(kSSOCapacity); }
     182             : 
     183             :   //! Returns the data of the string.
     184           0 :   inline char* data() noexcept { return isLargeOrExternal() ? _large.data : _small.data; }
     185             :   //! \overload
     186           0 :   inline const char* data() const noexcept { return isLargeOrExternal() ? _large.data : _small.data; }
     187             : 
     188             :   inline char* start() noexcept { return data(); }
     189             :   inline const char* start() const noexcept { return data(); }
     190             : 
     191             :   inline char* end() noexcept { return data() + size(); }
     192             :   inline const char* end() const noexcept { return data() + size(); }
     193             : 
     194             :   //! \}
     195             : 
     196             :   //! \name String Operations
     197             :   //! \{
     198             : 
     199             :   //! Swaps the content of this string with `other`.
     200             :   inline void swap(String& other) noexcept {
     201             :     std::swap(_raw, other._raw);
     202             :   }
     203             : 
     204             :   //! Clears the content of the string.
     205             :   ASMJIT_API Error clear() noexcept;
     206             : 
     207             :   ASMJIT_API char* prepare(ModifyOp op, size_t size) noexcept;
     208             : 
     209             :   ASMJIT_API Error _opString(ModifyOp op, const char* str, size_t size = SIZE_MAX) noexcept;
     210             :   ASMJIT_API Error _opChar(ModifyOp op, char c) noexcept;
     211             :   ASMJIT_API Error _opChars(ModifyOp op, char c, size_t n) noexcept;
     212             :   ASMJIT_API Error _opNumber(ModifyOp op, uint64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept;
     213             :   ASMJIT_API Error _opHex(ModifyOp op, const void* data, size_t size, char separator = '\0') noexcept;
     214             :   ASMJIT_API Error _opFormat(ModifyOp op, const char* fmt, ...) noexcept;
     215             :   ASMJIT_API Error _opVFormat(ModifyOp op, const char* fmt, va_list ap) noexcept;
     216             : 
     217             :   //! Replaces the current of the string with `data` of the given `size`.
     218             :   //!
     219             :   //! Null terminated strings can set `size` to `SIZE_MAX`.
     220             :   ASMJIT_API Error assign(const char* data, size_t size = SIZE_MAX) noexcept;
     221             : 
     222             :   //! Replaces the current of the string with `other` string.
     223             :   inline Error assign(const String& other) noexcept {
     224             :     return assign(other.data(), other.size());
     225             :   }
     226             : 
     227             :   //! Replaces the current of the string by a single `c` character.
     228             :   inline Error assign(char c) noexcept {
     229             :     return _opChar(ModifyOp::kAssign, c);
     230             :   }
     231             : 
     232             :   //! Replaces the current of the string by a `c` character, repeated `n` times.
     233             :   inline Error assignChars(char c, size_t n) noexcept {
     234             :     return _opChars(ModifyOp::kAssign, c, n);
     235             :   }
     236             : 
     237             :   //! Replaces the current of the string by a formatted integer `i` (signed).
     238             :   inline Error assignInt(int64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept {
     239             :     return _opNumber(ModifyOp::kAssign, uint64_t(i), base, width, flags | StringFormatFlags::kSigned);
     240             :   }
     241             : 
     242             :   //! Replaces the current of the string by a formatted integer `i` (unsigned).
     243             :   inline Error assignUInt(uint64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept {
     244             :     return _opNumber(ModifyOp::kAssign, i, base, width, flags);
     245             :   }
     246             : 
     247             :   //! Replaces the current of the string by the given `data` converted to a HEX string.
     248             :   inline Error assignHex(const void* data, size_t size, char separator = '\0') noexcept {
     249             :     return _opHex(ModifyOp::kAssign, data, size, separator);
     250             :   }
     251             : 
     252             :   //! Replaces the current of the string by a formatted string `fmt`.
     253             :   template<typename... Args>
     254             :   inline Error assignFormat(const char* fmt, Args&&... args) noexcept {
     255           0 :     return _opFormat(ModifyOp::kAssign, fmt, std::forward<Args>(args)...);
     256             :   }
     257             : 
     258             :   //! Replaces the current of the string by a formatted string `fmt` (va_list version).
     259             :   inline Error assignVFormat(const char* fmt, va_list ap) noexcept {
     260             :     return _opVFormat(ModifyOp::kAssign, fmt, ap);
     261             :   }
     262             : 
     263             :   //! Appends `str` having the given size `size` to the string.
     264             :   //!
     265             :   //! Null terminated strings can set `size` to `SIZE_MAX`.
     266           0 :   inline Error append(const char* str, size_t size = SIZE_MAX) noexcept {
     267           0 :     return _opString(ModifyOp::kAppend, str, size);
     268             :   }
     269             : 
     270             :   //! Appends `other` string to this string.
     271             :   inline Error append(const String& other) noexcept {
     272             :     return append(other.data(), other.size());
     273             :   }
     274             : 
     275             :   //! Appends a single `c` character.
     276           0 :   inline Error append(char c) noexcept {
     277           0 :     return _opChar(ModifyOp::kAppend, c);
     278             :   }
     279             : 
     280             :   //! Appends `c` character repeated `n` times.
     281             :   inline Error appendChars(char c, size_t n) noexcept {
     282           0 :     return _opChars(ModifyOp::kAppend, c, n);
     283             :   }
     284             : 
     285             :   //! Appends a formatted integer `i` (signed).
     286           0 :   inline Error appendInt(int64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept {
     287           0 :     return _opNumber(ModifyOp::kAppend, uint64_t(i), base, width, flags | StringFormatFlags::kSigned);
     288             :   }
     289             : 
     290             :   //! Appends a formatted integer `i` (unsigned).
     291           0 :   inline Error appendUInt(uint64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept {
     292           0 :     return _opNumber(ModifyOp::kAppend, i, base, width, flags);
     293             :   }
     294             : 
     295             :   //! Appends the given `data` converted to a HEX string.
     296             :   inline Error appendHex(const void* data, size_t size, char separator = '\0') noexcept {
     297           0 :     return _opHex(ModifyOp::kAppend, data, size, separator);
     298             :   }
     299             : 
     300             :   //! Appends a formatted string `fmt` with `args`.
     301             :   template<typename... Args>
     302           0 :   inline Error appendFormat(const char* fmt, Args&&... args) noexcept {
     303           0 :     return _opFormat(ModifyOp::kAppend, fmt, std::forward<Args>(args)...);
     304             :   }
     305             : 
     306             :   //! Appends a formatted string `fmt` (va_list version).
     307             :   inline Error appendVFormat(const char* fmt, va_list ap) noexcept {
     308           0 :     return _opVFormat(ModifyOp::kAppend, fmt, ap);
     309             :   }
     310             : 
     311             :   ASMJIT_API Error padEnd(size_t n, char c = ' ') noexcept;
     312             : 
     313             :   //! Truncate the string length into `newSize`.
     314             :   ASMJIT_API Error truncate(size_t newSize) noexcept;
     315             : 
     316             :   ASMJIT_API bool eq(const char* other, size_t size = SIZE_MAX) const noexcept;
     317             :   inline bool eq(const String& other) const noexcept { return eq(other.data(), other.size()); }
     318             : 
     319             :   //! \}
     320             : 
     321             :   //! \name Internal Functions
     322             :   //! \{
     323             : 
     324             :   //! Resets string to embedded and makes it empty (zero length, zero first char)
     325             :   //!
     326             :   //! \note This is always called internally after an external buffer was released as it zeroes all bytes
     327             :   //! used by String's embedded storage.
     328             :   inline void _resetInternal() noexcept {
     329      824760 :     for (size_t i = 0; i < ASMJIT_ARRAY_SIZE(_raw.uptr); i++)
     330      659808 :       _raw.uptr[i] = 0;
     331             :   }
     332             : 
     333             :   inline void _setSize(size_t newSize) noexcept {
     334           0 :     if (isLargeOrExternal())
     335           0 :       _large.size = newSize;
     336             :     else
     337           0 :       _small.type = uint8_t(newSize);
     338             :   }
     339             : 
     340             :   //! \}
     341             : };
     342             : 
     343             : //! Temporary string builder, has statically allocated `N` bytes.
     344             : template<size_t N>
     345       82476 : class StringTmp : public String {
     346             : public:
     347             :   ASMJIT_NONCOPYABLE(StringTmp)
     348             : 
     349             :   //! Embedded data.
     350             :   char _embeddedData[Support::alignUp(N + 1, sizeof(size_t))];
     351             : 
     352             :   //! \name Construction & Destruction
     353             :   //! \{
     354             : 
     355      137460 :   inline StringTmp() noexcept {
     356             :     _resetToTemporary();
     357           0 :   }
     358             : 
     359             :   inline void _resetToTemporary() noexcept {
     360      137460 :     _large.type = kTypeExternal;
     361      137460 :     _large.capacity = ASMJIT_ARRAY_SIZE(_embeddedData) - 1;
     362      137460 :     _large.data = _embeddedData;
     363      109968 :     _embeddedData[0] = '\0';
     364             :   }
     365             : 
     366             :   //! \}
     367             : };
     368             : 
     369             : //! \}
     370             : 
     371             : ASMJIT_END_NAMESPACE
     372             : 
     373             : #endif // ASMJIT_CORE_STRING_H_INCLUDED
     374             : 
     375             : #endif // __PLUMED_HAS_ASMJIT

Generated by: LCOV version 1.16