-
Notifications
You must be signed in to change notification settings - Fork 0
/
string.ceu
157 lines (126 loc) · 3.75 KB
/
string.ceu
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#ifndef _STRING_CEU
#define _STRING_CEU
#include "c.ceu"
// https://www.geeksforgeeks.org/implement-itoa/
native _double;
native/nohold _ceu_itona;
native/pre do
##include <string.h>
/* A utility function to reverse a string */
void reverse(char str[], int length)
{
int start = 0;
int end_ = length -1;
while (start < end_)
{
char tmp = *(str+start);
*(str+start) = *(str+end_);
*(str+end_) = tmp;
start++;
end_--;
}
}
// Implementation of itoa()
usize ceu_itona(int num, char* str, int base, usize max)
{
usize i = 0;
bool isNegative = 0;
/* Handle 0 explicitely, otherwise empty string is printed for 0 */
if (num == 0) {
if (i >= max) return 0;
str[i++] = '0';
if (i >= max) return 0;
str[i] = '\0';
return i+1;
}
// In standard itoa(), negative numbers are handled only with
// base 10. Otherwise numbers are considered unsigned.
if (num < 0 && base == 10) {
isNegative = 1;
num = -num;
}
// Process individual digits
while (num != 0) {
int rem = num % base;
if (i >= max) return 0;
str[i++] = (rem > 9)? (rem-10) + 'A' : rem + '0';
num = num/base;
}
// If number is negative, append '-'
if (isNegative) {
if (i >= max) return 0;
str[i++] = '-';
}
if (i >= max) return 0;
str[i] = '\0'; // Append string terminator
// Reverse the string
reverse(str, i);
return i+1;
}
end
code/call String_Check (var&[] byte dst) -> none do
_ceu_assert($$dst > 0, "dynamic vector is not supported");
if $dst > 0 then
_ceu_assert(dst[$dst-1] == {'\0'}, "invalid string");
else
dst = dst..[{'\0'}];
end
end
code/call String_Print (var&[] byte str) -> none do
{
const char* strC = @&&str[0] as _char&&;
printf("%s", strC);
}
end
code/call String_Append_STR (var&[] byte dst, var _char&& src) -> none do
call String_Check(&dst);
_strncat(&&dst[0] as _char&&, &&src[0] as _char&&, $$dst-$dst);
_ceu_vector_setlen(&&dst, $dst+_strlen(src), 1);
end
code/call String_Append_INT (var&[] byte dst, var int src, var int? base) -> none do
call String_Check(&dst);
//_ceu_assert($$dst-$dst >= 12, "no space available");
$dst = $dst - 1;
if not base? then
base = 10;
end
var usize n = _ceu_itona(src, &&dst[$dst] as _char&&, base!, $$dst-$dst);
_ceu_assert(n > 0, "access out of bounds");
_ceu_vector_setlen(&&dst, $dst+n, 1);
end
code/call String_Append_REAL (var&[] byte dst, var r64 src, var int? precision) -> none do
call String_Check(&dst);
if not precision? then
precision = 2;
end
_ceu_assert(precision! < 999, "precision error");
{
char format[6];
sprintf(format, "%%.%df", @precision!);
}
_sprintf(&&dst[0] as _char&&, {format}, src);
_ceu_vector_setlen(&&dst, $dst+_strlen(&&dst[0] as _char&&), 1);
end
code/call String_Equal (var&[] byte str1, var&[] byte str2) -> bool do
var int result=_;
{
@result = strcmp(@&&str1[0] as _char&&, @&&str2[0] as _char&&);
}
if (result == 0) then
escape true;
else
escape false;
end
end
code/call String_Equal_STR (var&[] byte str1, var _char&& str2) -> bool do
var int result=_;
{
@result = strcmp(@&&str1[0] as _char&&, @&&str2[0] as _char&&);
}
if (result == 0) then
escape true;
else
escape false;
end
end
#endif