@@ -30,178 +30,13 @@ spy_str_alloc(size_t length) {
3030 return res ;
3131}
3232
33- spy_StrObject *
34- spy_str_add (spy_StrObject * a , spy_StrObject * b ) {
35- size_t l = a -> length + b -> length ;
36- spy_StrObject * res = spy_str_alloc (l );
37- char * buf = (char * )spy_StrObject_UTF8 (res );
38- memcpy (buf , spy_StrObject_UTF8 (a ), a -> length );
39- memcpy (buf + a -> length , spy_StrObject_UTF8 (b ), b -> length );
40- return res ;
41- }
42-
43- spy_StrObject *
44- spy_str_replace (spy_StrObject * original , spy_StrObject * old , spy_StrObject * new_str ) {
45- size_t orig_len = original -> length ;
46- size_t old_len = old -> length ;
47- size_t new_len = new_str -> length ;
48-
49- if (old_len == 0 ) {
50- // when old_len is empty insert new_str before each byte and after the last
51- size_t result_len = orig_len + (orig_len + 1 ) * new_len ;
52- spy_StrObject * res = spy_str_alloc (result_len );
53- char * buf = (char * )spy_StrObject_UTF8 (res );
54- for (size_t i = 0 ; i < orig_len ; i ++ ) {
55- memcpy (buf , spy_StrObject_UTF8 (new_str ), new_len );
56- buf += new_len ;
57- buf [0 ] = spy_StrObject_UTF8 (original )[i ];
58- buf ++ ;
59- }
60- memcpy (buf , spy_StrObject_UTF8 (new_str ), new_len );
61- return res ;
62- }
63-
64- // First pass -> count occurrences
65- size_t count = 0 ;
66- const char * p = (const char * )spy_StrObject_UTF8 (original );
67- const char * end = p + orig_len ;
68- while (p <= end - old_len ) {
69- if (memcmp (p , spy_StrObject_UTF8 (old ), old_len ) == 0 ) {
70- count ++ ;
71- p += old_len ;
72- } else {
73- p ++ ;
74- }
75- }
76-
77- if (count == 0 ) {
78- // Return the original string when no occurrences are found
79- spy_StrObject * res = spy_str_alloc (orig_len );
80- memcpy ((char * )spy_StrObject_UTF8 (res ), spy_StrObject_UTF8 (original ), orig_len );
81- return res ;
82- }
83-
84- // Second pass -> build the result
85- size_t result_len = orig_len + count * (new_len - old_len );
86- spy_StrObject * res = spy_str_alloc (result_len );
87- char * buf = (char * )spy_StrObject_UTF8 (res );
88- p = (const char * )spy_StrObject_UTF8 (original );
89- while (p <= end - old_len ) {
90- if (memcmp (p , spy_StrObject_UTF8 (old ), old_len ) == 0 ) {
91- memcpy (buf , spy_StrObject_UTF8 (new_str ), new_len );
92- buf += new_len ;
93- p += old_len ;
94- } else {
95- * buf ++ = * p ++ ;
96- }
97- }
98- // Copy remaining bytes
99- size_t remaining = end - p ;
100- memcpy (buf , p , remaining );
101- return res ;
102- }
103-
104- spy_StrObject *
105- spy_str_mul (spy_StrObject * a , int32_t b ) {
106- size_t l = a -> length * b ;
107- spy_StrObject * res = spy_str_alloc (l );
108- char * buf = (char * )spy_StrObject_UTF8 (res );
109- for (int i = 0 ; i < b ; i ++ ) {
110- memcpy (buf , spy_StrObject_UTF8 (a ), a -> length );
111- buf += a -> length ;
112- }
113- return res ;
114- }
115-
11633bool
11734spy_str_eq (spy_StrObject * a , spy_StrObject * b ) {
11835 if (a -> length != b -> length )
11936 return false;
12037 return memcmp (spy_StrObject_UTF8 (a ), spy_StrObject_UTF8 (b ), a -> length ) == 0 ;
12138}
12239
123- spy_StrObject *
124- spy_str_getitem (spy_StrObject * s , int32_t i ) {
125- // XXX this is wrong: it should return a code point
126- size_t l = s -> length ;
127- if (i < 0 ) {
128- i += l ;
129- }
130- if (i >= l || i < 0 ) {
131- spy_panic ("IndexError" , "string index out of bound" , __FILE__ , __LINE__ );
132- return NULL ;
133- }
134- spy_StrObject * res = spy_str_alloc (1 );
135- char * buf = (char * )spy_StrObject_UTF8 (res );
136- buf [0 ] = spy_StrObject_UTF8 (s )[i ];
137- return res ;
138- }
139-
140- int32_t
141- spy_str_len (spy_StrObject * s ) {
142- return (int32_t )s -> length ;
143- }
144-
145- spy_StrObject *
146- spy_str_repr (spy_StrObject * s ) {
147- // Choose quote character: use double quotes if string contains ' but not "
148- char quote = '\'' ;
149- for (size_t i = 0 ; i < s -> length ; i ++ ) {
150- if (spy_StrObject_UTF8 (s )[i ] == '\'' ) {
151- quote = '"' ;
152- }
153- if (spy_StrObject_UTF8 (s )[i ] == '"' ) {
154- quote = '\'' ;
155- break ;
156- }
157- }
158-
159- // First pass: calculate the output length
160- size_t out_len = 2 ; // for the surrounding quotes
161- for (size_t i = 0 ; i < s -> length ; i ++ ) {
162- unsigned char c = (unsigned char )spy_StrObject_UTF8 (s )[i ];
163- if (c == '\\' || c == quote ) {
164- out_len += 2 ;
165- } else if (c == '\n' || c == '\r' || c == '\t' ) {
166- out_len += 2 ;
167- } else if (c < 0x20 ) {
168- out_len += 4 ; // \xNN
169- } else {
170- out_len += 1 ;
171- }
172- }
173-
174- // Second pass: fill the buffer
175- spy_StrObject * res = spy_str_alloc (out_len );
176- char * buf = (char * )spy_StrObject_UTF8 (res );
177- * buf ++ = quote ;
178- for (size_t i = 0 ; i < s -> length ; i ++ ) {
179- unsigned char c = (unsigned char )spy_StrObject_UTF8 (s )[i ];
180- if (c == '\\' ) {
181- * buf ++ = '\\' ;
182- * buf ++ = '\\' ;
183- } else if (c == quote ) {
184- * buf ++ = '\\' ;
185- * buf ++ = quote ;
186- } else if (c == '\n' ) {
187- * buf ++ = '\\' ;
188- * buf ++ = 'n' ;
189- } else if (c == '\r' ) {
190- * buf ++ = '\\' ;
191- * buf ++ = 'r' ;
192- } else if (c == '\t' ) {
193- * buf ++ = '\\' ;
194- * buf ++ = 't' ;
195- } else if (c < 0x20 ) {
196- buf += sprintf (buf , "\\x%02x" , c );
197- } else {
198- * buf ++ = c ;
199- }
200- }
201- * buf ++ = quote ;
202- return res ;
203- }
204-
20540int32_t
20641spy_str_hash (spy_StrObject * s ) {
20742 if (s -> hash != 0 )
0 commit comments