1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <taihe/string.abi.h>
16
17 #include <algorithm>
18
19 // Converts a TString into its corresponding heap-allocated TStringData
20 // structure.
21 // # Arguments
22 // - `tstr`: The TString to be converted.
23 // # Returns
24 // - A pointer to the TStringData structure if the TString is heap-allocated.
25 // - `nullptr` if the TString is a reference (TSTRING_REF is set).
to_heap(struct TString tstr)26 TH_INLINE struct TStringData *to_heap(struct TString tstr)
27 {
28 if (tstr.flags & TSTRING_REF) {
29 return nullptr;
30 }
31 return reinterpret_cast<struct TStringData *>(const_cast<char *>(tstr.ptr) - offsetof(struct TStringData, buffer));
32 }
33
tstr_initialize(struct TString * tstr_ptr,uint32_t capacity)34 char *tstr_initialize(struct TString *tstr_ptr, uint32_t capacity)
35 {
36 size_t bytes_required = sizeof(struct TStringData) + sizeof(char) * capacity;
37 struct TStringData *sh = reinterpret_cast<struct TStringData *>(malloc(bytes_required));
38 tref_set(&sh->count, 1);
39 tstr_ptr->flags = 0;
40 tstr_ptr->ptr = sh->buffer;
41 return sh->buffer;
42 }
43
tstr_new(char const * value TH_NONNULL,size_t len)44 struct TString tstr_new(char const *value TH_NONNULL, size_t len)
45 {
46 struct TString tstr;
47 char *buf = tstr_initialize(&tstr, len + 1);
48 buf = std::copy(value, value + len, buf);
49 *buf = '\0';
50 tstr.length = len;
51 return tstr;
52 }
53
tstr_new_ref(char const * buf TH_NONNULL,size_t len)54 struct TString tstr_new_ref(char const *buf TH_NONNULL, size_t len)
55 {
56 struct TString tstr;
57 tstr.flags = TSTRING_REF;
58 tstr.length = len;
59 tstr.ptr = buf;
60 return tstr;
61 }
62
tstr_dup(struct TString tstr)63 struct TString tstr_dup(struct TString tstr)
64 {
65 struct TStringData *sh = to_heap(tstr);
66 if (!sh) {
67 return tstr_new(tstr.ptr, tstr.length);
68 }
69 tref_inc(&sh->count);
70 return tstr;
71 }
72
tstr_drop(struct TString tstr)73 void tstr_drop(struct TString tstr)
74 {
75 struct TStringData *sh = to_heap(tstr);
76 if (!sh) {
77 return;
78 }
79 if (tref_dec(&sh->count)) {
80 free(sh);
81 }
82 }
83
tstr_concat(size_t count,struct TString const * tstr_list)84 struct TString tstr_concat(size_t count, struct TString const *tstr_list)
85 {
86 size_t len = 0;
87 for (size_t i = 0; i < count; ++i) {
88 len += tstr_list[i].length;
89 }
90 struct TString tstr;
91 char *buf = tstr_initialize(&tstr, len + 1);
92 for (size_t i = 0; i < count; ++i) {
93 buf = std::copy(tstr_list[i].ptr, tstr_list[i].ptr + tstr_list[i].length, buf);
94 }
95 *buf = '\0';
96 tstr.length = len;
97 return tstr;
98 }
99
tstr_substr(struct TString tstr,size_t pos,size_t len)100 struct TString tstr_substr(struct TString tstr, size_t pos, size_t len)
101 {
102 if (pos > tstr.length) {
103 len = 0;
104 } else if (pos + len > tstr.length) {
105 len = tstr.length - pos;
106 }
107 return tstr_new_ref(tstr.ptr + pos, len);
108 }