1/*
2 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 "utils.h"
17#include <cstdlib>
18#include <cstring>
19#include <fstream>
20#include <securec.h>
21#include <sstream>
22#include <sys/time.h>
23#include <thread>
24#include "common/common_macro.h"
25#include "common/media_log.h"
26
27namespace OHOS {
28namespace Sharing {
29unsigned long long GetThreadId()
30{
31    std::thread::id tid = std::this_thread::get_id();
32    std::stringstream buf;
33    buf << tid;
34    std::string stid = buf.str();
35    return std::stoull(stid);
36}
37
38std::vector<std::string> Split(const std::string &s, const char *delim)
39{
40    std::vector<std::string> ret;
41    if (delim == nullptr) {
42        return ret;
43    }
44
45    size_t last = 0;
46    auto index = s.find(delim, last);
47    while (index != std::string::npos) {
48        if (index - last > 0) {
49            ret.push_back(s.substr(last, index - last));
50        }
51        last = index + strlen(delim);
52        index = s.find(delim, last);
53    }
54    if (!s.size() || s.size() - last > 0) {
55        ret.push_back(s.substr(last));
56    }
57
58    return ret;
59}
60
61std::vector<std::string> SplitOnce(const std::string &s, const char *delim)
62{
63    std::vector<std::string> ret;
64    if (delim == nullptr) {
65        return ret;
66    }
67    size_t last = 0;
68    auto index = s.find(delim, last);
69    if (index != std::string::npos) {
70        ret.push_back(s.substr(0, index));
71        ret.push_back(s.substr(index + 1));
72    } else {
73        ret.push_back(s);
74    }
75
76    return ret;
77}
78
79#define TRIM(s, chars)                                             \
80    do {                                                           \
81        std::string map(0xFF, '\0');                               \
82        for (auto &ch : (chars)) {                                 \
83            map[(unsigned char &)ch] = '\1';                       \
84        }                                                          \
85        while ((s).size() && map.at((unsigned char &)(s).back()))  \
86            (s).pop_back();                                        \
87        while ((s).size() && map.at((unsigned char &)(s).front())) \
88            (s).erase(0, 1);                                       \
89    } while (0)
90
91std::string &Trim(std::string &s, const std::string &chars)
92{
93    TRIM(s, chars);
94    return s;
95}
96
97std::string Trim(std::string &&s, const std::string &chars)
98{
99    TRIM(s, chars);
100    return std::move(s);
101}
102
103#define ADD_VECTOR_END(v, i) (v).push_back((i))
104
105std::string LowerCase(std::string value)
106{
107    return ChangeCase(value, true);
108}
109
110std::string UpperCase(std::string value)
111{
112    return ChangeCase(value, false);
113}
114
115void LTrim(std::string &value)
116{
117    std::string::size_type i = 0;
118    for (i = 0; i < value.length(); i++) {
119        if (value[i] != ' ' && value[i] != '\t' && value[i] != '\n' && value[i] != '\r')
120            break;
121    }
122    value = value.substr(i);
123}
124
125void RTrim(std::string &value)
126{
127    int32_t i = 0;
128    for (i = (int32_t)value.length() - 1; i >= 0; i--) {
129        if (value[i] != ' ' && value[i] != '\t' && value[i] != '\n' && value[i] != '\r')
130            break;
131    }
132    value = value.substr(0, i + 1);
133}
134
135void Trim(std::string &value)
136{
137    LTrim(value);
138    RTrim(value);
139}
140
141std::string ChangeCase(const std::string &value, bool LowerCase)
142{
143    std::string newvalue(value);
144    for (std::string::size_type i = 0, l = newvalue.length(); i < l; ++i)
145        newvalue[i] = LowerCase ? tolower(newvalue[i]) : toupper(newvalue[i]);
146    return newvalue;
147}
148
149void Replace(std::string &target, std::string search, std::string replacement)
150{
151    if (search == replacement) {
152        return;
153    }
154
155    if (search == "") {
156        return;
157    }
158
159    std::string::size_type i = std::string::npos;
160    std::string::size_type lastPos = 0;
161    while ((i = target.find(search, lastPos)) != std::string::npos) {
162        target.replace(i, search.length(), replacement);
163        lastPos = i + replacement.length();
164    }
165}
166
167void Split(std::string str, std::string separator, std::vector<std::string> &result)
168{
169    result.clear();
170    std::string::size_type position = str.find(separator);
171    std::string::size_type lastPosition = 0;
172    uint32_t separatorLength = separator.length();
173
174    while (position != str.npos) {
175        ADD_VECTOR_END(result, str.substr(lastPosition, position - lastPosition));
176        lastPosition = position + separatorLength;
177        position = str.find(separator, lastPosition);
178    }
179    ADD_VECTOR_END(result, str.substr(lastPosition, std::string::npos));
180}
181
182uint64_t GetCurrentMillisecond()
183{
184    struct timeval tv {
185    };
186    gettimeofday(&tv, nullptr);
187    return tv.tv_sec * 1000 + tv.tv_usec / 1000; // 1000: time base conversion.
188}
189
190void SaveFile(const char *data, int32_t dataSize, const std::string &fileName)
191{
192    RETURN_IF_NULL(data);
193    std::ofstream out(fileName, std::ios::out | std::ios::binary);
194    if (!out.is_open()) {
195        SHARING_LOGD("failed to opne file: %{public}s", fileName.c_str());
196        return;
197    }
198
199    out.write(data, dataSize);
200    out.flush();
201    out.close();
202}
203
204void NeonMemcpy(volatile unsigned char *dst, volatile unsigned char *src, int size)
205{
206#if defined(__ARM_NEON__)
207    int neonCopy = size - size % 64;
208    if (neonCopy > 0) {
209        int tempCount = neonCopy;
210        asm volatile("NEONCopyPLD_%=: \n"
211                     " VLDM %[src]!,{d0-d7} \n"
212                     " VSTM %[dst]!,{d0-d7} \n"
213                     " SUBS %[tempCount],%[tempCount],#0x40 \n"
214                     " BGT NEONCopyPLD_%= \n"
215                     : [dst] "+r"(dst), [src] "+r"(src), [tempCount] "+r"(tempCount)::"d0", "d1", "d2", "d3", "d4",
216                       "d5", "d6", "d7", "cc", "memory");
217    }
218    if (size - neonCopy > 0) {
219        auto ret = memcpy_s((void *)dst, size - neonCopy, (void *)src, size - neonCopy);
220        if (ret != EOK) {
221            return;
222        }
223    }
224#else
225    if (size > 0) {
226        auto ret = memcpy_s((void *)dst, size, (void *)src, size);
227        if (ret != EOK) {
228            return;
229        }
230    }
231#endif
232}
233
234uint16_t SwapEndian16(uint16_t value)
235{
236    return (value & 0xff00) >> 8 | (value & 0x00ff) << 8; // 8: swap endian
237}
238
239uint32_t SwapEndian32(uint32_t value)
240{
241    uint8_t res[4];
242    for (int i = 0; i < 4; ++i) {            // 4: swap endian
243        res[i] = ((uint8_t *)&value)[3 - i]; // 3: swap endian
244    }
245    return *(uint32_t *)res;
246}
247
248uint64_t SwapEndian64(uint64_t value)
249{
250    uint8_t res[8];
251    for (int i = 0; i < 8; ++i) {            // 8: swap endian
252        res[i] = ((uint8_t *)&value)[7 - i]; // 7: swap endian
253    }
254    return *(uint64_t *)res;
255}
256
257uint16_t LoadBE16(const uint8_t *p)
258{
259    RETURN_INVALID_IF_NULL(p);
260    return SwapEndian16(*(uint16_t *)p);
261}
262
263uint32_t LoadBE24(const uint8_t *p)
264{
265    RETURN_INVALID_IF_NULL(p);
266    uint8_t res[4] = {0, p[0], p[1], p[2]};
267    return SwapEndian32(*(uint32_t *)res);
268}
269
270uint32_t LoadBE32(const uint8_t *p)
271{
272    RETURN_INVALID_IF_NULL(p);
273    return SwapEndian32(*(uint32_t *)p);
274}
275
276uint64_t LoadBE64(const uint8_t *p)
277{
278    RETURN_INVALID_IF_NULL(p);
279    return SwapEndian64(*(uint64_t *)p);
280}
281
282void SetBE24(void *p, uint32_t val)
283{
284    RETURN_IF_NULL(p);
285    uint8_t *data = (uint8_t *)p;
286    data[0] = val >> 16; // 16: byte offset
287    data[1] = val >> 8;  // 8: byte offset
288    data[2] = val;       // 2: transformed position
289}
290
291void SetBE32(void *p, uint32_t val)
292{
293    RETURN_IF_NULL(p);
294    uint8_t *data = (uint8_t *)p;
295    data[3] = val;       // 3: transformed position
296    data[2] = val >> 8;  // 2: transformed position, 8: byte offset
297    data[1] = val >> 16; // 16: byte offset
298    data[0] = val >> 24; // 24: byte offset
299}
300
301void SetLE32(void *p, uint32_t val)
302{
303    RETURN_IF_NULL(p);
304    uint8_t *data = (uint8_t *)p;
305    data[0] = val;
306    data[1] = val >> 8;  //  8: byte offset
307    data[2] = val >> 16; // 2: transformed position, 16: byte offset
308    data[3] = val >> 24; // 3: transformed position, 24: byte offset
309}
310
311std::string GetAnonyString(const std::string &value)
312{
313    constexpr size_t INT32_SHORT_ID_LENGTH = 20;
314    constexpr size_t INT32_MIN_ID_LENGTH = 3;
315    std::string result;
316    std::string tmpStr("******");
317    size_t strLen = value.length();
318    if (strLen < INT32_MIN_ID_LENGTH) {
319        return tmpStr;
320    }
321
322    if (strLen <= INT32_SHORT_ID_LENGTH) {
323        result += value[0];
324        result += tmpStr;
325        result += value[strLen - 1];
326    } else {
327        constexpr size_t INT32_PLAINTEXT_LENGTH = 4;
328        result.append(value, 0, INT32_PLAINTEXT_LENGTH);
329        result += tmpStr;
330        result.append(value, strLen - INT32_PLAINTEXT_LENGTH, INT32_PLAINTEXT_LENGTH);
331    }
332
333    return result;
334}
335
336} // namespace Sharing
337} // namespace OHOS
338