1//===----------------------------------------------------------------------===//
2// DuckDB
3//
4// duckdb/common/types/string_type.hpp
5//
6//
7//===----------------------------------------------------------------------===//
8
9#pragma once
10
11#include "duckdb/common/constants.hpp"
12#include <cstring>
13#include <cassert>
14
15namespace duckdb {
16
17struct string_t {
18 friend struct StringComparisonOperators;
19 friend class StringSegment;
20
21public:
22 static constexpr idx_t PREFIX_LENGTH = 4 * sizeof(char);
23 static constexpr idx_t INLINE_LENGTH = 12;
24
25 string_t() = default;
26 string_t(uint32_t len) : length(len) {
27 memset(prefix, 0, PREFIX_LENGTH);
28 value_.data = nullptr;
29 }
30 string_t(const char *data, uint32_t len) : length(len) {
31 assert(data || length == 0);
32 if (IsInlined()) {
33 // zero initialize the prefix first
34 // this makes sure that strings with length smaller than 4 still have an equal prefix
35 memset(prefix, 0, PREFIX_LENGTH);
36 if (length == 0) {
37 return;
38 }
39 // small string: inlined
40 memcpy(prefix, data, length);
41 prefix[length] = '\0';
42 } else {
43 // large string: store pointer
44 memcpy(prefix, data, PREFIX_LENGTH);
45 value_.data = (char *)data;
46 }
47 }
48 string_t(const char *data) : string_t(data, strlen(data)) {
49 }
50 string_t(const string &value) : string_t(value.c_str(), value.size()) {
51 }
52
53 bool IsInlined() const {
54 return length < INLINE_LENGTH;
55 }
56
57 char *GetData() {
58 return IsInlined() ? (char *)prefix : value_.data;
59 }
60
61 const char *GetData() const {
62 return IsInlined() ? (const char *)prefix : value_.data;
63 }
64
65 const char *GetPrefix() const {
66 return prefix;
67 }
68
69 idx_t GetSize() const {
70 return length;
71 }
72
73 string GetString() const {
74 return string(GetData(), GetSize());
75 }
76
77 void Finalize() {
78 // set trailing NULL byte
79 auto dataptr = (char *)GetData();
80 dataptr[length] = '\0';
81 if (length < INLINE_LENGTH) {
82 // fill prefix with zeros if the length is smaller than the prefix length
83 for (idx_t i = length; i < PREFIX_LENGTH; i++) {
84 prefix[i] = '\0';
85 }
86 } else {
87 // copy the data into the prefix
88 memcpy(prefix, dataptr, PREFIX_LENGTH);
89 }
90 }
91
92 void Verify();
93
94private:
95 uint32_t length;
96 char prefix[4];
97 union {
98 char inlined[8];
99 char *data;
100 } value_;
101};
102
103}; // namespace duckdb
104