1/*
2 * Copyright (C) 2021 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
16#include <string.h>
17#include "hc_string.h"
18#include "hc_types.h"
19
20const uint32_t STRING_ALLOC_SIZE = 10;
21const uint32_t STRING_END_CHAR_LENGTH = 1;
22const char STRING_END_CHAR = '\0';
23
24/*
25 * Append a HcString
26 * Notice: It will add '\0' automatically.
27 * @param self: self pointer.
28 * @param str: append string.
29 * @return HC_TRUE (ok), HC_FALSE (error)
30 */
31HcBool StringAppend(HcString *self, HcString str)
32{
33    uint32_t length = GetParcelDataSize(&str.parcel);
34    if (self != NULL && length > 0) {
35        // remove '\0'
36        ParcelPopBack(&self->parcel, STRING_END_CHAR_LENGTH);
37        // append string(include '\0')
38        return StringAppendPointer(self, GetParcelData(&str.parcel));
39    }
40
41    return HC_FALSE;
42}
43
44/*
45 * Append string pointer
46 * Notice: It will add '\0' automatically.
47 * @param self: self pointer.
48 * @param str: string pointer.
49 * @return HC_TRUE (ok), HC_FALSE (error)
50 */
51HcBool StringAppendPointer(HcString *self, const char *str)
52{
53    if (self != NULL && str != NULL) {
54        // remove '\0'
55        ParcelPopBack(&self->parcel, STRING_END_CHAR_LENGTH);
56        // append string (include '\0')
57        return ParcelWrite(&self->parcel, (void *)str, HcStrlen(str) + 1);
58    }
59
60    return HC_FALSE;
61}
62
63/*
64 * Append a char
65 * Notice: It will add '\0' automatically.
66 * @param self: self pointer.
67 * @param str: char.
68 * @return HC_TRUE (ok), HC_FALSE (error)
69 */
70HcBool StringAppendChar(HcString *self, char c)
71{
72    if (self != NULL && c != STRING_END_CHAR) {
73        // remove '\0'
74        ParcelPopBack(&self->parcel, STRING_END_CHAR_LENGTH);
75
76        if (ParcelWriteInt8(&self->parcel, c)) {
77            return ParcelWriteInt8(&self->parcel, (uint32_t)STRING_END_CHAR);
78        }
79    }
80
81    return HC_FALSE;
82}
83
84/*
85 * Assign a value to the HcString
86 * Notice: It will add '\0' automatically.
87 * @param self: self pointer.
88 * @param str: assign value of ta_sting.
89 * @return HC_TRUE (ok), HC_FALSE (error)
90 */
91HcBool StringSet(HcString *self, HcString str)
92{
93    if (self != NULL) {
94        DeleteParcel(&self->parcel);
95        return StringAppend(self, str);
96    }
97
98    return HC_FALSE;
99}
100
101/*
102 * Assign a value to the HcString
103 * Notice: It will add '\0' automatically.
104 * @param self: self pointer.
105 * @param str: assign value of string pointer.
106 * @return HC_TRUE (ok), HC_FALSE (error)
107 */
108HcBool StringSetPointer(HcString *self, const char *str)
109{
110    if (self != NULL) {
111        DeleteParcel(&self->parcel);
112        return StringAppendPointer(self, str);
113    }
114
115    return HC_FALSE;
116}
117
118/*
119 * Get the string pointer data
120 * @param self: self pointer.
121 * @return the pointer data of the string
122 */
123const char *StringGet(const HcString *self)
124{
125    if (self == NULL) {
126        return NULL;
127    }
128
129    return GetParcelData(&self->parcel);
130}
131
132/*
133 * Get the length of the string
134 * @param self: self pointer.
135 * @return the length of the string
136 */
137uint32_t StringLength(const HcString *self)
138{
139    if (self == NULL) {
140        return 0;
141    } else {
142        uint32_t length = GetParcelDataSize(&self->parcel);
143        if (length > 0) {
144            return length - STRING_END_CHAR_LENGTH;
145        } else {
146            return 0;
147        }
148    }
149}
150
151/*
152 * Create a string.
153 * Notice: You should delete_string when you don't need the string anymore.
154 * @return return the created string.
155 */
156HcString CreateString(void)
157{
158    HcString str;
159    str.parcel = CreateParcel(0, STRING_ALLOC_SIZE);
160    ParcelWriteInt8(&str.parcel, STRING_END_CHAR);
161    return str;
162}
163
164/*
165 * Delete a string. In fact it will not destroy the string,
166 * but only free the allocate memory of the string and reset the member's value
167 * of the string.
168 * You can continue to use the string if you want.
169 * Notice: You should delete the string when you don't need it any more to avoid memory leak.
170 * @param str: The string you want to delete.
171 */
172void DeleteString(HcString *str)
173{
174    if (str != NULL) {
175        DeleteParcel(&str->parcel);
176    }
177}
178