string.c 31 KB

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