1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#include "mos_stdlib.h"
4
5#include <mos/types.h>
6#include <mos_stdio.h>
7#include <mos_string.h>
8
9unsigned char tolower(unsigned char c)
10{
11 if (c >= 'A' && c <= 'Z')
12 return c - 'A' + 'a';
13 return c;
14}
15
16static int isspace(int _c)
17{
18 return ((_c > 8 && _c < 14) || (_c == 32));
19}
20
21s32 abs(s32 x)
22{
23 return (x < 0) ? -x : x;
24}
25
26long labs(long x)
27{
28 return (x < 0) ? -x : x;
29}
30
31s64 llabs(s64 x)
32{
33 return (x < 0) ? -x : x;
34}
35
36s32 atoi(const char *nptr)
37{
38 s32 c;
39 s32 neg = 0;
40 s32 val = 0;
41
42 while (isspace(c: *nptr))
43 nptr++;
44
45 if (*nptr == '-')
46 {
47 neg = 1;
48 nptr++;
49 }
50 else if (*nptr == '+')
51 {
52 nptr++;
53 }
54
55 while ((c = *nptr++) >= '0' && c <= '9')
56 {
57 val = val * 10 + (c - '0');
58 }
59
60 return neg ? -val : val;
61}
62
63unsigned long strtoul(const char *restrict nptr, char **restrict endptr, int base)
64{
65 return strtoll(str: nptr, endptr, base);
66}
67
68s64 strtoll(const char *str, char **endptr, int base)
69{
70 return strntoll(str, endptr, base, n: strlen(str));
71}
72
73s64 strntoll(const char *str, char **endptr, int base, size_t n)
74{
75 s64 result = 0;
76 bool negative = false;
77 size_t i = 0;
78
79 if (*str == '-')
80 negative = true, str++, i++;
81 else if (*str == '+')
82 str++, i++;
83
84 while (i < n && *str)
85 {
86 char c = *str;
87 if (c >= '0' && c <= '9')
88 result *= base, result += c - '0';
89 else if (c >= 'a' && c <= 'z')
90 result *= base, result += c - 'a' + 10;
91 else if (c >= 'A' && c <= 'Z')
92 result *= base, result += c - 'A' + 10;
93 else
94 break;
95 str++;
96 i++;
97 }
98 if (endptr)
99 *endptr = (char *) str;
100 return negative ? -result : result;
101}
102
103void format_size(char *buf, size_t buf_size, u64 size)
104{
105 static const char *const units[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB" };
106 size_t i = 0;
107 size_t diff = 0;
108 while (size >= 1024 && i < MOS_ARRAY_SIZE(units) - 1)
109 {
110 diff = size % 1024;
111 size /= 1024;
112 i++;
113 }
114 if (unlikely(diff == 0 || i == 0))
115 {
116 snprintf(str: buf, size: buf_size, format: "%llu %s", size, units[i]);
117 }
118 else
119 {
120 snprintf(str: buf, size: buf_size, format: "%llu %s + %zu %s", size, units[i], diff, units[i - 1]);
121 }
122}
123
124char *string_trim(char *in)
125{
126 if (in == NULL)
127 return NULL;
128
129 char *end;
130
131 // Trim leading space
132 while (*in == ' ')
133 in++;
134
135 if (*in == 0) // All spaces?
136 return in;
137
138 // Trim trailing space
139 end = in + strlen(str: in) - 1;
140 while (end > in && *end == ' ')
141 end--;
142
143 // Write new null terminator
144 *(end + 1) = '\0';
145 return in;
146}
147