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 "hcf_string.h"
18
19const uint32_t STRING_ALLOC_SIZE = 10;
20const uint32_t STRING_END_CHAR_LENGTH = 1;
21const char STRING_END_CHAR = '\0';
22#define MAX_INT 0x7FFFFFFF
23#define MAX_UINT 0xFFFFFFFF
24
25/*
26* Append string pointer
27* Notice: It will add '\0' automatically.
28* @param self: self pointer.
29* @param str: string pointer.
30* @return true (ok), false (error)
31*/
32bool StringAppendPointer(HcString *self, const char *str)
33{
34    if (self != NULL && str != NULL) {
35        // remove '\0'
36        ParcelPopBack(&self->parcel, STRING_END_CHAR_LENGTH);
37        // append string (include '\0')
38        return ParcelWrite(&self->parcel, (void *)str, strlen(str) + 1);
39    }
40
41    return false;
42}
43
44/*
45* Assign a value to the HcString
46* Notice: It will add '\0' automatically.
47* @param self: self pointer.
48* @param str: assign value of string pointer.
49* @return true (ok), false (error)
50*/
51bool StringSetPointer(HcString *self, const char *str)
52{
53    if (self != NULL) {
54        DeleteParcel(&self->parcel);
55        return StringAppendPointer(self, str);
56    }
57
58    return false;
59}
60
61/*
62* Assign a value to the HcString with fixed length
63* Notice: It will add '\0' automatically.
64* @param self: self pointer.
65* @param str: assign value of string pointer.
66* @param len: the length of string.
67* @return true (ok), false (error)
68*/
69bool StringSetPointerWithLength(HcString* self, const char *str, uint32_t len)
70{
71    if (self == NULL || str == NULL) {
72        return false;
73    }
74    uint32_t strLen = strlen(str);
75    if (strLen < len) {
76        return false;
77    }
78    DeleteParcel(&self->parcel);
79    if (len > 0) {
80        if (false == ParcelWrite(&self->parcel, str, len)) {
81            return false;
82        }
83    }
84    return ParcelWriteInt8(&self->parcel, (uint32_t)STRING_END_CHAR);
85}
86
87/*
88* Get the string pointer data
89* @param self: self pointer.
90* @return the pointer data of the string
91*/
92const char *StringGet(const HcString *self)
93{
94    if (self == NULL) {
95        return NULL;
96    }
97
98    return GetParcelData(&self->parcel);
99}
100
101/*
102* Get the length of the string
103* @param self: self pointer.
104* @return the length of the string
105*/
106uint32_t StringLength(const HcString *self)
107{
108    if (self == NULL) {
109        return 0;
110    } else {
111        uint32_t length = GetParcelDataSize(&self->parcel);
112        if (length > 0) {
113            return length - STRING_END_CHAR_LENGTH;
114        } else {
115            return 0;
116        }
117    }
118}
119
120/*
121* Find a char from string
122* @param self: self pointer.
123* @param c: the char you want find
124* @param begin: the position find from
125* @return the position of the char
126*/
127int StringFind(const HcString *self, char c, uint32_t begin)
128{
129    if (self == NULL) {
130        return -1;
131    }
132    uint32_t p = begin;
133    // because the return value is int
134    // so the string length cannot bigger than MAX_INT
135    uint32_t strLen = StringLength(self);
136    if (strLen >= MAX_INT) {
137        return -1;
138    }
139
140    const char* curChar = StringGet(self);
141    while (p < strLen) {
142        if (*(curChar + p) == c) {
143            return p;
144        }
145        ++p;
146    }
147    return -1;
148}
149
150/*
151* Get sub string from a string.
152* @param self: self pointer.
153* @param begin: the begin position of the sub string.
154* @param len: the length of the sub string.
155* @param dst: the string pointer which saved the sub string content.
156* @return the operation result.
157*/
158bool StringSubString(const HcString *self, uint32_t begin, uint32_t len, HcString* dst)
159{
160    if (self == NULL || dst == NULL) {
161        return false;
162    }
163    if (MAX_UINT - len <= begin) {
164        return false;
165    }
166    const char* beingPointer = StringGet(self) + begin;
167    return StringSetPointerWithLength(dst, beingPointer, len);
168}
169
170/*
171* Compare the string with another string.
172* @param self: self pointer.
173* @param dst: the pointer of another string.
174* @return the compare result.
175*  -1: self is smaller than dst
176*   0: self is equal with dst
177*   1: self is bigger than dst
178*/
179int StringCompare(const HcString *self, const char* dst)
180{
181    if (self == NULL || dst == NULL) {
182        return 0;
183    }
184
185    const char* src = StringGet(self);
186    if (src == NULL) {
187        return -1;
188    }
189
190    do {
191        if ((*src) > (*dst)) {
192            return 1;
193        } else if ((*src) < (*dst)) {
194            return -1;
195        } else {
196            if ((*src) == '\0') {
197                return 0;
198            }
199            ++src;
200            ++dst;
201        }
202    } while (1);
203    // should never be here
204    return 0;
205}
206
207/*
208* Create a string.
209* Notice: You should delete_string when you don't need the string anymore.
210* @return return the created string.
211*/
212HcString CreateString(void)
213{
214    HcString str;
215    str.parcel = CreateParcel(0, STRING_ALLOC_SIZE);
216    ParcelWriteInt8(&str.parcel, STRING_END_CHAR);
217    return str;
218}
219
220/*
221* Delete a string. In fact it will not destroy the string,
222* but only free the allocate memory of the string and reset the member's value
223* of the string.
224* You can continue to use the string if you want.
225* Notice: You should delete the string when you don't need it any more to avoid memory leak.
226* @param str: The string you want to delete.
227*/
228void DeleteString(HcString *str)
229{
230    if (str != NULL) {
231        DeleteParcel(&str->parcel);
232    }
233}
234