Line data Source code
1 : #define _GNU_SOURCE
2 : #include "fd_cstr.h"
3 :
4 : /* FIXME: WEAN THIS OFF STDLIB FOR NON-HOSTED TARGETS */
5 : #include <stdio.h>
6 : #include <stdlib.h>
7 : #include <stdarg.h>
8 : #include <strings.h>
9 : #include <ctype.h>
10 :
11 6003352 : char const * fd_cstr_to_cstr ( char const * cstr ) { return cstr; }
12 6000015 : char fd_cstr_to_char ( char const * cstr ) { return cstr[0]; }
13 6000015 : schar fd_cstr_to_schar ( char const * cstr ) { return (schar) strtol ( cstr, NULL, 0 ); }
14 6000015 : short fd_cstr_to_short ( char const * cstr ) { return (short) strtol ( cstr, NULL, 0 ); }
15 6002029 : int fd_cstr_to_int ( char const * cstr ) { return (int) strtol ( cstr, NULL, 0 ); }
16 6000024 : long fd_cstr_to_long ( char const * cstr ) { return (long) strtol ( cstr, NULL, 0 ); }
17 6011073 : uchar fd_cstr_to_uchar ( char const * cstr ) { return (uchar) strtoul( cstr, NULL, 0 ); }
18 6000015 : ushort fd_cstr_to_ushort( char const * cstr ) { return (ushort)strtoul( cstr, NULL, 0 ); }
19 6000051 : uint fd_cstr_to_uint ( char const * cstr ) { return (uint) strtoul( cstr, NULL, 0 ); }
20 6002589 : ulong fd_cstr_to_ulong ( char const * cstr ) { return (ulong) strtoul( cstr, NULL, 0 ); }
21 6000018 : float fd_cstr_to_float ( char const * cstr ) { return strtof ( cstr, NULL ); }
22 : #if FD_HAS_DOUBLE
23 6000006 : double fd_cstr_to_double( char const * cstr ) { return strtod ( cstr, NULL ); }
24 : #endif
25 :
26 222 : ulong fd_cstr_to_ulong_octal( char const * cstr ) { return (ulong)strtoul( cstr, NULL, 8 ); }
27 :
28 : ulong
29 : fd_cstr_to_ulong_seq( char const * cstr,
30 : ulong * seq,
31 330 : ulong seq_max ) {
32 330 : ulong seq_cnt = 0UL;
33 :
34 330 : if( !cstr ) return seq_cnt;
35 :
36 321 : char const * p = cstr;
37 624 : for(;;) {
38 :
39 624 : char c;
40 624 : char * q;
41 :
42 759 : c = *p; while( fd_isspace( (int)c ) ) c = *(++p); /* Move and peek at next non-white-space character */
43 624 : if( c=='\0' ) break; /* end of sequence */
44 :
45 435 : ulong seq_ele_0 = strtoul( p, &q, 0 );
46 435 : if( FD_UNLIKELY( p==(char const *)q ) ) return 0UL; /* Malformed sequence, seq_ele_0 is not a ulong */
47 414 : p = (char const *)q;
48 :
49 414 : ulong seq_ele_1 = seq_ele_0;
50 414 : ulong seq_stride = 1UL;
51 :
52 558 : c = *p; while( fd_isspace( (int)c ) ) c = *(++p); /* Move and peek at next non-white-space character */
53 414 : if( c=='-' ) {
54 240 : p++;
55 :
56 240 : seq_ele_1 = strtoul( p, &q, 0 );
57 240 : if( FD_UNLIKELY( p==(char const *)q ) ) return 0UL; /* Malformed sequence, seq_ele_1 is not a ulong */
58 213 : p = (char const *)q;
59 :
60 276 : c = *p; while( fd_isspace( (int)c ) ) c = *(++p); /* Move and peek at next non-white-space character */
61 213 : if( c=='/' || c==':' ) {
62 132 : p++;
63 :
64 132 : seq_stride = strtoul( p, &q, 0 );
65 132 : if( FD_UNLIKELY( p==(char const *)q ) ) return 0UL; /* Malformed sequence, seq_stride is not a ulong */
66 111 : p = (char const *)q;
67 111 : }
68 213 : }
69 :
70 384 : c = *p; while( fd_isspace( (int)c ) ) c = *(++p); /* Move and peek at next non-white-space character */
71 366 : if( !(c==',' || c=='\0' ) ) return 0UL; /* Malformed sequence, delimiter */
72 333 : if( c==',' ) p++;
73 :
74 : /* Append the range to sequence. Written this slightly funny way to
75 : be robust against overflow with seq_ele_1 and/or seq_stride being
76 : near or equal to ULONG_MAX */
77 :
78 333 : if( FD_UNLIKELY( (seq_ele_1<seq_ele_0) | (!seq_stride) )) return 0UL; /* Malformed sequence, bad range */
79 :
80 303 : ulong seq_ele = seq_ele_0;
81 6936 : while( ((seq_ele_0<=seq_ele) & (seq_ele<seq_ele_1)) ) {
82 6717 : if( FD_LIKELY( seq_cnt<seq_max ) ) seq[ seq_cnt ] = seq_ele;
83 6717 : seq_cnt++;
84 6717 : if( FD_UNLIKELY( seq_stride>seq_ele_1-seq_ele ) ) break;
85 6633 : seq_ele += seq_stride;
86 6633 : }
87 303 : if( seq_ele==seq_ele_1 ) {
88 219 : if( FD_LIKELY( seq_cnt<seq_max ) ) seq[ seq_cnt ] = seq_ele;
89 219 : seq_cnt++;
90 219 : }
91 303 : }
92 :
93 189 : return seq_cnt;
94 321 : }
95 :
96 : int
97 : fd_cstr_casecmp( char const * a,
98 15876 : char const * b ) {
99 15876 : return strcasecmp( a, b );
100 15876 : }
101 :
102 : ulong
103 : fd_cstr_nlen( char const * s,
104 846 : ulong m ) {
105 846 : return strnlen( s, m );
106 846 : }
107 :
108 : char *
109 : fd_cstr_ncpy( char * d,
110 : char const * s,
111 4495 : ulong m ) {
112 4495 : if( FD_LIKELY( m ) ){
113 4471 : ulong i = 0UL;
114 4471 : if( FD_LIKELY( s ) ) {
115 135393 : for( ; i<m-1UL; i++ ) {
116 132713 : char c = s[i];
117 132713 : if( !c ) break;
118 130946 : d[i] = c;
119 130946 : }
120 4447 : }
121 4471 : memset( d+i, 0, m-i );
122 4471 : }
123 4495 : return d;
124 4495 : }
125 :
126 : char *
127 : fd_cstr_printf( char * buf,
128 : ulong sz,
129 : ulong * opt_len,
130 60264856 : char const * fmt, ... ) {
131 60264856 : if( FD_UNLIKELY( (!buf) | (!sz) ) ) {
132 6 : if( opt_len ) *opt_len = 0UL;
133 6 : return buf;
134 6 : }
135 60264850 : va_list ap;
136 60264850 : va_start( ap, fmt );
137 60264850 : int ret = vsnprintf( buf, sz, fmt, ap );
138 60264850 : ulong len = fd_ulong_if( ret<0, 0UL, fd_ulong_min( (ulong)ret, sz-1UL ) );
139 60264850 : buf[ len ] = '\0';
140 60264850 : va_end( ap );
141 60264850 : if( opt_len ) *opt_len = len;
142 60264850 : return buf;
143 60264856 : }
144 :
145 : int
146 : fd_cstr_printf_check( char * buf,
147 : ulong sz,
148 : ulong * opt_len,
149 10793 : char const * fmt, ... ) {
150 10793 : if( FD_UNLIKELY( (!buf) | (!sz) ) ) {
151 6 : if( opt_len ) *opt_len = 0UL;
152 6 : return 0;
153 6 : }
154 10787 : va_list ap;
155 10787 : va_start( ap, fmt );
156 10787 : int ret = vsnprintf( buf, sz, fmt, ap );
157 10787 : ulong len = fd_ulong_if( ret<0, 0UL, fd_ulong_min( (ulong)ret, sz-1UL ) );
158 10787 : buf[ len ] = '\0';
159 10787 : va_end( ap );
160 10787 : if( opt_len ) *opt_len = len;
161 10787 : return len==(ulong)ret;
162 10793 : }
163 :
164 : char *
165 : fd_cstr_append_printf( char * buf,
166 1032 : char const * fmt, ... ) {
167 1032 : if( FD_UNLIKELY( !buf ) ) return NULL;
168 1032 : va_list ap;
169 1032 : va_start( ap, fmt );
170 1032 : int ret = vsprintf( buf, fmt, ap );
171 1032 : va_end( ap );
172 1032 : return buf + fd_ulong_if( ret<0, 0UL, (ulong)ret );
173 1032 : }
174 :
175 : ulong
176 : fd_cstr_tokenize( char ** tok,
177 : ulong tok_max,
178 : char * p,
179 1866 : char delim ) {
180 1866 : if( FD_UNLIKELY( !p ) ) return 0UL;
181 :
182 1863 : ulong tok_cnt = 0UL;
183 5541 : for(;;) {
184 :
185 : /* Find token start and record it (if possible) */
186 5658 : while( fd_isspace( (int)p[0] ) ) p++;
187 5541 : if( p[0]=='\0' ) break;
188 5385 : if( tok_cnt<tok_max ) tok[ tok_cnt ] = p;
189 5385 : tok_cnt++;
190 :
191 : /* Find the token end and terminate it */
192 27450 : while( ((p[0]!=delim) & (p[0]!='\0')) ) p++;
193 5385 : if( p[0]=='\0' ) break;
194 3678 : p[0] = '\0';
195 3678 : p++;
196 3678 : }
197 :
198 1863 : return tok_cnt;
199 1866 : }
|