string.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675
  1. // Public Domain.
  2. #include <stdarg.h>
  3. #include <stddef.h> // ptrdiff_t
  4. #include <string.h>
  5. #include <stdint.h>
  6. #include <stdio.h> // printf, sprintf, vsnprintf
  7. #include <stdlib.h> // malloc, realloc
  8. #include <ctype.h>
  9. #include "string.h"
  10. static inline int is_x_digit(int c) {
  11. return (
  12. ('0' <= c && c <= '9') ||
  13. ('a' <= c && c <= 'f') ||
  14. ('A' <= c && c <= 'F')
  15. );
  16. }
  17. // returns a pointer to the found char, or NULL
  18. char* strnchr(const char* s, int c, size_t n) {
  19. for (size_t i = 0; i < n; i++) {
  20. if (s[i] == c) return (char*)&s[i];
  21. }
  22. return NULL;
  23. }
  24. // returns s
  25. char* strrev(char* s) {
  26. size_t len = 0;
  27. while (s[len]) len++;
  28. char tmp = '\0';
  29. for (size_t i = 0, back = len - 1; i < len / 2; i++, back--) {
  30. tmp = s[back];
  31. s[back] = s[i];
  32. s[i] = tmp;
  33. }
  34. return s;
  35. }
  36. // returns s
  37. char* strnrev(const char* s, size_t n) {
  38. char tmp = '\0', *result = (char*)s;
  39. for (size_t i = 0, back = n - 1; i < n / 2; i++, back--) {
  40. tmp = result[back];
  41. result[back] = result[i];
  42. result[i] = tmp;
  43. }
  44. return result;
  45. }
  46. // returns a pointer to the first match character
  47. char* strnpbrk(const char* s, const char* accept, size_t n) {
  48. uint64_t table[4] = {0};
  49. for (size_t j = 0; accept[j] != '\0'; j++)
  50. table[accept[j] >> 6] |= 1 << (accept[j] & 63);
  51. for (size_t i = 0; i < n; i++)
  52. if (table[s[i] >> 6] & 1 << (s[i] & 63)) return (char*)&s[i];
  53. return NULL;
  54. }
  55. // returns a pointer to the first match character
  56. char* strrpbrk(const char* s, const char* accept) {
  57. uint64_t table[4] = {0};
  58. for (size_t j = 0; accept[j] != '\0'; j++)
  59. table[accept[j] >> 6] |= 1 << (accept[j] & 63);
  60. char *result = NULL;
  61. for (size_t i = 0; s[i] != '\0'; i++)
  62. if (table[s[i] >> 6] & 1 << (s[i] & 63)) result = (char*)&s[i];
  63. return result;
  64. }
  65. // returns a pointer to the first match character
  66. char* strnrpbrk(const char* s, const char* accept, size_t n) {
  67. uint64_t table[4] = {0};
  68. for (size_t j = 0; accept[j] != '\0'; j++)
  69. table[accept[j] >> 6] |= 1 << (accept[j] & 63);
  70. char *result = NULL;
  71. for (size_t i = 0; i < n; i++)
  72. if (table[s[i] >> 6] & 1 << (s[i] & 63)) result = (char*)&s[i];
  73. return result;
  74. }
  75. // The length of the initial part of "s" not containing any of the characters that are part of "reject".
  76. size_t strncspn(const char* s, const char* reject, size_t n) {
  77. uint64_t table[4] = {0};
  78. for (size_t j = 0; reject[j] != '\0'; j++)
  79. table[reject[j] >> 6] |= 1 << (reject[j] & 63);
  80. size_t i = 0;
  81. for (; i < n; i++)
  82. if (table[s[i] >> 6] & 1 << (s[i] & 63)) return i;
  83. return i;
  84. }
  85. // The length of the initial part of "s" not containing any of the characters that are part of "reject".
  86. size_t strrcspn(const char* s, const char* reject) {
  87. uint64_t table[4] = {0};
  88. for (size_t j = 0; reject[j] != '\0'; j++)
  89. table[reject[j] >> 6] |= 1 << (reject[j] & 63);
  90. size_t i = 0, count = 0;
  91. for (; s[i] != '\0'; i++)
  92. if (table[s[i] >> 6] & 1 << (s[i] & 63)) count = 0;
  93. else count++;
  94. return count;
  95. }
  96. // The length of the initial part of "s" not containing any of the characters that are part of "reject".
  97. size_t strnrcspn(const char* s, const char* reject, size_t n) {
  98. uint8_t v, index;
  99. uint64_t table[4] = {0};
  100. for (size_t j = 0; reject[j] != '\0'; j++)
  101. table[reject[j] >> 6] |= 1 << (reject[j] & 63);
  102. size_t i = 0, count = 0;
  103. for (; i < n; i++)
  104. if (table[s[i] >> 6] & 1 << (s[i] & 63)) count = 0;
  105. else count++;
  106. return count;
  107. }
  108. // return the number of characters spanned
  109. size_t strnrspn(const char* s, const char* accept, size_t n) {
  110. uint64_t table[4] = {0};
  111. for (size_t j = 0; accept[j] != '\0'; j++)
  112. table[accept[j] >> 6] |= 1 << (accept[j] & 63);
  113. size_t i = 0, count = 0;
  114. for (; i < n; i++)
  115. if (!(table[s[i] >> 6] & 1 << (s[i] & 63))) count = 0;
  116. else count++;
  117. return count;
  118. }
  119. // moves chars to left, returns s
  120. char* strnltrim(char* s, const char* charset, size_t n) {
  121. uint8_t v, index;
  122. uint64_t table[4] = {0};
  123. for (size_t j = 0; charset[j] != '\0'; j++)
  124. table[charset[j] >> 6] |= 1 << (charset[j] & 63);
  125. size_t i = 0;
  126. while (i < n) {
  127. if (!(table[s[i] >> 6] & 1 << (s[i] & 63))) break;
  128. i++;
  129. }
  130. memmove(s, s + i, n - i);
  131. return s;
  132. }
  133. // does not trim, returns s
  134. char* strcolwsp(char* s, int c) {
  135. size_t size = 0;
  136. uint8_t multiple = 0;
  137. for (size_t i = 0; s[i] != '\0'; i++) {
  138. if (isspace(s[i])) {
  139. if (!multiple) {
  140. s[size++] = c;
  141. multiple = 1;
  142. }
  143. }
  144. else {
  145. s[size++] = s[i];
  146. multiple = 0;
  147. }
  148. }
  149. s[size] = '\0';
  150. return s;
  151. }
  152. // does not trim, returns s
  153. char* strncolwsp(char* s, int c, size_t n) {
  154. size_t size = 0;
  155. uint8_t multiple = 0;
  156. for (size_t i = 0; i < n; i++) {
  157. if (isspace(s[i])) {
  158. if (!multiple) {
  159. s[size++] = c;
  160. multiple = 1;
  161. }
  162. }
  163. else {
  164. s[size++] = s[i];
  165. multiple = 0;
  166. }
  167. }
  168. s[size] = '\0';
  169. return s;
  170. }
  171. // also trims, returns s
  172. char* strcolwsptrim(char* s, int c) {
  173. size_t size = 0;
  174. uint8_t multiple = 0;
  175. for (size_t i = 0; s[i] != '\0'; i++) {
  176. if (isspace(s[i])) {
  177. if (!multiple && size > 0) {
  178. s[size++] = c;
  179. multiple = 1;
  180. }
  181. }
  182. else {
  183. s[size++] = s[i];
  184. multiple = 0;
  185. }
  186. }
  187. if (size > 0)
  188. if (isspace(s[size - 1]))
  189. size--;
  190. s[size] = '\0';
  191. return s;
  192. }
  193. // capitalize the first letter following whitespace, and the beginning of the string, returns s
  194. char* strcapwords(char* s) {
  195. for (size_t i = 0; s[i] != '\0'; i++) {
  196. if (i == 0) s[i] = toupper(s[i]);
  197. else if (isspace(s[i])) {
  198. while (isspace(s[++i]));
  199. s[i] = toupper(s[i]);
  200. }
  201. }
  202. return s;
  203. }
  204. // capitalize the first letter following whitespace, and the beginning of the string, returns s
  205. char* strncapwords(char* s, size_t n) {
  206. for (size_t i = 0; i < n; i++) {
  207. if (i == 0) s[i] = toupper(s[i]);
  208. else if (isspace(s[i])) {
  209. while (isspace(s[++i]));
  210. s[i] = toupper(s[i]);
  211. }
  212. }
  213. return s;
  214. }
  215. // capitalize the first letter following terminal punctuation, and the beginning of the string, returns s
  216. char* strcapsentences(char* s) {
  217. for (size_t i = 0; s[i] != '\0'; i++) {
  218. if (i == 0) s[i] = toupper(s[i]);
  219. else if (s[i] == '.' || s[i] == '!' || s[i] == '?') {
  220. while (isspace(s[++i]));
  221. s[i] = toupper(s[i]);
  222. }
  223. }
  224. return s;
  225. }
  226. // capitalize the first letter following terminal punctuation, and the beginning of the string, returns s
  227. char* strncapsentences(char* s, size_t n) {
  228. for (size_t i = 0; i < n; i++) {
  229. if (i == 0) s[i] = toupper(s[i]);
  230. else if (s[i] == '.' || s[i] == '!' || s[i] == '?') {
  231. while (isspace(s[++i]));
  232. s[i] = toupper(s[i]);
  233. }
  234. }
  235. return s;
  236. }
  237. // length of the line, or length of the string if no \n found
  238. size_t strlnlen(const char* s) {
  239. char* n;
  240. n = strchr(s, '\n');
  241. if(!n) return strlen(s);
  242. return n - s;
  243. }
  244. // strdup a line
  245. char* strlndup(const char* s) {
  246. return strndup(s, strlnlen(s));
  247. }
  248. // line count;
  249. size_t strlinecnt(const char* s) {
  250. size_t n;
  251. if(!*s) return 0;
  252. n = 1;
  253. while(*s) // just to make you cringe
  254. if(*s++ == '\n')
  255. n++;
  256. return n;
  257. }
  258. // allocates a new buffer and calls sprintf with it
  259. // why isn't this a standard function?
  260. char* sprintfdup(char* fmt, ...) {
  261. va_list va;
  262. va_start(va, fmt);
  263. size_t n = vsnprintf(NULL, 0, fmt, va);
  264. char* buf = malloc(n + 1);
  265. va_end(va);
  266. va_start(va, fmt);
  267. vsnprintf(buf, n + 1, fmt, va);
  268. va_end(va);
  269. return buf;
  270. }
  271. // concatenate all argument strings together in a new buffer
  272. char* strcatdup_(size_t nargs, ...) {
  273. size_t total = 0;
  274. char* out, *end;
  275. if(nargs == 0) return NULL;
  276. // calculate total buffer len
  277. va_list va;
  278. va_start(va, nargs);
  279. for(size_t i = 0; i < nargs; i++) {
  280. char* s = va_arg(va, char*);
  281. if(s) total += strlen(s);
  282. }
  283. va_end(va);
  284. out = malloc((total + 1) * sizeof(char*));
  285. end = out;
  286. va_start(va, nargs);
  287. for(size_t i = 0; i < nargs; i++) {
  288. char* s = va_arg(va, char*);
  289. if(s) {
  290. strcpy(end, s); // not exactly the ost efficient, but maybe faster than
  291. end += strlen(s); // a C version. TODO: test the speed
  292. };
  293. }
  294. va_end(va);
  295. *end = 0;
  296. return out;
  297. }
  298. // concatenate all argument strings together in a new buffer,
  299. // with the given joining string between them
  300. char* strjoin_(char* joiner, size_t nargs, ...) {
  301. size_t total = 0;
  302. char* out, *end;
  303. size_t j_len;
  304. if(nargs == 0) return NULL;
  305. // calculate total buffer len
  306. va_list va;
  307. va_start(va, nargs);
  308. for(size_t i = 0; i < nargs; i++) {
  309. char* s = va_arg(va, char*);
  310. if(s) total += strlen(s);
  311. }
  312. va_end(va);
  313. j_len = strlen(joiner);
  314. total += j_len * (nargs - 1);
  315. out = malloc((total + 1) * sizeof(char*));
  316. end = out;
  317. va_start(va, nargs);
  318. for(size_t i = 0; i < nargs; i++) {
  319. char* s = va_arg(va, char*);
  320. if(s) {
  321. if(i > 0) {
  322. strcpy(end, joiner);
  323. end += j_len;
  324. }
  325. strcpy(end, s); // not exactly the ost efficient, but maybe faster than
  326. end += strlen(s); // a C version. TODO: test the speed
  327. };
  328. }
  329. va_end(va);
  330. *end = 0;
  331. return out;
  332. }
  333. // returns a null-terminated list of pointers to each line.
  334. // mutates the source (replaces newlines with nulls)
  335. char** strsplit_inplace(char* src, char delim, size_t* outLen) {
  336. size_t alloc = 8;
  337. size_t len = 0;
  338. char** out = malloc(alloc * sizeof(*out));
  339. char* start = src;
  340. size_t i;
  341. for(i = 0; src[i] != 0; i++) {
  342. if(src[i] == delim) {
  343. src[i] = 0; // put in a null terminator
  344. out[len++] = start;
  345. start = src + i + 1;
  346. // always have two extra for the end
  347. if(len + 1 >= alloc){
  348. alloc *= 2;
  349. out = realloc(out, alloc * sizeof(*out));
  350. }
  351. }
  352. }
  353. if(src + i != start) {
  354. out[len++] = start;
  355. }
  356. out[len] = NULL;
  357. if(outLen) *outLen = len;
  358. return out;
  359. }
  360. char** strsplit(char* src, char delim, size_t* outLen) {
  361. size_t alloc = 8;
  362. size_t len = 0;
  363. char** out = malloc(alloc * sizeof(*out));
  364. size_t start_i = 0;
  365. size_t i;
  366. for(i = 0; src[i] != 0; i++) {
  367. if(src[i] == delim) {
  368. out[len++] = strndup(src + start_i, i - start_i);
  369. start_i = i + 1;
  370. // always have two extra for the end
  371. if(len + 1 >= alloc){
  372. alloc *= 2;
  373. out = realloc(out, alloc * sizeof(*out));
  374. }
  375. }
  376. }
  377. if(i >= start_i) {
  378. out[len++] = strdup(src + start_i);
  379. }
  380. out[len] = NULL;
  381. if(outLen) *outLen = len;
  382. return out;
  383. }
  384. size_t strnspn(const char* s, size_t count, const char* accept) {
  385. const char* e = s;
  386. for(size_t i = 0; i < count && NULL != strchr(accept, *e); i++, e++);
  387. return e - s;
  388. }
  389. size_t strrspn(const char* s, const char* accept) {
  390. const char* e, *r;
  391. e = s;
  392. while(*e) e++;
  393. r = e - 1;
  394. while(r >= s && NULL != strchr(accept, *r))
  395. r--;
  396. return e - r - 1;
  397. }
  398. const char* strrstr(const char* haystack, const char* needle) {
  399. const char* best = NULL;
  400. for(const char* p = haystack; *p; p++) {
  401. for(long i = 0; ; i++) {
  402. if(needle[i] == 0) {
  403. best = p;
  404. break;
  405. }
  406. if(needle[i] != p[i] || !p[i]) {
  407. break;
  408. }
  409. }
  410. }
  411. return best;
  412. }
  413. size_t strtriml(char* s, const char* trim) {
  414. size_t n, l;
  415. n = strspn(s, trim);
  416. l = strlen(s + n);
  417. memmove(s, s + n, l + 1);
  418. return l;
  419. }
  420. size_t strtrimr(char* s, const char* trim) {
  421. size_t n = strrspn(s, trim);
  422. s[strlen(s) - n] = 0;
  423. return n;
  424. }
  425. // left and right
  426. size_t strtrim(char* s, const char* trim) {
  427. size_t n;
  428. strtriml(s, trim);
  429. n = strtrimr(s, trim);
  430. return n;
  431. }
  432. unsigned int decodeHexDigit(char c) {
  433. if(c >= '0' && c <= '9') {
  434. return c - '0';
  435. }
  436. else if(c >= 'a' && c <= 'f') {
  437. return 10 + (c - 'a');
  438. }
  439. else if(c >= 'A' && c <= 'F') {
  440. return 10 + (c - 'A');
  441. }
  442. return 0;
  443. }
  444. /*
  445. static double nibbleHexNorm(char* s) {
  446. if(s[0] == '\0' || s[1] == '\0') return 0.0;
  447. double d = (decodeHexDigit(s[0]) * 16.0) + decodeHexDigit(s[1]);
  448. return d / 256.0;
  449. }
  450. */
  451. // returns rgba, with r in most significant bits and a in the least
  452. uint32_t decodeHexColor(char* s) {
  453. int i;
  454. unsigned short c[4] = {0,0,0,255};
  455. // throw away any leading BS
  456. char* e = s + strlen(s);
  457. if(s[0] == '#') s++;
  458. if(s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) s += 2;
  459. // the actual decoding
  460. for(i = 0; i < 4 && s < e; i++) {
  461. c[i] = (decodeHexDigit(s[0]) << 4) + decodeHexDigit(s[1]);
  462. c[i] = c[i] > 255 ? 255 : c[i];
  463. s += 2;
  464. }
  465. // printf(" color: %d,%d,%d,%d\n", c[0], c[1], c[2], c[3]);
  466. uint32_t o =
  467. (((uint32_t)c[0]) << 24) |
  468. (((uint32_t)c[1]) << 16) |
  469. (((uint32_t)c[2]) << 8) |
  470. (((uint32_t)c[3]) << 0);
  471. return o;
  472. }
  473. void decodeHexColorNorm(char* s, float* out) {
  474. int i;
  475. out[0] = 0.0;
  476. out[1] = 0.0;
  477. out[2] = 0.0;
  478. out[3] = 1.0;
  479. // throw away any leading BS
  480. char* e = s + strlen(s);
  481. if(s[0] == '#') s++;
  482. if(s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) s += 2;
  483. // the actual decoding
  484. for(i = 0; i < 4 && s < e; i++) {
  485. int n = (decodeHexDigit(s[0]) << 4) + decodeHexDigit(s[1]);
  486. out[i] = n / 255.0;
  487. s += 2;
  488. }
  489. }
  490. // decodes strings according to the string literal rules in C
  491. // *s is advanced to the next char
  492. // gleefully advances the pointer through nulls like any other character
  493. // returns 1 if the character was escaped
  494. // returns an error code on invalid escape sequences
  495. int decode_c_string_char(char** s, int* c_out) {
  496. int acc = 0;
  497. int max = 4;
  498. int i;
  499. int c = **s;
  500. (*s)++;
  501. if(c != '\\') {
  502. *c_out = c;
  503. return 0;
  504. }
  505. // escape sequence of some kind
  506. c = **s;
  507. (*s)++;
  508. switch(c) {
  509. case 'a': *c_out = 0x07; break;
  510. case 'b': *c_out = 0x08; break;
  511. case 'e': *c_out = 0x1b; break;
  512. case 'f': *c_out = 0x0c; break;
  513. case 'n': *c_out = 0x0a; break;
  514. case 'r': *c_out = 0x0d; break;
  515. case 't': *c_out = 0x09; break;
  516. case 'v': *c_out = 0x0b; break;
  517. case '\\': *c_out = 0x5c; break;
  518. case '\'': *c_out = 0x27; break;
  519. case '"': *c_out = 0x22; break;
  520. case '?': *c_out = 0x3f; break;
  521. case '0': // \nnn octal
  522. case '1': case '2': case '3': case '4': case '5': case '6': case '7':
  523. for(i = 0; i < 3; i++) {
  524. acc = (acc << 3) + c - '0';
  525. c = **s;
  526. (*s)++;
  527. if('0' > c || c > '9') break;
  528. }
  529. *c_out = acc;
  530. return 1;
  531. case 'x': // \xnn... hex sequence
  532. for(i = 0;; i++) {
  533. c = **s;
  534. (*s)++;
  535. if(!is_x_digit(c)) break;
  536. acc = (acc << 4) + decodeHexDigit(c);
  537. }
  538. *c_out = acc;
  539. return i >= 1 ? 1 : -1;
  540. case 'U': // \Unnnnnnnn
  541. max = 8;
  542. /* fallthrough */
  543. case 'u': // \unnnn hex
  544. for(i = 0; i < max; i++) {
  545. c = **s;
  546. (*s)++;
  547. if(!is_x_digit(c)) break;
  548. acc = (acc << 4) + decodeHexDigit(c);
  549. }
  550. *c_out = acc;
  551. return i == max ? 1 : -1;
  552. default:
  553. *c_out = c;
  554. return -2;
  555. }
  556. return 1;
  557. }
  558. int is_number_char(int c) {
  559. switch(c) {
  560. case '0':
  561. case '1':
  562. case '2':
  563. case '3':
  564. case '4':
  565. case '5':
  566. case '6':
  567. case '7':
  568. case '8':
  569. case '9':
  570. case '-':
  571. case '.':
  572. case 'e':
  573. case 'E':
  574. case 'x':
  575. case 'X':
  576. return 1;
  577. }
  578. return 0;
  579. }
  580. int read_c_number(char** s, number_parse_info* info) {
  581. char* s2 = *s;
  582. // probe the base
  583. if(s2[0] == '0') {
  584. if(s2[1] == 'x' || s2[1] == 'X') {
  585. info->base = 16;
  586. }
  587. if(s2[1] == 'b' || s2[1] == 'B') {
  588. info->base = 2;
  589. }
  590. else {
  591. info->base = 8;
  592. }
  593. s2 += 2;
  594. }
  595. else {
  596. info->base = 10;
  597. }
  598. // probe if it's a float or an integer type so the right fn can be called
  599. // skip past numbers until we find an indicator
  600. char type = 'i';
  601. for(int i = 0; s2[i]; i++) {
  602. if(isxdigit(s2[i])) continue;
  603. switch(s2[i]) {
  604. case '.':
  605. case 'e':
  606. case 'E':
  607. type = 'f';
  608. break;
  609. case 'p':
  610. case 'P':
  611. if(info->base == 16) {
  612. type = 'f';
  613. }
  614. break;
  615. }
  616. break;
  617. }
  618. // convert the numeric part
  619. if(type == 'i') {
  620. info->n = strtoull(*s, &s2, info->base);
  621. }
  622. else {
  623. info->f = strtold(*s, &s2);
  624. }
  625. // check for suffixes
  626. while(*s2) {
  627. switch(s2[0]) {
  628. case 'u':
  629. case 'U':
  630. info->not_signed = 'u';
  631. s2++;
  632. continue;
  633. case 'l':
  634. case 'L':
  635. info->longs++;
  636. s2++;
  637. continue;
  638. }
  639. break;
  640. }
  641. *s = s2;
  642. return 0;
  643. }
  644. /*
  645. char** sane_prefixes[] = {
  646. "B",
  647. "KB",
  648. "MB",
  649. "GB",
  650. "TB",
  651. "PB",
  652. "EB",
  653. "ZB",
  654. "YB",
  655. };
  656. void format_bytes(char* buf, size_t buf_len, uint64_t bytes, int sig_figs) {
  657. // find the greatest two sections
  658. uint64_t n = bytes;
  659. uint64_t old = 0;
  660. int oom = 0;
  661. while(1) {
  662. if(n < 1024) break;
  663. old = n;
  664. n /= 1024;
  665. }
  666. old -= n * 1024;
  667. }
  668. */
  669. /*
  670. Returns the reversed string
  671. Garbage in, garbage out.
  672. Unsigned ints only.
  673. Dont't give a base of 1.
  674. Dont't give a base greater than 36.
  675. Give a sufficiently long buffer. You figure it out first.
  676. Give a char set as long as your base.
  677. */
  678. /*static*/ int uint_r_cvt_str(uint64_t n, int base, char* buf, char* charset) {
  679. int i = 0;
  680. while(n > 0) {
  681. int64_t b = n / base;
  682. int a = n % base;
  683. buf[i++] = charset[a];
  684. n = b;
  685. }
  686. return i;
  687. }
  688. /*
  689. Does not add a minus character
  690. Garbage in, garbage out.
  691. Dont't give a base of 1.
  692. Dont't give a base greater than 36.
  693. Give a sufficiently long buffer. You figure it out first.
  694. Give a char set as long as your base.
  695. */
  696. /*static*/ int int_r_cvt_str(int64_t n, int base, char* buf, char* charset) {
  697. // char negative = 0;
  698. int i = 0;
  699. if(n < 0) {
  700. // negative = 1;
  701. n = -n;
  702. }
  703. i = uint_r_cvt_str(n, base, buf, charset);
  704. // if(negative) buf[i++] = '-';
  705. // GPUEDIT: reformat all numbers in selection by fmt string
  706. return i;
  707. }
  708. /*static*/ int flt_r_cvt_str(float f, int base, char* buf, char* charset) {
  709. int i = 0;
  710. union {
  711. float f;
  712. uint32_t u;
  713. } u;
  714. u.f = f;
  715. uint32_t nf = u.u;
  716. if(nf == 0x7f800000) { // infinity
  717. strcpy(buf, "infinity");
  718. return strlen("infinity");
  719. }
  720. if(nf == 0xff800000) { // -infinity
  721. strcpy(buf, "-infinity");
  722. return strlen("-infinity");
  723. }
  724. uint32_t sign = (nf & 0x80000000) >> 31;
  725. uint32_t exp_r = (nf & 0x7ff00000) >> 20;
  726. uint32_t frac = (nf & 0x000fffff) | 0x00100000;
  727. int32_t exp = exp_r - 127;
  728. printf("%x, %x, %x\n", sign, exp_r, frac);
  729. (void)base;
  730. (void)buf;
  731. (void)charset;
  732. (void)exp;
  733. while(nf > 0) {
  734. int64_t b = nf / base;
  735. int a = nf % base;
  736. buf[i++] = charset[a];
  737. nf = b;
  738. }
  739. // if(negative) buf[i++] = '-';
  740. return i;
  741. }
  742. /*
  743. Garbage in, garbage out.
  744. Dont't give a base of 1.
  745. Dont't give a base greater than 36.
  746. Give a sufficiently long buffer. You figure it out first.
  747. */
  748. /*static*/ int int_r_cvt(int64_t n, int base, int upper, char* buf) {
  749. if(n == 0) {
  750. buf[0] = '0';
  751. return 1;
  752. }
  753. static char* lchars = "0123456789abcdefghijklmnopqrstuvwxyz";
  754. static char* uchars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  755. return int_r_cvt_str(n, base, buf, upper ? uchars : lchars);
  756. }
  757. /*
  758. Garbage in, garbage out.
  759. Dont't give a base of 1.
  760. Dont't give a base greater than 36.
  761. Give a sufficiently long buffer. You figure it out first.
  762. */
  763. /*static*/ int uint_r_cvt(uint64_t n, int base, int upper, char* buf) {
  764. if(n == 0) {
  765. buf[0] = '0';
  766. return 1;
  767. }
  768. static char* lchars = "0123456789abcdefghijklmnopqrstuvwxyz";
  769. static char* uchars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  770. return uint_r_cvt_str(n, base, buf, upper ? uchars : lchars);
  771. }
  772. int sprintlongb(char* buf, int base, int64_t n, char* charset) {
  773. char negative = 0;
  774. int o = 0;
  775. if(n < 0) {
  776. negative = 1;
  777. n = -n;
  778. }
  779. while(n > 0) {
  780. int64_t b = n / base;
  781. int a = n % base;
  782. buf[o++] = charset[a];
  783. n = b;
  784. }
  785. if(negative) buf[o++] = '-';
  786. int limit = o / 2;
  787. char tmp;
  788. int i;
  789. for(i=0;i<limit;i++) {
  790. tmp = buf[o-i-1];
  791. buf[o-i-1] = buf[i];
  792. buf[i] = tmp;
  793. }
  794. buf[o] = '\0';
  795. return o;
  796. }
  797. int int_r_add_commas(char* buf, int len) {
  798. char tmp[64];
  799. int n = 0;
  800. strncpy(tmp, buf, len);
  801. for(int i = 0; i < len; n++, i++) {
  802. if(i && i % 3 == 0) {
  803. buf[n++] = ',';
  804. }
  805. buf[n] = tmp[i];
  806. }
  807. return n;
  808. }
  809. int iprintf(char* fmt, ...) {
  810. (void)fmt;
  811. #if 0
  812. va_list va;
  813. va_start(va, fmt);
  814. int n = 0;
  815. for(size_t i = 0; fmt[i]; i++) {
  816. char c = fmt[i];
  817. if(c == '%') {
  818. // %[flags][width][.precision][length]specifier
  819. int64_t i64;
  820. uint64_t u64;
  821. char* str;
  822. // double dbl;
  823. int len;
  824. int starti = i;
  825. char* start = fmt + i;
  826. char fmtbuf[16];
  827. char buf[64];
  828. char uppercase = 0;
  829. char add_commas = 0;
  830. char force_sign = 0;
  831. // char left_justify = 0;
  832. // char optional_sign = 0;
  833. // char force_decimal = 0;
  834. // char pad_zeroes = 0;
  835. // char vector_print = 0;
  836. // int width = 0;
  837. // int precision = 0;
  838. c = fmt[++i];
  839. if(c == 0) break;
  840. if(c == '%') {
  841. putc('%', stdout);
  842. continue;
  843. }
  844. // flags
  845. while(1) {
  846. if(c == 0) { // end of fmt string
  847. goto END_STR;
  848. }
  849. else if(c == ',') { // add thousands separators
  850. add_commas = 1;
  851. c = fmt[++i];
  852. }
  853. else if(c == '-') { // left-justify
  854. c = fmt[++i];
  855. }
  856. else if(c == '+') { // show sign
  857. force_sign = 1;
  858. c = fmt[++i];
  859. }
  860. else if(c == ' ') { // optional sign
  861. c = fmt[++i];
  862. }
  863. else if(c == '#') { // force decimal point
  864. c = fmt[++i];
  865. }
  866. else if(c == '0') { // left-pad zeroes
  867. c = fmt[++i];
  868. }
  869. else if(c == 'v') { // vector
  870. c = fmt[++i];
  871. }
  872. else break;
  873. }
  874. // width
  875. if(c == '*') { // specified in args
  876. i++;
  877. // va_arg(va, n);
  878. n++;
  879. }
  880. else if(c >= '0' && c <= '9') {
  881. while(c >= '0' && c <= '9') {
  882. c = fmt[i++];
  883. if(c == 0) goto END_STR;
  884. }
  885. }
  886. // precision
  887. if(c == '.') {
  888. c = fmt[++i];
  889. if(c == 0) goto END_STR;
  890. else if(c == '*') { // specified in args
  891. n++;
  892. // va_arg(va, n);
  893. }
  894. else {
  895. while(c >= '0' && c <= '9') {
  896. c = fmt[i++];
  897. if(c == 0) goto END_STR;
  898. }
  899. }
  900. }
  901. // length
  902. if(c == 0) goto END_STR;
  903. else if(c == 'h') { // short int // hh = char
  904. c = fmt[i++];
  905. }
  906. else if(c == 'l') { // long // ll = long long
  907. c = fmt[i++];
  908. }
  909. else if(c == 'z') { // size_t
  910. c = fmt[i++];
  911. }
  912. else if(c == 't') { // ptrdiff_t
  913. c = fmt[i++];
  914. }
  915. else if(c == 'j') { // uintmax_t
  916. c = fmt[i++];
  917. }
  918. else if(c == 'L') { // long double
  919. c = fmt[i++];
  920. }
  921. // specifier
  922. switch(c) {
  923. case 0: goto END_STR;
  924. case 'b': // binary
  925. u64 = va_arg(va, uint64_t);
  926. len = uint_r_cvt(u64, 2, uppercase, buf);
  927. for(int i = len - 1; i >=0; i--) {
  928. putc(buf[i], stdout);
  929. }
  930. break;
  931. case 'd':
  932. case 'i': // signed decimal int
  933. i64 = va_arg(va, int64_t);
  934. len = int_r_cvt(i64, 10, uppercase, buf);
  935. if(add_commas) {
  936. // causes an annoying warning i don't feel like dealing with now
  937. // len = int_r_add_commas(buf, len);
  938. }
  939. if(force_sign && i64 > 0) putc('+', stdout);
  940. if(i64 < 0) putc('-', stdout);
  941. for(int i = len - 1; i >=0; i--) {
  942. putc(buf[i], stdout);
  943. }
  944. break;
  945. case 'u': // unsigned decimal int
  946. u64 = va_arg(va, uint64_t);
  947. len = uint_r_cvt(u64, 10, uppercase, buf);
  948. if(add_commas) {
  949. // causes an annoying warning i don't feel like dealing with now
  950. // len = int_r_add_commas(buf, len);
  951. }
  952. if(force_sign) putc('+', stdout);
  953. for(int i = len - 1; i >=0; i--) {
  954. putc(buf[i], stdout);
  955. }
  956. break;
  957. case 'o': // unsigned octal int
  958. u64 = va_arg(va, uint64_t);
  959. len = uint_r_cvt(u64, 8, uppercase, buf);
  960. if(force_sign) putc('+', stdout);
  961. for(int i = len - 1; i >=0; i--) {
  962. putc(buf[i], stdout);
  963. }
  964. break;
  965. case 'X': uppercase = 1; /* fallthrough */
  966. case 'x': // unsigned hex int
  967. u64 = va_arg(va, uint64_t);
  968. len = uint_r_cvt(u64, 16, uppercase, buf);
  969. if(force_sign) putc('+', stdout);
  970. for(int i = len - 1; i >=0; i--) {
  971. putc(buf[i], stdout);
  972. }
  973. break;
  974. // printing floats is very complicated.
  975. // fall back to printf, because custom float printing is
  976. // not the point of iprintf()
  977. case 'F': uppercase = 1; /* fallthrough */
  978. // break;
  979. case 'E': uppercase = 1; /* fallthrough */
  980. // break; /* fallthrough */
  981. case 'G': uppercase = 1; /* fallthrough */
  982. // break; /* fallthrough */
  983. case 'A': uppercase = 1; /* fallthrough */
  984. case 'f': // float, decimal
  985. case 'e': // decimal scientific notation
  986. case 'g': // shortest of e/f
  987. case 'a': // hex float
  988. strncpy(fmtbuf, start, i - starti);
  989. sprintf(buf, fmtbuf, va_arg(va, double));
  990. puts(buf);
  991. break;
  992. case 'c': // character
  993. putc(va_arg(va, int), stdout);
  994. break;
  995. case 's': // string
  996. str = va_arg(va, char*);
  997. fputs(str, stdout);
  998. break;
  999. case 'P': // shortened pointer
  1000. case 'p': // pointer
  1001. u64 = va_arg(va, uint64_t);
  1002. len = uint_r_cvt(u64, 16, 0, buf);
  1003. fputs("0x", stdout);
  1004. for(int i = len - 1; i >=0; i--) {
  1005. putc(buf[i], stdout);
  1006. }
  1007. break;
  1008. case 'n': // set arg to number of chars written
  1009. break;
  1010. default:
  1011. break;
  1012. }
  1013. (void)uppercase;
  1014. }
  1015. else {
  1016. putc(c, stdout);
  1017. }
  1018. }
  1019. END_STR:
  1020. va_end(va);
  1021. #endif
  1022. return 0;
  1023. }
  1024. /*
  1025. static void indirect(int amt, int index, void** a, void** b, void** c) {
  1026. if(index == 0) {
  1027. while(amt-- > 0) *a = *((void**)(*a));
  1028. }
  1029. else if(index == 1) {
  1030. while(amt-- > 0) *b = *((void**)(*b));
  1031. }
  1032. else {
  1033. while(amt-- > 0) *c = *((void**)(*c));
  1034. }
  1035. }
  1036. */
  1037. int isnprintfv(char* out, ptrdiff_t out_sz, char* fmt, void** args) {
  1038. (void)out;
  1039. (void)out_sz;
  1040. (void)fmt;
  1041. (void)args;
  1042. #if 0
  1043. int n = 0;
  1044. int ar = 0;
  1045. char fmt_buf[64];
  1046. fmt_buf[0] = '%';
  1047. for(size_t i = 0; fmt[i];) {
  1048. char c = fmt[i];
  1049. // printf("+i:%ld+", i);
  1050. if(c == '%') {
  1051. int Indirect = 0;
  1052. char Int = 0;
  1053. char Double = 0;
  1054. char Pointer = 0;
  1055. // char Broken = 0;
  1056. char WidthStar = 0;
  1057. // char WidthDollar = 0;
  1058. char PrecStar = 0;
  1059. // char PrecDollar = 0;
  1060. char Long = 0;
  1061. char Half = 0;
  1062. int fblen = 1;
  1063. int numExtra = 0;
  1064. c = fmt[++i];
  1065. if(c == 0) break;
  1066. if(c == '%') {
  1067. if(n < out_sz - 1) out[n] = '%';
  1068. i++;
  1069. n++;
  1070. continue;
  1071. }
  1072. // flags
  1073. while(1) {
  1074. switch(c) {
  1075. default:
  1076. goto END_FLAGS;
  1077. case '#':
  1078. case '0':
  1079. case '-':
  1080. case ' ':
  1081. case '+':
  1082. case '\'':
  1083. case 'I':
  1084. fmt_buf[fblen++] = c;
  1085. c = fmt[++i];
  1086. continue;
  1087. case '>':
  1088. Indirect++;
  1089. c = fmt[++i];
  1090. continue;
  1091. }
  1092. }
  1093. END_FLAGS:
  1094. // field width
  1095. if(c == '*') {
  1096. WidthStar = 1;
  1097. fmt_buf[fblen++] = c;
  1098. c = fmt[++i];
  1099. }
  1100. while(1) {
  1101. if(c < '0' || c > '9') break;
  1102. fmt_buf[fblen++] = c;
  1103. c = fmt[++i];
  1104. }
  1105. if(WidthStar && c == '$') {
  1106. // WidthDollar = 1;
  1107. fmt_buf[fblen++] = c;
  1108. c = fmt[++i];
  1109. }
  1110. // precision
  1111. if(c == '.') {
  1112. fmt_buf[fblen++] = c;
  1113. c = fmt[++i];
  1114. if(c == '*') {
  1115. PrecStar = 1;
  1116. fmt_buf[fblen++] = c;
  1117. c = fmt[++i];
  1118. }
  1119. while(1) {
  1120. if(c < '0' || c > '9') break;
  1121. fmt_buf[fblen++] = c;
  1122. c = fmt[++i];
  1123. }
  1124. if(c == '$') {
  1125. // PrecDollar = 1;
  1126. fmt_buf[fblen++] = c;
  1127. c = fmt[++i];
  1128. }
  1129. }
  1130. // length
  1131. switch(c) {
  1132. case 'h':
  1133. Half = 1;
  1134. goto LENGTH_NEXT;
  1135. case 'l':
  1136. case 'L':
  1137. case 'z':
  1138. case 'Z':
  1139. case 't':
  1140. Long = 1; /* fallthrough */
  1141. // case 'hh':
  1142. // case 'll':
  1143. case 'q':
  1144. case 'j':
  1145. LENGTH_NEXT:
  1146. fmt_buf[fblen++] = c;
  1147. c = fmt[++i];
  1148. }
  1149. // conversion specifier
  1150. switch(c) {
  1151. case 'C':
  1152. Long = 1; /* fallthrough */
  1153. case 'd':
  1154. case 'i':
  1155. case 'o':
  1156. case 'u':
  1157. case 'x':
  1158. case 'X':
  1159. case 'c':
  1160. Int = 1;
  1161. break;
  1162. case 'e':
  1163. case 'E':
  1164. case 'f':
  1165. case 'F':
  1166. case 'g':
  1167. case 'G':
  1168. case 'a':
  1169. case 'A':
  1170. Double = 1;
  1171. break;
  1172. case 's':
  1173. case 'S':
  1174. case 'p':
  1175. Pointer = 1;
  1176. break;
  1177. case 'n':
  1178. *((uint64_t*)args[ar]) = n;
  1179. ar++;
  1180. i++;
  1181. continue;
  1182. // case 'm': // not supported
  1183. default:
  1184. // Broken = 1;
  1185. fprintf(stderr, "Broken format specifier.\n");
  1186. i++;
  1187. continue;
  1188. // broken specifier
  1189. }
  1190. fmt_buf[fblen++] = c;
  1191. fmt_buf[fblen] = 0;
  1192. c = fmt[++i];
  1193. // printf("(%s)", fmt_buf);
  1194. if(PrecStar) numExtra++;
  1195. if(WidthStar) numExtra++;
  1196. void* a = args[ar];
  1197. void* b = args[ar+1];
  1198. void* c = args[ar+2];
  1199. indirect(Indirect, numExtra, &a, &b, &c);
  1200. /*
  1201. if(Double) {
  1202. if(Half) { // yes, backwards, but compatible with standard format strings
  1203. if(numExtra == 0) n += snprintf(out + n, out_sz - n, fmt_buf, *((float*)&a));
  1204. else if(numExtra == 1) n += snprintf(out + n, out_sz - n, fmt_buf, (uint64_t)a, *((float*)&b));
  1205. else if(numExtra == 2) n += snprintf(out + n, out_sz - n, fmt_buf, (uint64_t)a, (uint64_t)b, *((float*)&c));
  1206. }
  1207. else {
  1208. if(numExtra == 0) n += snprintf(out + n, out_sz - n, fmt_buf, *((double*)&a));
  1209. else if(numExtra == 1) n += snprintf(out + n, out_sz - n, fmt_buf, (uint64_t)a, *((double*)&b));
  1210. else if(numExtra == 2) n += snprintf(out + n, out_sz - n, fmt_buf, (uint64_t)a, (uint64_t)b, *((double*)&c));
  1211. }
  1212. }
  1213. else if(Pointer) {
  1214. if(numExtra == 0) n += snprintf(out + n, out_sz - n, fmt_buf, (void*)a);
  1215. else if(numExtra == 1) n += snprintf(out + n, out_sz - n, fmt_buf, (uint64_t)a, (void*)b);
  1216. else if(numExtra == 2) n += snprintf(out + n, out_sz - n, fmt_buf, (uint64_t)a, (uint64_t)b, (void*)c);
  1217. }
  1218. else if(Int) {
  1219. if(Long) {
  1220. if(numExtra == 0) n += snprintf(out + n, out_sz - n, fmt_buf, (uint64_t)a);
  1221. else if(numExtra == 1) n += snprintf(out + n, out_sz - n, fmt_buf, (uint64_t)a, (uint64_t)b);
  1222. else if(numExtra == 2) n += snprintf(out + n, out_sz - n, fmt_buf, (uint64_t)a, (uint64_t)b, (uint64_t)c);
  1223. }
  1224. else { // careful of precision
  1225. // BUG fix int cast
  1226. if(numExtra == 0) n += snprintf(out + n, out_sz - n, fmt_buf, (uint32_t)(uint64_t)a);
  1227. else if(numExtra == 1) n += snprintf(out + n, out_sz - n, fmt_buf, (uint64_t)a, (uint32_t)(uint64_t)b);
  1228. else if(numExtra == 2) n += snprintf(out + n, out_sz - n, fmt_buf, (uint64_t)a, (uint64_t)b, (uint32_t)(uint64_t)c);
  1229. }
  1230. }
  1231. */
  1232. // printf("-ex:%d-", numExtra);
  1233. ar += 1 + numExtra;
  1234. }
  1235. else {
  1236. if(n < out_sz - 1) out[n] = c;
  1237. n++;
  1238. i++;
  1239. }
  1240. }
  1241. out[out_sz < n ? out_sz : n] = 0;
  1242. return n;
  1243. #endif
  1244. return 0;
  1245. }
  1246. #ifdef STI_REPLACE_STD_STRING
  1247. #if !__has_builtin(__builtin_memcpy)
  1248. void* memcpy(void* restrict dst, const void *restrict src, size_t n) {
  1249. void* d = dst;
  1250. while(n--) *dst++ = *src++;
  1251. return d;
  1252. }
  1253. #endif
  1254. #if !__has_builtin(__builtin_memset)
  1255. void* memset(void* s, int c, size_t n) {
  1256. while(n--) ((unsigned char*)s)[n] = c;
  1257. return s;
  1258. }
  1259. #endif
  1260. #endif // STI_REPLACE_STD_STRING