libsheepy.h (240569B)
1 // MIT License 2 // 3 // Copyright (c) 2026 Remy Noulin 4 // 5 // Permission is hereby granted, free of charge, to any person obtaining a copy 6 // of this software and associated documentation files (the "Software"), to deal 7 // in the Software without restriction, including without limitation the rights 8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 // copies of the Software, and to permit persons to whom the Software is 10 // furnished to do so, subject to the following conditions: 11 // 12 // The above copyright notice and this permission notice shall be included in all 13 // copies or substantial portions of the Software. 14 // 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 // SOFTWARE. 22 23 #ifndef _libsheepyH 24 #define _libsheepyH 25 // libsheepy 26 // can't use #pragma once for some reason (gcc 4.9), compilation fails 27 28 #ifndef _GNU_SOURCE 29 #define _GNU_SOURCE 30 #endif // _GNU_SOURCE 31 #include <sys/types.h> 32 #include <sys/stat.h> 33 #include <stdio.h> 34 #include <stdint.h> 35 #include <stdbool.h> 36 #include <stdlib.h> 37 #include <ctype.h> 38 #ifdef __GNUC__ 39 #if !defined(__arm__) && !defined(__aarch64__) && !defined(__riscv) 40 #include <immintrin.h> 41 #endif // #if !defined(__arm__) && !defined(__aarch64__) && !defined(__riscv) 42 #endif // __GNUC__ 43 #include <time.h> 44 #include <setjmp.h> 45 #ifdef __TINYC__ 46 #define and && 47 #define or || 48 #define not ! 49 #else 50 #include <iso646.h> /* and or not defines */ 51 #endif 52 #include <inttypes.h> /* for PRIu64 in stopwatchLog */ 53 #include <unistd.h> /* for sleep,... */ 54 #include <string.h> /* for strerror */ 55 #include <errno.h> 56 57 /** \file 58 * This file has basic file, random, string, list functions 59 * 60 * There are 2 types of lists: char** and void** 61 * 62 * The *S (not i*S) functions duplicate the parameters and results. 63 * You must free the result if result is non-NULL and free the parameters 64 * 65 * The functions starting with i*S are in place functions. 66 * 67 * In Place functions: iList*S and i*S 68 * The iList*S and i*S functions modify the input buffers 69 * The input buffers must be allocated with malloc/calloc 70 * Returns are pointers to original buffers 71 * 72 * buffer functions: b*, bL* 73 * In these functions, the destination buffer is allocated by the caller 74 * In the bL* functions, the destination size is the size of the buffer (strlen+1) 75 * 76 * Ignore case functions: ic* 77 * 78 * UTF-8 functions: *UTF8 79 * Rune is defined as single UTF-8 code point. 80 * 81 * libsheepy.h also has: 82 * - loops: range*, forEach*, linked list forEach (lForEach) 83 * - arrays: slice, vector, staticArray, indexer, ring, dArray, slab 84 * 85 * It is advised to use the C11 generics from libsheepyObject.h instead of the libsheepy.h functions directly because there are many functions. 86 * 87 * If you want to add a prefix for libsheepy functions, define a macro 88 * like this: 89 * #define SH_PREFIX(NAME) MY_PREFIX ## NAME 90 * 91 * Error from any function returning a status have 0, false or NULL for value 92 * (or specifed otherwise in the function description). 93 * Errors are reported when the parameters are NULL or invalid, when it happens no parameters and no data stuctures are freed or changed. 94 * Errors are detected with if (!func) 95 * 96 * For more information, the documentation is located at http://spartatek.se/libsheepy/ 97 */ 98 99 // version accoring to the version package: Release.Major.minor.patch 100 // https://noulin.net/version/file/README.md.html 101 #define LIBSHEEPY_VERSION "2.2.20" 102 103 #ifndef SH_PREFIX 104 #define SH_PREFIX(NAME) NAME 105 #endif 106 107 // libsheepy API Header file _libsheepyH 108 109 /** file internal declarations */ 110 #define internal static 111 112 /** file local declarations (same as internal, shorter word) */ 113 #define local static 114 115 /** declare variable type automaticaly: var a = ARGC; */ 116 #define var __auto_type 117 118 /** type bool true (glibc true is not bool), for use in generics */ 119 #undef TRUE /* avoid conflict with ncurses */ 120 extern const bool TRUE; 121 /** type bool false (glibc true is not bool), for use in generics */ 122 #undef FALSE /* avoid conflict with ncurses */ 123 extern const bool FALSE; 124 125 /** convenience defines */ 126 #define null NULL 127 #define yes true 128 #define on true 129 #define no false 130 #define off false 131 132 /** bool to const string: printf("%s\n", boolS(boolValue)); */ 133 #define boolS(x) x ? "TRUE" : "FALSE" 134 135 /** 136 * success 137 */ 138 #define XSUCCESS exit(EXIT_SUCCESS); 139 #define XSuccess XSUCCESS 140 141 /** 142 * failure 143 */ 144 #define XFAILURE exit(EXIT_FAILURE); 145 #define XFailure XFAILURE 146 147 /** 148 * log string with logP and exit with success 149 * 150 * This is useful to know at which line a program exits 151 */ 152 #define logXSuccess(string) MACRO(\ 153 logP("Success: %s", string);\ 154 XSuccess;\ 155 ) 156 157 /** 158 * log formated string with logP and exit with success 159 * 160 * This is useful to know at which line a program exits 161 * The format string is printed as given, "Success" is not added unlike 162 * logXSuccess 163 */ 164 #define logXSuccessf(format, ...) MACRO(\ 165 logP(format, __VA_ARGS__);\ 166 XSuccess;\ 167 ) 168 169 /** 170 - * log string with logC and exit with failure 171 * 172 * This is useful to know at which line a program exits 173 */ 174 #define logXFailure(string) MACRO(\ 175 logC("Failed: %s", string);\ 176 XFailure;\ 177 ) 178 179 /** 180 * log formated string with logC and exit with failure 181 * 182 * This is useful to know at which line a program exits 183 * The format string is printed as given, "Failed" is not added unlike 184 * logXFailure 185 */ 186 #define logXFailuref(format, ...) MACRO(\ 187 logC(format, __VA_ARGS__);\ 188 XFailure;\ 189 ) 190 191 /** 192 * log string with logI and exit with exitCode 193 * 194 * This is useful to know at which line a program exits 195 */ 196 #define logExit(exitCode, string) MACRO (\ 197 logI("Exit: %s", string);\ 198 exit(exitCode);\ 199 ) 200 201 /** 202 * exit failure 203 * 204 * Exits when cond is false 205 */ 206 #define exitFailure(cond) \ 207 if (!cond) \ 208 exit(EXIT_FAILURE); 209 210 211 /** 212 * defines for macro begin and end 213 * 214 * Macros not returning values are usually written as do while loops: 215 * #define macro(value) do{ 216 * puts(value); 217 * } while(0) 218 * 219 * Using the defines below: 220 * #define macro(value) procbegin\ 221 * puts(value);\ 222 * procend 223 * 224 * procbegin and procend are for macros not returning a value (like procedure in pascal) 225 * funcbegin and funcend are for macros returning a value like functions 226 * 227 * Macro returning a value (GNU extension): 228 * #define macro(value) funcbegin\ 229 * int returnResult = value + 2;\ 230 * returnResult;\ 231 * funcend 232 */ 233 #define procbegin do{ 234 #define procend }while(0) 235 #define funcbegin ({ 236 #define funcend }) 237 238 /** 239 * do while(0) alternative macro definition 240 * 241 * #define macro(param) MACRO( logVarG(param) ) 242 */ 243 #define MACRO( STATEMENTS ) do { STATEMENTS } while(0) 244 245 /** 246 * Macro returning a value (GNU extension): 247 * #define macro(value) FUNC(\ 248 * int returnResult = value + 2;\ 249 * returnResult;\ 250 * ) 251 * 252 */ 253 #define FUNC( STATEMENTS) ({ STATEMENTS }) 254 255 /** additions to iso646 256 * int a is 0; 257 * if (a equals 1 or a equals 2) a shl = 2; 258 * else a inc; 259 * return ptr_to a; 260 * 261 * int *b is &a; 262 * val_of b is a; 263 * val_of b dec; 264 */ 265 #define is = 266 #define equals == 267 #define nequal != 268 #define shr >> 269 #define shl << 270 #define inc ++ 271 #define dec -- 272 #define ptr_to & 273 #define val_of * 274 275 /** 276 * stringify Expression - Turn expression into a string literal 277 * 278 * Example: 279 * #define PRINT_COND_IF_FALSE(cond) \ 280 * ((cond) || printf("%s is false!", stringifyExpr(cond))) 281 */ 282 #define stringifyExpr(expr) stringifyExpr1(expr) 283 /* Double-indirection required to stringify expansions */ 284 #define stringifyExpr1(expr) #expr 285 286 // libsheepy uses bit 63 in logMask 287 // to disable log prints from libsheepy, add: 288 // logMask &= (~libsheepyErrorMask); 289 // or 290 // disableLibsheepyErrorLogs; 291 #define libsheepyErrorMask 0x8000000000000000UL 292 293 #define disableLibsheepyErrorLogs do{logMask &= (~libsheepyErrorMask);}while(0) 294 295 #define shperror(string) procbegin\ 296 char *errstr = strerror(errno);\ 297 logE("%s: %s", string, errstr);\ 298 procend 299 300 /** 301 * print function name and system error 302 * 303 * to print error, use either pFuncError and shEPrintfS 304 * or shPrintError and shEPrintfS 305 */ 306 #define pFuncError do{ if ((libsheepyErrorMask) & logMask) { shperror(__func__);logEBtrace;} }while(0); 307 308 /** 309 * print string and system error 310 */ 311 #define pStrError(str) do{ if ((libsheepyErrorMask) & logMask) { shperror(str);logEBtrace;} }while(0); 312 313 /** 314 * print error with line number, function name and file name to stderr 315 * 316 * to print error, use either pFuncError and shEPrintfS 317 * or shPrintError and shEPrintfS 318 */ 319 #define shPrintError do{ if ((libsheepyErrorMask) & logMask) { logE("Error line "stringifyExpr(__LINE__)", function %s, file "__FILE__"\n", __func__); logEBtrace;} }while(0); 320 321 /** 322 * print error when function failed. The error code must be -1 323 */ 324 #define pError(func) if (func == -1) shPrintError 325 326 /** 327 * print error when function failed. The error code must be 0 328 */ 329 #define pError0(func) if (func == 0) shPrintError 330 331 /** 332 * print error when function failed. The error code must be not 0 333 */ 334 #define pErrorNot0(func) if (func != 0) shPrintError 335 336 /** 337 * print error when function failed. The error code must be NULL 338 */ 339 #define pErrorNULL(func) if (func == NULL) shPrintError 340 341 /** 342 * print error when function failed. The error code must be -1 343 */ 344 #define pErrorValue(func, errorValue) if (func == errorValue) shPrintError 345 346 /** 347 * print error when test is true 348 */ 349 #define pTestError(test) if (test) shPrintError 350 351 /** 352 * print error and run command when test is true 353 */ 354 #define pTestErrorCmd(test, cmd) if (test) { shPrintError cmd; } 355 356 /** 357 * print error and run cmd when test is true 358 */ 359 #define pErrorCmd(func, test, cmd) if (func test) { shPrintError cmd; } 360 361 /** 362 * print error when test is true and return func result in result 363 * 364 * Example: 365 * pErrorResult(k, randomWordF(), == 0) 366 */ 367 #define pErrorResult(result, func, test) if ((result = func) test) shPrintError 368 369 /** 370 * print error and run cmd when test is true and return func result in result 371 * 372 * Example: 373 * pErrorResultCmd(k, randomWordF(), == 0, XFAILURE) 374 */ 375 #define pErrorResultCmd(result, func, test, cmd) if ((result = func) test) { shPrintError cmd; } 376 377 /** 378 * is Assigment Error 379 * catch error when `assigned` is false, 0 or NULL after being assigned with `left` 380 * 381 * Example: 382 * isError(r, malloc(16384)) { 383 * return 0; 384 * } 385 */ 386 #define isError(assigned, left) if (!(assigned = left)) 387 388 /** 389 * setjmp buffers for try/throw,throwV macros 390 */ 391 #define maxTryThrowCount 16 392 extern jmp_buf tryJumpBuffers[maxTryThrowCount]; 393 394 /** 395 * run setjmp using slot in tryJumpBuffers 396 */ 397 #define setJump(slot) setjmp(tryJumpBuffers[slot]) 398 399 /** 400 * try throw else 401 * try(slot) saves the environment in slot 402 * throw(slot) executes the else associated with try(slot) 403 * 404 * there are 16 slots 405 * 406 * Example: 407 * try(0) { 408 * throw(0); 409 * } 410 * else 411 * puts("except"); 412 * 413 */ 414 #define try(slot) if (!setjmp(tryJumpBuffers[slot])) 415 416 /** 417 * throw goes to else associated with try(slot) 418 */ 419 #define throw(slot) longjmp(tryJumpBuffers[slot], 1) 420 421 /** 422 * tryV stores the value from setjmp in result 423 * 424 * it is valid to try with throwV and tryV with throw (returns 1) 425 * 426 * Example: 427 */ 428 #define tryV(result, slot) if (!(result = setjmp(tryJumpBuffers[slot]))) 429 430 /** 431 * throwV returns value and goes to else associated with tryV(slot) 432 */ 433 #define throwV(slot, value) longjmp(tryJumpBuffers[slot], value) 434 435 // limited use macro - for test only 436 #define goNLabel(go, label) goto go; label: 437 438 /** 439 * types 440 */ 441 #define i8 int8_t 442 #define i16 int16_t 443 #define i32 int32_t 444 #define i64 int64_t 445 #define u8 uint8_t 446 #define u16 uint16_t 447 #define u32 uint32_t 448 #define u64 uint64_t 449 #define f32 float 450 #define f64 double 451 452 /** 453 * type cast 454 */ 455 #define I8(value) (i8)(value) 456 #define I16(value) (i16)(value) 457 #define I32(value) (i32)(value) 458 #define I64(value) (i64)(value) 459 #define U8(value) (u8)(value) 460 #define U16(value) (u16)(value) 461 #define U32(value) (u32)(value) 462 #define U64(value) (u64)(value) 463 #define F32(value) (f32)(value) 464 #define F64(value) (f64)(value) 465 466 #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 467 #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 468 #define MIN3(a, b, c) MIN((typeof(a))MIN(a, b), c) 469 #define MAX3(a, b, c) MAX((typeof(a))MAX(a, b), c) 470 #define ABS(a) (((a) < 0) ? -(a) : (a)) 471 #define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) 472 #define COUNT_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0])) 473 #define ARRAY_SIZE COUNT_ELEMENTS 474 475 /** 476 * get a bitfield in an integer (opposite of FIELD_SET) 477 */ 478 #define EXTRACT(x, msb, lsb) ((~(0xFFFFFFFFFFFFFFFEUL << (msb)) & (x)) >> (lsb)) 479 480 /** 481 * compare a to b 482 * a and b have to numbers 483 * 484 * \return 485 * 0 when a equals b 486 * -1 when a is less than b 487 * 1 when a is more than b 488 */ 489 #define CMP(a, b) ({\ 490 var UNIQVAR(_a) = a;\ 491 var UNIQVAR(_b) = b;\ 492 UNIQVAR(_a) > UNIQVAR(_b) ? 1 : UNIQVAR(_a) < UNIQVAR(_b) ? -1 : 0;\ 493 }) 494 495 /** 496 * initialize array or struct to zero 497 * 498 * int a[10] = init0Var; 499 * struct {} s = init0Var; 500 */ 501 #define init0Var {0} 502 503 /** 504 * memset array or struct to zero 505 */ 506 #define ZEROVAR(name) zeroBuf(&(name), sizeof(name)) 507 508 /** 509 * divide count by divider and add one when remainder is not zero 510 * this is used in segmented arrays to count the number of buckets from the element count 511 * 512 * For example, bucket have 64 elements and there are 66 elements in the array 513 * 66/64 = 1 514 * and there are 2 buckets, so BUCKETS returns 2 515 * 516 * could be: 517 * (((count) + (1UL<<(divider) -1))/ (divider)) 518 */ 519 #define BUCKETS(count, divider) ((count)/(divider) + (((count) % (divider)) ? 1 : 0)) 520 521 /** 522 * swap a and b, a and b should have the same type 523 */ 524 #define swapV(a, b) do{\ 525 var UNIQVAR(swaptmp) = a;\ 526 a = b;\ 527 b = UNIQVAR(swaptmp);\ 528 } while(0) 529 530 /** max a,b and store result in result, a and b are evaluated only once */ 531 #define setMax(result, a, b) do{\ 532 var UNIQVAR(_a) = a;\ 533 var UNIQVAR(_b) = b;\ 534 result = MAX(UNIQVAR(_a), UNIQVAR(_b));\ 535 } while(0) 536 537 /** min a,b and store result in result, a and b are evaluated only once */ 538 #define setMin(result, a, b) do{\ 539 var UNIQVAR(_a) = a;\ 540 var UNIQVAR(_b) = b;\ 541 result = MIN(UNIQVAR(_a), UNIQVAR(_b));\ 542 } while(0) 543 544 /** max a,b and return result, a and b are evaluated only once */ 545 #define maxV(a, b) ({\ 546 var UNIQVAR(_a) = a;\ 547 var UNIQVAR(_b) = b;\ 548 MAX(UNIQVAR(_a), UNIQVAR(_b));\ 549 }) 550 551 /** min a,b and return result, a and b are evaluated only once */ 552 #define minV(a, b) ({\ 553 var UNIQVAR(_a) = a;\ 554 var UNIQVAR(_b) = b;\ 555 MIN(UNIQVAR(_a), UNIQVAR(_b));\ 556 }) 557 558 /** absV return absolute value for a, a is evaluated only once*/ 559 #define absV(a) ({var UNIQVAR(_a) = a; ((UNIQVAR(_a)) < 0) ? -(UNIQVAR(_a)) : (UNIQVAR(_a));}) 560 561 /** 562 * FIELD_SIZEOF - get the size of a struct's field 563 * @t: the target struct 564 * @f: the target struct's field 565 * Return: the size of @f in the struct definition without having a 566 * declared instance of @t. 567 */ 568 #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) 569 570 /** true when value is odd integer */ 571 #define isIntOdd(value) (value&1) 572 573 /** true when value is even integer */ 574 #define isIntEven(value) (!(value&1)) 575 576 /** 577 * typ definition as alternative to typedef 578 */ 579 #define typ typedef 580 581 /** 582 * ret definition as alternative to return 583 */ 584 #define ret return 585 586 /** 587 * elif definition as alternative to else if 588 */ 589 #define elif else if 590 591 /** 592 * unless executes the statement unless the condition is true (that is, if the condition is false). 593 * 594 * Example: 595 * unless(isPath("/void")) { 596 * put("the '/void' directory doesn't exist."); 597 * } 598 */ 599 #define unless(cond) if(not(cond)) 600 601 /** 602 * until repeats the statement until the condition is true (or while the condition is false) 603 * 604 * Example: 605 * i16 i = 0; 606 * do { 607 * i++; 608 * logVarG(i); 609 * } until(i == 3); 610 */ 611 #define until(cond) while(not(cond)) 612 613 614 /** 615 * define variable and cast pointer 616 */ 617 #define cast(type, casted, toCast) type casted = (type) (toCast); 618 619 /** 620 * free pointer and set it to NULL 621 */ 622 #define freen(ptr) do {\ 623 free(ptr);\ 624 (ptr) = NULL;\ 625 } while(0) 626 627 /** 628 * Evaluate and assign 629 * Evaluate, assign result from func and return result using the comma operator 630 * 631 * Example: 632 * save pointer returned by a function in a function parameter: 633 * void *p; 634 * func2( EVA(p,func1()) ); 635 * free(p); 636 * 637 * Using libsheepy functions: 638 * char *s; 639 * puts( EVA(s, normalizePath("/wef/./../")) ); 640 * free(s); 641 */ 642 #define EVA(var, func) (var = func, var) 643 644 /** 645 * initialize the loop breaker 646 * declares loop breaker variables 647 * 648 * Example: 649 * 650 * loopBreakerInit; 651 * forever { 652 * loopBreaker(20); 653 * } 654 * if (didBreak) logE("infinite loop detected"); 655 * loopBreakerReset; 656 * forever { 657 * loopBreaker(100); 658 * } 659 * if (didBreak) logE("infinite loop detected"); 660 */ 661 #define loopBreakerInit\ 662 uint32_t libsheepyLoopCounter = 0;\ 663 bool didBreak = false; 664 665 /** 666 * reset the loop breaker variables 667 */ 668 #define loopBreakerReset\ 669 libsheepyLoopCounter = 0;\ 670 didBreak = false; 671 672 /** 673 * break the loop when the counter exceed breakCount 674 */ 675 #define loopBreaker(breakCount)\ 676 libsheepyLoopCounter++;\ 677 if(libsheepyLoopCounter>breakCount){didBreak=true;break;} 678 679 /** generate a string FILE:LINE number 680 * 681 * Example: 682 * puts(FILE_LINE); 683 */ 684 #define FILE_LINE __FILE__":"stringifyExpr(__LINE__) 685 #define PFILE_LINE puts(FILE_LINE) 686 687 /** 688 * print file, function name and line 689 * 690 * Example: 691 * AT; 692 * libsheepy.c, main:9149 693 */ 694 #define AT pLog(LOG_DEBUG, __FILE__", %s:"stringifyExpr(__LINE__)"\n",__func__); 695 696 /** 697 * print a todo message in log 698 */ 699 #define TODO(message) logD(BLD MGT BGBLK"TODO"RST BLD MGT": "message RST) 700 701 // macros for token paste for automatically creating unique variable names 702 // used in forEachCharP 703 #define TOKENPASTE2(a, b) a ## b 704 #define TOKENPASTE(a, b) TOKENPASTE2(a, b) 705 #define UNIQVAR(name) TOKENPASTE(name, __LINE__) 706 707 708 // free val when it is out of scope 709 void cleanUpCharFree(char **val); 710 711 /** 712 * declare pointer name with type char* and free name when it is out of scope 713 */ 714 #define cleanCharP(name) char *name CLEANUP(cleanUpCharFree) 715 716 // free val when it is out of scope 717 void cleanUpListFree(char*** val); 718 719 /** 720 * declare pointer name with type char* and free name when it is out of scope 721 */ 722 #define cleanListP(name) char **name CLEANUP(cleanUpListFree) 723 724 // free val when it is out of scope 725 void cleanUpVoidFree(void **val); 726 727 /** 728 * declare pointer name with type void* and free name when it is out of scope 729 */ 730 #define cleanVoidP(name) void *name CLEANUP(cleanUpVoidFree) 731 732 // free val when it is out of scope 733 void cleanUpFileFree(FILE **val); 734 735 /** 736 * declare pointer name with type FILE and free (close) name when it is out of scope 737 */ 738 #define cleanFileP(name) FILE *name CLEANUP(cleanUpFileFree) 739 740 // close val when it is out of scope 741 void cleanUpFd(int *val); 742 743 /** 744 * declare a file descriptor name and close name when it is out of scope 745 */ 746 #define cleanFd(name) int name CLEANUP(cleanUpFd) 747 #define cleanFdInit(name) int name CLEANUP(cleanUpFd) = -1 748 749 /** 750 * log variable and its value 751 * 752 * Example: 753 * logVar(k, PRIu64) 754 * k=14 755 */ 756 #define logVar(var, format) logD("%s=%" format, stringifyExpr(var), var); 757 #define logMVar(mask, var, format) logMD(mask, "%s=%" format, stringifyExpr(var), var); 758 759 /** log bool variable */ 760 #define logBoolVar(var) logVar(var, "b"); 761 #define logMBoolVar(mask, var) logMVar(mask, var, "b"); 762 763 /** 764 * log pointer 765 */ 766 #define logPtr(pointer) logD("%s=%p", stringifyExpr(pointer), pointer); 767 #define logMPtr(mask, pointer) logMD(mask, "%s=%p", stringifyExpr(pointer), pointer); 768 769 // colors and effects 770 /** reset for color function */ 771 #define RST "\x1B[0m" 772 /** bold for color function */ 773 #define BLD "\x1B[1m" 774 /** faint */ 775 #define FNT "\x1B[2m" 776 /** italic */ 777 #define ITL "\x1B[3m" 778 /** underline for color function */ 779 #define UDL "\x1B[4m" 780 /** blink */ 781 #define BLI "\x1B[5m" 782 /** inverse for color function */ 783 #define INV "\x1B[7m" 784 /** conceal/hidden for color function */ 785 #define COC "\x1B[8m" 786 /** crossed for color function */ 787 #define CRD "\x1B[9m" 788 789 // foreground 790 /** black for color function */ 791 #define BLK "\x1B[30m" 792 /** red for color function */ 793 #define RED "\x1B[31m" 794 /** green for color function */ 795 #define GRN "\x1B[32m" 796 /** yellow for color function */ 797 #define YLW "\x1B[33m" 798 /** blue for color function */ 799 #define BLU "\x1B[34m" 800 /** magenta for color function */ 801 #define MGT "\x1B[35m" 802 /** cyan for color function */ 803 #define CYN "\x1B[36m" 804 /** white for color function */ 805 #define WHT "\x1B[37m" 806 807 // background 808 /** bg black for color function */ 809 #define BGBLK "\x1B[40m" 810 /** bg red for color function */ 811 #define BGRED "\x1B[41m" 812 /** bg green for color function */ 813 #define BGGRN "\x1B[42m" 814 /** bg yellow for color function */ 815 #define BGYLW "\x1B[43m" 816 /** bg blue for color function */ 817 #define BGBLU "\x1B[44m" 818 /** bg magenta for color function */ 819 #define BGMGT "\x1B[45m" 820 /** bg cyan for color function */ 821 #define BGCYN "\x1B[46m" 822 /** bg white for color function */ 823 #define BGWHT "\x1B[47m" 824 825 // bug in cg_c.py 826 #define sheepyRGBFP len = fprintf(stream, "%*s", (int)(info->left ? -info->width : info->width), b) 827 #define sheepyBOOLFP len = fprintf(stream, "%*s", (int)(info->left ? -info->width : info->width), boolS(value)) 828 829 /** 830 * time a function in nanoseconds 831 * 832 * Example: 833 * timeNs(func(anInt)); 834 */ 835 #define timeNs(func) do{\ 836 u64 UNIQVAR(endTime);\ 837 u64 UNIQVAR(startTime) = getMonotonicTime();\ 838 func;\ 839 UNIQVAR(endTime) = getMonotonicTime();\ 840 printf(BLD GRN "time" RST ": %" PRIu64 "ns " BLD UDL YLW "%s" RST "\n", UNIQVAR(endTime)-UNIQVAR(startTime), stringifyExpr(func));\ 841 }while(0) 842 843 #define TIMEUNITUS "us" 844 #define TIMEUNITMS "ms" 845 #define TIMEUNITSC "s" 846 847 /** 848 * time a function with div 849 * 850 * Example: 851 * timeDivs(func(anInt), 1E3); 852 */ 853 #define timeDivs(func, div, timeunit) do{\ 854 u64 UNIQVAR(endTime);\ 855 u64 UNIQVAR(startTime) = getMonotonicTime();\ 856 func;\ 857 UNIQVAR(endTime) = getMonotonicTime();\ 858 printf(BLD GRN "time:" RST " %f"timeunit" " BLD UDL YLW "%s" RST "\n", (f32)(UNIQVAR(endTime)-UNIQVAR(startTime))/div, stringifyExpr(func));\ 859 }while(0) 860 861 /** 862 * time a function in microseconds 863 * 864 * Example: 865 * timeUs(func(anInt)); 866 */ 867 #define timeUs(func) timeDivs(func,1E3, TIMEUNITUS) 868 869 /** 870 * time a function in miliseconds 871 * 872 * Example: 873 * timeMs(func(anInt)); 874 */ 875 #define timeMs(func) timeDivs(func,1E6, TIMEUNITMS) 876 877 /** 878 * time a function in seconds 879 * 880 * Example: 881 * timeSec(func(anInt)); 882 */ 883 #define timeSec(func) timeDivs(func,1E9, TIMEUNITSC) 884 885 // nanosecond stopwatch, the returned value is in ns. op parameter: 0 to start, 1 to get the stopwatch value 886 uint64_t shStopwatch(uint8_t op); 887 888 #define stopwatchStart shStopwatch(0) 889 890 /** 891 * print stopwatch value in ns since last start 892 */ 893 #define stopwatchLog printf(BLD GRN "time" RST ": %" PRIu64 "ns\n", shStopwatch(1)) 894 895 /** 896 * print stopwatch value in provided unit since last start 897 */ 898 #define stopwatchLogDivs(div, timeunit) printf(BLD GRN "time" RST ": %f"timeunit"\n", ((float)shStopwatch(1))/div) 899 900 /** 901 * print stopwatch value in microseconds since last start 902 */ 903 #define stopwatchLogUs stopwatchLogDivs(1E3, TIMEUNITUS) 904 905 /** 906 * print stopwatch value in milliseconds since last start 907 */ 908 #define stopwatchLogMs stopwatchLogDivs(1E6, TIMEUNITMS) 909 910 /** 911 * print stopwatch value in seconds since last start 912 */ 913 #define stopwatchLogSec stopwatchLogDivs(1E9, TIMEUNITSC) 914 915 /** 916 * LOG LEVELS 917 * Note: When adding log levels or modes, the log_tags array in libsheepy.c 918 * must be updated. 919 */ 920 #define LOG_EMERGENCY 0 921 #define LOG_ALERT 1 922 #define LOG_CRITICAL 2 923 #define LOG_ERROR 3 924 #ifdef LOG_WARNING 925 #undef LOG_WARNING // conflict with syslog.h 926 #endif 927 #define LOG_WARNING 4 928 #define LOG_NOTICE 5 929 #define LOG_PASS 6 930 #ifdef LOG_INFO 931 #undef LOG_INFO // conflict with syslog.h 932 #endif 933 #define LOG_INFO 7 934 #define LOG_DEBUG 8 935 #define LOG_INVALID 9 936 #define LOG_MAX_LEVEL LOG_INVALID 937 938 /** getMaxLogLevel and setMaxLogLevel value disabling all logs */ 939 #define LOG_DISABLE -1 940 941 /** 942 * LOG MODES 943 * when a new mode is added, add symbols in log_tags in libsheepy.c 944 */ 945 946 /** 947 * log symbol, program name, filename, function, line, date 948 */ 949 #define LOG_VERBOSE 0 950 951 /** 952 * log symbol 953 */ 954 #define LOG_CONCISE 1 955 956 /** 957 * log symbol and date 958 */ 959 #define LOG_DATE 2 // default 960 961 /** 962 * log symbol and function 963 */ 964 #define LOG_FUNC 3 965 966 /** 967 * log symbol and program name 968 */ 969 #define LOG_PROG 4 970 971 /** 972 * log symbol, program name and date 973 */ 974 #define LOG_PROGNDATE 5 975 976 /** 977 * log message only 978 */ 979 #define LOG_VOID 6 980 981 /** 982 * UTF8 symbols and concise 983 */ 984 #define LOG_UTF8 7 985 986 /** 987 * log symbol, program name and function 988 */ 989 #define LOG_PROGNFUNC 8 990 991 /** 992 * invalid 993 */ 994 #define LOG_INVALID_MODE 9 995 996 // add a log file, maximum 15 files 997 FILE *SH_PREFIX(setLogFile)(char *filename); 998 #define openLogFile setLogFile 999 1000 #ifdef __GNUC__ 1001 /** force function callers to check return value 1002 * The warning is disabled with -Wno-unused-result (default in sheepy config ~/.sheepy/config.yml 1003 * Enable this warning to make all errors caught as early as possible and handled correctly. 1004 */ 1005 #define MUST_CHECK __attribute__ ((warn_unused_result)) 1006 #else 1007 #define MUST_CHECK 1008 #endif 1009 1010 // current log symbols 1011 int getLogSymbols(void) MUST_CHECK; 1012 1013 // set log symbols, LOG_VERBOSE for words, LOG_UTF8 for emojis, LOG_VOID for no symbols, LOG_INVALID_MODE (reset log symbols) for default log mode symbols, anything else (LOG_CONCISE,...) for symbols (!*+->~) 1014 void setLogSymbols(int mode); 1015 1016 // current max log level 1017 int getMaxLogLevel(void) MUST_CHECK; 1018 1019 // set max log level, logs above logMaxLevel are skipped 1020 void setMaxLogLevel(int logLevel); 1021 1022 // close logfiles opened with setLogFile 1023 void closeLogFiles(void); 1024 1025 // get current log mode (LOG_VERBOSE, LOG_CONCISE, ...) 1026 int getLogMode(void) MUST_CHECK; 1027 1028 // set log mode LOG_VERBOSE, LOG_CONCISE, ... 1029 void setLogMode(int mode); 1030 1031 // get current log long/short path value, default is TRUE (short paths) 1032 bool getLogShortPath(void) MUST_CHECK; 1033 1034 // set log long/short file path value for VERBOSE mode 1035 void setLogShortPath(bool shortPath); 1036 1037 // get stdout state, when TRUE (default) all logs are printed to stdout 1038 bool getLogStdout(void) MUST_CHECK; 1039 1040 // enable/disable printing logs to stdout 1041 void setLogStdout(bool state); 1042 1043 // log to a file named progName.log 1044 bool openProgLogFile(void) MUST_CHECK; 1045 1046 // keep ansi colors in logs 1047 void keepAnsiColorsInLog(bool state); 1048 1049 /** 1050 * print logging levels 1051 * 1052 * to disable logging, empty pLog define: 1053 * #undef pLog 1054 * #define pLog 1055 * 1056 * \param 1057 * level LOG_CRITICAL, LOG_ERROR, LOG_WARNING or LOG_INFO, anything else has log level LOG_INVALID 1058 * \param 1059 * message like printf 1060 */ 1061 #define pLog(level, ...) _pLog(level, __FILE__, __func__, __LINE__, __VA_ARGS__); 1062 1063 void _pLog(int, const char *, const char *, int, const char *, ...); 1064 1065 #define logY(...) pLog(LOG_EMERGENCY, __VA_ARGS__) 1066 #define logA(...) pLog(LOG_ALERT, __VA_ARGS__) 1067 #define logC(...) pLog(LOG_CRITICAL, __VA_ARGS__) 1068 #define logE(...) pLog(LOG_ERROR, __VA_ARGS__) 1069 #define logW(...) pLog(LOG_WARNING, __VA_ARGS__) 1070 #define logN(...) pLog(LOG_NOTICE, __VA_ARGS__) 1071 #define logP(...) pLog(LOG_PASS, __VA_ARGS__) 1072 #define logI(...) pLog(LOG_INFO, __VA_ARGS__) 1073 #define logD(...) pLog(LOG_DEBUG, __VA_ARGS__) 1074 1075 /** 1076 * log string and free 1077 * Example: 1078 * logSY("The list: %s", catS("1", "2")); 1079 */ 1080 #define logSY(format, string) do {\ 1081 char *libsheepyInternalString = string;\ 1082 logY(format, libsheepyInternalString);\ 1083 free(libsheepyInternalString);\ 1084 } while(0) 1085 1086 /** 1087 * log string and free 1088 * Example: 1089 * logSA("The list: %s", catS("1", "2")); 1090 */ 1091 #define logSA(format, string) do {\ 1092 char *libsheepyInternalString = string;\ 1093 logA(format, libsheepyInternalString);\ 1094 free(libsheepyInternalString);\ 1095 } while(0) 1096 1097 /** 1098 * log string and free 1099 * Example: 1100 * logSC("The list: %s", catS("1", "2")); 1101 */ 1102 #define logSC(format, string) do {\ 1103 char *libsheepyInternalString = string;\ 1104 logC(format, libsheepyInternalString);\ 1105 free(libsheepyInternalString);\ 1106 } while(0) 1107 1108 /** 1109 * log string and free 1110 * Example: 1111 * logSE("The list: %s", catS("1", "2")); 1112 */ 1113 #define logSE(format, string) do {\ 1114 char *libsheepyInternalString = string;\ 1115 logE(format, libsheepyInternalString);\ 1116 free(libsheepyInternalString);\ 1117 } while(0) 1118 1119 /** 1120 * log string and free 1121 * Example: 1122 * logSW("The list: %s", catS("1", "2")); 1123 */ 1124 #define logSW(format, string) do {\ 1125 char *libsheepyInternalString = string;\ 1126 logW(format, libsheepyInternalString);\ 1127 free(libsheepyInternalString);\ 1128 } while(0) 1129 1130 /** 1131 * log string and free 1132 * Example: 1133 * logSN("The list: %s", catS("1", "2")); 1134 */ 1135 #define logSN(format, string) do {\ 1136 char *libsheepyInternalString = string;\ 1137 logN(format, libsheepyInternalString);\ 1138 free(libsheepyInternalString);\ 1139 } while(0) 1140 1141 /** 1142 * log string and free 1143 * Example: 1144 * logSP("The list: %s", catS("1", "2")); 1145 */ 1146 #define logSP(format, string) do {\ 1147 char *libsheepyInternalString = string;\ 1148 logP(format, libsheepyInternalString);\ 1149 free(libsheepyInternalString);\ 1150 } while(0) 1151 1152 /** 1153 * log string and free 1154 * Example: 1155 * logSI("The list: %s", catS("1", "2")); 1156 */ 1157 #define logSI(format, string) do {\ 1158 char *libsheepyInternalString = string;\ 1159 logI(format, libsheepyInternalString);\ 1160 free(libsheepyInternalString);\ 1161 } while(0) 1162 1163 /** 1164 * log string and free 1165 * Example: 1166 * logSD("The list: %s", catS("1", "2")); 1167 */ 1168 #define logSD(format, string) do {\ 1169 char *libsheepyInternalString = string;\ 1170 logD(format, libsheepyInternalString);\ 1171 free(libsheepyInternalString);\ 1172 } while(0) 1173 1174 1175 /** variable to control which group logs to show, all logs are enabled by default (0xFFFFFFFFFFFFFFFF) */ 1176 extern uint64_t logMask; 1177 1178 /** 1179 * print mask logging levels 1180 * 1181 * print logs with a mask in logMask 1182 * normally, mask is 1 bit wide. 1183 * 1184 * pLogMask allows enabling/disabling groups of logs 1185 * 1186 * to disable logging, empty pLogMask define: 1187 * #undef pLogMask 1188 * #define pLogMask 1189 * 1190 * Example: 1191 * 1192 * #define group1 0x03 1193 * #define group11 0x01 1194 * #define group12 0x02 1195 * #define group2 0x04 1196 * 1197 * logMask = group11; 1198 * logMI(group1, "is shown when logMask has bit 0 or 1 set"); 1199 * logMI(group11, "is shown when logMask has bit 0 set"); 1200 * logMI(group12, "is shown when logMask has bit 1 set"); 1201 * logMI(group2, "is shown when logMask has bit 2 set"); 1202 * 1203 * \param 1204 * level LOG_CRITICAL, LOG_ERROR, LOG_WARNING or LOG_INFO, anything else has log level LOG_INVALID 1205 * \param 1206 * message like printf 1207 */ 1208 #define pLogMask(mask, level, ...) if ((mask) & logMask) pLog(level, __VA_ARGS__) 1209 1210 #define logMY(mask, ...) pLogMask(mask, LOG_EMERGENCY, __VA_ARGS__) 1211 #define logMA(mask, ...) pLogMask(mask, LOG_ALERT, __VA_ARGS__) 1212 #define logMC(mask, ...) pLogMask(mask, LOG_CRITICAL, __VA_ARGS__) 1213 #define logME(mask, ...) pLogMask(mask, LOG_ERROR, __VA_ARGS__) 1214 #define logMW(mask, ...) pLogMask(mask, LOG_WARNING, __VA_ARGS__) 1215 #define logMN(mask, ...) pLogMask(mask, LOG_NOTICE, __VA_ARGS__) 1216 #define logMP(mask, ...) pLogMask(mask, LOG_PASS, __VA_ARGS__) 1217 #define logMI(mask, ...) pLogMask(mask, LOG_INFO, __VA_ARGS__) 1218 #define logMD(mask, ...) pLogMask(mask, LOG_DEBUG, __VA_ARGS__) 1219 1220 // show log messages in mask 1221 #define showLogsInMask(mask) logMask |= mask 1222 1223 // hide log messages in mask 1224 #define hideLogsInMask(mask) logMask &= ~(mask) 1225 1226 /** 1227 * log and mask string and then free 1228 * Example: 1229 * logSMY("The list: %s", catS("1", "2")); 1230 */ 1231 #define logSMY(mask, format, string) do {\ 1232 char *libsheepyInternalString = string;\ 1233 logMY(mask, format, libsheepyInternalString);\ 1234 free(libsheepyInternalString);\ 1235 } while(0) 1236 1237 /** 1238 * log and mask string and then free 1239 * Example: 1240 * logSMA("The list: %s", catS("1", "2")); 1241 */ 1242 #define logSMA(mask, format, string) do {\ 1243 char *libsheepyInternalString = string;\ 1244 logMA(mask, format, libsheepyInternalString);\ 1245 free(libsheepyInternalString);\ 1246 } while(0) 1247 1248 /** 1249 * log and mask string and then free 1250 * Example: 1251 * logSMI("The list: %s", catS("1", "2")); 1252 */ 1253 #define logSMC(mask, format, string) do {\ 1254 char *libsheepyInternalString = string;\ 1255 logMC(mask, format, libsheepyInternalString);\ 1256 free(libsheepyInternalString);\ 1257 } while(0) 1258 1259 /** 1260 * log and mask string and then free 1261 * Example: 1262 * logSME("The list: %s", catS("1", "2")); 1263 */ 1264 #define logSME(mask, format, string) do {\ 1265 char *libsheepyInternalString = string;\ 1266 logME(mask, format, libsheepyInternalString);\ 1267 free(libsheepyInternalString);\ 1268 } while(0) 1269 1270 /** 1271 * log and mask string and then free 1272 * Example: 1273 * logSMW("The list: %s", catS("1", "2")); 1274 */ 1275 #define logSMW(mask, format, string) do {\ 1276 char *libsheepyInternalString = string;\ 1277 logMW(mask, format, libsheepyInternalString);\ 1278 free(libsheepyInternalString);\ 1279 } while(0) 1280 1281 /** 1282 * log and mask string and then free 1283 * Example: 1284 * logSMN("The list: %s", catS("1", "2")); 1285 */ 1286 #define logSMN(mask, format, string) do {\ 1287 char *libsheepyInternalString = string;\ 1288 logMN(mask, format, libsheepyInternalString);\ 1289 free(libsheepyInternalString);\ 1290 } while(0) 1291 1292 /** 1293 * log and mask string and then free 1294 * Example: 1295 * logSMP("The list: %s", catS("1", "2")); 1296 */ 1297 #define logSMP(mask, format, string) do {\ 1298 char *libsheepyInternalString = string;\ 1299 logMP(mask, format, libsheepyInternalString);\ 1300 free(libsheepyInternalString);\ 1301 } while(0) 1302 1303 /** 1304 * log and mask string and then free 1305 * Example: 1306 * logSMI("The list: %s", catS("1", "2")); 1307 */ 1308 #define logSMI(mask, format, string) do {\ 1309 char *libsheepyInternalString = string;\ 1310 logMI(mask, format, libsheepyInternalString);\ 1311 free(libsheepyInternalString);\ 1312 } while(0) 1313 1314 /** 1315 * log and mask string and then free 1316 * Example: 1317 * logSMD("The list: %s", catS("1", "2")); 1318 */ 1319 #define logSMD(mask, format, string) do {\ 1320 char *libsheepyInternalString = string;\ 1321 logMD(mask, format, libsheepyInternalString);\ 1322 free(libsheepyInternalString);\ 1323 } while(0) 1324 1325 // QSORT 1326 1327 /* 1328 * Copyright (c) 2013, 2017 Alexey Tourbin 1329 * 1330 * Permission is hereby granted, free of charge, to any person obtaining a copy 1331 * of this software and associated documentation files (the "Software"), to deal 1332 * in the Software without restriction, including without limitation the rights 1333 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1334 * copies of the Software, and to permit persons to whom the Software is 1335 * furnished to do so, subject to the following conditions: 1336 * 1337 * The above copyright notice and this permission notice shall be included in 1338 * all copies or substantial portions of the Software. 1339 * 1340 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1341 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1342 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1343 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1344 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1345 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1346 * SOFTWARE. 1347 */ 1348 1349 /* 1350 * https://github.com/svpv/qsort.git 1351 * commit 21f056356e901467b7362240dac70edeedfa2b89 1352 */ 1353 1354 /* 1355 * This is a traditional Quicksort implementation which mostly follows 1356 * [Sedgewick 1978]. Sorting is performed entirely on array indices, 1357 * while actual access to the array elements is abstracted out with the 1358 * user-defined `LESS` and `SWAP` primitives. 1359 * 1360 * Synopsis: 1361 * QSORT(N, LESS, SWAP); 1362 * where 1363 * N - the number of elements in A[]; 1364 * LESS(i, j) - compares A[i] to A[j]; 1365 * SWAP(i, j) - exchanges A[i] with A[j]. 1366 * 1367 * Examples: 1368 * - int array: 1369 * int A[] = {3,2,1}; 1370 * int tmp; 1371 * 1372 * #define LESS(i, j) A[i] < A[j] 1373 * #define SWAP(i, j) tmp = A[i], A[i] = A[j], A[j] = tmp 1374 * 1375 * QSORT(3, LESS, SWAP); 1376 * #undef LESS 1377 * #undef SWAP 1378 * 1379 * 1380 * - string array/list: 1381 * char **strs = listCreateS("fsd", "sdf", "ffds","asd"); 1382 * char *tmp; 1383 * 1384 * #define LESS(i,j) (strcmp(strs[i], strs[j]) < 0) 1385 * #define SWAP(i,j) tmp = strs[i], strs[i] = strs[j], strs[j] = tmp 1386 * 1387 * QSORT(listLengthS(strs), LESS, SWAP); 1388 * #undef LESS 1389 * #undef SWAP 1390 * 1391 */ 1392 1393 /* Sort 3 elements. */ 1394 #define Q_SORT3(q_a1, q_a2, q_a3, Q_LESS, Q_SWAP) do {\ 1395 if (Q_LESS(q_a2, q_a1)) {\ 1396 if (Q_LESS(q_a3, q_a2))\ 1397 Q_SWAP(q_a1, q_a3);\ 1398 else {\ 1399 Q_SWAP(q_a1, q_a2);\ 1400 if (Q_LESS(q_a3, q_a2))\ 1401 Q_SWAP(q_a2, q_a3);\ 1402 }\ 1403 }\ 1404 else if (Q_LESS(q_a3, q_a2)) {\ 1405 Q_SWAP(q_a2, q_a3);\ 1406 if (Q_LESS(q_a2, q_a1))\ 1407 Q_SWAP(q_a1, q_a2); \ 1408 }\ 1409 } while (0) 1410 1411 /* Partition [q_l,q_r] around a pivot. After partitioning, 1412 * [q_l,q_j] are the elements that are less than or equal to the pivot, 1413 * while [q_i,q_r] are the elements greater than or equal to the pivot. */ 1414 #define Q_PARTITION(q_l, q_r, q_i, q_j, Q_UINT, Q_LESS, Q_SWAP) do {\ 1415 /* The middle element, not to be confused with the median. */\ 1416 Q_UINT UNIQVAR(q_m) = q_l + ((q_r - q_l) >> 1);\ 1417 /* Reorder the second, the middle, and the last items.\ 1418 * As [Edelkamp Weiss 2016] explain, using the second element\ 1419 * instead of the first one helps avoid bad behaviour for\ 1420 * decreasingly sorted arrays. This method is used in recent\ 1421 * versions of gcc's std::sort, see gcc bug 58437#c13, although\ 1422 * the details are somewhat different (cf. #c14). */\ 1423 Q_SORT3(q_l + 1, UNIQVAR(q_m), q_r, Q_LESS, Q_SWAP);\ 1424 /* Place the median at the beginning. */\ 1425 Q_SWAP(q_l, UNIQVAR(q_m));\ 1426 /* Partition [q_l+2, q_r-1] around the median which is in q_l.\ 1427 * q_i and q_j are initially off by one, they get decremented\ 1428 * in the do-while loops. */\ 1429 q_i = q_l + 1; q_j = q_r;\ 1430 while (1) {\ 1431 do q_i++; while (Q_LESS(q_i, q_l));\ 1432 do q_j--; while (Q_LESS(q_l, q_j));\ 1433 if (q_i >= q_j) break; /* Sedgewick says "until j < i" */\ 1434 Q_SWAP(q_i, q_j);\ 1435 }\ 1436 /* Compensate for the i==j case. */\ 1437 q_i = q_j + 1;\ 1438 /* Put the median to its final place. */\ 1439 Q_SWAP(q_l, q_j);\ 1440 /* The median is not part of the left subfile. */\ 1441 q_j--;\ 1442 } while (0) 1443 1444 /* Insertion sort is applied to small subfiles - this is contrary to 1445 * Sedgewick's suggestion to run a separate insertion sort pass after 1446 * the partitioning is done. The reason I don't like a separate pass 1447 * is that it triggers extra comparisons, because it can't see that the 1448 * medians are already in their final positions and need not be rechecked. 1449 * Since I do not assume that comparisons are cheap, I also do not try 1450 * to eliminate the (q_j > q_l) boundary check. */ 1451 #define Q_INSERTION_SORT(q_l, q_r, Q_UINT, Q_LESS, Q_SWAP) do {\ 1452 Q_UINT UNIQVAR(q_i), UNIQVAR(q_j);\ 1453 /* For each item starting with the second... */\ 1454 for (UNIQVAR(q_i) = q_l + 1; UNIQVAR(q_i) <= q_r; UNIQVAR(q_i)++)\ 1455 /* move it down the array so that the first part is sorted. */\ 1456 for (UNIQVAR(q_j) = UNIQVAR(q_i); UNIQVAR(q_j) > q_l && (Q_LESS(UNIQVAR(q_j), UNIQVAR(q_j) - 1)); UNIQVAR(q_j)--)\ 1457 Q_SWAP(UNIQVAR(q_j), UNIQVAR(q_j) - 1);\ 1458 } while (0) 1459 1460 /* When the size of [q_l,q_r], i.e. q_r-q_l+1, is greater than or equal to 1461 * Q_THRESH, the algorithm performs recursive partitioning. When the size 1462 * drops below Q_THRESH, the algorithm switches to insertion sort. 1463 * The minimum valid value is probably 5 (with 5 items, the second and 1464 * the middle items, the middle itself being rounded down, are distinct). */ 1465 #define Q_THRESH 16 1466 1467 /* The main loop. */ 1468 #define Q_LOOP(Q_UINT, Q_N, Q_LESS, Q_SWAP) do {\ 1469 Q_UINT UNIQVAR(q_l) = 0;\ 1470 Q_UINT UNIQVAR(q_r) = (Q_N) - 1;\ 1471 Q_UINT UNIQVAR(q_sp) = 0; /* the number of frames pushed to the stack */\ 1472 struct { Q_UINT q_l, q_r; }\ 1473 /* On 32-bit platforms, to sort a "char[3GB+]" array,\ 1474 * it may take full 32 stack frames. On 64-bit CPUs,\ 1475 * though, the address space is limited to 48 bits.\ 1476 * The usage is further reduced if Q_N has a 32-bit type. */\ 1477 UNIQVAR(q_st)[sizeof(Q_UINT) > 4 && sizeof(Q_N) > 4 ? 48 : 32];\ 1478 while (1) {\ 1479 if (UNIQVAR(q_r) - UNIQVAR(q_l) + 1 >= Q_THRESH) {\ 1480 Q_UINT UNIQVAR(q_i), UNIQVAR(q_j);\ 1481 Q_PARTITION(UNIQVAR(q_l), UNIQVAR(q_r), UNIQVAR(q_i), UNIQVAR(q_j), Q_UINT, Q_LESS, Q_SWAP);\ 1482 /* Now have two subfiles: [q_l,q_j] and [q_i,q_r].\ 1483 * Dealing with them depends on which one is bigger. */\ 1484 if (UNIQVAR(q_j) - UNIQVAR(q_l) >= UNIQVAR(q_r) - UNIQVAR(q_i))\ 1485 Q_SUBFILES(UNIQVAR(q_l), UNIQVAR(q_j), UNIQVAR(q_i), UNIQVAR(q_r));\ 1486 else\ 1487 Q_SUBFILES(UNIQVAR(q_i), UNIQVAR(q_r), UNIQVAR(q_l), UNIQVAR(q_j));\ 1488 }\ 1489 else {\ 1490 Q_INSERTION_SORT(UNIQVAR(q_l), UNIQVAR(q_r), Q_UINT, Q_LESS, Q_SWAP);\ 1491 /* Pop subfiles from the stack, until it gets empty. */\ 1492 if (UNIQVAR(q_sp) == 0) break;\ 1493 UNIQVAR(q_sp)--;\ 1494 UNIQVAR(q_l) = UNIQVAR(q_st)[UNIQVAR(q_sp)].q_l;\ 1495 UNIQVAR(q_r) = UNIQVAR(q_st)[UNIQVAR(q_sp)].q_r;\ 1496 }\ 1497 }\ 1498 } while (0) 1499 1500 /* The missing part: dealing with subfiles. 1501 * Assumes that the first subfile is not smaller than the second. */ 1502 #define Q_SUBFILES(q_l1, q_r1, q_l2, q_r2) do {\ 1503 /* If the second subfile is only a single element, it needs\ 1504 * no further processing. The first subfile will be processed\ 1505 * on the next iteration (both subfiles cannot be only a single\ 1506 * element, due to Q_THRESH). */\ 1507 if (q_l2 == q_r2) {\ 1508 UNIQVAR(q_l) = q_l1;\ 1509 UNIQVAR(q_r) = q_r1;\ 1510 }\ 1511 else {\ 1512 /* Otherwise, both subfiles need processing.\ 1513 * Push the larger subfile onto the stack. */\ 1514 UNIQVAR(q_st)[UNIQVAR(q_sp)].q_l = q_l1;\ 1515 UNIQVAR(q_st)[UNIQVAR(q_sp)].q_r = q_r1;\ 1516 UNIQVAR(q_sp)++;\ 1517 /* Process the smaller subfile on the next iteration. */\ 1518 UNIQVAR(q_l) = q_l2;\ 1519 UNIQVAR(q_r) = q_r2;\ 1520 }\ 1521 } while (0) 1522 1523 /* And now, ladies and gentlemen, may I proudly present to you... */ 1524 #define QSORT(Q_N, Q_LESS, Q_SWAP) do {\ 1525 if ((Q_N) > 1) {\ 1526 if (sizeof(Q_N) == sizeof(unsigned long)) {\ 1527 Q_LOOP(unsigned long, Q_N, Q_LESS, Q_SWAP);}\ 1528 else if (sizeof(Q_N) <= sizeof(unsigned)) {\ 1529 Q_LOOP(unsigned, Q_N, Q_LESS, Q_SWAP);}\ 1530 }\ 1531 } while (0) 1532 1533 // QSORT END 1534 1535 // BINARY SEARCH 1536 1537 /** 1538 * binary search macro 1539 * 1540 * Synopsis: 1541 * BSEARCH(RESULT_INDEX, SEARCH_ELEMENT, N, LESS, EQUAL); 1542 * where 1543 * RESULT_INDEX - variable holding the result index, signed int type (example: ssize_t), 1544 * declare RESULT_INDEX before calling BSEARCH; 1545 * SEARCH_ELEMENT - element to search in the array; 1546 * N - the number of elements in A[]; 1547 * LESS(i, SEARCH_ELEMENT) - compares A[i] to SEARCH_ELEMENT, 1 when less; 1548 * EQUAL(i, SEARCH_ELEMENT) - compares A[i] to SEARCH_ELEMENT, 1 when equal; 1549 * 1550 * Example: 1551 * int A[] = {1,5,7,9,10,65}; 1552 * ssize_t bsr; 1553 * 1554 * #define LESS(i, se) A[i] < se 1555 * #define EQUAL(i, se) A[i] == se 1556 * BSEARCH(bsr, 9, COUNT_ELEMENTS(A), LESS, EQUAL); 1557 * #undef LESS 1558 * #undef EQUAL 1559 * 1560 * logVar(bsr,"zd"); 1561 * 1562 */ 1563 #define BSEARCH(RESULT_INDEX, SEARCH_ELEMENT, B_N, B_LESS, B_EQUAL) do {\ 1564 ssize_t UNIQVAR(b_first) = 0, UNIQVAR(b_middle), UNIQVAR(b_last);\ 1565 UNIQVAR(b_last) = B_N-1;\ 1566 while (UNIQVAR(b_first) <= UNIQVAR(b_last)) {\ 1567 UNIQVAR(b_middle) = (UNIQVAR(b_first)+UNIQVAR(b_last))/2;\ 1568 if (B_LESS(UNIQVAR(b_middle), SEARCH_ELEMENT)) UNIQVAR(b_first) = UNIQVAR(b_middle) + 1;\ 1569 else if (B_EQUAL(UNIQVAR(b_middle), SEARCH_ELEMENT)) {\ 1570 RESULT_INDEX = UNIQVAR(b_middle);\ 1571 goto UNIQVAR(end);\ 1572 }\ 1573 else UNIQVAR(b_last) = UNIQVAR(b_middle) -1;\ 1574 }\ 1575 /* element not found */\ 1576 RESULT_INDEX = -1;\ 1577 UNIQVAR(end):;\ 1578 } while(0) 1579 1580 // BINARY SEARCH END 1581 1582 // makeRoom is dynamic memory allocation algorithm 1583 // given a length, an allocated size and the additionnal length, 1584 // makeRoom returns the new allocated size for realloc 1585 // when the new allocated size equals alloc value, there is no need to realloc the memory, enough space is already available 1586 #define libsheepyPrealloc (1024*1024) 1587 #define makeRoom(length, alloc, addlength) funcbegin\ 1588 typeof(alloc) r;\ 1589 typeof(alloc) newlen = (length) + (addlength);\ 1590 if (newlen < (alloc)) {\ 1591 r = alloc;\ 1592 } \ 1593 else {\ 1594 if (newlen < libsheepyPrealloc) {\ 1595 r = newlen * 2;\ 1596 }\ 1597 else {\ 1598 r = newlen + libsheepyPrealloc;\ 1599 }\ 1600 }\ 1601 r;\ 1602 funcend 1603 1604 // initialize libsheepy (optional, for debug) 1605 typedef void(*initLibsheepyObjectP)(void); 1606 void initLibsheepyF(const char *progPath, initLibsheepyObjectP initF); 1607 #define initLibsheepy(progPath) initLibsheepyF(progPath, NULL) 1608 1609 // free internal buffers at exit 1610 void finalizeLibsheepyCharAtExit(void); 1611 1612 // get current stack limit - returns 0 when error 1613 int64_t getStackLimit(void) MUST_CHECK; 1614 1615 // set stack limit (-1 for unlimited) - returns 0 when error 1616 int setStackLimit(int64_t stackSize) MUST_CHECK; 1617 1618 // enable core dump 1619 int enableCoreDump(void) MUST_CHECK; 1620 1621 // get program name 1622 const char *getProgName(void) MUST_CHECK; 1623 1624 // set program name 1625 bool setProgName(const char *name) MUST_CHECK; 1626 1627 // set default program name 1628 void setDefaultProgName(void); 1629 1630 // free ProgName 1631 void freeProgName(void); 1632 1633 // get program path as given in the shell 1634 const char *getProgPath(void) MUST_CHECK; 1635 1636 // get real program path, allocates path string internally 1637 const char *getRealProgPath(void) MUST_CHECK; 1638 1639 // free real program path 1640 void freeRealProgPath(void); 1641 1642 // run system command and free command buffer 1643 #define systemNFree(command) systemNFreeF(command, __LINE__, __func__, __FILE__) 1644 int systemNFreeF(char *command, int line, const char *thisFunc, const char *thisFileName) MUST_CHECK; 1645 1646 // get modification time for path 1647 time_t getModificationTime(const char *path) MUST_CHECK; 1648 1649 // set modification time for path 1650 int setModificationTime(const char *path, time_t mtime) MUST_CHECK; 1651 1652 // true when path is readable 1653 bool isReadable(const char *path) MUST_CHECK; 1654 1655 // true when path is writable 1656 bool isWritable(const char *path) MUST_CHECK; 1657 1658 // true when path is executable 1659 bool isExecutable(const char *path) MUST_CHECK; 1660 1661 // compare modification times for path1 and path2 1662 bool equalModificationTimes(const char *path1, const char *path2) MUST_CHECK; 1663 1664 // get current unix time 1665 time_t getCurrentUnixTime(void) MUST_CHECK; 1666 1667 // convert date string to unix time 1668 time_t strToUnixTime(const char *date, const char *format) MUST_CHECK; 1669 1670 // convert unix time to string 1671 char *timeToS(const time_t t) MUST_CHECK; 1672 char *bTimeToS(char *dst, const time_t t) MUST_CHECK; 1673 char *bLTimeToS(char *dst, size_t dstSize, const time_t t) MUST_CHECK; 1674 1675 // convert unix time to Y-m-d H:M:S string 1676 char *timeToYMDS(const time_t t) MUST_CHECK; 1677 char *bTimeToYMDS(char *dst, const time_t t) MUST_CHECK; 1678 char *bLTimeToYMDS(char *dst, size_t dstSize, const time_t t) MUST_CHECK; 1679 1680 // get current date in ctime format 1681 char *getCurrentDate(void) MUST_CHECK; 1682 char *bGetCurrentDate(char *dst) MUST_CHECK; 1683 char *bLGetCurrentDate(char *dst, size_t dstSize) MUST_CHECK; 1684 1685 // get current date in Y-m-d H:M:S format 1686 char *getCurrentDateYMD(void) MUST_CHECK; 1687 char *bGetCurrentDateYMD(char *dst) MUST_CHECK; 1688 char *bLGetCurrentDateYMD(char *dst, size_t dstSize) MUST_CHECK; 1689 1690 // dirname 1691 char *shDirname(const char *path) MUST_CHECK; 1692 char *bDirname(char *path) MUST_CHECK; 1693 char *bLDirname(char *path, size_t pathSize) MUST_CHECK; 1694 1695 // expand home ~/ 1696 char *expandHome(const char *path) MUST_CHECK; 1697 char *iExpandHome(char **path) MUST_CHECK; 1698 char *bExpandHome(char *path) MUST_CHECK; 1699 char *bLExpandHome(char *path, size_t pathSize) MUST_CHECK; 1700 1701 // normalize path 1702 char *normalizePath(const char *path) MUST_CHECK; 1703 char *iNormalizePath(char **path) MUST_CHECK; 1704 char *bNormalizePath(char *path) MUST_CHECK; 1705 char *bLNormalizePath(char *path, size_t pathSize) MUST_CHECK; 1706 1707 // relative path 1708 char *relPath(const char *path, const char *start) MUST_CHECK; 1709 char *iRelPath(char **path, const char *start) MUST_CHECK; 1710 char *bRelPath(char *dest, const char *path, const char *start) MUST_CHECK; 1711 char *bLRelPath(char *dest, size_t destSize, char *path, const char *start) MUST_CHECK; 1712 1713 // get home path 1714 char *getHomePath(void) MUST_CHECK; 1715 char *bGetHomePath(char *path) MUST_CHECK; 1716 char *bLGetHomePath(char *path, size_t pathSize) MUST_CHECK; 1717 const char *getCHomePath(void) MUST_CHECK; 1718 1719 // get current working directory 1720 char *getCwd(void) MUST_CHECK; 1721 char *bLGetCwd(char *path, size_t pathSize) MUST_CHECK; 1722 1723 // change directory 1724 int chDir(const char *path) MUST_CHECK; 1725 1726 // true when path is directory 1727 bool isDir(const char *path) MUST_CHECK; 1728 1729 // read link to a new string 1730 char *shReadlink(const char *path) MUST_CHECK; 1731 1732 // read link chain to the end to a new string 1733 char *endlink(const char *path) MUST_CHECK; 1734 1735 // true when path is symbolic link 1736 bool isLink(const char *path) MUST_CHECK; 1737 1738 // file and dir exists 1739 bool fileExists(const char *filePath) MUST_CHECK; 1740 #define isPath fileExists 1741 1742 // chmod "721" 1743 bool fileChmod(const char *filePath, mode_t mode) MUST_CHECK; 1744 1745 // file size 1746 ssize_t fileSize(const char *filePath) MUST_CHECK; 1747 ssize_t fileSizeFP(FILE *fp) MUST_CHECK; 1748 1749 // read file 1750 void *readFileToS(const char *filePath) MUST_CHECK; 1751 void *bReadFileToS(const char *filePath, void *dst) MUST_CHECK; 1752 void *bLReadFileToS(const char *filePath, void *dst, size_t dstSize) MUST_CHECK; 1753 ssize_t readFile(const char *filePath, void **buffer) MUST_CHECK; 1754 ssize_t bReadFile(const char *filePath, void *buffer) MUST_CHECK; 1755 ssize_t bLReadFile(const char *filePath, void *buffer, size_t dstSize) MUST_CHECK; 1756 void *readStreamToS(FILE *fp) MUST_CHECK; 1757 void *bReadStreamToS(FILE *fp, void *dst) MUST_CHECK; 1758 void *bLReadStreamToS(FILE *fp, void *dst, size_t dstSize) MUST_CHECK; 1759 // defines without '...ToS' 1760 #define readFileS readFileToS 1761 #define bReadFileS bReadFileToS 1762 #define bLReadFileS bLReadFileToS 1763 #define readStreamS readStreamToS 1764 #define bReadStreamS bReadStreamToS 1765 #define bLReadStreamS bLReadStreamToS 1766 1767 // write file 1768 int writeFileS(const char *filePath, const char *string) MUST_CHECK; 1769 int writeFile(const char *filePath, void *buffer, size_t len) MUST_CHECK; 1770 int writeStreamS(FILE *fp, const char *string) MUST_CHECK; 1771 int writeLStream(FILE *fp, void *buffer, size_t len) MUST_CHECK; 1772 1773 // append string to file 1774 bool appendFileS(const char *filePath, const char *string) MUST_CHECK; 1775 bool appendFile(const char *filePath, void *buffer, size_t len) MUST_CHECK; 1776 1777 // walkDir lists files only 1778 char **walkDir(const char* dirPath) MUST_CHECK; 1779 1780 // walkDirDir lists directories 1781 char **walkDirDir(const char* dirPath) MUST_CHECK; 1782 1783 // readDir lists files in a directory 1784 char **readDir(const char *dirPath) MUST_CHECK; 1785 1786 // readDirDir lists directories in a directory 1787 char **readDirDir(const char *dirPath) MUST_CHECK; 1788 1789 // walkDirAll lists files and directories 1790 char **walkDirAll(const char* dirPath) MUST_CHECK; 1791 1792 // readDirAll lists files and directories in a directory 1793 char **readDirAll(const char *dirPath) MUST_CHECK; 1794 1795 // get umask 1796 mode_t getUmask(void) MUST_CHECK; 1797 1798 // get current permissions for creating directories 1799 mode_t getCurrentPermissions(void) MUST_CHECK; 1800 1801 // recursive mkdir 1802 int mkdirParents(const char* path) MUST_CHECK; 1803 1804 // delete files and directories 1805 int rmAll(const char* path) MUST_CHECK; 1806 1807 // copy files recursively 1808 int copy(const char* src, const char* dst) MUST_CHECK; 1809 1810 // rename file 1811 int shRename(const char* src, const char* dst) MUST_CHECK; 1812 1813 // move files recursively 1814 int shMove(const char* src, const char* dst) MUST_CHECK; 1815 1816 // use /dev/urandom as a source of random numbers 1817 void setSoftwareRandom(void); 1818 1819 // use cpu random instruction as a source of random numbers 1820 void setHardwareRandom(void); 1821 1822 // open /dev/urandom in libsheepy 1823 int randomUrandomOpen(void) MUST_CHECK; 1824 1825 // close /dev/urandom in libsheepy 1826 void randomUrandomClose(void); 1827 1828 // return random 64 bit unsigned integer 1829 uint64_t randomWord(void) MUST_CHECK; 1830 1831 // return random 64 bit unsigned integer from the cpu 1832 uint64_t randomWordFromHW(void) MUST_CHECK; 1833 1834 // return a random value between 0 and range 0<=value<range 1835 uint64_t randomChoice(uint64_t range) MUST_CHECK; 1836 1837 // generate random string 1838 char *randomS(uint64_t length) MUST_CHECK; 1839 char *bRandomS(char *dst, size_t length) MUST_CHECK; 1840 1841 // generate random alpha numerical string 1842 char *randomAlphaNumS(uint64_t length) MUST_CHECK; 1843 char *bRandomAlphaNumS(char *dst, size_t dstSize) MUST_CHECK; 1844 1845 // read user input (one line) as a string 1846 char *readS(void) MUST_CHECK; 1847 char *bLReadS(char *dst, size_t dstSize) MUST_CHECK; 1848 1849 // read hidden password as a string - like getpass 1850 char *readPasswordS(void) MUST_CHECK; 1851 1852 // write zero to all bytes in string with memset, for clearing password buffers 1853 bool zeroS(char *string) MUST_CHECK; 1854 1855 // write zero to all bytes in buffer with memset 1856 bool zeroBuf(void *buf, size_t len) MUST_CHECK; 1857 1858 // allocate and copy buffer 1859 void *memdup(const void *buf, size_t size) MUST_CHECK; 1860 1861 // wait until press the enter key 1862 void readEnter(void); 1863 1864 // TODO writeLine - copy cg_c code 1865 1866 // readLine 1867 char *readLine(FILE *fp) MUST_CHECK; 1868 1869 // convert char to string by declaring string dst with c in it 1870 #define charToS(dst, c) \ 1871 ;char dst[2] = {c, 0} 1872 1873 // free many char* 1874 void freeManySF(char *paramType, ...); 1875 #define freeManyS(...) freeManySF("", __VA_ARGS__, NULL) 1876 1877 // duplicate string 1878 char *dupS(const char *string) MUST_CHECK; 1879 1880 // print like printf, the formating can be NULL 1881 void shPrintfS(const char *fmt, ...); 1882 1883 // stderr printf, the formating can be NULL 1884 void shEPrintfS(const char *fmt, ...); 1885 1886 // print and free s 1887 void logNFree(char *s); 1888 1889 // print buf as hexadecimal 1890 void loghex(const void *buf, size_t len); 1891 1892 // create a string with bytes in buf converted to hex strings: 0xff, 1893 char *toHexS(const void *buf, size_t len) MUST_CHECK; 1894 1895 // create a string with bytes in buf converted to hex strings separated by separator: 0xffSEP 1896 char *toHexSepS(const void *buf, size_t len, const char *separator) MUST_CHECK; 1897 1898 // create a string with bytes in buf converted to hex strings separated by separator and with head string in front of earch byte: HEADffSEP 1899 char *toHexHeadSepS(const void *buf, size_t len, const char *head, const char *separator) MUST_CHECK; 1900 1901 // print new line 1902 #define put puts(""); 1903 1904 // copy src to dst 1905 char *strCpy(char *restrict dst, const char *restrict src) MUST_CHECK; 1906 // copy string to buffer given string length: strNCpy(buffer, string, lenS(string)); 1907 // null safe version of strncpy 1908 char *strNCpy(char *restrict dst, const char *restrict src, size_t srcSize) MUST_CHECK; 1909 char *strLCpy(char *restrict dst, size_t dstSize, const char *restrict src) MUST_CHECK; 1910 1911 // concatenate src to dst 1912 char *strCat(char *restrict dst, const char *restrict src) MUST_CHECK; 1913 char *strNCat(char *restrict dst, const char *restrict src, size_t srcLen) MUST_CHECK; 1914 char *strLCat(char *restrict dst, size_t dstSize, const char *restrict src) MUST_CHECK; 1915 char *strLNCat(char *restrict dst, size_t dstSize, const char *restrict src, size_t srcLen) MUST_CHECK; 1916 1917 // cat: f("qwd ", str," werr ", str2) 1918 char *catSF(const char *paramType, ...) MUST_CHECK; 1919 #define catS(...) catSF("", __VA_ARGS__, NULL) 1920 1921 // cat and copy result to dst buffer 1922 char *iCatSF(char *dst, const char *paramType, ...) MUST_CHECK; 1923 #define iCatS(dst, ...) iCatSF(dst, "", __VA_ARGS__, NULL) 1924 #define bCatS iCatS 1925 char *bLCatSF(char *dst, size_t dstSize, const char *paramType, ...) MUST_CHECK; 1926 #define bLCatS(dst, dstSize, ...) bLCatSF(dst, dstSize, "", __VA_ARGS__, NULL) 1927 1928 // allocate and format string using asprintf 1929 char *formatS(const char *fmt, ...) MUST_CHECK; 1930 1931 /** format and store in string: bFormatS(string, "Value %d", i); */ 1932 char *bFormatS(char *string, const char *fmt, ...) MUST_CHECK; 1933 1934 /** format and store in string: bLFormatS(string, sizeof(string), "Value %d", i); */ 1935 char *bLFormatS(char *string, size_t stringSize, const char *fmt, ...) MUST_CHECK; 1936 1937 // append strings 1938 char *appendS(const char *string1, const char *string2) MUST_CHECK; 1939 char *appendCharS(const char *string1, char c) MUST_CHECK; 1940 char *appendSChar(char c, const char *string2) MUST_CHECK; 1941 char *iAppendS(char **string1, const char *string2) MUST_CHECK; 1942 char *iAppendCharS(char **string1, char c) MUST_CHECK; 1943 char *iAppendNFreeS(char **string1, char *string2) MUST_CHECK; 1944 char *iAppendManySF(char **string, const char *paramType, ...) MUST_CHECK; 1945 #define iAppendManyS(s, s1, ...) iAppendManySF(s, s1, __VA_ARGS__, NULL) 1946 char *bAppendManySF(char *string, const char *paramType, ...) MUST_CHECK; 1947 #define bAppendManyS(s, s1, ...) bAppendManySF(s, s1, __VA_ARGS__, NULL) 1948 char *bLAppendManySF(char *string, size_t stringSize, const char *paramType, ...) MUST_CHECK; 1949 #define bLAppendManyS(s, sSize, s1, ...) bLAppendManySF(s, sSize, s1, __VA_ARGS__, NULL) 1950 1951 // prepend string 1952 char *prependS(const char *string1, const char *string2) MUST_CHECK; 1953 char *prependCharS(const char *string1, char c) MUST_CHECK; 1954 char *prependSChar(char c, const char *string2) MUST_CHECK; 1955 char *iPrependS(char **string1, const char *string2) MUST_CHECK; 1956 char *iPrependCharS(char **string1, char c) MUST_CHECK; 1957 char *iPrependNFreeS(char **string1, char *string2) MUST_CHECK; 1958 char *bPrependS(char *string1, const char *string2) MUST_CHECK; 1959 char *bLPrependS(char *string1, size_t string1Size, const char *string2) MUST_CHECK; 1960 1961 // string replace 1962 char *replaceS(const char *s, const char *olds, const char *news, size_t max) MUST_CHECK; 1963 char *replaceCharSS(const char *s, char olds, const char *news, size_t max) MUST_CHECK; 1964 char *replaceSCharS(const char *s, const char *olds, char news, size_t max) MUST_CHECK; 1965 char *replaceCharCharS(const char *s, char olds, char news, size_t max) MUST_CHECK; 1966 #define replaceS_max(s,olds,news) replaceS(s,olds,news, 0) 1967 #define replaceSMax replaceS_max 1968 // TODO add support for all types, create a generic, create ignore case version 1969 size_t replaceSLen(const char *s, const char *olds, const char *news, size_t max) MUST_CHECK; 1970 #define replaceSMaxLen(s,olds,news) replaceSLen(s,olds,news, 0) 1971 char* iReplaceS(char **s, const char *olds, const char *news, size_t max) MUST_CHECK; 1972 char* iReplaceCharSS(char **s, char olds, const char *news, size_t max) MUST_CHECK; 1973 char* iReplaceSCharS(char **s, const char *olds, char news, size_t max) MUST_CHECK; 1974 char* iReplaceCharCharS(char **s, char olds, char news, size_t max) MUST_CHECK; 1975 #define iReplaceS_max(s,olds,news) iReplaceS(s,olds,news, 0) 1976 #define iReplaceSMax iReplaceS_max 1977 char* bReplaceS(char *s, const char *olds, const char *news, size_t max) MUST_CHECK; 1978 #define bReplaceS_max(s,olds,news) bReplaceS(s,olds,news, 0) 1979 #define bReplaceSMax bReplaceS_max 1980 char* bLReplaceS(char *s, size_t sSize, const char *olds, const char *news, size_t max) MUST_CHECK; 1981 #define bLReplaceS_max(s,sSize,olds,news) bLReplaceS(s,sSize,olds,news, 0) 1982 #define bLReplaceSMax bLReplaceS_max 1983 1984 // string replace many olds with news (s, olds1, news1, olds2, news2,...) 1985 char *replaceManySF(const char *paramType, ...) MUST_CHECK; 1986 #define replaceManyS(s, ...) replaceManySF(s, __VA_ARGS__, NULL) 1987 char *iReplaceManySF(char **string, char *paramType, ...) MUST_CHECK; 1988 #define iReplaceManyS(s, olds, ...) iReplaceManySF(s, olds, __VA_ARGS__, NULL) 1989 char *bReplaceManySF(char *s, char *paramType, ...) MUST_CHECK; 1990 #define bReplaceManyS(s, olds, ...) bReplaceManySF(s, olds, __VA_ARGS__, NULL) 1991 char *bLReplaceManySF(char *s, size_t sSize, char *paramType, ...) MUST_CHECK; 1992 #define bLReplaceManyS(s, sSize, olds, ...) bLReplaceManySF(s, sSize, olds, __VA_ARGS__, NULL) 1993 1994 // ignore case string replace 1995 char *icReplaceS(const char *s, const char *olds, const char *news, size_t max) MUST_CHECK; 1996 char *icReplaceCharSS(const char *s, char olds, const char *news, size_t max) MUST_CHECK; 1997 char *icReplaceSCharS(const char *s, const char *olds, char news, size_t max) MUST_CHECK; 1998 char *icReplaceCharCharS(const char *s, char olds, char news, size_t max) MUST_CHECK; 1999 #define icReplaceS_max(s,olds,news) icReplaceS(s,olds,news, 0) 2000 #define icReplaceSMax icReplaceS_max 2001 char* iicReplaceS(char **s, const char *olds, const char *news, size_t max) MUST_CHECK; 2002 char* iicReplaceCharSS(char **s, char olds, const char *news, size_t max) MUST_CHECK; 2003 char* iicReplaceSCharS(char **s, const char *olds, char news, size_t max) MUST_CHECK; 2004 char* iicReplaceCharCharS(char **s, char olds, char news, size_t max) MUST_CHECK; 2005 #define iicReplaceS_max(s,olds,news) iicReplaceS(s,olds,news, 0) 2006 #define iicReplaceSMax iicReplaceS_max 2007 char* bicReplaceS(char *s, const char *olds, const char *news, size_t max) MUST_CHECK; 2008 #define bicReplaceS_max(s,olds,news) bicReplaceS(s,olds,news, 0) 2009 #define bicReplaceSMax bicReplaceS_max 2010 char* bLicReplaceS(char *s, size_t sSize, const char *olds, const char *news, size_t max) MUST_CHECK; 2011 #define bLicReplaceS_max(s,sSize,olds,news) bLicReplaceS(s,sSize,olds,news, 0) 2012 #define bLicReplaceSMax bLicReplaceS_max 2013 2014 // string replace many olds with news (s, olds1, news1, olds2, news2,...) 2015 char *icReplaceManySF(const char *paramType, ...) MUST_CHECK; 2016 #define icReplaceManyS(s, ...) icReplaceManySF(s, __VA_ARGS__, NULL) 2017 char *iicReplaceManySF(char **string, char *paramType, ...) MUST_CHECK; 2018 #define iicReplaceManyS(s, olds, ...) iicReplaceManySF(s, olds, __VA_ARGS__, NULL) 2019 char *bicReplaceManySF(char *s, char *paramType, ...) MUST_CHECK; 2020 #define bicReplaceManyS(s, olds, ...) bicReplaceManySF(s, olds, __VA_ARGS__, NULL) 2021 char *bLicReplaceManySF(char *s, size_t sSize, char *paramType, ...) MUST_CHECK; 2022 #define bLicReplaceManyS(s, sSize, olds, ...) bLicReplaceManySF(s, sSize, olds, __VA_ARGS__, NULL) 2023 2024 // string equal (compare content) 2025 bool eqS(const char *string1, const char *string2) MUST_CHECK; 2026 #define strEq eqS 2027 bool eqCharS(char c, const char *string2) MUST_CHECK; 2028 bool eqSChar(const char *string1, char c) MUST_CHECK; 2029 2030 // string equal at index (compare content) 2031 bool eqIS(const char *string1, const char *string2, int64_t index) MUST_CHECK; 2032 #define strIEq eqIS 2033 bool eqICharS(const char *string1, char c, int64_t index) MUST_CHECK; 2034 2035 // look for string2 at string1 start 2036 bool startsWithS(const char *string1, const char *string2) MUST_CHECK; 2037 bool startsWithCharS(const char *string1, char c) MUST_CHECK; 2038 2039 // look for string2 at string1 end 2040 bool endsWithS(const char *string1, const char *string2) MUST_CHECK; 2041 bool endsWithCharS(const char *string1, char c) MUST_CHECK; 2042 2043 // count number of (non-overlapping) occurrences of a substring 2044 ssize_t countS(const char *s, const char *needle) MUST_CHECK; 2045 ssize_t countCharS(const char *s, char c) MUST_CHECK; 2046 2047 // ignore case string equal (compare content) 2048 bool icEqS(const char *string1, const char *string2) MUST_CHECK; 2049 bool icEqCharS(char c, const char *string2) MUST_CHECK; 2050 bool icEqSChar(const char *string1, char c) MUST_CHECK; 2051 2052 // ignore case string equal at index (compare content) 2053 bool icEqIS(const char *string1, const char *string2, int64_t index) MUST_CHECK; 2054 bool icEqICharS(const char *string1, char c, int64_t index) MUST_CHECK; 2055 2056 // ignore case and look for string2 at string1 start 2057 bool icStartsWithS(const char *string1, const char *string2) MUST_CHECK; 2058 bool icStartsWithCharS(const char *string1, char c) MUST_CHECK; 2059 2060 // ignore case look for string2 at string1 end 2061 bool icEndsWithS(const char *string1, const char *string2) MUST_CHECK; 2062 bool icEndsWithCharS(const char *string1, char c) MUST_CHECK; 2063 2064 // ignore case and count number of (non-overlapping) occurrences of a substring 2065 ssize_t icCountS(const char *s, const char *needle) MUST_CHECK; 2066 ssize_t icCountCharS(const char *s, char c) MUST_CHECK; 2067 2068 // has terminal control char (for example colors) 2069 bool hasCtrlChar(const char *string) MUST_CHECK; 2070 2071 // remove terminal control char from string 2072 char *stripCtrlS(const char *string) MUST_CHECK; 2073 char *iStripCtrlS(char **string) MUST_CHECK; 2074 char *bStripCtrlS(char *string) MUST_CHECK; 2075 2076 // remove ansi colors from string 2077 char *stripColorsS(const char *string) MUST_CHECK; 2078 char *iStripColorsS(char **string) MUST_CHECK; 2079 char *bStripColorsS(char *string) MUST_CHECK; 2080 2081 // escape quotes and backslashes in string 2082 char* quoteS(const char *s, char delim) MUST_CHECK; 2083 char* bQuoteS(char *dest, const char *s, char delim) MUST_CHECK; 2084 char* bLQuoteS(char *dest, size_t destSize, const char *s, char delim) MUST_CHECK; 2085 size_t quoteLenS(const char *s, char delim) MUST_CHECK; 2086 // escape string to become a parsable json string 2087 char* escapeS(const char *s, char delim /*string delimiter ' or "*/) MUST_CHECK; 2088 char* bEscapeS(char *dest, const char *s, char delim /*string delimiter ' or "*/) MUST_CHECK; 2089 char* bLEscapeS(char *dest, size_t destSize, const char *s, char delim /*string delimiter ' or "*/) MUST_CHECK; 2090 size_t escapeLenS(const char *s, char delim /*string delimiter ' or "*/) MUST_CHECK; 2091 // convert nibble to hexadecimal digit character 2092 char nibbleToHex(u8 n) MUST_CHECK; 2093 // escape string to become compilable in a C source code 2094 char* cEscapeS(const char *S) MUST_CHECK; 2095 char* bCEscapeS(char *dest, const char *S) MUST_CHECK; 2096 char* bLCEscapeS(char *dest, size_t destSize, const char *S) MUST_CHECK; 2097 size_t cEscapeLenS(const char *s) MUST_CHECK; 2098 2099 // true when string is a number (integer or float) 2100 bool isNumber(const char *string) MUST_CHECK; 2101 2102 // true when string is an integer 2103 bool isInt(const char *string) MUST_CHECK; 2104 2105 // parseInt 2106 int64_t parseInt(const char *string) MUST_CHECK; 2107 int64_t parseIntChar(char c) MUST_CHECK; 2108 int64_t parseI64(const char *string) MUST_CHECK; 2109 int64_t parseI64Char(char c) MUST_CHECK; 2110 2111 // parseDouble 2112 double parseDouble(const char *string) MUST_CHECK; 2113 double parseDoubleChar(char c) MUST_CHECK; 2114 2115 // parse hexadecimal string: 0xff 2116 uint64_t parseHex(const char *string) MUST_CHECK; 2117 // TODO parseHexChar 2118 2119 // convert int to string 2120 char *intToS(int64_t n) MUST_CHECK; 2121 char *bIntToS(char *s, int64_t n) MUST_CHECK; 2122 2123 // convert double to string 2124 char *doubleToS(double n) MUST_CHECK; 2125 char *bDoubleToS(char *s, double n) MUST_CHECK; 2126 2127 // length 2128 size_t lenS(const char *string) MUST_CHECK; 2129 // string buffer size: strlen+1 2130 size_t sizeS(const char *string) MUST_CHECK; 2131 2132 /** 2133 * upper case and store the result in c and return the result 2134 */ 2135 #define toUpper(c) ((c) = toupper(c), c) 2136 2137 // duplicate and upper case 2138 char *upperS(const char *string) MUST_CHECK; 2139 char *iUpperS(char **string) MUST_CHECK; 2140 char *bUpperS(char *string) MUST_CHECK; 2141 2142 /** 2143 * lower case and store the result in c and return the result 2144 */ 2145 #define toLower(c) ((c) = tolower(c), c) 2146 2147 // duplicate and lower case 2148 char *lowerS(const char *string) MUST_CHECK; 2149 char *iLowerS(char **string) MUST_CHECK; 2150 char *bLowerS(char *string) MUST_CHECK; 2151 2152 // duplicate and trim 2153 char *trimS(const char *string) MUST_CHECK; 2154 char *iTrimS(char **string) MUST_CHECK; 2155 char *bTrimS(char *string) MUST_CHECK; 2156 char *lTrimS(const char *string) MUST_CHECK; 2157 char *iLTrimS(char **string) MUST_CHECK; 2158 char *bLTrimS(char *string) MUST_CHECK; 2159 char *rTrimS(const char *string) MUST_CHECK; 2160 char *iRTrimS(char **string) MUST_CHECK; 2161 char *bRTrimS(char *string) MUST_CHECK; 2162 2163 // remove successive repetitions of char c 2164 char *uniqS(const char *string, char c) MUST_CHECK; 2165 char *iUniqS(char **string, char c) MUST_CHECK; 2166 char *bUniqS(char *string, char c) MUST_CHECK; 2167 #define uniqSlash(s) uniqS(s, '/') 2168 #define iUniqSlash(s) iUniqS(&(s), '/') 2169 #define bUniqSlash(s) bUniqS(s, '/') 2170 2171 // ignore case and remove successive repetitions of char c 2172 char *icUniqS(const char *string, char c) MUST_CHECK; 2173 char *iicUniqS(char **string, char c) MUST_CHECK; 2174 char *bicUniqS(char *string, char c) MUST_CHECK; 2175 2176 // repeat string count times 2177 char *repeatS(const char *string, size_t count) MUST_CHECK; 2178 char *iRepeatS(char **string, size_t count) MUST_CHECK; 2179 char *bRepeatS(char *dest, const char *string, size_t count) MUST_CHECK; 2180 char *bLRepeatS(char *dest, size_t destSize, const char *string, size_t count) MUST_CHECK; 2181 char *repeatCharS(char c, size_t count) MUST_CHECK; 2182 char *bRepeatCharS(char *dest, char c, size_t count) MUST_CHECK; 2183 char *bLRepeatCharS(char *dest, size_t destSize, char c, size_t count) MUST_CHECK; 2184 2185 // length of string repeated count times 2186 ssize_t repeatLenS(const char *string, size_t count) MUST_CHECK; 2187 2188 // ellipsisStart string 2189 char *ellipsisStartS(const char *string, size_t targetLength, const char *ellipsisString) MUST_CHECK; 2190 char *iEllipsisStartS(char **string, size_t targetLength, const char *ellipsisString) MUST_CHECK; 2191 char *bEllipsisStartS(char *dest, const char *string, size_t targetLength, const char *ellipsisString) MUST_CHECK; 2192 char *bLEllipsisStartS(char *dest, size_t destSize, const char *string, size_t targetLength, const char *ellipsisString) MUST_CHECK; 2193 char *ellipsisStartCharS(const char *string, size_t targetLength, char ellipsisChar) MUST_CHECK; 2194 char *iEllipsisStartCharS(char **string, size_t targetLength, char ellipsisChar) MUST_CHECK; 2195 char *bEllipsisStartCharS(char *dest, const char *string, size_t targetLength, char ellipsisChar) MUST_CHECK; 2196 char *bLEllipsisStartCharS(char *dest, size_t destSize, const char *string, size_t targetLength, char ellipsisChar) MUST_CHECK; 2197 2198 // length of string after ellipsis 2199 ssize_t ellipsisLenS(const char *string, size_t targetLength, const char *ellipsisString) MUST_CHECK; 2200 2201 // ellipsisEnd string 2202 char *ellipsisEndS(const char *string, size_t targetLength, const char *ellipsisString) MUST_CHECK; 2203 char *iEllipsisEndS(char **string, size_t targetLength, const char *ellipsisString) MUST_CHECK; 2204 char *bEllipsisEndS(char *dest, const char *string, size_t targetLength, const char *ellipsisString) MUST_CHECK; 2205 char *bLEllipsisEndS(char *dest, size_t destSize, const char *string, size_t targetLength, const char *ellipsisString) MUST_CHECK; 2206 char *ellipsisEndCharS(const char *string, size_t targetLength, char ellipsisChar) MUST_CHECK; 2207 char *iEllipsisEndCharS(char **string, size_t targetLength, char ellipsisChar) MUST_CHECK; 2208 char *bEllipsisEndCharS(char *dest, const char *string, size_t targetLength, char ellipsisChar) MUST_CHECK; 2209 char *bLEllipsisEndCharS(char *dest, size_t destSize, const char *string, size_t targetLength, char ellipsisChar) MUST_CHECK; 2210 2211 // padStart string 2212 char *padStartS(const char *string, size_t targetLength, const char *padString) MUST_CHECK; 2213 char *iPadStartS(char **string, size_t targetLength, const char *padString) MUST_CHECK; 2214 char *bPadStartS(char *dest, const char *string, size_t targetLength, const char *padString) MUST_CHECK; 2215 char *bLPadStartS(char *dest, size_t destSize, const char *string, size_t targetLength, const char *padString) MUST_CHECK; 2216 char *padStartCharS(const char *string, size_t targetLength, char padChar) MUST_CHECK; 2217 char *iPadStartCharS(char **string, size_t targetLength, char padChar) MUST_CHECK; 2218 char *bPadStartCharS(char *dest, const char *string, size_t targetLength, char padChar) MUST_CHECK; 2219 char *bLPadStartCharS(char *dest, size_t destSize, const char *string, size_t targetLength, char padChar) MUST_CHECK; 2220 2221 // length of string after padStart 2222 ssize_t padStartLenS(const char *string, size_t targetLength, const char *padString) MUST_CHECK; 2223 2224 // padEnd string 2225 char *padEndS(const char *string, size_t targetLength, const char *padString) MUST_CHECK; 2226 char *iPadEndS(char **string, size_t targetLength, const char *padString) MUST_CHECK; 2227 char *bPadEndS(char *dest, const char *string, size_t targetLength, const char *padString) MUST_CHECK; 2228 char *bLPadEndS(char *dest, size_t destSize, const char *string, size_t targetLength, const char *padString) MUST_CHECK; 2229 char *padEndCharS(const char *string, size_t targetLength, char padChar) MUST_CHECK; 2230 char *iPadEndCharS(char **string, size_t targetLength, char padChar) MUST_CHECK; 2231 char *bPadEndCharS(char *dest, const char *string, size_t targetLength, char padChar) MUST_CHECK; 2232 char *bLPadEndCharS(char *dest, size_t destSize, const char *string, size_t targetLength, char padChar) MUST_CHECK; 2233 2234 // length of string after padEnd 2235 ssize_t padEndLenS(const char *string, size_t targetLength, const char *padString) MUST_CHECK; 2236 2237 // get char at python index 2238 char getS(const char *string, int64_t index) MUST_CHECK; 2239 2240 // set char at python index 2241 char *setS(char *string, int64_t index, char c) MUST_CHECK; 2242 2243 // swap characters in a string 2244 char *swapS(char *string, int64_t index1, int64_t index2) MUST_CHECK; 2245 char *iSwapS(char **string, int64_t index1, int64_t index2) MUST_CHECK; 2246 char *bSwapS(char *string, int64_t index1, int64_t index2) MUST_CHECK; 2247 char *bLSwapS(char *string, size_t size, int64_t index1, int64_t index2) MUST_CHECK; 2248 2249 // slice string 2250 // function to slice parts of a string [1:10] - python style indexes 0..len-1 -1..-len+1 2251 char *sliceS(const char *string, int64_t start, int64_t end) MUST_CHECK; 2252 char *iSliceS(char **string, int64_t start, int64_t end) MUST_CHECK; 2253 char *bSliceS(char *string, int64_t start, int64_t end) MUST_CHECK; 2254 char *bLSliceS(char *string, size_t stringSize, int64_t start, int64_t end) MUST_CHECK; 2255 2256 // crop string (slice+del) 2257 char *cropS(char *string, int64_t start, int64_t end) MUST_CHECK; 2258 char *iCropS(char **string, int64_t start, int64_t end) MUST_CHECK; 2259 char cropElemS(char *string, int64_t index) MUST_CHECK; 2260 char iCropElemS(char **string, int64_t index) MUST_CHECK; 2261 2262 // insert string in string 2263 char *insertS(const char *string, int64_t index, const char *toInsert) MUST_CHECK; 2264 char *insertNFreeS(const char *string, int64_t index, char *toInsert) MUST_CHECK; 2265 char *iInsertS(char **string, int64_t index, const char *toInsert) MUST_CHECK; 2266 char *iInsertNFreeS(char **string, int64_t index, char *toInsert) MUST_CHECK; 2267 char *bInsertS(char *string, int64_t index, const char *toInsert) MUST_CHECK; 2268 char *bLInsertS(char *string, size_t stringSize, int64_t index, const char *toInsert) MUST_CHECK; 2269 2270 // inject a char in string 2271 char *injectS(const char *string, int64_t index, char toInject) MUST_CHECK; 2272 char *iInjectS(char **string, int64_t index, char toInject) MUST_CHECK; 2273 char *bInjectS(char *string, int64_t index, char toInject) MUST_CHECK; 2274 char *bLInjectS(char *string, size_t stringSize, int64_t index, char toInject) MUST_CHECK; 2275 2276 // del string 2277 // function to delete parts of a string [1:10] - python style indexes 0..len-1 -1..-len+1 2278 char *delS(const char *string, int64_t start, int64_t end) MUST_CHECK; 2279 char *iDelS(char **string, int64_t start, int64_t end) MUST_CHECK; 2280 char *bDelS(char *string, int64_t start, int64_t end) MUST_CHECK; 2281 char *bLDelS(char *string, size_t stringSize, int64_t start, int64_t end) MUST_CHECK; 2282 2283 // del a character in string 2284 char *delElemS(const char *string, int64_t index) MUST_CHECK; 2285 char *iDelElemS(char **string, int64_t index) MUST_CHECK; 2286 char *bDelElemS(char *string, int64_t index) MUST_CHECK; 2287 char *bLDelElemS(char *string, size_t stringSize, int64_t index) MUST_CHECK; 2288 2289 // find substring 2290 char *findS(const char *string, const char *needle) MUST_CHECK; 2291 char *findCharS(const char *string, char c) MUST_CHECK; 2292 ssize_t indexOfS(const char *string, const char *needle) MUST_CHECK; 2293 ssize_t indexOfCharS(const char *string, char c) MUST_CHECK; 2294 2295 // true when needle is found 2296 bool hasS(const char *string, const char *needle) MUST_CHECK; 2297 bool hasCharS(const char *string, char c) MUST_CHECK; 2298 2299 // ignore case find substring 2300 char *icFindS(const char *string, const char *needle) MUST_CHECK; 2301 char *icFindCharS(const char *string, char c) MUST_CHECK; 2302 ssize_t icIndexOfS(const char *string, const char *needle) MUST_CHECK; 2303 ssize_t icIndexOfCharS(const char *string, char c) MUST_CHECK; 2304 2305 // ignore case, true when needle is found 2306 bool icHasS(const char *string, const char *needle) MUST_CHECK; 2307 bool icHasCharS(const char *string, char c) MUST_CHECK; 2308 2309 // parse s string with delim - work like strtok_r from stdlib 2310 char *tokS(char *s, const char *delim, char **saveptr) MUST_CHECK; 2311 2312 // ignore case and parse s string with delim - work like strtok_r from stdlib 2313 char *icTokS(char *s, const char *delim, char **saveptr) MUST_CHECK; 2314 2315 // 2316 // UTF8 string functions 2317 // 2318 2319 // rune is a 32 bit unicode integer 2320 typedef int rune; 2321 2322 // character length of UTF-8 encoded string 2323 size_t lenUTF8(const char *s) MUST_CHECK; 2324 size_t bLLenUTF8(const char *s, size_t maxSize) MUST_CHECK; 2325 2326 // is string valid UTF-8 encoded string 2327 bool isUTF8(const char * string) MUST_CHECK; 2328 bool bLIsUTF8(const char * string, size_t stringSize) MUST_CHECK; 2329 2330 // is string a valid UTF-8 code point 2331 bool isCodeUTF8(const char *code) MUST_CHECK; 2332 2333 extern const uint8_t codeSzUTF8[256]; 2334 2335 /** size in bytes of UTF-8 code point */ 2336 #define codeSizeUTF8(utf8) codeSzUTF8[*(const uint8_t *)(utf8)] 2337 2338 /** move pointer to next UTF-8 code point, no checks are done, the utf8 pointer parameter is unchanged */ 2339 #define nextCodeUTF8(utf8) ((utf8) + codeSizeUTF8(utf8)) 2340 2341 /** change the utf8 pointer parameter to next UTF-8 code point, like char *s; s++; */ 2342 #define nxtCodeUTF8(utf8) EVA(utf8, nextCodeUTF8(utf8)) 2343 #define nxCodeUTF8(utf8) (utf8 = nextCodeUTF8(utf8)) 2344 2345 // next code point, works only when utf8 points to a valid code point 2346 const char *nextUTF8(const char *utf8) MUST_CHECK; 2347 const char *bLNextUTF8(const char *string, size_t utf8Size, const char *utf8) MUST_CHECK; 2348 2349 // find next code point even when utf8 points inside a code point 2350 const char *findNextUTF8(const char *string, size_t utf8Size, const char *utf8) MUST_CHECK; 2351 2352 // previous code point, undefined behavior when utf8 points to the start of the string 2353 const char *prevUTF8(const char *utf8) MUST_CHECK; 2354 2355 // previous code point 2356 const char *bPrevUTF8(const char *string, const char *utf8) MUST_CHECK; 2357 2358 // character index to pointer 2359 const char *idx2PtrUTF8(const char *utf8, int64_t index) MUST_CHECK; 2360 const char *bLIdx2PtrUTF8(const char *utf8, size_t utf8Size, int64_t index) MUST_CHECK; 2361 2362 // pointer to character index 2363 int64_t ptr2IdxUTF8(const char *utf8, const char *pos) MUST_CHECK; 2364 int64_t bPtr2IdxUTF8(const char *start, const char *utf8, const char *pos) MUST_CHECK; 2365 int64_t bLPtr2IdxUTF8(const char *utf8, size_t utf8Size, const char *pos) MUST_CHECK; 2366 int64_t bLPtr2NegIdxUTF8(const char *utf8, size_t utf8Size, const char *pos) MUST_CHECK; 2367 2368 // make new valid UTF-8 encoded string 2369 char *makeValidUTF8(const char *utf8) MUST_CHECK; 2370 // make utf8 a valid UTF-8 encoded string 2371 char *bMakeValidUTF8(char *utf8) MUST_CHECK; 2372 char *nMakeValidUTF8(const char *utf8, size_t utf8Len) MUST_CHECK; 2373 char *bNMakeValidUTF8(char *dst, const char *utf8, size_t utf8Len) MUST_CHECK; 2374 char *bLMakeValidUTF8(char *dst, size_t dstSize, const char *utf8) MUST_CHECK; 2375 char *bLNMakeValidUTF8(char *dst, size_t dstSize, const char *utf8, size_t utf8Len) MUST_CHECK; 2376 2377 // strncpy where srcLen is number of characters 2378 char *strNCpyUTF8(char *dst, const char *src, size_t srcLen) MUST_CHECK; 2379 2380 // strLCpy for UTF-8 encoded strings 2381 char *strLCpyUTF8(char *dst, size_t dstSize, const char *src) MUST_CHECK; 2382 2383 // strncat where srcLen is number of characters 2384 char *strNCatUTF8(char *dst, const char *src, size_t srcLen) MUST_CHECK; 2385 2386 // strLCat for UTF-8 encoded strings 2387 char *strLCatUTF8(char *dst, size_t dstSize, const char *src) MUST_CHECK; 2388 2389 // strLNCat for UTF-8 encoded strings 2390 char *strLNCatUTF8(char *dst, size_t dstSize, const char *src, size_t srcLen) MUST_CHECK; 2391 2392 // TODO 2393 char* icReplaceUTF8(const char *s, const char *olds, const char *news, size_t max) MUST_CHECK; 2394 // TODO 2395 char *icReplaceCharSUTF8(const char *s, char olds, const char *news, size_t max) MUST_CHECK; 2396 // TODO 2397 char *icReplaceSCharUTF8(const char *s, const char *olds, char news, size_t max) MUST_CHECK; 2398 // TODO 2399 char* iicReplaceUTF8(char **s, const char *olds, const char *news, size_t max) MUST_CHECK; 2400 // TODO 2401 char *iicReplaceCharSUTF8(char **s, char olds, const char *news, size_t max) MUST_CHECK; 2402 // TODO 2403 char *iicReplaceSCharUTF8(char **s, const char *olds, char news, size_t max) MUST_CHECK; 2404 // TODO 2405 char* bicReplaceUTF8(char *s, const char *olds, const char *news, size_t max) MUST_CHECK; 2406 // TODO 2407 char* bLicReplaceUTF8(char *s, size_t sSize, const char *olds, const char *news, size_t max) MUST_CHECK; 2408 // TODO 2409 char *icReplaceManyUTF8F(const char *paramType, ...) MUST_CHECK; 2410 // TODO 2411 char *iicReplaceManyUTF8F(char **s, char *paramType, ...) MUST_CHECK; 2412 // TODO 2413 char *bicReplaceManyUTF8F(char *s, char *paramType, ...) MUST_CHECK; 2414 // TODO 2415 char *bLicReplaceManyUTF8F(char *s, size_t sSize, char *paramType, ...) MUST_CHECK; 2416 2417 // UTF8 encoded string Index Equal 2418 bool eqIUTF8(const char *string1, const char *string2, int64_t index) MUST_CHECK; 2419 2420 // UTF8 encoded string Index Equal 2421 bool eqICharUTF8(const char *string1, char c, int64_t index) MUST_CHECK; 2422 2423 // ignore case UTF8 encoded string Equal 2424 bool icEqUTF8(const char *string1, const char *string2) MUST_CHECK; 2425 bool icEqCharUTF8(char c, const char *string2) MUST_CHECK; 2426 bool icEqUTF8Char(const char *string1, char c) MUST_CHECK; 2427 2428 // TODO 2429 bool icEqIUTF8(const char *string1, const char *string2, int64_t index) MUST_CHECK; 2430 // TODO 2431 bool icEqICharUTF8(const char *string1, char c, int64_t index) MUST_CHECK; 2432 2433 // starts with for UTF-8 encoded string 2434 bool icStartsWithUTF8(const char *string1, const char *string2) MUST_CHECK; 2435 2436 // ends with for UTF-8 encoded string 2437 bool icEndsWithUTF8(const char *string1, const char *string2) MUST_CHECK; 2438 2439 // ignore case count UTF8 encoded String 2440 ssize_t icCountUTF8(const char *s, const char *needle) MUST_CHECK; 2441 2442 // UTF-8 code point to rune 2443 rune code2RuneUTF8(const char *code) MUST_CHECK; 2444 rune code2RuneLUTF8(const char *code, uint8_t *n) MUST_CHECK; 2445 2446 // rune to UTF-8 code point 2447 size_t bRune2CodeUTF8(char *dst, rune c) MUST_CHECK; 2448 2449 // rune length as UTF-8 code point 2450 uint8_t runeLenUTF8(rune r) MUST_CHECK; 2451 2452 // rune toupper UTF8 2453 rune toupperUTF8(rune c) MUST_CHECK; 2454 2455 // upper case UTF-8 encoded string 2456 char *upperUTF8(const char *string) MUST_CHECK; 2457 char *iUpperUTF8(char **string) MUST_CHECK; 2458 // TODO 2459 char *bUpperUTF8(char *string) MUST_CHECK; 2460 2461 // rune tolower UTF8 2462 rune tolowerUTF8(rune c) MUST_CHECK; 2463 2464 // lower case UTF-8 String 2465 char *lowerUTF8(const char *string) MUST_CHECK; 2466 char *iLowerUTF8(char **string) MUST_CHECK; 2467 // TODO 2468 char *bLowerUTF8(char *string) MUST_CHECK; 2469 2470 // transform UTF-8 string to make it comparable regardless of case 2471 char *casefoldUTF8(const char *utf8) MUST_CHECK; 2472 2473 // uniquify code point in UTF-8 String 2474 char *uniqUTF8(const char *string, const char *code) MUST_CHECK; 2475 char *iUniqUTF8(char **string, const char *code) MUST_CHECK; 2476 char *bUniqUTF8(char *string, const char *code) MUST_CHECK; 2477 // TODO 2478 char *icUniqUTF8(const char *string, const char *code) MUST_CHECK; 2479 // TODO 2480 char *iicUniqUTF8(char **string, const char *code) MUST_CHECK; 2481 // TODO 2482 char *bicUniqUTF8(char *string, char c) MUST_CHECK; 2483 2484 // get rune in UTF8 encoded string 2485 rune getUTF8(const char *string, int64_t index) MUST_CHECK; 2486 2487 // TODO 2488 char *setUTF8(char *string, int64_t index, rune c) MUST_CHECK; 2489 2490 // slice UTF8 encoded String 2491 char *sliceUTF8(const char *string, int64_t start, int64_t end) MUST_CHECK; 2492 char *iSliceUTF8(char **string, int64_t start, int64_t end) MUST_CHECK; 2493 char *bSliceUTF8(char *string, int64_t start, int64_t end) MUST_CHECK; 2494 char *bLSliceUTF8(char *string, size_t stringSize, int64_t start, int64_t end) MUST_CHECK; 2495 2496 // insert string in UTF8 encoded string at index 2497 char *insertUTF8(const char *string, int64_t index, const char *toInsert) MUST_CHECK; 2498 char *insertNFreeUTF8(const char *string, int64_t index, char *toInsert) MUST_CHECK; 2499 char *iInsertUTF8(char **string, int64_t index, const char *toInsert) MUST_CHECK; 2500 char *iInsertNFreeUTF8(char **string, int64_t index, char *toInsert) MUST_CHECK; 2501 char *bInsertUTF8(char *string, int64_t index, const char *toInsert) MUST_CHECK; 2502 char *bLInsertUTF8(char *string, size_t stringSize, int64_t index, const char *toInsert) MUST_CHECK; 2503 2504 // delete UTF8 encoded string 2505 char *delUTF8(const char *string, int64_t start, int64_t end) MUST_CHECK; 2506 char *iDelUTF8(char **string, int64_t start, int64_t end) MUST_CHECK; 2507 char *bDelUTF8(char *string, int64_t start, int64_t end) MUST_CHECK; 2508 char *bLDelUTF8(char *string, size_t stringSize, int64_t start, int64_t end) MUST_CHECK; 2509 2510 // indexOf UTF8 encoded String 2511 ssize_t indexOfUTF8(const char *string, const char *needle) MUST_CHECK; 2512 // TODO 2513 ssize_t icIndexOfUTF8(const char *string, const char *needle) MUST_CHECK; 2514 2515 // ignore case has UTF8 encoded String 2516 bool icHasUTF8(const char *string, const char *needle) MUST_CHECK; 2517 2518 // TODO 2519 char *icTokUTF8(const char *s, const char *delim, char **saveptr) MUST_CHECK; 2520 2521 // TODO 2522 char **icExtractUTF8(const char *string, const char* delim1, const char* delim2) MUST_CHECK; 2523 char **icExtractCharSUTF8(const char *string, char delim1, const char* delim2) MUST_CHECK; 2524 char **icExtractSCharUTF8(const char *string, const char* delim1, char delim2) MUST_CHECK; 2525 2526 // ignore case list Sort UTF8 encoded String 2527 char **icListSortUTF8(char **list) MUST_CHECK; 2528 char **iicListSortUTF8(char ***list) MUST_CHECK; 2529 2530 // ignore case list Equal UTF8 encoded String 2531 bool icListEqUTF8(char **list1, char **list2) MUST_CHECK; 2532 2533 // ignore case and return true when list has UTF8 encoded string 2534 bool icListHasUTF8(char **list, const char *string) MUST_CHECK; 2535 2536 // ignore case and return index of UTF8 encoded string in list 2537 ssize_t icListIndexOfUTF8(char **list, const char *string) MUST_CHECK; 2538 2539 // ignore case list binary search UTF8 encoded string 2540 ssize_t icListBinarySearchUTF8(char **list, const char *string) MUST_CHECK; 2541 2542 // ignore case and uniquify UTF8 encoded elements of list 2543 char **icListUniqUTF8(char **list) MUST_CHECK; 2544 char **iicListUniqUTF8(char ***list) MUST_CHECK; 2545 2546 // 2547 // End UTF8 string functions 2548 // 2549 2550 2551 // create empty string 2552 #define emptyS(string) \ 2553 string = strdup(""); 2554 char *emptySF(void) MUST_CHECK; 2555 char *iEmptySF(char **string) MUST_CHECK; 2556 // string buffer empty - set 0 at index 0 2557 #define bEmptyS(string) \ 2558 (string)[0] = 0 2559 2560 // is empty string 2561 bool isEmptyS(const char *string) MUST_CHECK; 2562 2563 /** 2564 * orS - if string is empty, the value is alternative 2565 */ 2566 #define orS(string, alternative) \ 2567 !isEmptyS(string) ? (string) : (alternative) 2568 2569 // true when string is empty or white spaces 2570 bool isBlankS(const char *string) MUST_CHECK; 2571 2572 /** 2573 * blankS - if string is blank(white spaces) or empty, the value is alternative 2574 */ 2575 #define orBlankS(string, alternative) \ 2576 !isBlankS(string) ? (string) : (alternative) 2577 2578 /** 2579 * nS - null String - replace null string with "" string (empty string) 2580 */ 2581 #define nS(string) \ 2582 (string) ? (string) : "" 2583 2584 /** 2585 * nAS - null Alternative String - replace null string with alternative string 2586 */ 2587 #define nAS(string, alternative) \ 2588 (string) ? (string) : (alternative) 2589 2590 2591 // convert python index (int, positive and negative) to always positive index (uint), this function is more generic than listIntIndexS 2592 ssize_t intIndex(int64_t index, int64_t length); 2593 2594 // create empty list 2595 #define listEmptyS(list) \ 2596 do {\ 2597 list = malloc(1 * sizeof(char *)); \ 2598 if (list) list[0] = NULL; \ 2599 } while(0); 2600 2601 char **listEmptySF(void) MUST_CHECK; 2602 char **iListEmptySF(char ***list) MUST_CHECK; 2603 2604 // false when there are elements in the list 2605 bool listIsEmptyS(char **list) MUST_CHECK; 2606 2607 // false when there are non blank elements in the list 2608 bool listIsBlankS(char **list) MUST_CHECK; 2609 2610 // String Lists 2611 // createList(...) 2612 char **listCreateSF(const char *paramType, ...) MUST_CHECK; 2613 #define listCreateS(...) listCreateSF("", __VA_ARGS__, NULL) 2614 2615 // copy array to new list 2616 char **listFromArrayS(char **array, size_t size) MUST_CHECK; 2617 char **listFromCArrayS(const char **array, size_t size) MUST_CHECK; 2618 2619 // push and pop (append) str 2620 // modifies the list 2621 char **listPushS(char ***list, const char *s) MUST_CHECK; 2622 char **listPushCharS(char ***list, char c) MUST_CHECK; 2623 char **iListPushS(char ***list, char *s) MUST_CHECK; 2624 2625 // copy last string and free it in the list 2626 char *listPopS(char ***list) MUST_CHECK; 2627 2628 // prepend and dequeue (append) str 2629 // modifies the list 2630 char **listPrependS(char ***list, const char *s) MUST_CHECK; 2631 char **listPrependCharS(char ***list, char c) MUST_CHECK; 2632 char **iListPrependS(char ***list, char *s) MUST_CHECK; 2633 2634 // copy fist string and free it in the list 2635 char *listDequeueS(char ***list) MUST_CHECK; 2636 2637 // freeList 2638 void listFreeS(char **list); 2639 2640 // free many char** 2641 void listFreeManySF(char **paramType, ...); 2642 #define listFreeManyS(...) listFreeManySF(NULL, __VA_ARGS__, NULL) 2643 2644 // length 2645 size_t listLengthS(char **list) MUST_CHECK; 2646 size_t listLengthCS(const char **list) MUST_CHECK; 2647 2648 // list length as a single string 2649 ssize_t listStrLengthS(char **list) MUST_CHECK; 2650 2651 // convert python index (int) to always positive index (uint) 2652 ssize_t listIntIndexS(char **list, int64_t index) MUST_CHECK; 2653 2654 // pointer to the char* at python index 2655 char **listAddrS(char **list, int64_t index) MUST_CHECK; 2656 2657 // list get - get a string at python index 2658 char *listGetS(char **list, int64_t index) MUST_CHECK; 2659 char *iListGetS(char **list, int64_t index) MUST_CHECK; 2660 char *listGetCS(const char **list, int64_t index) MUST_CHECK; 2661 const char *iListGetCS(const char **list, int64_t index) MUST_CHECK; 2662 2663 // list set - replace a string at python index 2664 char **listSetS(char **list, int64_t index, const char *s) MUST_CHECK; 2665 char **listSetCharS(char **list, int64_t index, char c) MUST_CHECK; 2666 char **iListSetS(char **list, int64_t index, char *s) MUST_CHECK; 2667 2668 // swap elements in a list 2669 char **listSwapS(char **list, int64_t index1, int64_t index2) MUST_CHECK; 2670 char **iListSwapS(char **list, int64_t index1, int64_t index2) MUST_CHECK; 2671 2672 // split 2673 char **split(const char *string, const char* delim) MUST_CHECK; 2674 char **splitS(const char *string, const char* delim) MUST_CHECK; 2675 char **splitChar(const char *string, char delim) MUST_CHECK; 2676 2677 // ignore case split 2678 char **icSplit(const char *string, const char* delim) MUST_CHECK; 2679 char **icSplitS(const char *string, const char* delim) MUST_CHECK; 2680 char **icSplitChar(const char *string, char delim) MUST_CHECK; 2681 2682 // list length after joined with delimiter 2683 ssize_t joinLength(char **list, const char* delim) MUST_CHECK; 2684 2685 // join 2686 char *join(char **list, const char* delim) MUST_CHECK; 2687 char *joinS(char **list, const char* delim) MUST_CHECK; 2688 char *joinCS(const char **list, const char* delim) MUST_CHECK; 2689 char *joinChar(char **list, char delim) MUST_CHECK; 2690 char *bJoin(char *string, char **list, const char* delim) MUST_CHECK; 2691 char *bJoinChar(char *string, char **list, char delim) MUST_CHECK; 2692 char *bLJoin(char *string, size_t stringSize, char **list, const char* delim) MUST_CHECK; 2693 char *bLJoinChar(char *string, size_t stringSize, char **list, char delim) MUST_CHECK; 2694 2695 // extract string 2696 char **extractS(const char *string, const char* delim1, const char* delim2) MUST_CHECK; 2697 char **extractCharSS(const char *string, char delim1, const char* delim2) MUST_CHECK; 2698 char **extractSCharS(const char *string, const char* delim1, char delim2) MUST_CHECK; 2699 char **extractCharCharS(const char *string, char delim1, char delim2) MUST_CHECK; 2700 2701 // ignore case extract string 2702 char **icExtractS(const char *string, const char* delim1, const char* delim2) MUST_CHECK; 2703 char **icExtractCharSS(const char *string, char delim1, const char* delim2) MUST_CHECK; 2704 char **icExtractSCharS(const char *string, const char* delim1, char delim2) MUST_CHECK; 2705 char **icExtractCharCharS(const char *string, char delim1, char delim2) MUST_CHECK; 2706 2707 // duplicate list 2708 char **listDupS(char **list) MUST_CHECK; 2709 char **listDupCS(const char **list) MUST_CHECK; 2710 char **iListDupS(char **list) MUST_CHECK; 2711 2712 // duplicate and reverse list 2713 char **listReverseS(char **list) MUST_CHECK; 2714 char **iListReverseS(char ***list) MUST_CHECK; 2715 2716 // listCatS: f(l1, l2, l3) 2717 char **listCatSF(char **paramType, ...) MUST_CHECK; 2718 #define listCatS(...) listCatSF(NULL, __VA_ARGS__, NULL) 2719 2720 // append lists 2721 char **listAppendS(char ***list1, char **list2) MUST_CHECK; 2722 char **iListAppendS(char ***list1, char **list2) MUST_CHECK; 2723 char **iListAppendNSmashS(char ***list1, char **list2) MUST_CHECK; 2724 2725 // prepend list at the start and shift existing elements 2726 char **listShiftS(char ***list1, char **list2) MUST_CHECK; 2727 char **iListShiftS(char ***list1, char **list2) MUST_CHECK; 2728 char **iListShiftNSmashS(char ***list1, char **list2) MUST_CHECK; 2729 2730 // add lists 2731 char **listAddS(char **list1, char **list2); 2732 char **listAddCS(char **list1, const char **list2); 2733 2734 // slice - python style indexes 0..len-1 -1..-len+1 2735 char **listSliceS(char **list, int64_t start, int64_t end) MUST_CHECK; 2736 char **iListCopyS(char **list, int64_t start, int64_t end) MUST_CHECK; 2737 char **iListSliceS(char ***list, int64_t start, int64_t end) MUST_CHECK; 2738 2739 // crop list (slice+del) 2740 char **listCropS(char **list, int64_t start, int64_t end) MUST_CHECK; 2741 char **iListCropS(char ***list, int64_t start, int64_t end) MUST_CHECK; 2742 char *listCropElemS(char **list, int64_t index) MUST_CHECK; 2743 char *iListCropElemS(char ***list, int64_t index) MUST_CHECK; 2744 2745 // insert list in list 2746 char **listInsertS(char **list, int64_t index, char **toInsert) MUST_CHECK; 2747 char **iListInsertS(char ***list, int64_t index, char **toInsert) MUST_CHECK; 2748 char **iListInsertNFreeS(char ***list, int64_t index, char **toInsert) MUST_CHECK; 2749 2750 // inject string in list 2751 char **listInjectS(char **list, int64_t index, char *toInject) MUST_CHECK; 2752 char **listInjectCharS(char **list, int64_t index, char toInject) MUST_CHECK; 2753 char **iListInjectS(char ***list, int64_t index, char *toInject) MUST_CHECK; 2754 char **iListInjectCharS(char ***list, int64_t index, char toInject) MUST_CHECK; 2755 2756 // del - python style indexes 0..len-1 -1..-len+1 2757 char **listDelS(char **list, int64_t start, int64_t end) MUST_CHECK; 2758 char **iListDelS(char ***list, int64_t start, int64_t end) MUST_CHECK; 2759 char **iListRemoveS(char ***list, int64_t start, int64_t end); 2760 2761 // del element in list 2762 char **listDelElemS(char **list, int64_t index) MUST_CHECK; 2763 char **iListDelElemS(char ***list, int64_t index) MUST_CHECK; 2764 char **iListRemoveElemS(char ***list, int64_t index) MUST_CHECK; 2765 2766 // print list 2767 int listPrintS(char **list) MUST_CHECK; 2768 int listPrintCS(const char **list) MUST_CHECK; 2769 2770 /** 2771 * forever loop 2772 */ 2773 #define forever while(1) 2774 2775 /** 2776 * range loop 2777 * ;size_t UNIQVAR needed to avoid: error: a label can only be part of a statement and a declaration is not a statement 2778 * on older compilers 2779 */ 2780 #define range(index, maxCount) \ 2781 ;size_t UNIQVAR(maxCnt) = (size_t)(maxCount); \ 2782 for (size_t index = 0 ; index < UNIQVAR(maxCnt) ; index++) 2783 2784 /** 2785 * infinity loop 2786 * increase the index infinitly 2787 */ 2788 #define rangeInf(index) \ 2789 for (size_t index = 0 ;; index++) 2790 2791 /** 2792 * range down loop, index is ssize_t 2793 */ 2794 #define rangeDown(index, maxCount) \ 2795 for (ssize_t index = (maxCount)-1 ; index >= 0 ; index--) 2796 2797 /** 2798 * range down loop to to index, index is ssize_t 2799 * ;ssize_t UNIQVAR needed to avoid: error: a label can only be part of a statement and a declaration is not a statement 2800 * on older compilers 2801 */ 2802 #define rangeDownTo(index, maxCount, to) \ 2803 ;ssize_t UNIQVAR(_to) = to;\ 2804 for (ssize_t index = (maxCount)-1 ; index >= UNIQVAR(_to) ; index--) 2805 2806 /** 2807 * range loop starting at value from 2808 * ;size_t UNIQVAR needed to avoid: error: a label can only be part of a statement and a declaration is not a statement 2809 * on older compilers 2810 */ 2811 #define rangeFrom(index, from, maxCount) \ 2812 ;size_t UNIQVAR(maxCnt) = (size_t)(maxCount); \ 2813 for (size_t index = from ; index < UNIQVAR(maxCnt) ; index++) 2814 2815 /** 2816 * loop on the elements of C static array of any type 2817 * 2818 * Example: 2819 * u32 array[20]; 2820 * arange(i, array) {} 2821 */ 2822 #define arange(index, array) range(index, ARRAY_SIZE(array)) 2823 2824 /** 2825 * loop on the elements of C static array of any type from highest index down to 0 2826 * 2827 * Example: 2828 * u32 array[20]; 2829 * arangeDown(i, array) {} 2830 */ 2831 #define arangeDown(index, array) rangeDown(index, ARRAY_SIZE(array)) 2832 2833 /** 2834 * loop on the elements of C static array of any type from highest index down to index 'to' 2835 * 2836 * Example: 2837 * u32 array[20]; 2838 * arangeDownTo(i, array, 5) {} 2839 */ 2840 #define arangeDownTo(index, array, to) rangeDownTo(index, ARRAY_SIZE(array), to) 2841 2842 /** 2843 * loop on the elements of C static array of any type starting at index 'from' 2844 * 2845 * Example: 2846 * u32 array[20]; 2847 * arange(i, 10, array) {} 2848 */ 2849 #define arangeFrom(index, from, array) rangeFrom(index, from, ARRAY_SIZE(array)) 2850 2851 /** 2852 * range from value from to maxCount-1 then from 0 to from-1 2853 * 2854 * Example: 2855 * circular(i, 2, 4) 2856 * 2857 * counts: 2, 3, 0, 1 2858 * 2859 * ;bool UNIQVAR needed to avoid: error: a label can only be part of a statement and a declaration is not a statement 2860 * on older compilers 2861 */ 2862 #define circular(index, from, maxCount) \ 2863 ;bool UNIQVAR(libsheepyInternalStatus) = true; \ 2864 size_t UNIQVAR(maxCnt) = (size_t)(maxCount); \ 2865 size_t UNIQVAR(frm) = (size_t)(from); \ 2866 for (size_t index = UNIQVAR(frm) ; (index != UNIQVAR(frm)) || (UNIQVAR(libsheepyInternalStatus)); index == (UNIQVAR(maxCnt)-1) ? index = 0 : index++, UNIQVAR(libsheepyInternalStatus) = false) 2867 2868 /** 2869 * range from value from down to 0 then from maxCount-1 to from+1 2870 * 2871 * Example: 2872 * circularDown(i, 2, 4) 2873 * 2874 * counts: 2, 1, 0, 3 2875 * 2876 * ;bool UNIQVAR needed to avoid: error: a label can only be part of a statement and a declaration is not a statement 2877 * on older compilers 2878 */ 2879 #define circularDown(index, from, maxCount) \ 2880 ;bool UNIQVAR(libsheepyInternalStatus) = true; \ 2881 size_t UNIQVAR(maxCnt) = (size_t)(maxCount); \ 2882 size_t UNIQVAR(frm) = (size_t)(from); \ 2883 for (size_t index = UNIQVAR(frm) ; (index != UNIQVAR(frm)) || (UNIQVAR(libsheepyInternalStatus)); index == 0 ? index = (UNIQVAR(maxCnt)-1) : index--, UNIQVAR(libsheepyInternalStatus) = false) 2884 2885 /** 2886 * range step loop 2887 * ;size_t UNIQVAR needed to avoid: error: a label can only be part of a statement and a declaration is not a statement 2888 * on older compilers 2889 */ 2890 #define rangeStep(index, maxCount, step) \ 2891 ;size_t UNIQVAR(maxCnt) = (size_t)(maxCount); \ 2892 for (size_t index = 0 ; index < UNIQVAR(maxCnt) ; index+=step) 2893 2894 /** 2895 * range down step loop, index is int64_t 2896 */ 2897 #define rangeDownStep(index, maxCount, step) \ 2898 for (int64_t index = (maxCount)-1 ; index >= 0 ; index-=step) 2899 2900 /** 2901 * range step loop starting at value from 2902 * ;size_t UNIQVAR needed to avoid: error: a label can only be part of a statement and a declaration is not a statement 2903 * on older compilers 2904 */ 2905 #define rangeFromStep(index, from, maxCount, step) \ 2906 ;size_t UNIQVAR(maxCnt) = (size_t)(maxCount); \ 2907 for (size_t index = from ; index < UNIQVAR(maxCnt) ; index+=(size_t)step) 2908 2909 2910 /** 2911 * loops without index 2912 * ;size_t UNIQVAR needed to avoid: error: a label can only be part of a statement and a declaration is not a statement 2913 * on older compilers 2914 */ 2915 #define loop(maxCount) \ 2916 ;size_t UNIQVAR(maxCnt) = (size_t)(maxCount); \ 2917 for (size_t UNIQVAR(index) = 0 ; UNIQVAR(index) < UNIQVAR(maxCnt) ; UNIQVAR(index)++) 2918 2919 /** 2920 * loop to to index 2921 * ;ssize_t UNIQVAR needed to avoid: error: a label can only be part of a statement and a declaration is not a statement 2922 * on older compilers 2923 */ 2924 #define loopDownTo(maxCount, to) \ 2925 ;ssize_t UNIQVAR(_to) = to;\ 2926 for (ssize_t UNIQVAR(index) = (maxCount)-1 ; UNIQVAR(index) >= UNIQVAR(_to) ; UNIQVAR(index)--) 2927 2928 /** 2929 * loop starting at value from 2930 * ;size_t UNIQVAR needed to avoid: error: a label can only be part of a statement and a declaration is not a statement 2931 * on older compilers 2932 */ 2933 #define loopFrom(from, maxCount) \ 2934 ;size_t UNIQVAR(maxCnt) = (size_t)(maxCount); \ 2935 for (size_t UNIQVAR(index) = from ; UNIQVAR(index) < UNIQVAR(maxCnt) ; UNIQVAR(index)++) 2936 2937 /** 2938 * step loop 2939 * ;size_t UNIQVAR needed to avoid: error: a label can only be part of a statement and a declaration is not a statement 2940 * on older compilers 2941 */ 2942 #define loopStep(maxCount, step) \ 2943 ;size_t UNIQVAR(maxCnt) = (size_t)(maxCount); \ 2944 for (size_t UNIQVAR(index) = 0 ; UNIQVAR(index) < UNIQVAR(maxCnt) ; UNIQVAR(index)+=step) 2945 2946 /** 2947 * step loop starting at value from 2948 * ;size_t UNIQVAR needed to avoid: error: a label can only be part of a statement and a declaration is not a statement 2949 * on older compilers 2950 */ 2951 #define loopFromStep(from, maxCount, step) \ 2952 ;size_t UNIQVAR(maxCnt) = (size_t)(maxCount); \ 2953 for (size_t UNIQVAR(index) = from ; UNIQVAR(index) < UNIQVAR(maxCnt) ; UNIQVAR(index)+=step) 2954 2955 2956 /** 2957 * loop on array elements 2958 * element is a pointer to a value in the array 2959 * 2960 * aForEach(array, e) { 2961 * e->x = 0; 2962 * } 2963 */ 2964 #define aForEach(array, element) \ 2965 ;size_t UNIQVAR(libsheepyInternalIndex) = 0; \ 2966 for (typeof(&array[0]) element = &array[0] ; UNIQVAR(libsheepyInternalIndex) < ARRAY_SIZE(array) ; UNIQVAR(libsheepyInternalIndex)++, element = &array[UNIQVAR(libsheepyInternalIndex)]) 2967 2968 /** 2969 * enumerate array elements 2970 * index is the position of the element in the array 2971 * index is declared as size_t and is available after the loop 2972 * element is a pointer to a value in the array 2973 * 2974 * aEnumerate(array, i, e) { 2975 * e->x = 0; 2976 * printf("aEnumerate %d\n", i); 2977 * } 2978 */ 2979 #define aEnumerate(array, index, element) \ 2980 ; size_t index = 0 ; \ 2981 for (typeof(&array[0]) element = &array[0] ; index < ARRAY_SIZE(array) ; index++, element = &array[index]) 2982 2983 /** 2984 * forEach - loop macro on list indexes 2985 * to access the element in the loop, use *element 2986 */ 2987 #define forEachCharP(list, element) \ 2988 for (char **element=list ; *element != NULL ; element++) 2989 2990 /** 2991 * forEach for const char** lists 2992 */ 2993 #define forEachCCharP(list, element) \ 2994 for (const char **element=list ; *element != NULL ; element++) 2995 2996 /** 2997 * forEach - loop macro on list indexes 2998 * to access the element in the loop, use element 2999 * ;size_t UNIQVAR needed to avoid: error: a label can only be part of a statement and a declaration is not a statement 3000 * on older compilers 3001 */ 3002 #define forEachS(list, element) \ 3003 ;size_t UNIQVAR(libsheepyInternalIndex) = 0; \ 3004 for (char *element = (list)[0]; (list)[UNIQVAR(libsheepyInternalIndex)]!= NULL ; UNIQVAR(libsheepyInternalIndex)++, element = (list)[UNIQVAR(libsheepyInternalIndex)]) 3005 3006 /** 3007 * forEach for const char** lists 3008 */ 3009 #define forEachCS(list, element) \ 3010 ;size_t UNIQVAR(libsheepyInternalIndex) = 0; \ 3011 for (const char *element = (list)[0]; (list)[UNIQVAR(libsheepyInternalIndex)]!= NULL ; UNIQVAR(libsheepyInternalIndex)++, element = (list)[UNIQVAR(libsheepyInternalIndex)]) 3012 3013 /** 3014 * forEach - loop macro on list indexes 3015 */ 3016 #define forEachType(type, list, element) \ 3017 for (type **element=list ; *element != NULL ; element++) 3018 3019 /** 3020 * enumerateCharP list 3021 * to access the element in the loop, use *element 3022 * ;size_t needed to avoid: error: a label can only be part of a statement and a declaration is not a statement 3023 * on older compilers 3024 */ 3025 #define enumerateCharP(list, element, index) \ 3026 ;size_t index = 0; \ 3027 for (char **element=list; *element != NULL ; element++, index++) 3028 3029 /** 3030 * enumerateCCharP const list 3031 * to access the element in the loop, use *element 3032 * ;size_t needed to avoid: error: a label can only be part of a statement and a declaration is not a statement 3033 * on older compilers 3034 */ 3035 #define enumerateCCharP(list, element, index) \ 3036 ;size_t index = 0; \ 3037 for (const char **element=list; *element != NULL ; element++, index++) 3038 3039 /** 3040 * enumerateS list 3041 * to acess the element in the loop, use element 3042 * ;size_t needed to avoid: error: a label can only be part of a statement and a declaration is not a statement 3043 * on older compilers 3044 */ 3045 #define enumerateS(list, element, index) \ 3046 ;size_t index = 0; \ 3047 for (char *element=(list)[0]; element != NULL ; index++, element = (list)[index]) 3048 3049 /** 3050 * enumerateCS const list 3051 * to acess the element in the loop, use element 3052 * ;size_t needed to avoid: error: a label can only be part of a statement and a declaration is not a statement 3053 * on older compilers 3054 */ 3055 #define enumerateCS(list, element, index) \ 3056 ;size_t index = 0; \ 3057 for (const char *element=(list)[0]; element != NULL ; index++, element = (list)[index]) 3058 3059 /** 3060 * enumerateType list 3061 * ;size_t needed to avoid: error: a label can only be part of a statement and a declaration is not a statement 3062 * on older compilers 3063 */ 3064 #define enumerateType(type, list, element, index) \ 3065 ;size_t index = 0; \ 3066 for (type **element=list; *element != NULL ; element++, index++) 3067 3068 /** 3069 * loop for linked lists from startNode to last 3070 * 3071 * node must be a pointer to a struct with a next member pointing 3072 * to the next node in the list 3073 * 3074 * when node->next is NULL, the list end is reached 3075 * */ 3076 #define lForEach(node, startNode)\ 3077 for(var node = startNode; node ; node = (node)->next) 3078 3079 /** 3080 * loop for linked lists from startNode to head 3081 * 3082 * node must be a pointer to a struct with a prev member pointing 3083 * to the previous node in the list 3084 * 3085 * when node->prev is NULL, the list head is reached 3086 */ 3087 #define lForEachDown(node, startNode)\ 3088 for(var node = startNode; node ; node = (node)->prev) 3089 3090 #define lForEachPrev lForEachDown 3091 3092 // user defined function for sort functions 3093 typedef int (*shCmpt)(const void * a, const void * b); 3094 3095 // duplicate and sort 3096 char **listSortS(char **list) MUST_CHECK; 3097 char **iListSortS(char ***list) MUST_CHECK; 3098 char **listSortFS(char **list, shCmpt compareFunction) MUST_CHECK; 3099 char **iListSortFS(char ***list, shCmpt compareFunction) MUST_CHECK; 3100 3101 // ignore case, duplicate and sort 3102 char **icListSortS(char **list) MUST_CHECK; 3103 char **iicListSortS(char ***list) MUST_CHECK; 3104 3105 // open text file and return lines in list 3106 char **readText(const char *filePath) MUST_CHECK; 3107 3108 // read opened text file and return lines in list 3109 // the file is left open 3110 char **readStream(FILE *fp) MUST_CHECK; 3111 3112 // write text file 3113 bool writeText(const char *filePath, char **list) MUST_CHECK; 3114 bool writeCText(const char *filePath, const char **list) MUST_CHECK; 3115 3116 // write buffer 3117 bool writeStream(FILE *fp, char **list) MUST_CHECK; 3118 bool writeCStream(FILE *fp, const char **list) MUST_CHECK; 3119 3120 // append text to file 3121 bool appendText(const char *filePath, char **list) MUST_CHECK; 3122 bool appendCText(const char *filePath, const char **list) MUST_CHECK; 3123 3124 // execOut 3125 char **execOut(const char *cmd) MUST_CHECK; 3126 // convenience define 3127 #define execOutf systemOutf 3128 #define execf systemf 3129 3130 // system command with formatting 3131 char **systemOutf(const char *fmt, ...) MUST_CHECK; 3132 // convenience define 3133 #define systemOut execOut 3134 int systemf(const char *fmt, ...) MUST_CHECK; 3135 3136 // system commands and log 3137 #define logSystem(cmd) funcbegin\ 3138 var UNIQVAR(cm) = cmd;\ 3139 logI("%s",UNIQVAR(cm));\ 3140 system (UNIQVAR(cm));\ 3141 funcend 3142 #define logExec logSystem 3143 #define logSystemOut(cmd) ({\ 3144 var UNIQVAR(cm) = cmd;\ 3145 logI("%s",UNIQVAR(cm));\ 3146 systemOut(UNIQVAR(cm));\ 3147 }) 3148 #define logExecOut logSystemOut 3149 #define logSystemOutf(fmt, ...) ({\ 3150 logI (fmt, __VA_ARGS__);\ 3151 systemOutf(fmt, __VA_ARGS__);}) 3152 #define logExecOutf logSystemOutf 3153 #define logSystemf(fmt, ...) ({\ 3154 logI (fmt, __VA_ARGS__);\ 3155 systemf(fmt, __VA_ARGS__);}) 3156 #define logExecf logSystemf 3157 3158 // run command and return exit code from command (not system return value like system, systemf and systemNFree) 3159 #define command(cmd) commandF(cmd, __LINE__, __func__, __FILE__) 3160 int commandF(const char *cmd, int line, const char *thisFunc, const char *thisFileName) MUST_CHECK; 3161 #define commandf(...) commandfF(__LINE__, __func__, __FILE__, __VA_ARGS__) 3162 int commandfF(int line, const char *thisFunc, const char *thisFileName, const char *fmt, ...) MUST_CHECK; 3163 #define commandNFree(cmd) commandNFreeF(cmd, __LINE__, __func__, __FILE__) 3164 int commandNFreeF(char *cmd, int line, const char *thisFunc, const char *thisFileName) MUST_CHECK; 3165 #define commandOut execOut 3166 #define commandOutf systemOutf 3167 3168 // log then run command and return exit code from command (not system return value like system, systemf and systemNFree) 3169 #define logCommand(cmd) funcbegin\ 3170 var UNIQVAR(cm) = cmd;\ 3171 logI("%s",UNIQVAR(cm));\ 3172 command (UNIQVAR(cm));\ 3173 funcend 3174 3175 #define logCommandf(fmt, ...) funcbegin\ 3176 logI (fmt, __VA_ARGS__);\ 3177 commandf(fmt, __VA_ARGS__);\ 3178 funcend 3179 3180 #define logCommandNFree(cmd) funcbegin\ 3181 var UNIQVAR(cm) = cmd;\ 3182 logI ("%s",UNIQVAR(cm));\ 3183 commandNFree(UNIQVAR(cm));\ 3184 funcend 3185 3186 #define logCommandOut logExecOut 3187 #define logCommandOutf logExecOutf 3188 3189 // compare lists 3190 bool listEqS(char **list1, char **list2) MUST_CHECK; 3191 bool listEqCS(char **list1, const char **list2) MUST_CHECK; 3192 bool listEqC1S(const char **list1, char **list2) MUST_CHECK; 3193 bool listEqCCS(const char **list1, const char **list2) MUST_CHECK; 3194 3195 // has 3196 bool listHasS(char **list, const char *string) MUST_CHECK; 3197 bool listHasCS(const char **list, const char *string) MUST_CHECK; 3198 bool listHasCharS(char **list, char c) MUST_CHECK; 3199 bool listHasCharCS(const char **list, char c) MUST_CHECK; 3200 3201 // indexOf 3202 ssize_t listIndexOfS(char **list, const char *string) MUST_CHECK; 3203 ssize_t listIndexOfCS(const char **list, const char *string) MUST_CHECK; 3204 ssize_t listIndexOfCharS(char **list, char c) MUST_CHECK; 3205 ssize_t listIndexOfCharCS(const char **list, char c) MUST_CHECK; 3206 3207 // list binary search string 3208 ssize_t listBinarySearchS(char **list, const char *string) MUST_CHECK; 3209 ssize_t listBinarySearchCharS(char **list, char c) MUST_CHECK; 3210 3211 // duplicate and uniquify 3212 char **listUniqS(char **list) MUST_CHECK; 3213 char **iListUniqS(char ***list) MUST_CHECK; 3214 3215 // ignore case and compare lists 3216 bool icListEqS(char **list1, char **list2) MUST_CHECK; 3217 bool icListEqCS(char **list1, const char **list2) MUST_CHECK; 3218 bool icListEqC1S(const char **list1, char **list2) MUST_CHECK; 3219 bool icListEqCCS(const char **list1, const char **list2) MUST_CHECK; 3220 3221 // ignore case has 3222 bool icListHasS(char **list, const char *string) MUST_CHECK; 3223 bool icListHasCharS(char **list, char c) MUST_CHECK; 3224 bool icListHasCS(const char **list, const char *string) MUST_CHECK; 3225 bool icListHasCharCS(const char **list, char c) MUST_CHECK; 3226 3227 // ignore case indexOf 3228 ssize_t icListIndexOfS(char **list, const char *string) MUST_CHECK; 3229 ssize_t icListIndexOfCS(const char **list, const char *string) MUST_CHECK; 3230 ssize_t icListIndexOfCharS(char **list, char c) MUST_CHECK; 3231 ssize_t icListIndexOfCharCS(const char **list, char c) MUST_CHECK; 3232 3233 // ignore case list binary search string 3234 ssize_t icListBinarySearchS(char **list, const char *string) MUST_CHECK; 3235 ssize_t icListBinarySearchCharS(char **list, char c) MUST_CHECK; 3236 3237 // ignore case, duplicate and uniquify 3238 char **icListUniqS(char **list) MUST_CHECK; 3239 char **iicListUniqS(char ***list) MUST_CHECK; 3240 3241 // duplicate and compact 3242 char **listCompactS(char **list) MUST_CHECK; 3243 char **iListCompactS(char ***list) MUST_CHECK; 3244 3245 void btraceEnable(void); 3246 void btraceDisable(void); 3247 bool btraceConfig(void) MUST_CHECK; 3248 3249 // get backtrace 3250 char **btrace(void); 3251 3252 // print backtrace 3253 #if __APPLE__ 3254 // TODO readelf missing in macOS 3255 #define logBtrace 3256 #else 3257 #define logBtrace char **UNIQVAR(r)=btrace();if(UNIQVAR(r)){logN("\n"BLD WHT"Backtrace:"RST);forEachS(UNIQVAR(r), element){logN(element);}listFreeS(UNIQVAR(r));logN("---");} 3258 #endif 3259 3260 extern bool btraceCfg; 3261 3262 /** print backtrace in error messages, default is on, use btraceEnable and btraceDisable to configure */ 3263 #define logEBtrace if (btraceCfg) { char **UNIQVAR(r)=btrace();if(UNIQVAR(r)){logE("\n"BLD WHT"Backtrace:"RST);forEachS(UNIQVAR(r), element){logE(element);}listFreeS(UNIQVAR(r));logE("---");} } 3264 3265 3266 // ************************** 3267 // void ** lists 3268 // ************************** 3269 3270 // create empty list 3271 #define listEmpty(list) \ 3272 do {\ 3273 list = malloc(1 * sizeof(void *)); \ 3274 if (list) list[0] = NULL; \ 3275 } while(0); 3276 3277 void **listEmptyF(void) MUST_CHECK; 3278 void **iListEmptyF(void ***list) MUST_CHECK; 3279 3280 // false when there are elements in the list 3281 bool listIsEmpty(void **list) MUST_CHECK; 3282 3283 // createList(...) 3284 void **listCreateF(void *paramType, ...) MUST_CHECK; 3285 #define listCreate(...) listCreateF(NULL, __VA_ARGS__, NULL) 3286 3287 // copy array to new list 3288 void **listFromArray(void **array, size_t size) MUST_CHECK; 3289 3290 // push and pop (append) element 3291 // modifies the list 3292 void **listPush(void ***list, void *s) MUST_CHECK; 3293 3294 // return last element and remove it from the list 3295 void *listPop(void ***list) MUST_CHECK; 3296 3297 // prepend and dequeue (append) element 3298 // modifies the list 3299 void **listPrepend(void ***list, void *s) MUST_CHECK; 3300 3301 // return fist element and remove it from the list 3302 void *listDequeue(void ***list) MUST_CHECK; 3303 3304 // freeList 3305 void listFree(void **list); 3306 3307 // free many void** 3308 void listFreeManyF(void **paramType, ...); 3309 #define listFreeMany(...) listFreeManyF(NULL, __VA_ARGS__, NULL) 3310 3311 // length 3312 size_t listLength(void **list) MUST_CHECK; 3313 3314 // list get - get an element at python index 3315 void *listGet(void **list, int64_t index) MUST_CHECK; 3316 3317 // list set - replace a string at python index 3318 void **listSet(void **list, int64_t index, void *s) MUST_CHECK; 3319 3320 // duplicate list 3321 void **listDup(void **list) MUST_CHECK; 3322 3323 // duplicate and reverse list 3324 void **listReverse(void **list) MUST_CHECK; 3325 void **iListReverse(void ***list) MUST_CHECK; 3326 3327 // listCatS: f(l1, l2, l3) 3328 void **listCatF(void **paramType, ...) MUST_CHECK; 3329 #define listCat(...) listCatF(NULL, __VA_ARGS__, NULL) 3330 3331 // append lists 3332 void **listAppend(void ***list1, void **list2) MUST_CHECK; 3333 3334 // add lists 3335 void **listAdd(void **list1, void **list2) MUST_CHECK; 3336 3337 // slice - python style indexes 0..len-1 -1..-len+1 3338 void **listSlice(void **list, int64_t start, int64_t end) MUST_CHECK; 3339 void **iListSlice(void ***list, int64_t start, int64_t end) MUST_CHECK; 3340 3341 // insert list in list 3342 void **listInsert(void **list, int64_t index, void **toInsert) MUST_CHECK; 3343 void **iListInsert(void ***list, int64_t index, void **toInsert) MUST_CHECK; 3344 3345 // del - python style indexes 0..len-1 -1..-len+1 3346 void **listDel(void **list, int64_t start, int64_t end) MUST_CHECK; 3347 void **iListDel(void ***list, int64_t start, int64_t end) MUST_CHECK; 3348 //NOT NEEDED same as iListDel - void **iListRemove(void ***list, int64_t start, int64_t end); 3349 3350 // duplicate and sort 3351 //TODO void **listSort(void **list); 3352 //TODO void iListSort(void ***list); 3353 3354 // compare lists 3355 //TODO bool listEq(void **list1, void **list2); 3356 3357 // indexOf 3358 //TODO ssize_t listIndexOf(void **list, const void *string); 3359 3360 // list binary search string 3361 //TODO ssize_t listBinarySearch(void **list, const void *string); 3362 3363 // duplicate and uniquify 3364 //TODO void **listUniq(void **list); 3365 //TODO void iListUniq(void ***list); 3366 3367 // duplicate and compact 3368 //TODO void **listCompact(void **list); 3369 //TODO void iListCompact(void ***list); 3370 3371 // create name variable and allocate it on heap 3372 #define newPtr(name, type)\ 3373 ;type *name = malloc(sizeof(type)) 3374 3375 // create name variable and calloc it on heap 3376 #define new0Ptr(name, type)\ 3377 ;type *name = calloc(1, sizeof(type)) 3378 3379 // allocate struct on heap and assign address 3380 #define allocAPtr(name) name = malloc(sizeof(*(name))) 3381 3382 // calloc struct on heap and assign address 3383 #define callocAPtr(name) name = calloc(1, sizeof(*(name))) 3384 3385 // create name variable and allocate array of type on heap 3386 #define newArray(name, type, count)\ 3387 ;type *name = malloc((count) * sizeof(type)) 3388 3389 // create name variable and calloc array of type on heap 3390 #define new0Array(name, type, count)\ 3391 ;type *name = calloc(count, sizeof(type)) 3392 3393 // allocate array 3394 #define allocArray(name, count) malloc((count) * sizeof(*(name))) 3395 3396 // allocate and assign array 3397 #define allocAArray(name, count) name = malloc((count) * sizeof(*(name))) 3398 3399 // calloc array 3400 #define callocArray(name, count) calloc(count, sizeof(*(name))) 3401 3402 // calloc and assign array 3403 #define callocAArray(name, count) name = calloc(count, sizeof(*(name))) 3404 3405 // realloc array 3406 #define reallocArray(name, count) realloc(name, (count) * sizeof(*(name))) 3407 3408 /** 3409 * slice - dynamic array in one chunk of memory (similar to vector and slab below) 3410 * 3411 * This is a simple dynamic array holding element count and the data 3412 * 3413 * this type of array has a dynamic element count 3414 * pushing elements into the array increases the element count 3415 * poping elements only decreases the element count, call sliceFit to realloc the slice 3416 * 3417 * no sanity checks are done 3418 * 3419 * the prefix is slice 3420 * 3421 * Usage: 3422 * 3423 * to declare a slice: 3424 * 3425 * sliceT(typeName, type); 3426 * 3427 * typeName slce; 3428 * 3429 * sliceInit(&slce); 3430 * or 3431 * sliceInitCount(&slce, 17); 3432 * 3433 * sliceAppend(&slce, value); 3434 * 3435 * // get an element 3436 * int a = sliceAt(&slce, 0); 3437 * 3438 * set 3439 * sliceAt(&slce, 1) = 3; 3440 * 3441 * sliceFree(&slce); 3442 * 3443 * Slice variables: 3444 * slce.array: elements 3445 * slce.count: current element count 3446 * 3447 * Note: some functions are macros to be able to have structs as element and 3448 * access the struct members directly, for example: 3449 * sliceLast(chan).a = 0; 3450 */ 3451 3452 /** number of elements added by sliceAlloc */ 3453 #define sliceSz 1 3454 3455 /** 3456 * declares type for slice 3457 * 3458 * \param 3459 * typeName slice type name 3460 * \param 3461 * element type of elements (int, struct, pointer...) 3462 */ 3463 #define sliceT(typeName, elementType)\ 3464 typedef struct {\ 3465 size_t count;\ 3466 elementType *array;\ 3467 } typeName 3468 3469 #define createSlice(typeName, name) ;typeName name; sliceInit(&name) 3470 3471 #define createSliceCount(typeName, name, count) ;typeName name; sliceInitCount(&name, count) 3472 3473 #define createSliceClearCount(typeName, name, count) ;typeName name; sliceCalloc(&name, count) 3474 3475 #define createAllocateSlice(typeName, name) ;typeName *name = calloc(1, sizeof(typeName)) 3476 3477 #define createAllocateSliceCount(typeName, name, count) ;typeName *name = calloc(1, sizeof(typeName)); sliceInitCount(name, count) 3478 3479 #define createAllocateSliceClearCount(typeName, name, count) ;typeName *name = calloc(1, sizeof(typeName)); sliceCalloc(name, count) 3480 3481 #define sliceTerminate(name) if (name) sliceFree(name);free(name) 3482 3483 /** 3484 * initialize empty slice 3485 * 3486 * \param 3487 * name variable name for slice 3488 */ 3489 #define sliceInit(name) do{\ 3490 (name)->array = NULL;\ 3491 (name)->count = 0;\ 3492 } while(0) 3493 3494 /** 3495 * initialize slice and count 3496 * 3497 * \param 3498 * name variable name for slice 3499 * \param 3500 * count initial element count for name type 3501 */ 3502 #define sliceInitCount(name, countInt) do{\ 3503 var UNIQVAR(c) = countInt;\ 3504 /* TODO check if countInt is 0 then +1 */\ 3505 (name)->array = malloc(UNIQVAR(c) * sizeof (name)->array[0]);\ 3506 (name)->count = UNIQVAR(c);\ 3507 } while(0) 3508 3509 /** 3510 * initialize slice and count and set slice data to 0 3511 * 3512 * \param 3513 * name variable name for slice 3514 * \param 3515 * count initial element count for name type 3516 */ 3517 #define sliceCalloc(name, countInt) do{\ 3518 var UNIQVAR(c) = countInt;\ 3519 (name)->array = calloc(UNIQVAR(c), sizeof (name)->array[0]);\ 3520 (name)->count = 0;\ 3521 } while(0) 3522 3523 /** 3524 * resize slice (even empty slices) 3525 */ 3526 #define sliceResize(name, countInt) do{\ 3527 var UNIQVAR(c) = countInt;\ 3528 if ((name)->array) {\ 3529 /* realloc */\ 3530 (name)->array = realloc((name)->array, sizeof((name)->array[0]) * UNIQVAR(c));\ 3531 }\ 3532 else {\ 3533 /* was empty */\ 3534 (name)->array = malloc(sizeof((name)->array[0]) * UNIQVAR(c));\ 3535 }\ 3536 /* element count when shrinking */\ 3537 if (UNIQVAR(c) < (name)->count) (name)->count = UNIQVAR(c);\ 3538 } while(0) 3539 3540 /** 3541 * resize slice and clear the new elements with memset 3542 * even empty slices can be resized and cleared 3543 */ 3544 #define sliceClearResize(name, countInt) do{\ 3545 var UNIQVAR(c) = countInt;\ 3546 if ((name)->array) {\ 3547 /* realloc */\ 3548 (name)->array = realloc((name)->array, sizeof((name)->array[0]) * UNIQVAR(c));\ 3549 if ((name)->count < UNIQVAR(c)) {\ 3550 /* there are new elements */\ 3551 memset(&(name)->array[(name)->count], 0, (UNIQVAR(c) - (name)->count) * sizeof (name)->array[0]);\ 3552 }\ 3553 }\ 3554 else {\ 3555 /* was empty */\ 3556 (name)->array = calloc(UNIQVAR(c), sizeof((name)->array[0]));\ 3557 }\ 3558 /* element count when shrinking */\ 3559 if (UNIQVAR(c) < (name)->count) (name)->count = UNIQVAR(c);\ 3560 } while(0) 3561 3562 /** 3563 * free the internal buffers 3564 * 3565 * \param 3566 * name slice 3567 */ 3568 #define sliceFree(name) free((name)->array) 3569 3570 /** 3571 * element type in slice 3572 */ 3573 #define sliceElemType(name) typeof((name)->array[0]) 3574 3575 /** 3576 * element pointer type in slice 3577 */ 3578 #define sliceElemPtrType(name) typeof(&(name)->array[0]) 3579 3580 /** 3581 * duplicate slice 3582 */ 3583 #define sliceDup(name) ({\ 3584 typeof(*(name)) dest;\ 3585 sliceInitCount(&dest, (name)->count);\ 3586 if ((name)->array) {\ 3587 memcpy(dest.array, (name)->array, (name)->count * sizeof (name)->array[0]);\ 3588 dest.count = (name)->count;\ 3589 }\ 3590 /* return */ dest;\ 3591 }) 3592 3593 /** 3594 * assign slice from to slice to 3595 * the data is shared between slice from and slice to 3596 * the counts are not shared 3597 * 3598 * NO need for this macro, do like this: 3599 * *to = *from; 3600 */ 3601 /* #define sliceAgn(to, from) do{\ 3602 (to)->count = (from)->count;\ 3603 (to)->array = (from)->array;\ 3604 } while(0) */ 3605 3606 /** 3607 * declare dest slice and duplicate slice 3608 */ 3609 #define sliceCreateNDup(name, dest) ;typeof(*(name)) dest; sliceInitCount(&dest, (name)->count); if ((name)->array) { memcpy(dest.array, (name)->array, (name)->count * sizeof (name)->array[0]); dest.count = (name)->count;} 3610 3611 /** 3612 * duplicate slice to already declared dest slice 3613 */ 3614 #define sliceBDup(name, dest) do{\ 3615 var UNIQVAR(dst) = dest;\ 3616 sliceResize(UNIQVAR(dst), (name)->count);\ 3617 if ((name)->array) {\ 3618 memcpy(UNIQVAR(dst)->array, (name)->array, (name)->count * sizeof (name)->array[0]);\ 3619 UNIQVAR(dst)->count = (name)->count;\ 3620 }\ 3621 } while(0) 3622 3623 3624 /** 3625 * direct access to underlying array 3626 */ 3627 #define sliceData(name) (name)->array 3628 3629 /** 3630 * copy data from array to slice 3631 */ 3632 #define sliceFrom(name, arrayIn, countInt) do{\ 3633 var UNIQVAR(c) = countInt;\ 3634 var UNIQVAR(a) = arrayIn;\ 3635 if (sizeof((name)->array[0]) == sizeof(*(UNIQVAR(a)))) {\ 3636 sliceResize(name, UNIQVAR(c));\ 3637 memcpy((name)->array, UNIQVAR(a), UNIQVAR(c) * sizeof UNIQVAR(a)[0]);\ 3638 (name)->count = UNIQVAR(c);\ 3639 }\ 3640 } while(0) 3641 3642 /** 3643 * mirror a range in a slice 3644 * the data is not copied to dest slice, to copy data see sliceCopy or sliceBCopy 3645 */ 3646 #define sliceMirror(name, start, end) ({\ 3647 var UNIQVAR(strt) = start;\ 3648 typeof(*(name)) UNIQVAR(r);\ 3649 UNIQVAR(r).array = slicePtr(name, UNIQVAR(strt));\ 3650 UNIQVAR(r).count = end - UNIQVAR(strt);\ 3651 UNIQVAR(r);\ 3652 }) 3653 3654 /** 3655 * mirror a range in a slice 3656 * the data is not copied to dest slice, to copy data see sliceCopy or sliceBCopy 3657 * 3658 * name can be slice, vector or slab 3659 * dest must be slice 3660 */ 3661 #define sliceBMirror(name, dest, start, end) do{\ 3662 var UNIQVAR(strt) = start;\ 3663 var UNIQVAR(dst) = dest;\ 3664 UNIQVAR(dst)->array = slicePtr(name, UNIQVAR(strt));\ 3665 UNIQVAR(dst)->count = end - UNIQVAR(strt);\ 3666 } while(0) 3667 3668 /** 3669 * mirror from array to slice 3670 * the data is not copied to dest slice, to copy data see sliceCopy or sliceBCopy 3671 */ 3672 #define sliceMirrorFrom(name, array, countInt) do{\ 3673 var UNIQVAR(strt) = start;\ 3674 (name)->array = array;\ 3675 (name)->count = countInt;\ 3676 } while(0) 3677 3678 3679 /** 3680 * set 0 in slice elements 3681 * count is unchanged 3682 */ 3683 #define sliceClear(name) do{\ 3684 if ((name)->array)\ 3685 memset((name)->array, 0, (name)->count * sizeof (name)->array[0]);\ 3686 } while(0) 3687 3688 #define sliceClearRange(name, start, end) do{\ 3689 if ((name)->array)\ 3690 memset((name)->array + start, 0, (end-start) * sizeof (name)->array[0]);\ 3691 } while(0) 3692 3693 /** 3694 * Empty slice 3695 * Set count to 0 3696 * Allocated buffers in the slice must be freed before running sliceEmpty 3697 */ 3698 #define sliceEmpty(name) (name)->count = 0 3699 3700 /** 3701 * is slice Empty 3702 */ 3703 #define sliceIsEmpty(name) ((name)->count == 0 || !(name)->array) 3704 3705 /** 3706 * realloc slice to count 3707 */ 3708 #define sliceFit(name) do{\ 3709 sliceResize(name, (name)->count);\ 3710 } while(0) 3711 3712 /** 3713 * return element count 3714 */ 3715 #define sliceCount(name) (name)->count 3716 3717 /** 3718 * size of slice element 3719 */ 3720 #define sliceElemSize(name) sizeof((name)->array[0]) 3721 3722 /** 3723 * allocate an element 3724 * only when the slice is full 3725 */ 3726 #define sliceAlloc(name) do{\ 3727 if (!(name)->array) {\ 3728 (name)->array = malloc(sliceSz * sizeof (name)->array[0]);\ 3729 }\ 3730 else {\ 3731 (name)->array = realloc((name)->array, ((name)->count + sliceSz) * sizeof (name)->array[0]);\ 3732 }\ 3733 } while(0) 3734 3735 /** 3736 * clear (set 0) in element at index 3737 */ 3738 #define sliceClearElem(name, index) memset(&(name)->array[index], 0, sizeof (name)->array[0]) 3739 3740 /** 3741 * push element and expand the slice 3742 * no data (random) is set in the new element 3743 * 3744 * \param 3745 * name slice 3746 */ 3747 #define slicePush(name) do {\ 3748 sliceAlloc(name);\ 3749 (name)->count++;\ 3750 } while(0) 3751 3752 /** 3753 * append element and expand the slice 3754 * 3755 * \param 3756 * name slice 3757 * \param 3758 * v element to push 3759 */ 3760 #define sliceAppend(name, v) do{\ 3761 slicePush(name);\ 3762 sliceLast(name) = v;\ 3763 } while(0) 3764 3765 3766 /** 3767 * push element and expand the slice 3768 * the new element is cleared 3769 * 3770 * \param 3771 * name slice 3772 */ 3773 #define sliceClearPush(name) do{\ 3774 slicePush(name);\ 3775 sliceClearElem(name, (name)->count - 1);\ 3776 } while(0) 3777 3778 /** 3779 * pop element 3780 * the element count is decreased 3781 * 3782 * NOTE: using comma operator to avoid warning 3783 * warning: operation on ‘b.head’ may be undefined [-Wsequence-point] 3784 * 3785 * 3786 * \param 3787 * name slice 3788 */ 3789 #define slicePop(name) ((name)->count--, (name)->array[(name)->count]) 3790 3791 /** 3792 * delete the last element 3793 * useful for avoiding warning: right-hand operand of comma expression has no effect 3794 * when the poped value is not used 3795 */ 3796 #define sliceDelLast(name) ((name)->count--) 3797 3798 /** 3799 * set value at index and clearResize slice when index is outside slice count 3800 */ 3801 #define sliceSet(name, index, v) do{\ 3802 var UNIQVAR(idx) = index;\ 3803 if (UNIQVAR(idx) >= (name)->count) {\ 3804 /* clear and resize */\ 3805 sliceClearResize(name, UNIQVAR(idx)+1);\ 3806 }\ 3807 sliceAt(name, UNIQVAR(idx)) = v;\ 3808 } while(0) 3809 3810 /** 3811 * get / set element at index 3812 * 3813 * \param 3814 * name slice 3815 * \param 3816 * index index in array 3817 */ 3818 #define sliceAt(name, index) ((name)->array[index]) 3819 3820 /** 3821 * get pointer to element at index 3822 * 3823 * \param 3824 * name slice 3825 * \param 3826 * index index in array 3827 */ 3828 #define slicePtr(name, index) ((name)->array + index) 3829 3830 /** 3831 * last element 3832 * 3833 * \param 3834 * name slice 3835 */ 3836 #define sliceLast(name) ((name)->array[(name)->count-1]) 3837 3838 /** 3839 * pointer to last element 3840 * 3841 * \param 3842 * name slice 3843 */ 3844 #define sliceLastPtr(name) ((name)->array + (name)->count - 1) 3845 3846 /** 3847 * index of last element 3848 */ 3849 #define sliceLastIndex(name) ((name)->count - 1) 3850 3851 3852 /** 3853 * first element 3854 * 3855 * \param 3856 * name slice 3857 */ 3858 #define sliceFirst(name) ((name)->array[0]) 3859 3860 3861 /** 3862 * write the slice content to filename file 3863 * No NULL checks are done on the parameters 3864 * 3865 * \param 3866 * filename file name string 3867 */ 3868 #define sliceWriteFilename(name, filename) do {\ 3869 FILE *UNIQVAR(f) = fopen(filename, "w");\ 3870 if (UNIQVAR(f)) {\ 3871 fwrite((name)->array, sizeof((name)->array[0]), sliceCount(name), UNIQVAR(f));\ 3872 fclose(UNIQVAR(f));\ 3873 }\ 3874 } while(0) 3875 3876 /** 3877 * write the slice content to disk 3878 * No NULL checks are done on the parameters 3879 * 3880 * \param 3881 * file already opened file 3882 */ 3883 #define sliceWrite(name, file) fwrite((name)->array, sizeof((name)->array[0]), sliceCount(name), file) 3884 3885 /** 3886 * read a slice from filename file 3887 * No NULL checks are done on the parameters 3888 * 3889 * \param 3890 * filename file name string 3891 */ 3892 #define sliceReadFilename(name, filename) do {\ 3893 if (fileExists(filename)) {\ 3894 size_t UNIQVAR(sz) = fileSize(filename);\ 3895 FILE *UNIQVAR(f) = fopen(filename, "r");\ 3896 if (UNIQVAR(f)) {\ 3897 range(UNIQVAR(i), UNIQVAR(sz)/sizeof((name)->array[0])) {\ 3898 slicePush(name);\ 3899 fread(sliceLastPtr(name), 1, sizeof((name)->array[0]), UNIQVAR(f));\ 3900 }\ 3901 fclose(UNIQVAR(f));\ 3902 }\ 3903 }\ 3904 } while(0) 3905 3906 /** 3907 * read a slice from disk 3908 * No NULL checks are done on the parameters 3909 * 3910 * \param 3911 * file already opened file 3912 */ 3913 #define sliceRead(name, file) do {\ 3914 fseek(file, 0 , SEEK_END);\ 3915 size_t UNIQVAR(sz) = ftell(file);\ 3916 fseek(file, 0 , SEEK_SET);\ 3917 range(UNIQVAR(i), UNIQVAR(sz)/sizeof((name)->array[0])) {\ 3918 slicePush(name);\ 3919 fread(sliceLastPtr(name), 1, sizeof((name)->array[0]), file);\ 3920 }\ 3921 } while(0) 3922 3923 3924 /** 3925 * loop index on slice elements 3926 * 3927 * For example: 3928 * forEachV(vec, i) { 3929 * sliceAt(vec, i) = 0; 3930 * } 3931 */ 3932 #define forEachSc(name, index) range(index, (name)->count) 3933 3934 /** 3935 * loop on slice elements 3936 * element is a pointer to a value in the array 3937 * 3938 * sliceForEach(&slc, e) { 3939 * e->x = 0; 3940 * } 3941 */ 3942 #define sliceForEach(name, element) \ 3943 ;size_t UNIQVAR(libsheepyInternalIndex) = 0; \ 3944 for (sliceElemPtrType(name) element = slicePtr(name, 0) ; UNIQVAR(libsheepyInternalIndex) < (name)->count ; UNIQVAR(libsheepyInternalIndex)++, element = slicePtr(name, UNIQVAR(libsheepyInternalIndex))) 3945 3946 /** 3947 * enumerate slice elements 3948 * index is the position of the element in the array 3949 * index is declared as size_t and is available after the loop 3950 * element is a pointer to a value in the array 3951 * 3952 * sliceEnumerate(&slc, i, e) { 3953 * e->x = 0; 3954 * printf("sliceEnumerate %d\n", i); 3955 * } 3956 */ 3957 #define sliceEnumerate(name, index, element) \ 3958 ; size_t index = 0 ; \ 3959 for (sliceElemPtrType(name) element = slicePtr(name, 0) ; index < (name)->count ; index++, element = slicePtr(name, index)) 3960 3961 /** 3962 * insert an element at index 3963 * the data is moved to create space for the new element 3964 * to set data at the new element, use sliceAt(name, index) = value; 3965 */ 3966 #define sliceInject(name, index) do {\ 3967 var UNIQVAR(idx) = index;\ 3968 slicePush(name);\ 3969 if (index < sliceCount(name)) {\ 3970 memmove(slicePtr(name, UNIQVAR(idx) +1), slicePtr(name, UNIQVAR(idx)), ((name)->count - UNIQVAR(idx)-1) * sizeof (name)->array[0]);\ 3971 }\ 3972 } while(0) 3973 3974 /** 3975 * prepend element 3976 * 3977 * \param 3978 * name slice 3979 * \param 3980 * v element to prepend 3981 */ 3982 #define slicePrepend(name, v) do {\ 3983 sliceInject(name, 0);\ 3984 sliceAt(name, 0) = v;\ 3985 } while(0) 3986 3987 /** 3988 * dequeue element 3989 * 3990 * \param 3991 * name slice 3992 */ 3993 #define sliceDequeue(name) ({\ 3994 var r = sliceAt(name, 0);\ 3995 sliceDelFirst(name);\ 3996 /* return */r;\ 3997 }) 3998 3999 /** 4000 * delete first element in slice 4001 * the data is moved when count > 1 4002 */ 4003 #define sliceDelFirst(name) do {\ 4004 if ((name)->count) {\ 4005 if ((name)->count > 1) {\ 4006 /* move elements */\ 4007 memcpy((name)->array, (name)->array +1 , ((name)->count - 1) * sizeof (name)->array[0]);\ 4008 }\ 4009 (name)->count--;\ 4010 }\ 4011 } while(0) 4012 4013 4014 /** 4015 * delete an element in slice 4016 * the data is moved when index < (count-1) 4017 * when index = count -1, the last element is deleted and no data is moved 4018 */ 4019 #define sliceDelElem(name, index) do {\ 4020 var UNIQVAR(idx) = index;\ 4021 if ((size_t)UNIQVAR(idx) < (size_t)sliceLastIndex(name)) {\ 4022 /* move elements */\ 4023 memmove(slicePtr(name, UNIQVAR(idx)), slicePtr(name, UNIQVAR(idx) +1), ((name)->count - (UNIQVAR(idx) +1)) * sizeof (name)->array[0]);\ 4024 }\ 4025 (name)->count--;\ 4026 } while(0) 4027 4028 /** 4029 * delete range in slice 4030 * start must be between 0 and last index 4031 * end must be between 1 and count 4032 */ 4033 #define sliceDel(name, start, end) do {\ 4034 var UNIQVAR(strt) = start;\ 4035 var UNIQVAR(ed) = end;\ 4036 if (UNIQVAR(ed) < (name)->count and UNIQVAR(strt) < UNIQVAR(ed)) {\ 4037 /* move elements */\ 4038 memmove(slicePtr(name, UNIQVAR(strt)), slicePtr(name, UNIQVAR(ed)), ((name)->count - UNIQVAR(ed)) * sizeof (name)->array[0]);\ 4039 }\ 4040 (name)->count -= UNIQVAR(ed) - UNIQVAR(strt);\ 4041 } while(0) 4042 4043 /** 4044 * append slice to slice name 4045 * the data is copied 4046 */ 4047 #define sliceVAppend(name, slice) do {\ 4048 var UNIQVAR(vec) = slice;\ 4049 if (sizeof((name)->array[0]) == sizeof((UNIQVAR(vec))->array[0])) {\ 4050 sliceResize(name, (name)->count + (UNIQVAR(vec))->count);\ 4051 memmove((name)->array + (name)->count, (UNIQVAR(vec))->array, (UNIQVAR(vec))->count * sizeof (name)->array[0]);\ 4052 (name)->count += (UNIQVAR(vec))->count;\ 4053 }\ 4054 } while(0) 4055 4056 /** 4057 * append array to slice 4058 * the data is copied 4059 */ 4060 #define sliceAppendFrom(name, array, countInt) do {\ 4061 var UNIQVAR(c) = countInt;\ 4062 var UNIQVAR(a) = array;\ 4063 if (sizeof((name)->array[0]) == sizeof(*(UNIQVAR(a)))) {\ 4064 sliceResize(name, (name)->count + UNIQVAR(c));\ 4065 memmove((name)->array + (name)->count, UNIQVAR(a), UNIQVAR(c) * sizeof (name)->array[0]);\ 4066 (name)->count += UNIQVAR(c);\ 4067 }\ 4068 } while(0) 4069 4070 /** 4071 * prepend slice to slice name 4072 * the data in slice name is moved and 4073 * the data in slice is copied to slice name 4074 */ 4075 #define sliceVPrepend(name, slice) do {\ 4076 var UNIQVAR(vec) = slice;\ 4077 if (sizeof((name)->array[0]) == sizeof((UNIQVAR(vec))->array[0])) {\ 4078 sliceResize(name, (name)->count + (UNIQVAR(vec))->count);\ 4079 memmove((name)->array + (UNIQVAR(vec))->count, (name)->array, (name)->count * sizeof (name)->array[0]);\ 4080 memmove((name)->array, (UNIQVAR(vec))->array, (UNIQVAR(vec))->count * sizeof (name)->array[0]);\ 4081 (name)->count += (UNIQVAR(vec))->count;\ 4082 }\ 4083 } while(0) 4084 4085 /** 4086 * prepend array to slice 4087 * the data in slice is moved and 4088 * the data in array is copied to slice 4089 */ 4090 #define slicePrependFrom(name, array, countInt) do {\ 4091 var UNIQVAR(c) = countInt;\ 4092 var UNIQVAR(a) = array;\ 4093 if (sizeof((name)->array[0]) == sizeof(*(UNIQVAR(a)))) {\ 4094 sliceResize(name, (name)->count + UNIQVAR(c));\ 4095 memmove((name)->array + UNIQVAR(c), (name)->array, (name)->count * sizeof (name)->array[0]);\ 4096 memmove((name)->array, UNIQVAR(a), UNIQVAR(c) * sizeof (name)->array[0]);\ 4097 (name)->count += UNIQVAR(c);\ 4098 }\ 4099 } while(0); 4100 4101 /** 4102 * insert slice at position index 4103 * the data in slice name is moved and 4104 * the data in slice is copied to slice name 4105 */ 4106 #define sliceInsert(name, index, slice) do {\ 4107 var UNIQVAR(idx) = index;\ 4108 var UNIQVAR(vec) = slice;\ 4109 if (UNIQVAR(idx) == (name)->count) {\ 4110 sliceAppend(name, UNIQVAR(vec));\ 4111 }\ 4112 else if (sizeof((name)->array[0]) == sizeof((UNIQVAR(vec))->array[0])) {\ 4113 sliceResize(name, (name)->count + (UNIQVAR(vec))->count);\ 4114 memmove((name)->array + UNIQVAR(idx) + (UNIQVAR(vec))->count, (name)->array + UNIQVAR(idx), ((name)->count - UNIQVAR(idx)) * sizeof (name)->array[0]);\ 4115 memmove((name)->array + UNIQVAR(idx), (UNIQVAR(vec))->array, (UNIQVAR(vec))->count * sizeof (name)->array[0]);\ 4116 (name)->count += (UNIQVAR(vec))->count;\ 4117 }\ 4118 } while(0) 4119 4120 /** 4121 * insert array at position index 4122 * the data in slice is moved and 4123 * the data in array is copied to slice 4124 */ 4125 #define sliceInsertFrom(name, index, array, countInt) do {\ 4126 var UNIQVAR(idx) = index;\ 4127 var UNIQVAR(c) = countInt;\ 4128 var UNIQVAR(a) = array;\ 4129 if (UNIQVAR(idx) == (name)->count) {\ 4130 sliceAppendFrom(name, UNIQVAR(a), UNIQVAR(c));\ 4131 }\ 4132 else if (sizeof((name)->array[0]) == sizeof(UNIQVAR(a)[0])) {\ 4133 sliceResize(name, (name)->count + UNIQVAR(c));\ 4134 memmove((name)->array + UNIQVAR(idx) + UNIQVAR(c), (name)->array + UNIQVAR(idx), ((name)->count - UNIQVAR(idx)) * sizeof (name)->array[0]);\ 4135 memmove((name)->array + UNIQVAR(idx), UNIQVAR(a), UNIQVAR(c) * sizeof (name)->array[0]);\ 4136 (name)->count += UNIQVAR(c);\ 4137 }\ 4138 } while(0) 4139 4140 /** 4141 * slice slice, keep only elements between start and end 4142 * start must be between 0 and last index 4143 * end must be between 1 and count 4144 * the slice is returned 4145 */ 4146 #define sliceSlice(name, start, end) ({\ 4147 var UNIQVAR(strt) = start;\ 4148 var UNIQVAR(ed) = end;\ 4149 if (UNIQVAR(strt))\ 4150 memmove((name)->array, (name)->array + UNIQVAR(strt), (UNIQVAR(ed) - UNIQVAR(strt)) * sizeof (name)->array[0]);\ 4151 (name)->count = UNIQVAR(ed) - UNIQVAR(strt);\ 4152 name;\ 4153 }) 4154 4155 /** 4156 * copy slice elements between start and end to a new slice 4157 * start must be between 0 and last index 4158 * end must be between 1 and count 4159 * the new slice is returned and must be freed with sliceTerminate 4160 */ 4161 #define sliceCopy(name, start, end) ({\ 4162 var UNIQVAR(strt) = start;\ 4163 var UNIQVAR(ed) = end;\ 4164 createAllocateSliceCount(typeof(*(name)),UNIQVAR(r), UNIQVAR(ed) - UNIQVAR(strt));\ 4165 memmove(UNIQVAR(r)->array, (name)->array + UNIQVAR(strt), (UNIQVAR(ed) - UNIQVAR(strt)) * sizeof (name)->array[0]);\ 4166 UNIQVAR(r)->count = UNIQVAR(ed) - UNIQVAR(strt);\ 4167 UNIQVAR(r);\ 4168 }) 4169 4170 /** 4171 * copy slice elements between start and end to the dest slice 4172 * start must be between 0 and last index 4173 * end must be between 1 and count 4174 */ 4175 #define sliceBCopy(name, dest, start, end) do{\ 4176 if (sizeof((name)->array[0]) == sizeof((dest)->array[0])) {\ 4177 var UNIQVAR(strt) = start;\ 4178 var UNIQVAR(ed) = end;\ 4179 sliceResize(dest, UNIQVAR(ed) - UNIQVAR(strt));\ 4180 memmove((dest)->array, (name)->array + UNIQVAR(strt), (UNIQVAR(ed) - UNIQVAR(strt)) * sizeof (name)->array[0]);\ 4181 (dest)->count = UNIQVAR(ed) - UNIQVAR(strt);\ 4182 }\ 4183 } while(0) 4184 4185 /** 4186 * sort the slice 4187 * the compareFunction must prototype of type: 4188 * int cmp(const void * a, const void * b); 4189 * the results of the compareFunction should be: 4190 * <0 when a < b 4191 * 0 when a = b 4192 * >0 when a > b 4193 */ 4194 #define sliceSort(name, compareFunction) do{ \ 4195 qsort((name)->array, sizeof (name)->array[0], compareFunction);\ 4196 } while(0) 4197 4198 /** 4199 * return true when slice name is equal to slice 4200 * eqFunction should return true when the elements are equal 4201 * eqFunction can be either a macro or a function 4202 */ 4203 #define sliceEq(name, slice, eqFunction) ({\ 4204 var UNIQVAR(vec) = slice;\ 4205 bool UNIQVAR(r) = true;\ 4206 if (sizeof((name)->array[0]) == sizeof((UNIQVAR(vec))->array[0]) and (name)->count == UNIQVAR(vec)->count) {\ 4207 forEachV(name, UNIQVAR(idx)) {\ 4208 if (not eqFunction(sliceAt(name,UNIQVAR(idx)), sliceAt(UNIQVAR(vec),UNIQVAR(idx)))) {\ 4209 UNIQVAR(r) = false;\ 4210 break;\ 4211 }\ 4212 }\ 4213 }\ 4214 else UNIQVAR(r) = false;\ 4215 UNIQVAR(r);\ 4216 }) 4217 4218 /** 4219 * return true when slice has value 4220 * eqFunction should return true when the elements are equal 4221 * eqFunction can be either a macro or a function 4222 */ 4223 #define sliceHas(name, value, eqFunction) ({\ 4224 var UNIQVAR(v) = value;\ 4225 bool UNIQVAR(r) = false;\ 4226 forEachV(name, UNIQVAR(idx)) {\ 4227 if (eqFunction(sliceAt(name,UNIQVAR(idx)), UNIQVAR(v))) {\ 4228 UNIQVAR(r) = true;\ 4229 break;\ 4230 }\ 4231 }\ 4232 UNIQVAR(r);\ 4233 }) 4234 4235 /** 4236 * return index (ssize_t) of value in slice 4237 * eqFunction should return true when the elements are equal 4238 * eqFunction can be either a macro or a function 4239 * 4240 * return value is -1 when value is not found 4241 */ 4242 #define sliceIndexOf(name, value, eqFunction) ({\ 4243 var UNIQVAR(v) = value;\ 4244 ssize_t UNIQVAR(r) = -1;\ 4245 forEachV(name, UNIQVAR(idx)) {\ 4246 if (eqFunction(sliceAt(name,UNIQVAR(idx)), UNIQVAR(v))) {\ 4247 UNIQVAR(r) = UNIQVAR(idx);\ 4248 break;\ 4249 }\ 4250 }\ 4251 UNIQVAR(r);\ 4252 }) 4253 4254 /** 4255 * binary search value in slice 4256 * 4257 * efficiently finds the index of value in slice 4258 * the slice has to be sorted before calling sliceBinarySearch 4259 * 4260 * less is a macro taking an index and the search value returning 1 when sliceAt(name,index) is less than value: 4261 * #define less(index, value) sliceAt(name, index) < value 4262 * 4263 * equal is a macro returning 1 when sliceAt(name,index) is equal to value: 4264 * #define equal(index, value) sliceAt(name,index) == value 4265 * 4266 * return value is -1 when value is not found 4267 */ 4268 #define sliceBinarySearch(name, value, less, equal) ({\ 4269 var UNIQVAR(v) = value;\ 4270 ssize_t UNIQVAR(r);\ 4271 BSEARCH(UNIQVAR(r), UNIQVAR(v), (name)->count, less, equal);\ 4272 UNIQVAR(r);\ 4273 }) 4274 4275 /** 4276 * Uniquify elements in slice 4277 * each elements are unique in the slice 4278 * 4279 * eqFunction should return true when the elements are equal 4280 * eqFunction can be either a macro or a function 4281 */ 4282 #define sliceUniq(name, eqFunction) do{\ 4283 if ((name)->count > 1) {\ 4284 /* more than 1 element in slice, it is possible to have non unique elements */\ 4285 /* where to copy unique elements */\ 4286 size_t UNIQVAR(addIdx) = 0;\ 4287 /* scan all elements */\ 4288 forEachV(name, UNIQVAR(idx)) {\ 4289 /* whether [idx+1, count] has an element equal the one at idx */\ 4290 bool UNIQVAR(has) = false;\ 4291 /* last element is always unique */\ 4292 if (UNIQVAR(idx) < (name)->count) {\ 4293 rangeFrom(UNIQVAR(i), UNIQVAR(idx)+1, (name)->count) {\ 4294 if (eqFunction(sliceAt(name,UNIQVAR(i)), sliceAt(name,UNIQVAR(idx)))) {\ 4295 UNIQVAR(r) = true;\ 4296 break;\ 4297 }\ 4298 }\ 4299 }\ 4300 /* if [idx+1, count] doesnt have an equal element then the element at idx is unique */\ 4301 if (not UNIQVAR(has)) {\ 4302 /* copy element to addIdx when addIdx < idx */\ 4303 /* when addIdx == idx there is no need to copy the element */\ 4304 if (UNIQVAR(addIdx) < UNIQVAR(idx)) {\ 4305 sliceAt(name,UNIQVAR(addIdx)) = sliceAt(name,UNIQVAR(idx));\ 4306 }\ 4307 UNIQVAR(addIdx)++;\ 4308 }\ 4309 }\ 4310 /* set new count */\ 4311 (name)->count = UNIQVAR(addIdx);\ 4312 }\ 4313 } while(0) 4314 4315 /* 4316 * end slice 4317 */ 4318 4319 /** 4320 * staticSlice - static array with element count 4321 * 4322 * pushing elements into the array increases the element count 4323 * poping elements only decreases the element count 4324 * 4325 * no sanity checks are done 4326 * 4327 * the prefix is staticSlice 4328 * 4329 * Usage: 4330 * 4331 * to declare a staticSlice: 4332 * 4333 * staticSliceT(typeName, type, 10); 4334 * 4335 * typeName slce; 4336 * 4337 * staticSliceInit(&slce); 4338 * 4339 * staticSliceAppend(&slce, value); 4340 * 4341 * // get an element 4342 * int a = staticSliceAt(&slce, 0); 4343 * 4344 * set 4345 * staticSliceAt(&slce, 1) = 3; 4346 * 4347 * staticSliceFree(&slce); 4348 * 4349 * StaticSlice variables: 4350 * slce.array: elements 4351 * slce.count: current element count 4352 * 4353 * Note: some functions are macros to be able to have structs as element and 4354 * access the struct members directly, for example: 4355 * staticSliceLast(chan).a = 0; 4356 */ 4357 4358 /** 4359 * declares type for staticSlice 4360 * 4361 * \param 4362 * typeName staticSlice type name 4363 * \param 4364 * element type of elements (int, struct, pointer...) 4365 * \param 4366 * MAXCOUNT array/ring buffer size 4367 */ 4368 #define staticSliceT(typeName, elementType, MAXCOUNT)\ 4369 typedef struct {\ 4370 size_t count;\ 4371 elementType array[MAXCOUNT];\ 4372 } typeName 4373 4374 #define createStaticSlice(typeName, name) ;typeName name; staticSliceInit(&name) 4375 4376 /** 4377 * initialize empty staticSlice 4378 * 4379 * \param 4380 * name variable name for staticSlice 4381 */ 4382 #define staticSliceInit(name) do{\ 4383 (name)->count = 0;\ 4384 } while(0) 4385 4386 /** 4387 * element type in slice 4388 */ 4389 #define staticSliceElemType(name) typeof((name)->array[0]) 4390 4391 /** 4392 * element pointer type in slice 4393 */ 4394 #define staticSliceElemPtrType(name) typeof(&(name)->array[0]) 4395 4396 /** 4397 * duplicate staticSlice to already declared dest staticSlice 4398 */ 4399 #define staticSliceBDup(name, dest) do{\ 4400 var UNIQVAR(dst) = dest;\ 4401 if ((name)->count <= ARRAY_SIZE(UNIQVAR(dst)->array)) {\ 4402 memcpy(UNIQVAR(dst)->array, (name)->array, (name)->count * sizeof (name)->array[0]);\ 4403 UNIQVAR(dst)->count = (name)->count;\ 4404 }\ 4405 } while(0) 4406 4407 4408 /** 4409 * direct access to underlying array 4410 */ 4411 #define staticSliceData sliceData 4412 4413 /** 4414 * copy data from array to staticSlice 4415 */ 4416 #define staticSliceFrom(name, arrayIn, countInt) do{\ 4417 var UNIQVAR(c) = countInt;\ 4418 var UNIQVAR(a) = arrayIn;\ 4419 if (sizeof((name)->array[0]) == sizeof(*(UNIQVAR(a))) /* slice compatibility and UNIQVAR(c) <= ARRAY_SIZE((name)->array)*/) {\ 4420 memcpy((name)->array, UNIQVAR(a), UNIQVAR(c) * sizeof UNIQVAR(a)[0]);\ 4421 (name)->count = UNIQVAR(c);\ 4422 }\ 4423 } while(0) 4424 4425 4426 /** 4427 * set 0 in staticSlice elements 4428 * count is unchanged 4429 */ 4430 #define staticSliceClear(name) memset((name)->array, 0, (name)->count * sizeof (name)->array[0]) 4431 4432 #define staticSliceClearRange(name, start, end) memset((name)->array + start, 0, (end-start) * sizeof (name)->array[0]) 4433 4434 /** 4435 * Empty staticSlice 4436 * Set count to 0 4437 * Allocated buffers in the staticSlice must be freed before running staticSliceEmpty 4438 */ 4439 #define staticSliceEmpty sliceEmpty 4440 4441 /** 4442 * is staticSlice Empty 4443 */ 4444 #define staticSliceIsEmpty(name) ((name)->count == 0) 4445 4446 /** 4447 * return element count 4448 */ 4449 #define staticSliceCount sliceCount 4450 4451 /** 4452 * size of staticSlice element 4453 */ 4454 #define staticSliceElemSize sliceElemSize 4455 4456 /** 4457 * clear (set 0) in element at index 4458 */ 4459 #define staticSliceClearElem sliceClearElem 4460 4461 /** 4462 * push element and expand the staticSlice 4463 * no data (random) is set in the new element 4464 * 4465 * \param 4466 * name staticSlice 4467 */ 4468 #define staticSlicePush(name) (name)->count++ 4469 4470 /** 4471 * append element and expand the staticSlice 4472 * 4473 * \param 4474 * name staticSlice 4475 * \param 4476 * v element to push 4477 */ 4478 #define staticSliceAppend(name, v) do{\ 4479 staticSlicePush(name);\ 4480 staticSliceLast(name) = v;\ 4481 } while(0) 4482 4483 4484 /** 4485 * push element and expand the staticSlice 4486 * the new element is cleared 4487 * 4488 * \param 4489 * name staticSlice 4490 */ 4491 #define staticSliceClearPush(name) do{\ 4492 staticSlicePush(name);\ 4493 staticSliceClearElem(name, (name)->count - 1);\ 4494 } while(0) 4495 4496 /** 4497 * pop element 4498 * the element count is decreased 4499 * 4500 * NOTE: using comma operator to avoid warning 4501 * warning: operation on ‘b.head’ may be undefined [-Wsequence-point] 4502 * 4503 * 4504 * \param 4505 * name staticSlice 4506 */ 4507 #define staticSlicePop slicePop 4508 4509 /** 4510 * delete the last element 4511 * useful for avoiding warning: right-hand operand of comma expression has no effect 4512 * when the poped value is not used 4513 */ 4514 #define staticSliceDelLast sliceDelLast 4515 4516 /** 4517 * get / set element at index 4518 * 4519 * \param 4520 * name staticSlice 4521 * \param 4522 * index index in array 4523 */ 4524 #define staticSliceAt sliceAt 4525 4526 /** 4527 * get pointer to element at index 4528 * 4529 * \param 4530 * name staticSlice 4531 * \param 4532 * index index in array 4533 */ 4534 #define staticSlicePtr slicePtr 4535 4536 /** 4537 * last element 4538 * 4539 * \param 4540 * name staticSlice 4541 */ 4542 #define staticSliceLast sliceLast 4543 4544 /** 4545 * pointer to last element 4546 * 4547 * \param 4548 * name staticSlice 4549 */ 4550 #define staticSliceLastPtr sliceLastPtr 4551 4552 /** 4553 * index of last element 4554 */ 4555 #define staticSliceLastIndex sliceLastIndex 4556 4557 4558 /** 4559 * first element 4560 * 4561 * \param 4562 * name staticSlice 4563 */ 4564 #define staticSliceFirst sliceFirst 4565 4566 4567 /** 4568 * write the staticSlice content to filename file 4569 * No NULL checks are done on the parameters 4570 * 4571 * \param 4572 * filename file name string 4573 */ 4574 #define staticSliceWriteFilename sliceWriteFilename 4575 4576 /** 4577 * write the staticSlice content to disk 4578 * No NULL checks are done on the parameters 4579 * 4580 * \param 4581 * file already opened file 4582 */ 4583 #define staticSliceWrite sliceWrite 4584 4585 /** 4586 * read a staticSlice from filename file 4587 * No NULL checks are done on the parameters 4588 * 4589 * \param 4590 * filename file name string 4591 */ 4592 #define staticSliceReadFilename(name, filename) do {\ 4593 if (fileExists(filename)) {\ 4594 size_t UNIQVAR(sz) = fileSize(filename);\ 4595 FILE *UNIQVAR(f) = fopen(filename, "r");\ 4596 if (UNIQVAR(f)) {\ 4597 range(UNIQVAR(i), UNIQVAR(sz)/sizeof((name)->array[0])) {\ 4598 staticSlicePush(name);\ 4599 fread(staticSliceLastPtr(name), 1, sizeof((name)->array[0]), UNIQVAR(f));\ 4600 }\ 4601 fclose(UNIQVAR(f));\ 4602 }\ 4603 }\ 4604 } while(0) 4605 4606 /** 4607 * read a staticSlice from disk 4608 * No NULL checks are done on the parameters 4609 * 4610 * \param 4611 * file already opened file 4612 */ 4613 #define staticSliceRead(name, file) do {\ 4614 fseek(file, 0 , SEEK_END);\ 4615 size_t UNIQVAR(sz) = ftell(file);\ 4616 fseek(file, 0 , SEEK_SET);\ 4617 range(UNIQVAR(i), UNIQVAR(sz)/sizeof((name)->array[0])) {\ 4618 staticSlicePush(name);\ 4619 fread(staticSliceLastPtr(name), 1, sizeof((name)->array[0]), file);\ 4620 }\ 4621 } while(0) 4622 4623 4624 /** 4625 * loop index on staticSlice elements 4626 * 4627 * For example: 4628 * forEachV(vec, i) { 4629 * staticSliceAt(vec, i) = 0; 4630 * } 4631 */ 4632 #define forEachSSc forEachSc 4633 4634 /** 4635 * loop on slice elements 4636 * element is a pointer to a value in the array 4637 * 4638 * staticSliceForEach(&slc, e) { 4639 * e->x = 0; 4640 * } 4641 */ 4642 #define staticSliceForEach(name, element) \ 4643 ;size_t UNIQVAR(libsheepyInternalIndex) = 0; \ 4644 for (staticSliceElemPtrType(name) element = staticSlicePtr(name, 0) ; UNIQVAR(libsheepyInternalIndex) < (name)->count ; UNIQVAR(libsheepyInternalIndex)++, element = staticSlicePtr(name, UNIQVAR(libsheepyInternalIndex))) 4645 4646 /** 4647 * enumerate slice elements 4648 * index is the position of the element in the array 4649 * index is declared as size_t and is available after the loop 4650 * element is a pointer to a value in the array 4651 * 4652 * sliceEnumerate(&slc, i, e) { 4653 * e->x = 0; 4654 * printf("sliceEnumerate %d\n", i); 4655 * } 4656 */ 4657 #define staticSliceEnumerate(name, index, element) \ 4658 ; size_t index = 0 ; \ 4659 for (staticSliceElemPtrType(name) element = staticSlicePtr(name, 0) ; index < (name)->count ; index++, element = staticSlicePtr(name, index)) 4660 4661 /** 4662 * insert an element at index 4663 * the data is moved to create space for the new element 4664 * to set data at the new element, use staticSliceAt(name, index) = value; 4665 */ 4666 #define staticSliceInject(name, index) do {\ 4667 var UNIQVAR(idx) = index;\ 4668 staticSlicePush(name);\ 4669 memmove(staticSlicePtr(name, UNIQVAR(idx) +1), staticSlicePtr(name, UNIQVAR(idx)), ((name)->count - UNIQVAR(idx)) * sizeof (name)->array[0]);\ 4670 } while(0) 4671 4672 /** 4673 * prepend element 4674 * 4675 * \param 4676 * name staticSlice 4677 * \param 4678 * v element to prepend 4679 */ 4680 #define staticSlicePrepend(name, v) do {\ 4681 staticSliceInject(name, 0);\ 4682 staticSliceAt(name, 0) = v;\ 4683 } while(0) 4684 4685 /** 4686 * dequeue element 4687 * 4688 * \param 4689 * name staticSlice 4690 */ 4691 #define staticSliceDequeue sliceDequeue 4692 4693 /** 4694 * delete first element in staticSlice 4695 * the data is moved when count > 1 4696 */ 4697 #define staticSliceDelFirst sliceDelFirst 4698 4699 4700 /** 4701 * delete an element in staticSlice 4702 * the data is moved when index < (count-1) 4703 * when index = count -1, the last element is deleted and no data is moved 4704 */ 4705 #define staticSliceDelElem sliceDelElem 4706 4707 /** 4708 * delete range in staticSlice 4709 * start must be between 0 and last index 4710 * end must be between 1 and count 4711 */ 4712 #define staticSliceDel sliceDel 4713 4714 /** 4715 * append staticSlice to staticSlice name 4716 * the data is copied 4717 */ 4718 #define staticSliceVAppend(name, staticSlice) do {\ 4719 var UNIQVAR(vec) = staticSlice;\ 4720 if (sizeof((name)->array[0]) == sizeof(UNIQVAR(vec)->array[0]) /* slice compatibility and ((name)->count + UNIQVAR(vec)->count) <= ARRAY_SIZE((name)->array)*/) {\ 4721 memcpy((name)->array + (name)->count, UNIQVAR(vec)->array, UNIQVAR(vec)->count * sizeof (name)->array[0]);\ 4722 (name)->count += UNIQVAR(vec)->count;\ 4723 }\ 4724 } while(0) 4725 4726 /** 4727 * append array to staticSlice 4728 * the data is copied 4729 */ 4730 #define staticSliceAppendFrom(name, array, countInt) do {\ 4731 var UNIQVAR(c) = countInt;\ 4732 var UNIQVAR(a) = array;\ 4733 if (sizeof((name)->array[0]) == sizeof(*(UNIQVAR(a))) /* slice compatibility and ((name)->count + UNIQVAR(c)) <= ARRAY_SIZE((name)->array)*/) {\ 4734 memcpy((name)->array + (name)->count, UNIQVAR(a), UNIQVAR(c) * sizeof (name)->array[0]);\ 4735 (name)->count += UNIQVAR(c);\ 4736 }\ 4737 } while(0) 4738 4739 /** 4740 * prepend staticSlice to staticSlice name 4741 * the data in staticSlice name is moved and 4742 * the data in staticSlice is copied to staticSlice name 4743 */ 4744 #define staticSliceVPrepend(name, staticSlice) do {\ 4745 var UNIQVAR(vec) = staticSlice;\ 4746 if (sizeof((name)->array[0]) == sizeof((UNIQVAR(vec))->array[0]) /* slice compatibility and ((name)->count + UNIQVAR(vec)->count) <= ARRAY_SIZE((name)->array)*/) {\ 4747 memmove((name)->array + (UNIQVAR(vec))->count, (name)->array, (name)->count * sizeof (name)->array[0]);\ 4748 memcpy((name)->array, (UNIQVAR(vec))->array, (UNIQVAR(vec))->count * sizeof (name)->array[0]);\ 4749 (name)->count += (UNIQVAR(vec))->count;\ 4750 }\ 4751 } while(0) 4752 4753 /** 4754 * prepend array to staticSlice 4755 * the data in staticSlice is moved and 4756 * the data in array is copied to staticSlice 4757 */ 4758 #define staticSlicePrependFrom(name, array, countInt) do {\ 4759 var UNIQVAR(c) = countInt;\ 4760 var UNIQVAR(a) = array;\ 4761 if (sizeof((name)->array[0]) == sizeof(*(UNIQVAR(a))) /* slice compatibility and ((name)->count + UNIQVAR(c)) <= ARRAY_SIZE((name)->array)*/) {\ 4762 staticSliceResize(name, (name)->count + UNIQVAR(c));\ 4763 memmove((name)->array + UNIQVAR(c), (name)->array, (name)->count * sizeof (name)->array[0]);\ 4764 memcpy((name)->array, UNIQVAR(a), UNIQVAR(c) * sizeof (name)->array[0]);\ 4765 (name)->count += UNIQVAR(c);\ 4766 }\ 4767 } while(0); 4768 4769 /** 4770 * insert staticSlice at position index 4771 * the data in staticSlice name is moved and 4772 * the data in staticSlice is copied to staticSlice name 4773 */ 4774 #define staticSliceInsert(name, index, staticSlice) do {\ 4775 var UNIQVAR(idx) = index;\ 4776 var UNIQVAR(vec) = staticSlice;\ 4777 if (UNIQVAR(idx) == (name)->count) {\ 4778 staticSliceAppend(name, UNIQVAR(vec));\ 4779 }\ 4780 else if (sizeof((name)->array[0]) == sizeof((UNIQVAR(vec))->array[0]) /* slice compatibility and ((name)->count + UNIQVAR(vec)->count) <= ARRAY_SIZE((name)->array)*/) {\ 4781 memmove((name)->array + UNIQVAR(idx) + (UNIQVAR(vec))->count, (name)->array + UNIQVAR(idx), ((name)->count - UNIQVAR(idx)) * sizeof (name)->array[0]);\ 4782 memcpy((name)->array + UNIQVAR(idx), (UNIQVAR(vec))->array, (UNIQVAR(vec))->count * sizeof (name)->array[0]);\ 4783 (name)->count += (UNIQVAR(vec))->count;\ 4784 }\ 4785 } while(0) 4786 4787 /** 4788 * insert array at position index 4789 * the data in staticSlice is moved and 4790 * the data in array is copied to staticSlice 4791 */ 4792 #define staticSliceInsertFrom(name, index, array, countInt) do {\ 4793 var UNIQVAR(idx) = index;\ 4794 var UNIQVAR(c) = countInt;\ 4795 var UNIQVAR(a) = array;\ 4796 if (UNIQVAR(idx) == (name)->count) {\ 4797 staticSliceAppendFrom(name, UNIQVAR(a), UNIQVAR(c));\ 4798 }\ 4799 else if (sizeof((name)->array[0]) == sizeof(UNIQVAR(a)[0]) /* slice compatibility and ((name)->count + UNIQVAR(c)) <= ARRAY_SIZE((name)->array)*/) {\ 4800 memmove((name)->array + UNIQVAR(idx) + UNIQVAR(c), (name)->array + UNIQVAR(idx), ((name)->count - UNIQVAR(idx)) * sizeof (name)->array[0]);\ 4801 memcpy((name)->array + UNIQVAR(idx), UNIQVAR(a), UNIQVAR(c) * sizeof (name)->array[0]);\ 4802 (name)->count += UNIQVAR(c);\ 4803 }\ 4804 } while(0) 4805 4806 /** 4807 * staticSlice staticSlice, keep only elements between start and end 4808 * start must be between 0 and last index 4809 * end must be between 1 and count 4810 * the staticSlice is returned 4811 */ 4812 #define staticSliceSlice sliceSlice 4813 4814 /** 4815 * copy staticSlice elements between start and end to the dest staticSlice 4816 * start must be between 0 and last index 4817 * end must be between 1 and count 4818 */ 4819 #define staticSliceBCopy(name, dest, start, end) do{\ 4820 if (sizeof((name)->array[0]) == sizeof((dest)->array[0]) /* slice compatibility and (UNIQVAR(ed) - UNIQVAR(strt)) <= ARRAY_SIZE((dest)->array)*/) {\ 4821 var UNIQVAR(strt) = start;\ 4822 var UNIQVAR(ed) = end;\ 4823 staticSliceResize(dest, UNIQVAR(ed) - UNIQVAR(strt));\ 4824 memcpy((dest)->array, (name)->array + UNIQVAR(strt), (UNIQVAR(ed) - UNIQVAR(strt)) * sizeof (name)->array[0]);\ 4825 (dest)->count = UNIQVAR(ed) - UNIQVAR(strt);\ 4826 }\ 4827 } while(0) 4828 4829 /** 4830 * sort the staticSlice 4831 * the compareFunction must prototype of type: 4832 * int cmp(const void * a, const void * b); 4833 * the results of the compareFunction should be: 4834 * <0 when a < b 4835 * 0 when a = b 4836 * >0 when a > b 4837 */ 4838 #define staticSliceSort sliceSort 4839 4840 /** 4841 * return true when staticSlice name is equal to staticSlice 4842 * eqFunction should return true when the elements are equal 4843 * eqFunction can be either a macro or a function 4844 */ 4845 #define staticSliceEq sliceEq 4846 4847 /** 4848 * return true when staticSlice has value 4849 * eqFunction should return true when the elements are equal 4850 * eqFunction can be either a macro or a function 4851 */ 4852 #define staticSliceHas sliceHas 4853 4854 /** 4855 * return index (ssize_t) of value in staticSlice 4856 * eqFunction should return true when the elements are equal 4857 * eqFunction can be either a macro or a function 4858 * 4859 * return value is -1 when value is not found 4860 */ 4861 #define staticSliceIndexOf sliceIndexOf 4862 4863 /** 4864 * binary search value in staticSlice 4865 * 4866 * efficiently finds the index of value in staticSlice 4867 * the staticSlice has to be sorted before calling staticSliceBinarySearch 4868 * 4869 * less is a macro taking an index and the search value returning 1 when staticSliceAt(name,index) is less than value: 4870 * #define less(index, value) staticSliceAt(name, index) < value 4871 * 4872 * equal is a macro returning 1 when staticSliceAt(name,index) is equal to value: 4873 * #define equal(index, value) staticSliceAt(name,index) == value 4874 * 4875 * return value is -1 when value is not found 4876 */ 4877 #define staticSliceBinarySearch sliceBinarySearch 4878 4879 /** 4880 * Uniquify elements in staticSlice 4881 * each elements are unique in the staticSlice 4882 * 4883 * eqFunction should return true when the elements are equal 4884 * eqFunction can be either a macro or a function 4885 */ 4886 #define staticSliceUniq sliceUniq 4887 4888 /* 4889 * end staticSlice 4890 */ 4891 4892 /** 4893 * vector - dynamic array in one chunk of memory (similar to slab below) 4894 * 4895 * This is a simple dynamic array holding element count, maximum element count and the data 4896 * 4897 * vector supports shrinking through vectorResize 4898 * 4899 * this type of array has a dynamic element count 4900 * pushing elements into the array increases the element count 4901 * poping elements only decreases the element count, call vectorFit to resize the vector 4902 * 4903 * no sanity checks are done 4904 * 4905 * the prefix is vector 4906 * 4907 * Usage: 4908 * 4909 * to declare a vector: 4910 * 4911 * vectorT(typeName, type); 4912 * 4913 * typeName vectr; 4914 * 4915 * vectorInit(&vectr); 4916 * or 4917 * vectorInitCount(&vectr, 17); 4918 * 4919 * vectorAppend(&vectr, value); 4920 * 4921 * // get an element 4922 * int a = vectorAt(&vectr, 0); 4923 * 4924 * set 4925 * vectorAt(&vectr, 1) = 3; 4926 * 4927 * vectorFree(&vectr); 4928 * 4929 * Vector variables: 4930 * vectr.array: elements 4931 * vectr.count: current element count 4932 * vectr.maxCount: maximum element count allowed 4933 * 4934 * Note: some functions are macros to be able to have structs as element and 4935 * access the struct members directly, for example: 4936 * vectorLast(chan).a = 0; 4937 */ 4938 4939 /** number of elements added by vectorAlloc */ 4940 #define vectorSz 1 4941 4942 /** 4943 * declares type for vector 4944 * 4945 * \param 4946 * typeName vector type name 4947 * \param 4948 * element type of elements (int, struct, pointer...) 4949 */ 4950 #define vectorT(typeName, elementType)\ 4951 typedef struct {\ 4952 size_t count;\ 4953 size_t maxCount;\ 4954 elementType *array;\ 4955 } typeName 4956 4957 4958 #define createVector(typeName, name) ;typeName name; vectorInit(&name) 4959 4960 #define createVectorCount(typeName, name, count) ;typeName name; vectorInitCount(&name, count) 4961 4962 #define createVectorClearCount(typeName, name, count) ;typeName name; vectorCalloc(&name, count) 4963 4964 #define createAllocateVector(typeName, name) ;typeName *name = calloc(1, sizeof(typeName)) 4965 4966 #define createAllocateVectorCount(typeName, name, count) ;typeName *name = calloc(1, sizeof(typeName)); vectorInitCount(name, count) 4967 4968 #define createAllocateVectorClearCount(typeName, name, count) ;typeName *name = calloc(1, sizeof(typeName)); vectorCalloc(name, count) 4969 4970 #define vectorTerminate(name) if (name) vectorFree(name);free(name) 4971 4972 /** 4973 * initialize empty vector 4974 * 4975 * \param 4976 * name variable name for vector 4977 */ 4978 #define vectorInit(name) do{\ 4979 (name)->array = NULL;\ 4980 (name)->count = 0;\ 4981 (name)->maxCount = 0;\ 4982 } while(0) 4983 4984 /** 4985 * initialize vector and count 4986 * 4987 * \param 4988 * name variable name for vector 4989 * \param 4990 * count initial element count for name type 4991 */ 4992 #define vectorInitCount(name, countInt) do{\ 4993 var UNIQVAR(c) = countInt;\ 4994 (name)->array = malloc(UNIQVAR(c) * sizeof (name)->array[0]);\ 4995 (name)->count = 0;\ 4996 (name)->maxCount = UNIQVAR(c);\ 4997 } while(0) 4998 4999 /** 5000 * initialize vector and count and set vector data to 0 5001 * 5002 * \param 5003 * name variable name for vector 5004 * \param 5005 * count initial element count for name type 5006 */ 5007 #define vectorCalloc(name, countInt) do{\ 5008 var UNIQVAR(c) = countInt;\ 5009 (name)->array = calloc(UNIQVAR(c), sizeof (name)->array[0]);\ 5010 (name)->count = 0;\ 5011 (name)->maxCount = UNIQVAR(c);\ 5012 } while(0) 5013 5014 /** 5015 * resize vector (even empty vectors) 5016 */ 5017 #define vectorResize(name, countInt) do{\ 5018 var UNIQVAR(c) = countInt;\ 5019 if ((name)->array) {\ 5020 /* realloc */\ 5021 (name)->array = realloc((name)->array, sizeof((name)->array[0]) * UNIQVAR(c));\ 5022 }\ 5023 else {\ 5024 /* was empty */\ 5025 (name)->array = malloc(sizeof((name)->array[0]) * UNIQVAR(c));\ 5026 }\ 5027 /* element count when shrinking */\ 5028 if (UNIQVAR(c) < (name)->count) (name)->count = UNIQVAR(c);\ 5029 (name)->maxCount = UNIQVAR(c);\ 5030 } while(0) 5031 5032 /** 5033 * resize vector and clear the new elements with memset 5034 * even empty vectors can be resized and cleared 5035 */ 5036 #define vectorClearResize(name, countInt) do{\ 5037 var UNIQVAR(c) = countInt;\ 5038 if ((name)->array) {\ 5039 /* realloc */\ 5040 (name)->array = realloc((name)->array, sizeof((name)->array[0]) * UNIQVAR(c));\ 5041 if ((name)->count < UNIQVAR(c)) {\ 5042 /* there are new elements */\ 5043 memset(&(name)->array[(name)->count], 0, (UNIQVAR(c) - (name)->count) * sizeof (name)->array[0]);\ 5044 }\ 5045 }\ 5046 else {\ 5047 /* was empty */\ 5048 (name)->array = calloc(UNIQVAR(c), sizeof((name)->array[0]));\ 5049 }\ 5050 /* element count when shrinking */\ 5051 if (UNIQVAR(c) < (name)->count) (name)->count = UNIQVAR(c);\ 5052 (name)->maxCount = UNIQVAR(c);\ 5053 } while(0) 5054 5055 /** 5056 * free the internal buffers 5057 * 5058 * \param 5059 * name vector 5060 */ 5061 #define vectorFree sliceFree 5062 5063 /** 5064 * element type in vector 5065 */ 5066 #define vectorElemType(name) typeof((name)->array[0]) 5067 5068 /** 5069 * element pointer type in vector 5070 */ 5071 #define vectorElemPtrType(name) typeof(&(name)->array[0]) 5072 5073 /** 5074 * duplicate vector 5075 */ 5076 #define vectorDup(name) ({\ 5077 typeof(*(name)) dest;\ 5078 vectorInitCount(dest, (name)->count);\ 5079 if ((name)->array) {\ 5080 memcpy(dest->array, (name)->array, (name)->count * sizeof (name)->array[0]);\ 5081 dest->count = (name)->count;\ 5082 }\ 5083 /* return */ dest;\ 5084 }) 5085 /** 5086 * declare dest vector and duplicate vector 5087 */ 5088 #define vectorCreateNDup(name, dest) ;typeof(*(name)) dest; vectorInitCount(dest, (name)->count); if ((name)->array) { memcpy(dest->array, (name)->array, (name)->count * sizeof (name)->array[0]); dest->count = (name)->count;} 5089 5090 /** 5091 * duplicate vector to already declared dest vector 5092 */ 5093 #define vectorBDup(name, dest) do{\ 5094 var UNIQVAR(dst) = dest;\ 5095 vectorResize(UNIQVAR(dst), (name)->count);\ 5096 if ((name)->array) {\ 5097 memcpy(UNIQVAR(dst)->array, (name)->array, (name)->count * sizeof (name)->array[0]);\ 5098 dest->count = (name)->count;\ 5099 }\ 5100 } while(0) 5101 5102 /** 5103 * direct access to underlying array 5104 */ 5105 #define vectorData sliceData 5106 5107 /** 5108 * copy data from array to vector 5109 */ 5110 #define vectorFrom(name, array, countInt) do{\ 5111 var UNIQVAR(c) = countInt;\ 5112 var UNIQVAR(a) = array;\ 5113 if (sizeof((name)->array[0]) == sizeof(*(UNIQVAR(a)))) {\ 5114 if (UNIQVAR(c) > (name)->maxCount)\ 5115 vectorResize(name, UNIQVAR(c));\ 5116 memcpy((name)->array, UNIQVAR(a), UNIQVAR(c) * sizeof UNIQVAR(a)[0]);\ 5117 (name)->count = UNIQVAR(c);\ 5118 }\ 5119 } while(0) 5120 5121 /** 5122 * set 0 in vector elements 5123 * count is unchanged 5124 */ 5125 #define vectorClear sliceClear 5126 5127 #define vectorClearRange sliceClearRange 5128 5129 /** 5130 * Empty vector 5131 * Set count to 0 5132 * Allocated buffers in the vector must be freed before running vectorEmpty 5133 */ 5134 #define vectorEmpty sliceEmpty 5135 5136 /** 5137 * is vector Empty 5138 */ 5139 #define vectorIsEmpty sliceIsEmpty 5140 5141 /** 5142 * resize vector from maxCount to count 5143 */ 5144 #define vectorFit(name) do{\ 5145 if ((name)->maxCount > (name)->count) {\ 5146 vectorResize(name, (name)->count);\ 5147 }\ 5148 } while(0) 5149 5150 /** 5151 * return element count 5152 */ 5153 #define vectorCount sliceCount 5154 5155 /** 5156 * return max element count 5157 */ 5158 #define vectorMaxCount(name) (name)->maxCount 5159 5160 /** 5161 * size of vector element 5162 */ 5163 #define vectorElemSize sliceElemSize 5164 5165 /** 5166 * allocate an element 5167 * only when the vector is full 5168 */ 5169 #define vectorAlloc(name) do{\ 5170 if (!(name)->array) {\ 5171 (name)->array = malloc(vectorSz * sizeof (name)->array[0]);\ 5172 (name)->maxCount = vectorSz;\ 5173 }\ 5174 else if ((name)->count == (name)->maxCount) {\ 5175 (name)->maxCount += vectorSz;\ 5176 (name)->array = realloc((name)->array, (name)->maxCount * sizeof (name)->array[0]);\ 5177 }\ 5178 } while(0) 5179 5180 /** 5181 * clear (set 0) in element at index 5182 */ 5183 #define vectorClearElem sliceClearElem 5184 5185 /** 5186 * push element and expand the vector 5187 * no data (random) is set in the new element 5188 * 5189 * \param 5190 * name vector 5191 */ 5192 #define vectorPush(name) do {\ 5193 vectorAlloc(name);\ 5194 (name)->count++;\ 5195 } while(0) 5196 5197 /** 5198 * append element and expand the vector 5199 * 5200 * \param 5201 * name vector 5202 * \param 5203 * v element to push 5204 */ 5205 #define vectorAppend(name, v) do{\ 5206 vectorPush(name);\ 5207 vectorLast(name) = v;\ 5208 } while(0) 5209 5210 5211 /** 5212 * push element and expand the vector 5213 * the new element is cleared 5214 * 5215 * \param 5216 * name vector 5217 */ 5218 #define vectorClearPush(name) do{\ 5219 vectorPush(name);\ 5220 vectorClearElem(name, (name)->count - 1);\ 5221 } while(0) 5222 5223 /** 5224 * pop element 5225 * the element count is decreased 5226 * 5227 * NOTE: using comma operator to avoid warning 5228 * warning: operation on ‘b.head’ may be undefined [-Wsequence-point] 5229 * 5230 * 5231 * \param 5232 * name vector 5233 */ 5234 #define vectorPop slicePop 5235 5236 /** 5237 * delete the last element 5238 * useful for avoiding warning: right-hand operand of comma expression has no effect 5239 * when the poped value is not used 5240 */ 5241 #define vectorDelLast sliceDelLast 5242 5243 /** 5244 * push multiple elements at once 5245 * 5246 * \param 5247 * name vector 5248 * \param 5249 * countp number of elements to add 5250 */ 5251 #define vectorPushCount(name, countp) procbegin\ 5252 u32 UNIQVAR(count) = countp;\ 5253 if (((name)->count + UNIQVAR(count)) > (name)->maxCount) {\ 5254 (name)->maxCount += UNIQVAR(count);\ 5255 (name)->array = realloc((name)->array, (name)->maxCount * sizeof (name)->array[0]);\ 5256 }\ 5257 (name)->count += UNIQVAR(count);\ 5258 procend 5259 5260 5261 /** 5262 * set value at index and clearResize vector when index is outside vector maxCount 5263 */ 5264 #define vectorSet(name, index, v) do{\ 5265 var UNIQVAR(idx) = index;\ 5266 if (UNIQVAR(idx) >= (name)->count) {\ 5267 /* clear and resize */\ 5268 vectorClearResize(name, UNIQVAR(idx)+1);\ 5269 }\ 5270 vectorAt(name, UNIQVAR(idx)) = v;\ 5271 } while(0) 5272 5273 /** 5274 * get / set element at index 5275 * 5276 * \param 5277 * name vector 5278 * \param 5279 * index index in array 5280 */ 5281 #define vectorAt sliceAt 5282 5283 /** 5284 * get pointer to element at index 5285 * 5286 * \param 5287 * name vector 5288 * \param 5289 * index index in array 5290 */ 5291 #define vectorPtr slicePtr 5292 5293 /** 5294 * last element 5295 * 5296 * \param 5297 * name vector 5298 */ 5299 #define vectorLast sliceLast 5300 5301 /** 5302 * pointer to last element 5303 * 5304 * \param 5305 * name vector 5306 */ 5307 #define vectorLastPtr sliceLastPtr 5308 5309 /** 5310 * index of last element 5311 */ 5312 #define vectorLastIndex sliceLastIndex 5313 5314 5315 /** 5316 * first element 5317 * 5318 * \param 5319 * name vector 5320 */ 5321 #define vectorFirst sliceFirst 5322 5323 5324 /** 5325 * write the vector content to filename file 5326 * No NULL checks are done on the parameters 5327 * 5328 * \param 5329 * filename file name string 5330 */ 5331 #define vectorWriteFilename sliceWriteFilename 5332 5333 /** 5334 * write the vector content to disk 5335 * No NULL checks are done on the parameters 5336 * 5337 * \param 5338 * file already opened file 5339 */ 5340 #define vectorWrite sliceWrite 5341 5342 /** 5343 * read a vector from filename file 5344 * No NULL checks are done on the parameters 5345 * 5346 * \param 5347 * filename file name string 5348 */ 5349 #define vectorReadFilename(name, filename) do {\ 5350 if (fileExists(filename)) {\ 5351 size_t UNIQVAR(sz) = fileSize(filename);\ 5352 FILE *UNIQVAR(f) = fopen(filename, "r");\ 5353 if (UNIQVAR(f)) {\ 5354 range(UNIQVAR(i), UNIQVAR(sz)/sizeof((name)->array[0])) {\ 5355 vectorPush(name);\ 5356 fread(vectorLastPtr(name), 1, sizeof((name)->array[0]), UNIQVAR(f));\ 5357 }\ 5358 fclose(UNIQVAR(f));\ 5359 }\ 5360 }\ 5361 } while(0) 5362 5363 /** 5364 * read a vector from disk 5365 * No NULL checks are done on the parameters 5366 * 5367 * \param 5368 * file already opened file 5369 */ 5370 #define vectorRead(name, file) do {\ 5371 fseek(file, 0 , SEEK_END);\ 5372 size_t UNIQVAR(sz) = ftell(file);\ 5373 fseek(file, 0 , SEEK_SET);\ 5374 range(UNIQVAR(i), UNIQVAR(sz)/sizeof((name)->array[0])) {\ 5375 vectorPush(name);\ 5376 fread(vectorLastPtr(name), 1, sizeof((name)->array[0]), file);\ 5377 }\ 5378 } while(0) 5379 5380 5381 /** 5382 * loop index on vector elements 5383 * 5384 * For example: 5385 * forEachV(vec, i) { 5386 * vectorAt(vec, i) = 0; 5387 * } 5388 */ 5389 #define forEachV forEachSc 5390 5391 /** 5392 * loop on vector elements 5393 * element is a pointer to a value in the array 5394 * 5395 * vectorForEach(&slc, e) { 5396 * e->x = 0; 5397 * } 5398 */ 5399 #define vectorForEach(name, element) \ 5400 ;size_t UNIQVAR(libsheepyInternalIndex) = 0; \ 5401 for (vectorElemPtrType(name) element = vectorPtr(name, 0) ; UNIQVAR(libsheepyInternalIndex) < (name)->count ; UNIQVAR(libsheepyInternalIndex)++, element = vectorPtr(name, UNIQVAR(libsheepyInternalIndex))) 5402 5403 /** 5404 * enumerate vector elements 5405 * index is the position of the element in the array 5406 * index is declared as size_t and is available after the loop 5407 * element is a pointer to a value in the array 5408 * 5409 * vectorEnumerate(&slc, i, e) { 5410 * e->x = 0; 5411 * printf("vectorEnumerate %d\n", i); 5412 * } 5413 */ 5414 #define vectorEnumerate(name, index, element) \ 5415 ; size_t index = 0 ; \ 5416 for (vectorElemPtrType(name) element = vectorPtr(name, 0) ; index < (name)->count ; index++, element = vectorPtr(name, index)) 5417 5418 /** 5419 * insert an element at index 5420 * the data is moved to create space for the new element 5421 * to set data at the new element, use vectorAt(name, index) = value; 5422 */ 5423 #define vectorInject(name, index) do {\ 5424 var UNIQVAR(idx) = index;\ 5425 vectorPush(name);\ 5426 memmove(vectorPtr(name, UNIQVAR(idx) +1), vectorPtr(name, UNIQVAR(idx)), ((name)->count - UNIQVAR(idx)) * sizeof (name)->array[0]);\ 5427 } while(0) 5428 5429 /** 5430 * prepend element 5431 * 5432 * \param 5433 * name vector 5434 * \param 5435 * v element to prepend 5436 */ 5437 #define vectorPrepend(name, v) do {\ 5438 vectorInject(name, 0);\ 5439 vectorAt(name, 0) = v;\ 5440 } while(0) 5441 5442 /** 5443 * dequeue element 5444 * 5445 * \param 5446 * name vector 5447 */ 5448 #define vectorDequeue sliceDequeue 5449 5450 /** 5451 * delete first element in vector 5452 * the data is moved when count > 1 5453 */ 5454 #define vectorDelFirst sliceDelFirst 5455 5456 5457 /** 5458 * delete an element in vector 5459 * the data is moved when index < (count-1) 5460 * when index = count -1, the last element is deleted and no data is moved 5461 */ 5462 #define vectorDelElem sliceDelElem 5463 5464 /** 5465 * delete range in vector 5466 * start must be between 0 and last index 5467 * end must be between 1 and count 5468 */ 5469 #define vectorDel sliceDel 5470 5471 /** 5472 * append vector to vector name 5473 * the data is copied 5474 */ 5475 #define vectorVAppend(name, vector) do {\ 5476 var UNIQVAR(vec) = vector;\ 5477 if (sizeof((name)->array[0]) == sizeof((UNIQVAR(vec))->array[0])) {\ 5478 if (((name)->count + (UNIQVAR(vec))->count) > (name)->maxCount)\ 5479 vectorResize(name, (name)->count + (UNIQVAR(vec))->count);\ 5480 memcpy((name)->array + (name)->count, (UNIQVAR(vec))->array, (UNIQVAR(vec))->count * sizeof (name)->array[0]);\ 5481 (name)->count += (UNIQVAR(vec))->count;\ 5482 }\ 5483 } while(0) 5484 5485 /** 5486 * append array to vector 5487 * the data is copied 5488 */ 5489 #define vectorAppendFrom(name, array, countInt) do {\ 5490 var UNIQVAR(c) = countInt;\ 5491 var UNIQVAR(a) = array;\ 5492 if (sizeof((name)->array[0]) == sizeof(*(UNIQVAR(a)))) {\ 5493 if (((name)->count + UNIQVAR(c)) > (name)->maxCount)\ 5494 vectorResize(name, (name)->count + UNIQVAR(c));\ 5495 memcpy((name)->array + (name)->count, UNIQVAR(a), UNIQVAR(c) * sizeof (name)->array[0]);\ 5496 (name)->count += UNIQVAR(c);\ 5497 }\ 5498 } while(0) 5499 5500 /** 5501 * prepend vector to vector name 5502 * the data in vector name is moved and 5503 * the data in vector is copied to vector name 5504 */ 5505 #define vectorVPrepend(name, vector) do {\ 5506 var UNIQVAR(vec) = vector;\ 5507 if (sizeof((name)->array[0]) == sizeof((UNIQVAR(vec))->array[0])) {\ 5508 if (((name)->count + (UNIQVAR(vec))->count) > (name)->maxCount)\ 5509 vectorResize(name, (name)->count + (UNIQVAR(vec))->count);\ 5510 memmove((name)->array + (UNIQVAR(vec))->count, (name)->array, (name)->count * sizeof (name)->array[0]);\ 5511 memcpy((name)->array, (UNIQVAR(vec))->array, (UNIQVAR(vec))->count * sizeof (name)->array[0]);\ 5512 (name)->count += (UNIQVAR(vec))->count;\ 5513 }\ 5514 } while(0) 5515 5516 /** 5517 * prepend array to vector 5518 * the data in vector is moved and 5519 * the data in array is copied to vector 5520 */ 5521 #define vectorPrependFrom(name, array, countInt) do {\ 5522 var UNIQVAR(c) = countInt;\ 5523 var UNIQVAR(a) = array;\ 5524 if (sizeof((name)->array[0]) == sizeof(*(UNIQVAR(a)))) {\ 5525 if (((name)->count + UNIQVAR(c)) > (name)->maxCount)\ 5526 vectorResize(name, (name)->count + UNIQVAR(c));\ 5527 memmove((name)->array + UNIQVAR(c), (name)->array, (name)->count * sizeof (name)->array[0]);\ 5528 memcpy((name)->array, UNIQVAR(a), UNIQVAR(c) * sizeof (name)->array[0]);\ 5529 (name)->count += UNIQVAR(c);\ 5530 }\ 5531 } while(0); 5532 5533 /** 5534 * insert vector at position index 5535 * the data in vector name is moved and 5536 * the data in vector is copied to vector name 5537 */ 5538 #define vectorInsert(name, index, vector) do {\ 5539 var UNIQVAR(idx) = index;\ 5540 var UNIQVAR(vec) = vector;\ 5541 if (UNIQVAR(idx) == (name)->count) {\ 5542 vectorAppend(name, UNIQVAR(vec));\ 5543 }\ 5544 else if (sizeof((name)->array[0]) == sizeof((UNIQVAR(vec))->array[0])) {\ 5545 if (((name)->count + (UNIQVAR(vec))->count) > (name)->maxCount)\ 5546 vectorResize(name, (name)->count + (UNIQVAR(vec))->count);\ 5547 memmove((name)->array + UNIQVAR(idx) + (UNIQVAR(vec))->count, (name)->array + UNIQVAR(idx), ((name)->count - UNIQVAR(idx)) * sizeof (name)->array[0]);\ 5548 memcpy((name)->array + UNIQVAR(idx), (UNIQVAR(vec))->array, (UNIQVAR(vec))->count * sizeof (name)->array[0]);\ 5549 (name)->count += (UNIQVAR(vec))->count;\ 5550 }\ 5551 } while(0) 5552 5553 /** 5554 * insert array at position index 5555 * the data in vector is moved and 5556 * the data in array is copied to vector 5557 */ 5558 #define vectorInsertFrom(name, index, array, countInt) do {\ 5559 var UNIQVAR(idx) = index;\ 5560 var UNIQVAR(c) = countInt;\ 5561 var UNIQVAR(a) = array;\ 5562 if (UNIQVAR(idx) == (name)->count) {\ 5563 vectorAppendFrom(name, UNIQVAR(a), UNIQVAR(c));\ 5564 }\ 5565 else if (sizeof((name)->array[0]) == sizeof(UNIQVAR(a)[0])) {\ 5566 if (((name)->count + UNIQVAR(c)) > (name)->maxCount)\ 5567 vectorResize(name, (name)->count + UNIQVAR(c));\ 5568 memmove((name)->array + UNIQVAR(idx) + UNIQVAR(c), (name)->array + UNIQVAR(idx), ((name)->count - UNIQVAR(idx)) * sizeof (name)->array[0]);\ 5569 memcpy((name)->array + UNIQVAR(idx), UNIQVAR(a), UNIQVAR(c) * sizeof (name)->array[0]);\ 5570 (name)->count += UNIQVAR(c);\ 5571 }\ 5572 } while(0) 5573 5574 /** 5575 * slice vector, keep only elements between start and end 5576 * start must be between 0 and last index 5577 * end must be between 1 and count 5578 * the vector is returned 5579 */ 5580 #define vectorSlice sliceSlice 5581 5582 /** 5583 * copy vector elements between start and end to a new vector 5584 * start must be between 0 and last index 5585 * end must be between 1 and count 5586 * the new vector is returned and must be freed with vectorTerminate 5587 */ 5588 #define vectorCopy(name, start, end) ({\ 5589 var UNIQVAR(strt) = start;\ 5590 var UNIQVAR(ed) = end;\ 5591 createAllocateVectorCount(typeof(*(name)),UNIQVAR(r), UNIQVAR(ed) - UNIQVAR(strt));\ 5592 memcpy(UNIQVAR(r)->array, (name)->array + UNIQVAR(strt), (UNIQVAR(ed) - UNIQVAR(strt)) * sizeof (name)->array[0]);\ 5593 UNIQVAR(r)->count = UNIQVAR(ed) - UNIQVAR(strt);\ 5594 UNIQVAR(r);\ 5595 }) 5596 5597 /** 5598 * copy vector elements between start and end to the dest vector 5599 * start must be between 0 and last index 5600 * end must be between 1 and count 5601 */ 5602 #define vectorBCopy(name, dest, start, end) do{\ 5603 if (sizeof((name)->array[0]) == sizeof((dest)->array[0])) {\ 5604 var UNIQVAR(strt) = start;\ 5605 var UNIQVAR(ed) = end;\ 5606 if ((UNIQVAR(ed) - UNIQVAR(strt)) > (dest)->maxCount)\ 5607 vectorResize(dest, UNIQVAR(ed) - UNIQVAR(strt));\ 5608 memcpy((dest)->array, (name)->array + UNIQVAR(strt), (UNIQVAR(ed) - UNIQVAR(strt)) * sizeof (name)->array[0]);\ 5609 (dest)->count = UNIQVAR(ed) - UNIQVAR(strt);\ 5610 }\ 5611 } while(0) 5612 5613 /** 5614 * sort the vector 5615 * the compareFunction must prototype of type: 5616 * int cmp(const void * a, const void * b); 5617 * the results of the compareFunction should be: 5618 * <0 when a < b 5619 * 0 when a = b 5620 * >0 when a > b 5621 */ 5622 #define vectorSort sliceSort 5623 5624 /** 5625 * return true when vector name is equal to vector 5626 * eqFunction should return true when the elements are equal 5627 * eqFunction can be either a macro or a function 5628 */ 5629 #define vectorEq sliceEq 5630 5631 /** 5632 * return true when vector has value 5633 * eqFunction should return true when the elements are equal 5634 * eqFunction can be either a macro or a function 5635 */ 5636 #define vectorHas sliceHas 5637 5638 /** 5639 * return index (ssize_t) of value in vector 5640 * eqFunction should return true when the elements are equal 5641 * eqFunction can be either a macro or a function 5642 * 5643 * return value is -1 when value is not found 5644 */ 5645 #define vectorIndexOf sliceIndexOf 5646 5647 /** 5648 * binary search value in vector 5649 * 5650 * efficiently finds the index of value in vector 5651 * the vector has to be sorted before calling vectorBinarySearch 5652 * 5653 * less is a macro taking an index and the search value returning 1 when vectorAt(name,index) is less than value: 5654 * #define less(index, value) vectorAt(name, index) < value 5655 * 5656 * equal is a macro returning 1 when vectorAt(name,index) is equal to value: 5657 * #define equal(index, value) vectorAt(name,index) == value 5658 * 5659 * return value is -1 when value is not found 5660 */ 5661 #define vectorBinarySearch sliceBinarySearch 5662 5663 /** 5664 * Uniquify elements in vector 5665 * each elements are unique in the vector 5666 * 5667 * eqFunction should return true when the elements are equal 5668 * eqFunction can be either a macro or a function 5669 */ 5670 #define vectorUniq sliceUniq 5671 5672 /* 5673 * end vector 5674 */ 5675 5676 5677 /** 5678 * dynamic segmented vector 5679 * 5680 * this type of array is faster than vector when there are many elements and has a dynamic element count 5681 * pushing elements into the array increases the element count 5682 * the data is stored in static array segments 5683 * 5684 * no sanity checks are done 5685 * 5686 * usage examples: regular array, stack 5687 * 5688 * the prefix is dVector 5689 * 5690 * Usage: 5691 * 5692 * to declare an array: 5693 * 5694 * dVectorT(typeName, type); 5695 * 5696 * typeName dvector; 5697 * 5698 * dVectorInit(&dvector); 5699 * or 5700 * dVectorInitCount(&dvector, 17); 5701 * 5702 * dVectorAppend(&dvector, value); 5703 * 5704 * // get an element 5705 * int a = dVectorAt(&dvector, 0); 5706 * 5707 * set 5708 * dVectorAt(&dvector, 1) = 3; 5709 * 5710 * dVectorFree(&dvector); 5711 * 5712 * dVector variables: 5713 * dvector.maxCount: maximum element count allowed 5714 * 5715 * Note: dont combine the macros, it gives wrong results: 5716 * a = dVectorAt(&dvector, dVectorPop(&dvector2)); 5717 * dVectorPop is run several time, more than one element is popped 5718 * 5719 * Note: some functions are macros to be able to have structs as element and 5720 * access the struct members directly, for example: 5721 * dVectorLast(chan).a = 0; 5722 */ 5723 5724 // user parameters 5725 /** 5726 * chunk size: 2^dVectorBits elements 5727 */ 5728 #define dVectorBits 6 5729 // user parameters end 5730 5731 #define dVectorSz (1<<dVectorBits) 5732 #define dVectorMask (dVectorSz-1) 5733 5734 /** 5735 * declares type for dynamic array 5736 * 5737 * \param 5738 * typeName dVector type name 5739 * \param 5740 * element type of elements (int, struct, pointer...) 5741 */ 5742 #define dVectorT(typeName, elementType)\ 5743 typedef struct {\ 5744 int64_t count;\ 5745 int64_t maxCount;\ 5746 void** buffers;\ 5747 elementType element;\ 5748 } typeName 5749 5750 5751 #define createDVector(typeName, name) ;typeName name; dVectorInit(&name) 5752 5753 #define createDVectorCount(typeName, name, count) ;typeName name; dVectorInitCount(&name, count) 5754 5755 /** 5756 * initialize dynamic array with minimum element count 5757 * 5758 * \param 5759 * a variable name for dVector 5760 */ 5761 #define dVectorInit(a) do{\ 5762 (a)->count = 0;\ 5763 (a)->buffers = malloc(sizeof(void*));\ 5764 (a)->buffers[0] = malloc(dVectorSz * sizeof((a)->element));\ 5765 (a)->maxCount = 1;\ 5766 }while(0) 5767 5768 5769 /** 5770 * initialize dynamic array and count 5771 * 5772 * \param 5773 * a variable name for dVector 5774 * \param 5775 * count initial element count for name type 5776 */ 5777 #define dVectorInitCount(a, count) do{\ 5778 dVectorInit(a);\ 5779 if (count > dVectorSz) {\ 5780 (a)->buffers = realloc((a)->buffers, ((count>>dVectorBits)+1) * sizeof(void*));\ 5781 rangeFrom(UNIQVAR(i), 1, (count>>dVectorBits)+1) {\ 5782 (a)->buffers[UNIQVAR(i)] = malloc(dVectorSz * sizeof((a)->element));\ 5783 }\ 5784 (a)->maxCount = (count>>dVectorBits)+1;\ 5785 }\ 5786 }while(0) 5787 5788 #define dVectorResize(a, count) do{\ 5789 if (count > (a)->maxCount * dVectorSz) {\ 5790 /* grow array */\ 5791 (a)->buffers = realloc((a)->buffers, ((count>>dVectorBits)+1) * sizeof(void*));\ 5792 rangeFrom(UNIQVAR(i), (a)->maxCount, (count>>dVectorBits)+1) {\ 5793 (a)->buffers[UNIQVAR(i)] = malloc(dVectorSz * sizeof((a)->element));\ 5794 }\ 5795 (a)->maxCount = (count>>dVectorBits)+1;\ 5796 }\ 5797 /*else TODO dVector shrink */\ 5798 }while(0) 5799 5800 /** 5801 * free the internal buffers 5802 * 5803 * \param 5804 * a dynamic array 5805 */ 5806 #define dVectorFree(a) do{\ 5807 range(UNIQVAR(i), (size_t)(a)->maxCount) {\ 5808 free((a)->buffers[UNIQVAR(i)]);\ 5809 }\ 5810 free((a)->buffers);\ 5811 }while(0) 5812 5813 /** 5814 * element type in vector 5815 */ 5816 #define dVectorElemType(name) typeof((name)->element) 5817 5818 /** 5819 * element pointer type in vector 5820 */ 5821 #define dVectorElemPtrType(name) typeof(&(name)->element) 5822 5823 /** 5824 * Empty Array 5825 * Allocated buffers in the array must be freed before running dVectorEmpty 5826 */ 5827 #define dVectorEmpty(name) (name)->count = 0 5828 5829 /** 5830 * is Array Empty 5831 */ 5832 #define dVectorIsEmpty(name) ((name)->count == 0) 5833 5834 /** 5835 * return element count 5836 */ 5837 #define dVectorCount(name) (name)->count 5838 5839 /** 5840 * return max element count 5841 */ 5842 #define dVectorMaxCount(name) ((name)->maxCount * dVectorSz) 5843 5844 /** 5845 * allocate buffer for new elements 5846 * only when the array is full 5847 * 5848 * \param 5849 * a dynamic array 5850 */ 5851 #define dVectorAlloc(a) do{\ 5852 if ((a)->count == dVectorMaxCount(a)) {\ 5853 (a)->maxCount++;\ 5854 (a)->buffers = realloc((a)->buffers, (a)->maxCount * sizeof(void*));\ 5855 (a)->buffers[(a)->maxCount-1] = malloc(dVectorSz * sizeof((a)->element));\ 5856 }\ 5857 }while(0) 5858 5859 /** 5860 * push element and expand the dynamic array 5861 * no data (random) is set in the new element. 5862 * 5863 * \param 5864 * a dynamic array 5865 * \param 5866 * v element to push 5867 */ 5868 #define dVectorPush(a) do{\ 5869 dVectorAlloc(a);\ 5870 (a)->count++;\ 5871 }while(0) 5872 5873 /** 5874 * append element and expand the dynamic array 5875 * 5876 * \param 5877 * a dynamic array 5878 * \param 5879 * v element to push 5880 */ 5881 #define dVectorAppend(a, v) do{\ 5882 dVectorAlloc(a);\ 5883 if ((a)->count < dVectorMaxCount(a)) {\ 5884 typeof((a)->element) *UNIQVAR(buffer) = (a)->buffers[((a)->count)>>dVectorBits];\ 5885 *(UNIQVAR(buffer)+ (((a)->count)&dVectorMask)) = v;\ 5886 (a)->count++;\ 5887 }\ 5888 }while(0) 5889 5890 /** 5891 * pop element 5892 * the index of the last element is decreased 5893 * 5894 * NOTE: using comma operator to avoid warning 5895 * warning: operation on ‘b.head’ may be undefined [-Wsequence-point] 5896 * 5897 * 5898 * \param 5899 * a dynamic array 5900 */ 5901 #define dVectorPop(a) ((a)->count--, *((typeof((a)->element)*)((a)->buffers[((a)->count)>>dVectorBits])+(((a)->count)&dVectorMask))) 5902 5903 /** 5904 * delete the last element 5905 * useful for avoiding warning: right-hand operand of comma expression has no effect 5906 * when the poped value is not used 5907 */ 5908 #define dVectorDelLast(a) ((a)->count--) 5909 5910 // TODO poor perfomance #define dVectorPrepend(a, v) 5911 5912 // TODO poor perfomance #define dVectorDequeue(a) 5913 5914 // TODO poor perfomance #define dVectorDelFirst(a) 5915 5916 /** 5917 * get / set element at index 5918 * 5919 * \param 5920 * a dynamic array 5921 * \param 5922 * index index in array 5923 */ 5924 #define dVectorAt(a, index) (*((typeof((a)->element)*)((a)->buffers[(index)>>dVectorBits])+((index)&dVectorMask))) 5925 5926 /** 5927 * get pointer to element at index 5928 * 5929 * \param 5930 * a dynamic array 5931 * \param 5932 * index index in array 5933 */ 5934 #define dVectorPtr(a, index) ((typeof((a)->element)*)((a)->buffers[(index)>>dVectorBits])+((index)&dVectorMask)) 5935 5936 /** 5937 * last element 5938 * 5939 * \param 5940 * a dynamic array 5941 */ 5942 #define dVectorLast(a) (*((typeof((a)->element)*)((a)->buffers[((a)->count-1)>>dVectorBits])+(((a)->count-1)&dVectorMask))) 5943 5944 /** 5945 * pointer to last element 5946 * 5947 * \param 5948 * a dynamic array 5949 */ 5950 #define dVectorLastPtr(a) ((typeof((a)->element)*)((a)->buffers[((a)->count-1)>>dVectorBits])+(((a)->count-1)&dVectorMask)) 5951 5952 /** 5953 * index of last element 5954 */ 5955 #define dVectorLastIndex(a) ((a)->count-1) 5956 5957 /** 5958 * first element 5959 * 5960 * \param 5961 * a dynamic array 5962 */ 5963 #define dVectorFirst(a) (*((typeof((a)->element)*)((a)->buffers[0]))) 5964 5965 /** 5966 * write the dVector content to filename file 5967 * No NULL checks are done on the parameters 5968 * 5969 * \param 5970 * filename file name string 5971 */ 5972 #define dVectorWriteFilename(a, filename) do {\ 5973 FILE *UNIQVAR(f) = fopen(filename, "w");\ 5974 if (UNIQVAR(f)) {\ 5975 range(UNIQVAR(i), (size_t)dVectorCount(a)) {\ 5976 typeof((a)->element) *firstElement = (a)->buffers[UNIQVAR(i)/dVectorSz];\ 5977 fwrite(firstElement+(UNIQVAR(i)%dVectorSz), 1, sizeof((a)->element), UNIQVAR(f));\ 5978 }\ 5979 fclose(UNIQVAR(f));\ 5980 }\ 5981 } while(0) 5982 5983 /** 5984 * write the dVector content to disk 5985 * No NULL checks are done on the parameters 5986 * 5987 * \param 5988 * file already opened file 5989 */ 5990 #define dVectorWrite(a, file) do {\ 5991 range(UNIQVAR(i), (size_t)dVectorCount(a)) {\ 5992 typeof((a)->element) *firstElement = (a)->buffers[UNIQVAR(i)/dVectorSz];\ 5993 fwrite(firstElement+(UNIQVAR(i)%dVectorSz), 1, sizeof((a)->element), file);\ 5994 }\ 5995 } while(0) 5996 5997 /** 5998 * read a dVector from filename file 5999 * No NULL checks are done on the parameters 6000 * 6001 * \param 6002 * filename file name string 6003 */ 6004 #define dVectorReadFilename(a, filename) do {\ 6005 if (fileExists(filename)) {\ 6006 size_t UNIQVAR(sz) = fileSize(filename);\ 6007 FILE *UNIQVAR(f) = fopen(filename, "r");\ 6008 if (UNIQVAR(f)) {\ 6009 range(UNIQVAR(i), UNIQVAR(sz)/sizeof((a)->element)) {\ 6010 dVectorPush(a);\ 6011 fread(dVectorLastPtr(a), 1, sizeof((a)->element), UNIQVAR(f));\ 6012 }\ 6013 fclose(UNIQVAR(f));\ 6014 }\ 6015 }\ 6016 } while(0) 6017 6018 /** 6019 * read a dVector from disk 6020 * No NULL checks are done on the parameters 6021 * 6022 * \param 6023 * file already opened file 6024 */ 6025 #define dVectorRead(a, file) do {\ 6026 fseek(file, 0 , SEEK_END);\ 6027 size_t UNIQVAR(sz) = ftell(file);\ 6028 fseek(file, 0 , SEEK_SET);\ 6029 range(UNIQVAR(i), UNIQVAR(sz)/sizeof((a)->element)) {\ 6030 dVectorPush(a);\ 6031 fread(dVectorLastPtr(a), 1, sizeof((a)->element), file);\ 6032 }\ 6033 } while(0) 6034 6035 /** 6036 * loop on dVector elements 6037 * element is a pointer to a value in the array 6038 * 6039 * dVectorForEach(&vec, e) { 6040 * e->x = 0; 6041 * } 6042 */ 6043 #define dVectorForEach(name, element) \ 6044 ;size_t UNIQVAR(libsheepyInternalIndex) = 0; \ 6045 for (dVectorElemPtrType(name) element = dVectorPtr(name, 0) ; UNIQVAR(libsheepyInternalIndex) < (name)->count ; UNIQVAR(libsheepyInternalIndex)++, element = dVectorPtr(name, UNIQVAR(libsheepyInternalIndex))) 6046 6047 /** 6048 * enumerate dVector elements 6049 * index is the position of the element in the array 6050 * index is declared as size_t and is available after the loop 6051 * element is a pointer to a value in the array 6052 * 6053 * dVectorEnumerate(&vec, i, e) { 6054 * e->x = 0; 6055 * printf("dVectorEnumerate %d\n", i); 6056 * } 6057 */ 6058 #define dVectorEnumerate(name, index, element) \ 6059 ; size_t index = 0 ; \ 6060 for (dVectorElemPtrType(name) element = dVectorPtr(name, 0) ; index < (name)->count ; index++, element = dVectorPtr(name, index)) 6061 6062 6063 6064 /* 6065 * end dynamic segmented vector 6066 */ 6067 6068 6069 /** 6070 * staticArray type definition 6071 * 6072 * this type of array has a static maximum element count (fixed) 6073 * staticArray has head and last indexes, this allows dequeuing from head elements fast 6074 * it is used as a circular buffer, queue, fifo... 6075 * a ring is a pointer to a staticArray 6076 * 6077 * no sanity checks are done 6078 * 6079 * Usage: 6080 * 6081 * to declare an array: 6082 * 6083 * typedef struct { 6084 * int a; 6085 * char *key; 6086 * } element; 6087 * 6088 * staticArrayT(typeName, element, 10); 6089 * 6090 * typeName array; 6091 * staticArrayInit(array); 6092 * 6093 * staticArrayPush(array); 6094 * staticArrayLast(array).a = fork(); 6095 * 6096 * val = staticArrayLast(array).a; 6097 * staticArrayPop(array); 6098 * 6099 * Array variables: 6100 * array.list: elements 6101 * array.maxCount: maximum element count allowed 6102 * 6103 * Note: some functions are macros to be able to have structs as element and 6104 * access the struct members directly, for example: 6105 * staticArrayLast(chan).a = 0; 6106 */ 6107 6108 // 6109 // TODO add print elements func 6110 // TODO check boundaries 6111 6112 /** 6113 * base type for all staticArrays and rings 6114 */ 6115 typedef struct { 6116 i64 last; // last element 6117 i64 head; 6118 i64 maxCount; 6119 bool isEmpty; 6120 } staticArrayBase; 6121 6122 /** 6123 * declares type for staticArray or ring 6124 * 6125 * \param 6126 * typeName staticArray/ring type name 6127 * \param 6128 * element type of elements (int, struct, pointer...) 6129 * \param 6130 * MAXCOUNT array/ring buffer size 6131 */ 6132 #define staticArrayT(typeName, element, MAXCOUNT)\ 6133 typedef struct {\ 6134 i64 last;\ 6135 i64 head;\ 6136 i64 maxCount;\ 6137 bool isEmpty;\ 6138 element list[MAXCOUNT];\ 6139 } typeName; 6140 6141 #define createStaticArray(typeName, name) ;typeName name; staticArrayInit(name) 6142 6143 /** 6144 * initialize count in array/static ring 6145 * this macro can initialize rings if the struct is accessed directly 6146 * 6147 * \param 6148 * name variable name for staticArray 6149 */ 6150 #define staticArrayInit(name)\ 6151 do{\ 6152 (name).last = (name).head = 0;\ 6153 (name).maxCount = COUNT_ELEMENTS((name).list);\ 6154 (name).isEmpty = true;\ 6155 } while(0); 6156 6157 /** 6158 * element type in array 6159 */ 6160 #define staticArrayElemType(name) typeof((name).list[0]) 6161 6162 /** 6163 * element pointer type in array 6164 */ 6165 #define staticArrayElemPtrType(name) typeof(&(name).list[0]) 6166 6167 /** 6168 * Empty Array 6169 * Allocated buffers in the list must be freed before running staticArrayEmpty 6170 */ 6171 #define staticArrayEmpty(name)\ 6172 do{\ 6173 (name).last = (name).head = 0;\ 6174 (name).isEmpty = true;\ 6175 } while(0); 6176 6177 /** 6178 * is Array Empty 6179 */ 6180 #define staticArrayIsEmpty(name) ((name).isEmpty) 6181 6182 /** 6183 * is Array Full 6184 */ 6185 #define staticArrayIsFull(name) ((name).isEmpty ? 0 : ((((name).last+1) % (name).maxCount) == (name).head)) 6186 6187 /** 6188 * return elements count 6189 */ 6190 #define staticArrayCount(name) ((name).isEmpty ? 0 : ((((name).last) >= ((name).head)) ? ((name).last-(name).head+1) : (((name).maxCount-(name).head + (name).last+1))) ) 6191 6192 /** 6193 * push element to array (only increases last) 6194 * use staticArrayLast to access the element 6195 */ 6196 #define staticArrayPush(name)\ 6197 do{\ 6198 if ((name).isEmpty) {\ 6199 (name).isEmpty = false;\ 6200 }\ 6201 else {\ 6202 (name).last++;\ 6203 (name).last %= (name).maxCount;\ 6204 }\ 6205 } while(0); 6206 6207 /** 6208 * pop element from array (only decreases last) 6209 */ 6210 #define staticArrayPop(name)\ 6211 do{\ 6212 if (!(name).isEmpty && ((name).last == (name).head)) {\ 6213 (name).isEmpty = true;\ 6214 }\ 6215 else if (!(name).isEmpty && ((name).last != (name).head)) {\ 6216 if ((name).last)\ 6217 (name).last--;\ 6218 else\ 6219 (name).last+=(name).maxCount-1;\ 6220 }\ 6221 } while(0); 6222 6223 #define staticArrayDelLast staticArrayPop 6224 6225 /** 6226 * prepend element to array (only decreases head) 6227 * use staticArrayFirst to access the element 6228 */ 6229 #define staticArrayPrepend(name)\ 6230 do{\ 6231 if ((name).isEmpty) {\ 6232 (name).isEmpty = false;\ 6233 }\ 6234 else {\ 6235 if ((name).head)\ 6236 (name).head--;\ 6237 else\ 6238 (name).head+=(name).maxCount-1;\ 6239 }\ 6240 } while(0); 6241 6242 /** 6243 * dequeue element from array (only increases head) 6244 */ 6245 #define staticArrayDequeue(name)\ 6246 do{\ 6247 if (!(name).isEmpty && ((name).last == (name).head)) {\ 6248 (name).isEmpty = true;\ 6249 }\ 6250 else if (!(name).isEmpty && ((name).last != (name).head)) {\ 6251 (name).head++;\ 6252 (name).head %= (name).maxCount;\ 6253 }\ 6254 } while(0); 6255 6256 #define staticArrayDelFirst staticArrayDequeue 6257 6258 /** 6259 * get element at index, negative index is supported 6260 */ 6261 #define staticArrayGet(name, index) (name).list[(((index) >= 0) ? (index) : staticArrayCount(name) + (index) )] 6262 #define staticArrayAt staticArrayGet 6263 6264 /** 6265 * index of element for an index relative to 0, negative index is supported 6266 */ 6267 #define staticArrayGetIndex(name, index) ((((index) >= 0) ? (index) : staticArrayCount(name) + (index) )) 6268 6269 /** 6270 * get element at index with name->head index 0, negative index is supported 6271 */ 6272 #define staticArrayRef(name, index) (name).list[((((index) >= 0) ? (index) : staticArrayCount(name) + (index) ) + name.head) % name.maxCount] 6273 6274 /** 6275 * index of element for an index relative to head, negative index is supported 6276 */ 6277 #define staticArrayRefIndex(name, index) (((((index) >= 0) ? (index) : staticArrayCount(name) + (index) ) + name.head) % name.maxCount) 6278 6279 /** 6280 * last element in array 6281 */ 6282 #define staticArrayLast(name) (name).list[(name).last] 6283 6284 /** 6285 * index of last element 6286 */ 6287 #define staticArrayLastIndex(name) (name).last 6288 6289 /** 6290 * first element in array 6291 */ 6292 #define staticArrayFirst(name) (name).list[(name).head] 6293 6294 /** 6295 * index of first element 6296 */ 6297 #define staticArrayFirstIndex(name) (name).head 6298 6299 /** 6300 * delete an element in the array and move elements after it to fill the gap 6301 */ 6302 #define staticArrayDelElem(name, index) do {\ 6303 if ((name).head < (name).last) {\ 6304 /* move elements after index in latest static array */\ 6305 if (index < (name).last) {\ 6306 memmove(&(name).list[index], &(name).list[index+1], ((name).last - index) * sizeof((name).list[0]));\ 6307 }\ 6308 }\ 6309 elif ((name).head > (name).last) {\ 6310 if (index >= (name).head) {\ 6311 /* move elements after index in latest static array */\ 6312 if (index < (name).maxCount - 1) {\ 6313 memmove(&(name).list[index], &(name).list[index+1], ((name).maxCount - index -1) * sizeof((name).list[0]));\ 6314 }\ 6315 /* move list[0] to list[maxCount-1] */\ 6316 /* then shift elements in [1..last+1] to [0..last] if needed */\ 6317 staticArrayAt((name), (name).maxCount-1) = staticArrayAt((name), 0);\ 6318 if ((name).last > 0) {\ 6319 memmove(&(name).list[0], &(name).list[1], (name).last * sizeof((name).list[0]));\ 6320 }\ 6321 }\ 6322 else {\ 6323 /* 0 < index < last+1 */\ 6324 /* move elements after index in latest static array */\ 6325 if (index < (name).last) {\ 6326 memmove(&(name).list[index], &(name).list[index+1], ((name).last - index) * sizeof((name).list[0]));\ 6327 }\ 6328 }\ 6329 }\ 6330 staticArrayDelLast((name));\ 6331 } while(0) 6332 6333 /** 6334 * write the staticArray content to filename file 6335 * No NULL checks are done on the parameters 6336 * 6337 * \param 6338 * filename file name string 6339 */ 6340 #define staticArrayWriteFilename(name, filename) do {\ 6341 FILE *UNIQVAR(f) = fopen(filename, "w");\ 6342 if (UNIQVAR(f)) {\ 6343 if ((name).head <= (name).last) {\ 6344 fwrite(&((name).list[(name).head]), 1, (size_t)staticArrayCount(name) * sizeof((name).list[0]), UNIQVAR(f));\ 6345 } else {\ 6346 /* write from head to maxcount and then from 0 to last*/\ 6347 fwrite(&((name).list[(name).head]), 1, (size_t)((name).maxCount - (name).head) * sizeof((name).list[0]), UNIQVAR(f));\ 6348 fwrite(&((name).list[(name).head])+((name).maxCount - (name).head), 1, (size_t)((name).last+1) * sizeof((name).list[0]), UNIQVAR(f));\ 6349 }\ 6350 fclose(UNIQVAR(f));\ 6351 }\ 6352 } while(0) 6353 6354 /** 6355 * write the staticArray content to disk 6356 * No NULL checks are done on the parameters 6357 * 6358 * \param 6359 * file already opened file 6360 */ 6361 #define staticArrayWrite(name, file) do {\ 6362 if ((name).head <= (name).last) {\ 6363 fwrite(&((name).list[(name).head]), 1, (size_t)staticArrayCount(name) * sizeof((name).list[0]), file);\ 6364 } else {\ 6365 /* write from head to maxcount and then from 0 to last*/\ 6366 fwrite(&((name).list[(name).head]), 1, (size_t)((name).maxCount - (name).head) * sizeof((name).list[0]), file);\ 6367 fwrite(&((name).list[(name).head])+((name).maxCount - (name).head), 1, (size_t)((name).last+1) * sizeof((name).list[0]), file);\ 6368 }\ 6369 } while(0) 6370 6371 /** 6372 * read name staticArray from filename file 6373 * No NULL checks are done on the parameters 6374 * 6375 * \param 6376 * filename file name string 6377 */ 6378 #define staticArrayReadFilename(name, filename) do {\ 6379 if (fileExists(filename)) {\ 6380 size_t UNIQVAR(sz) = fileSize(filename);\ 6381 if (UNIQVAR(sz) > sizeof((name).list)) break;\ 6382 /* check that UNIQVAR(sz) is a multiple of sizeof((name).list[0]), if not the file data doesnt fit the array */\ 6383 if (UNIQVAR(sz) % sizeof((name).list[0])) break;\ 6384 FILE *UNIQVAR(f) = fopen(filename, "r");\ 6385 if (UNIQVAR(f)) {\ 6386 fread((name).list, 1, UNIQVAR(sz), UNIQVAR(f));\ 6387 fclose(UNIQVAR(f));\ 6388 (name).head = 0;\ 6389 if (UNIQVAR(sz)) {\ 6390 (name).last = (UNIQVAR(sz) / sizeof((name).list[0])) - 1;\ 6391 (name).isEmpty = false;\ 6392 }\ 6393 else {\ 6394 (name).last = 0;\ 6395 (name).isEmpty = true;\ 6396 }\ 6397 }\ 6398 }\ 6399 } while(0) 6400 6401 /** 6402 * read name staticArray from disk 6403 * No NULL checks are done on the parameters 6404 * 6405 * \param 6406 * file already opened file 6407 */ 6408 #define staticArrayRead(name, file) do {\ 6409 fseek(file, 0 , SEEK_END);\ 6410 size_t UNIQVAR(sz) = ftell(file);\ 6411 fseek(file, 0 , SEEK_SET);\ 6412 if (UNIQVAR(sz) > sizeof((name).list)) break;\ 6413 /* check that UNIQVAR(sz) is a multiple of sizeof((name).list[0]), if not the file data doesnt fit the array */\ 6414 if (UNIQVAR(sz) % sizeof((name).list[0])) break;\ 6415 fread((name).list, 1, UNIQVAR(sz), file);\ 6416 (name).head = 0;\ 6417 if (UNIQVAR(sz)) {\ 6418 (name).last = (UNIQVAR(sz) / sizeof((name).list[0])) - 1;\ 6419 (name).isEmpty = false;\ 6420 }\ 6421 else {\ 6422 (name).last = 0;\ 6423 (name).isEmpty = true;\ 6424 }\ 6425 } while(0) 6426 6427 /** 6428 * loop on staticArray elements 6429 * element is a pointer to a value in the array 6430 * 6431 * staticArrayForEach(sa, e) { 6432 * e->x = 0; 6433 * } 6434 */ 6435 #define staticArrayForEach(name, element) \ 6436 ;size_t UNIQVAR(libsheepyInternalIndex) = 0; \ 6437 for (staticArrayElemPtrType(name) element = &staticArrayRef(name, 0) ; UNIQVAR(libsheepyInternalIndex) < staticArrayCount(name) ; UNIQVAR(libsheepyInternalIndex)++, element = &staticArrayRef(name, UNIQVAR(libsheepyInternalIndex))) 6438 6439 /** 6440 * enumerate staticArray elements 6441 * index is the position of the element in the array 6442 * index is declared as size_t and is available after the loop 6443 * element is a pointer to a value in the array 6444 * 6445 * staticArrayEnumerate(sa, i, e) { 6446 * e->x = 0; 6447 * printf("staticArrayEnumerate %d\n", i); 6448 * } 6449 */ 6450 #define staticArrayEnumerate(name, index, element) \ 6451 ;size_t UNIQVAR(libsheepyInternalIndex) = 0; \ 6452 ; size_t index = name.head ; \ 6453 for (staticArrayElemPtrType(name) element = &staticArrayRef(name, 0) ; UNIQVAR(libsheepyInternalIndex) < staticArrayCount(name) ; UNIQVAR(libsheepyInternalIndex)++, index = (name.head + UNIQVAR(libsheepyInternalIndex)) % name.maxCount, element = &staticArrayRef(name, index)) 6454 6455 /** 6456 * indexer is a staticArray without the list 6457 * It indexes an independent array 6458 * 6459 * Usage: 6460 * 6461 * declare an array: 6462 * char array[10][5]; 6463 * 6464 * declare an indexer: 6465 * indexer indx; 6466 * 6467 * or declare an indexer with smaller counters (default is int64_t): 6468 * indexerT(typeName, i8); 6469 * typeName indx; 6470 * 6471 * indexerInit(indx, 10); 6472 * 6473 * indexerPush(indx); 6474 * array[indexerLast(indx)][0] = '0'; 6475 * 6476 * // or 6477 * indexerPush(indx); 6478 * array[indx.last][0] = '0'; 6479 * 6480 * indexerPop(indx); 6481 * 6482 * // accessing the first/head element 6483 * 6484 * char c = array[indexerFirst(indx)][0]; 6485 * char c = array[indx.head][0]; 6486 * 6487 * 6488 * For pointer to indexers (idxP), use: 6489 * indexerPInit, 6490 * indexerPEmpty, 6491 * indexerPIsEmpty, 6492 * indexerPIsFull, 6493 * indexerPCount, 6494 * indexerPPush, 6495 * indexerPPop, 6496 * indexerPPrepend, 6497 * indexerPDequeue, 6498 * indexerPRef, 6499 * indexerPLast or idxP->last, 6500 * indexerPFirst or idxP->head 6501 * 6502 */ 6503 6504 /** 6505 * base type, same as staticArray 6506 */ 6507 #define indexer staticArrayBase 6508 6509 /** 6510 * declare an indexer type with INT_TYPE counters instead of the default i64 6511 * INT_TYPE has to be signed integer 6512 * 6513 * The indexers of this type are not compatible with the indexerP* functions 6514 */ 6515 #define indexerT(typeName, INT_TYPE)\ 6516 typedef struct {\ 6517 INT_TYPE last;\ 6518 INT_TYPE head;\ 6519 INT_TYPE maxCount;\ 6520 bool isEmpty;\ 6521 } typeName; 6522 6523 #define createIndexer(typeName, name, maxCount) ;typeName name; indexerInit(name, maxCount) 6524 6525 /** 6526 * initialize count in array/static ring 6527 * this macro can initialize rings if the struct is accessed directly 6528 * 6529 * \param 6530 * name variable name for staticArray 6531 * \param 6532 * MAXCOUNT max count for name type 6533 */ 6534 #define indexerInit(name, MAXCOUNT)\ 6535 do{\ 6536 (name).last = (name).head = 0;\ 6537 (name).maxCount = MAXCOUNT;\ 6538 (name).isEmpty = true;\ 6539 } while(0); 6540 6541 #define indexerPInit ringInit 6542 6543 /** 6544 * Empty Array 6545 * Allocated buffers in the list must be freed before running staticArrayEmpty 6546 */ 6547 #define indexerEmpty staticArrayEmpty 6548 #define indexerPEmpty ringEmpty 6549 6550 /** 6551 * is Array Empty 6552 */ 6553 #define indexerIsEmpty staticArrayIsEmpty 6554 #define indexerPIsEmpty ringIsEmpty 6555 6556 /** 6557 * is Array Full 6558 */ 6559 #define indexerIsFull staticArrayIsFull 6560 #define indexerPIsFull ringIsFull 6561 6562 /** 6563 * return elements count 6564 */ 6565 #define indexerCount staticArrayCount 6566 #define indexerPCount ringCount 6567 6568 /** 6569 * push element to array (only increases last) 6570 * use staticArrayLast to access the element 6571 */ 6572 #define indexerPush staticArrayPush 6573 #define indexerPPush ringPush 6574 6575 /** 6576 * pop element from array (only decreases last) 6577 */ 6578 #define indexerPop staticArrayPop 6579 #define indexerPPop ringPop 6580 6581 /** 6582 * prepend element to array (only decreases head) 6583 * use staticArrayFirst to access the element 6584 */ 6585 #define indexerPrepend staticArrayPrepend 6586 #define indexerPPrepend ringPrepend 6587 6588 /** 6589 * dequeue element from array (only increases head) 6590 */ 6591 #define indexerDequeue staticArrayDequeue 6592 #define indexerPDequeue ringDequeue 6593 6594 /** 6595 * index element at index with name->head index 0, negative index is supported 6596 */ 6597 #define indexerRef(name, index) (((((index) >= 0) ? (index) : indexerCount(name) + (index) ) + name.head) % name.maxCount) 6598 #define indexerPRef(name, index) (((((index) >= 0) ? (index) : indexerPCount(name) + (index) ) + name->head) % name->maxCount) 6599 6600 /** 6601 * index of last element in array 6602 */ 6603 #define indexerLast(name) name.last 6604 #define indexerPLast(name) (name)->last 6605 6606 /** 6607 * index of first element in array 6608 */ 6609 #define indexerFirst(name) (name.head) 6610 #define indexerPFirst(name) (name)->head 6611 6612 6613 /** 6614 * rings usage 6615 * 6616 * Make the ring type: 6617 * 6618 * #define chanMax 30 // max message count in ring type chanT 6619 * ringMake(chanT, int, chanMax); // ring type is chanT, list 30 of ints 6620 * 6621 * Add ring to a fiber context: 6622 * 6623 * typedef struct {int slot; int a; chanT *c;} AArgs; 6624 * 6625 * Declare a ring of type chanT and initialize: 6626 * 6627 * chanT c; 6628 * ringInit(&c, chanMax); 6629 * 6630 * When the ring is empty, ringLast and ringFirst are valid and equal (same index). 6631 * 6632 * Send and receive data through the ring: 6633 * 6634 * ringSend(ctx->c, 10); 6635 * int r; 6636 * if (!ringIsEmpty(ctx->c)) 6637 * ringRecv(ctx->c, r); 6638 * 6639 * Note: some functions are macros to be able to have structs as element and 6640 * access the struct members directly, for example: 6641 * ringLast(chan).a = 0; 6642 * 6643 */ 6644 /** 6645 * base type, same as staticArray 6646 */ 6647 #define ringBase staticArrayBase 6648 6649 /** 6650 * declares type for staticArray or ring 6651 * staticArrayT(typeName, element, MAXCOUNT) 6652 * 6653 * \param 6654 * typeName staticArray/ring type name 6655 * \param 6656 * element type of elements (int, struct, pointer...) 6657 * \pointer 6658 * MAXCOUNT array/ring buffer size 6659 */ 6660 #define ringMake staticArrayT 6661 6662 /** 6663 * initialize count in array/static ring 6664 * staticArrayInit(name, MAXCOUNT) 6665 * 6666 * this macro can initialize rings if the struct is accessed directly 6667 * 6668 * \param 6669 * name variable name for ring 6670 */ 6671 #define ringStaticInit staticArrayInit 6672 6673 // initialize ring/pointer to staticArray 6674 int ringInit(void *ring, int maxCount); 6675 6676 // empty ring 6677 int ringEmpty(void *ring); 6678 6679 // is ring Empty 6680 int ringIsEmpty(void *ring); 6681 6682 // is ring Full 6683 int ringIsFull(void *ring); 6684 6685 // return elements count 6686 ssize_t ringCount(void *ring); 6687 6688 6689 // push element to ring (only increases last, use ringSend), use ringLast to access the element 6690 i64 ringPush(void *ring); 6691 6692 6693 // pop element from ring (only decreases last) 6694 int ringPop(void *ring); 6695 6696 6697 // prepend element to ring (only decreases head), use ringFirst to access the element 6698 i64 ringPrepend(void *ring); 6699 6700 // dequeue element from ring (only increases head, use ringRecv) 6701 int ringDequeue(void *ring); 6702 6703 /** 6704 * get element at index, negative index is supported 6705 */ 6706 #define ringGet(name, index) (name)->list[(((index) >= 0) ? (index) : ringCount(name) + (index) )] 6707 6708 /** 6709 * get element at index with name->head index 0, negative index is supported 6710 */ 6711 #define ringRef(name, index) (name)->list[((((index) >= 0) ? (index) : ringCount(name) + (index) ) + name->head) % name->maxCount] 6712 6713 /** 6714 * last element in ring 6715 */ 6716 #define ringLast(name) (name)->list[(name)->last] 6717 6718 /** 6719 * index of last element 6720 */ 6721 #define ringLastIndex(name) (name)->last 6722 6723 /** 6724 * last element in ring 6725 */ 6726 #define ringFirst(name) (name)->list[(name)->head] 6727 6728 6729 /** 6730 * send data in ring 6731 * 6732 * \param 6733 * name variable name for ring 6734 * \param 6735 * value data 6736 */ 6737 #define ringSend(name, value)\ 6738 do {\ 6739 if (ringPush(name) >= 0) ringLast(name) = value;\ 6740 } while(0); 6741 6742 // send data and get ring status 6743 #define ringSendSt(status, name, value)\ 6744 do {\ 6745 if ((status = ringPush(name)) >= 0) ringLast(name) = value;\ 6746 } while(0); 6747 6748 6749 /** 6750 * receive data from ring 6751 * 6752 * \param 6753 * name variable name for ring 6754 * \param 6755 * result previously declared variable to store the data 6756 */ 6757 #define ringRecv(name, result)\ 6758 do {\ 6759 result = ringFirst(name);\ 6760 ringDequeue(name);\ 6761 } while(0); 6762 6763 // receive data and get ring status 6764 #define ringRecvSt(status, name, result)\ 6765 do {\ 6766 if ((status = ringIsEmpty(name)) == 0) {\ 6767 result = ringFirst(name);\ 6768 ringDequeue(name);\ 6769 }\ 6770 } while(0); 6771 6772 /** 6773 * fiber usage 6774 * 6775 * The stack is not restored, so all local variables should 6776 * be stored in the context struct. 6777 * 6778 * Declare a context type for the fiber: 6779 * 6780 * typedef struct {int slot; int a; chanT *c;} AArgs; 6781 * 6782 * the context type must start with int slot; 6783 * in this example, the fiber has a ring c of type chanT 6784 * 6785 * Declare a function of type: 6786 * 6787 * void fiberA(int thisSlot) { 6788 * static AArgs *ctx; 6789 * int slot; 6790 * ctx = fiberCtx(thisSlot); 6791 * ... 6792 * } 6793 * 6794 * several fibers can have the function fiberA with different slots 6795 * 6796 * To yield, add: 6797 * 6798 * yield(slot, ctx->slot); // switch to scheduler 6799 * ctx = fiberCtx(slot); // restore the context for this fiber 6800 * 6801 * The next steps show how to start the fibers 6802 * 6803 * Declare a variable for the context and create the ring chanT: 6804 * 6805 * AArgs Aa; 6806 * chanT c; 6807 * ringInit(&c, chanMax); 6808 * 6809 * Initialize the fiber: 6810 * 6811 * Aa.a = 0; 6812 * Aa.c = &c; 6813 * fiberAdd(&Aa, 1, fiberA); 6814 * 6815 * this can also be done from a running fiber 6816 * 6817 * Finally, start the scheduler: 6818 * 6819 * scheduler(); 6820 * 6821 */ 6822 6823 // schedule fibers 6824 void scheduler(void); 6825 6826 // the scheduler takes slot 0 6827 // the system can handle tCount-1 fibers 6828 #define tCount 10 6829 6830 /** 6831 * all contexts must start with fiberBaseT 6832 * 6833 * Example: 6834 * typedef struct {int slot; int a;} AArgs; 6835 */ 6836 typedef struct {int slot;} fiberBaseT; 6837 6838 /** 6839 * staticArray to hold the fiber slots 6840 */ 6841 staticArrayT(fiberLT, int, tCount); 6842 6843 /** 6844 * data type for fiber system 6845 */ 6846 typedef struct { 6847 /** 6848 * setjmp buffers for fibers 6849 */ 6850 jmp_buf jumpBuffers[tCount]; 6851 /** 6852 * running fibers 6853 */ 6854 fiberLT L; 6855 /** 6856 * fibers to start 6857 */ 6858 fiberLT startL; 6859 /** 6860 * fiber context data 6861 */ 6862 void *context[tCount]; 6863 /** 6864 * fiber functions 6865 */ 6866 void (*F[tCount])(int thisSlot); 6867 } fibersT; 6868 6869 /** 6870 * data for fiber system 6871 */ 6872 extern fibersT fibers; 6873 6874 /** 6875 * get fiber context for thisSlot 6876 */ 6877 #define fiberCtx(thisSlot) fibers.context[thisSlot] 6878 6879 /** 6880 * fiber function type 6881 */ 6882 typedef void (*fiberFT)(int); 6883 6884 /** 6885 * add new fiber 6886 */ 6887 bool fiberAdd(void *ctx, int thisSlot, fiberFT func); 6888 6889 /** 6890 * add new fiber and start immediately after next yield 6891 */ 6892 bool fiberPrepend(void *ctx, int thisSlot, fiberFT func); 6893 6894 /** 6895 * fibers with setjmp (not ucontext) 6896 * internal 6897 * 6898 * startJump starts another fiber 6899 * slot is the index in fiberJumpBuffers for current fiber 6900 * func is the fiber to start 6901 * 6902 * the first fiber has to finish last 6903 */ 6904 #define startJump(func)\ 6905 if (!setjmp(fibers.jumpBuffers[0])) {\ 6906 func;\ 6907 } 6908 6909 #if !__sun__ 6910 /** 6911 * yield jumps back to other fiber 6912 * slot should be a local variable in the fiber 6913 * slot is set to the index in fiberJumpBuffers for current fiber 6914 * backToSlot is the index in fiberJumpBuffers for the other fiber 6915 */ 6916 #define yield(slotValue, slot)\ 6917 if (!(slotValue = setjmp(fibers.jumpBuffers[slot]))) {\ 6918 staticArrayPush(fibers.L);\ 6919 staticArrayLast(fibers.L) = slot;\ 6920 longjmp(fibers.jumpBuffers[0], 1);\ 6921 } 6922 #endif 6923 6924 /** 6925 * return to scheduler and end the fiber 6926 */ 6927 #define fiberEnd(slot)\ 6928 if (!setjmp(fibers.jumpBuffers[slot])) {\ 6929 longjmp(fibers.jumpBuffers[0], 1);\ 6930 } 6931 6932 // internal for scheduler 6933 #define schedulerYield(backToSlot)\ 6934 if (!setjmp(fibers.jumpBuffers[0])) {\ 6935 longjmp(fibers.jumpBuffers[backToSlot], backToSlot);\ 6936 } 6937 6938 6939 6940 /** 6941 * dynamic segmented array 6942 * 6943 * this type of array is faster than slab when there are many elements and has a dynamic element count 6944 * pushing elements into the array increases the element count 6945 * the data is stored in static array segments 6946 * dArray has head and last indexes, this allows dequeuing from head elements fast 6947 * 6948 * no sanity checks are done 6949 * 6950 * usage examples: regular array, stack, lifo, fifo 6951 * 6952 * the prefix is dArray 6953 * 6954 * Usage: 6955 * 6956 * to declare an array: 6957 * 6958 * dArrayT(typeName, type); 6959 * 6960 * typeName darray; 6961 * 6962 * dArrayInit(&darray); 6963 * or 6964 * dArrayInitCount(&darray, 17); 6965 * 6966 * dArrayAppend(&darray, value); 6967 * 6968 * // get an element 6969 * int a = dArrayAt(&darray, 0); 6970 * 6971 * set 6972 * dArrayAt(&darray, 1) = 3; 6973 * 6974 * dArrayFree(&darray); 6975 * 6976 * dArray variables: 6977 * darray.maxCount: maximum element count allowed 6978 * 6979 * Note: dont combine the macros, it gives wrong results: 6980 * a = dArrayAt(&darray, dArrayPop(&darray2)); 6981 * dArrayPop is run several time, more than one element is popped 6982 * 6983 * Note: some functions are macros to be able to have structs as element and 6984 * access the struct members directly, for example: 6985 * dArrayLast(chan).a = 0; 6986 */ 6987 6988 // user parameters 6989 /** 6990 * chunk size: 2^dArrayBits elements 6991 */ 6992 #define dArrayBits 6 6993 // user parameters end 6994 6995 #define dArraySz (1<<dArrayBits) 6996 #define dArrayMask (dArraySz-1) 6997 6998 /** 6999 * declares type for dynamic array 7000 * 7001 * \param 7002 * typeName dArray type name 7003 * \param 7004 * element type of elements (int, struct, pointer...) 7005 */ 7006 #define dArrayT(typeName, elementType)\ 7007 typedef struct {\ 7008 int64_t last;\ 7009 int64_t head;\ 7010 int64_t maxCount;\ 7011 void** buffers;\ 7012 elementType element;\ 7013 } typeName 7014 7015 7016 #define createDArray(typeName, name) ;typeName name; dArrayInit(&name) 7017 7018 #define createDArrayCount(typeName, name, count) ;typeName name; dArrayInitCount(&name, count) 7019 7020 /** 7021 * initialize dynamic array with minimum element count 7022 * 7023 * \param 7024 * a variable name for dArray 7025 */ 7026 #define dArrayInit(a) do{\ 7027 (a)->last = (a)->head = 0;\ 7028 (a)->buffers = malloc(sizeof(void*));\ 7029 (a)->buffers[0] = malloc(dArraySz * sizeof((a)->element));\ 7030 (a)->maxCount = 1;\ 7031 }while(0) 7032 7033 /** 7034 * initialize dynamic array and count 7035 * 7036 * \param 7037 * a variable name for dArray 7038 * \param 7039 * count initial element count for name type 7040 */ 7041 #define dArrayInitCount(a, count) do{\ 7042 dArrayInit(a);\ 7043 if ((count) > dArraySz) {\ 7044 (a)->buffers = realloc((a)->buffers, (((count)>>dArrayBits)+1) * sizeof(void*));\ 7045 rangeFrom(UNIQVAR(i), 1, ((count)>>dArrayBits)+1) {\ 7046 (a)->buffers[UNIQVAR(i)] = malloc(dArraySz * sizeof((a)->element));\ 7047 }\ 7048 (a)->maxCount = ((count)>>dArrayBits)+1;\ 7049 }\ 7050 }while(0) 7051 7052 #define dArrayResize(a, count) do{\ 7053 if ((count) > (a)->maxCount * dArraySz) {\ 7054 /* grow array */\ 7055 (a)->buffers = realloc((a)->buffers, (((count)>>dArrayBits)+1) * sizeof(void*));\ 7056 rangeFrom(UNIQVAR(i), (a)->maxCount, ((count)>>dArrayBits)+1) {\ 7057 (a)->buffers[UNIQVAR(i)] = malloc(dArraySz * sizeof((a)->element));\ 7058 }\ 7059 (a)->maxCount = ((count)>>dArrayBits)+1;\ 7060 }\ 7061 /*else TODO dArray shrink */\ 7062 }while(0) 7063 7064 /** 7065 * free the internal buffers 7066 * 7067 * \param 7068 * a dynamic array 7069 */ 7070 #define dArrayFree dVectorFree 7071 7072 /** 7073 * element type in array 7074 */ 7075 #define dArrayElemType(a) typeof((a)->element) 7076 7077 /** 7078 * element pointer type in array 7079 */ 7080 #define dArrayElemPtrType(a) typeof(&(a)->element) 7081 7082 /** 7083 * Empty Array 7084 * Allocated buffers in the array must be freed before running dArrayEmpty 7085 */ 7086 #define dArrayEmpty(name) do{\ 7087 (name)->last = (name)->head = 0;\ 7088 } while(0); 7089 7090 /** 7091 * is Array Empty 7092 */ 7093 #define dArrayIsEmpty(name) ((name)->head == (name)->last) 7094 7095 /** 7096 * return element count 7097 */ 7098 #define dArrayCount(name) ((name)->last - (name)->head) 7099 7100 /** 7101 * return max element count 7102 */ 7103 #define dArrayMaxCount(name) ((name)->maxCount * dArraySz) 7104 7105 /** 7106 * allocate buffer for new elements 7107 * only when the array is full 7108 * 7109 * \param 7110 * a dynamic array 7111 */ 7112 #define dArrayAlloc(a) do{\ 7113 if ((a)->last == dArrayMaxCount(a)) {\ 7114 (a)->maxCount++;\ 7115 (a)->buffers = realloc((a)->buffers, (size_t)(a)->maxCount * sizeof(void*));\ 7116 (a)->buffers[(a)->maxCount-1] = malloc(dArraySz * sizeof((a)->element));\ 7117 }\ 7118 }while(0) 7119 7120 /** 7121 * push element and expand the dynamic array 7122 * no data (random) is set in the new element. 7123 * 7124 * \param 7125 * a dynamic array 7126 * \param 7127 * v element to push 7128 */ 7129 #define dArrayPush(a) do{\ 7130 dArrayAlloc(a);\ 7131 (a)->last++;\ 7132 }while(0) 7133 7134 /** 7135 * append element and expand the dynamic array 7136 * 7137 * \param 7138 * a dynamic array 7139 * \param 7140 * v element to push 7141 */ 7142 #define dArrayAppend(a, v) do{\ 7143 dArrayAlloc(a);\ 7144 if ((a)->last < dArrayMaxCount(a)) {\ 7145 typeof((a)->element) *UNIQVAR(buffer) = (a)->buffers[((a)->last)>>dArrayBits];\ 7146 *(UNIQVAR(buffer)+ (((a)->last)&dArrayMask)) = v;\ 7147 (a)->last++;\ 7148 }\ 7149 }while(0) 7150 7151 /** 7152 * pop element 7153 * the index of the last element is decreased 7154 * 7155 * NOTE: using comma operator to avoid warning 7156 * warning: operation on ‘b.head’ may be undefined [-Wsequence-point] 7157 * 7158 * 7159 * \param 7160 * a dynamic array 7161 */ 7162 #define dArrayPop(a) ((a)->last--, *((typeof((a)->element)*)((a)->buffers[((a)->last)>>dArrayBits])+(((a)->last)&dArrayMask))) 7163 7164 /** 7165 * delete the last element 7166 * useful for avoiding warning: right-hand operand of comma expression has no effect 7167 * when the poped value is not used 7168 */ 7169 #define dArrayDelLast(a) ((a)->last--) 7170 7171 /** 7172 * prepend element 7173 * 7174 * \param 7175 * a dynamic array 7176 * \param 7177 * v element to prepend 7178 */ 7179 #define dArrayPrepend(a, v) do{\ 7180 if ((a)->head > 0) {\ 7181 (a)->head--;\ 7182 typeof((a)->element) *UNIQVAR(buffer) = (a)->buffers[((a)->head)>>dArrayBits];\ 7183 *(UNIQVAR(buffer)+ (((a)->head)&dArrayMask)) = v;\ 7184 }\ 7185 }while(0) 7186 7187 /** 7188 * dequeue element 7189 * the index of the head element is increased 7190 * 7191 * NOTE: using comma operator to avoid warning 7192 * warning: operation on ‘b.head’ may be undefined [-Wsequence-point] 7193 * 7194 * 7195 * \param 7196 * a dynamic array 7197 */ 7198 #define dArrayDequeue(a) ((a)->head++, *((typeof((a)->element)*)((a)->buffers[((a)->head-1)>>dArrayBits])+(((a)->head-1)&dArrayMask))) 7199 7200 /** 7201 * delete the first element 7202 * useful for avoiding warning: right-hand operand of comma expression has no effect 7203 * when the dequeued value is not used 7204 */ 7205 #define dArrayDelFirst(a) ((a)->head++) 7206 7207 /** 7208 * get / set element at index 7209 * 7210 * \param 7211 * a dynamic array 7212 * \param 7213 * index index in array 7214 */ 7215 #define dArrayAt(a, index) (*((typeof((a)->element)*)((a)->buffers[(index)>>dArrayBits])+((index)&dArrayMask))) 7216 7217 /** 7218 * get pointer to element at index 7219 * 7220 * \param 7221 * a dynamic array 7222 * \param 7223 * index index in array 7224 */ 7225 #define dArrayPtr(a, index) ((typeof((a)->element)*)((a)->buffers[(index)>>dArrayBits])+((index)&dArrayMask)) 7226 7227 /** 7228 * set at index and resize dArray when index is greater then maxCount 7229 */ 7230 #define dArraySet(a, index, v) do{\ 7231 var UNIQVAR(idx) = index;\ 7232 if (UNIQVAR(idx) < (a)->last) {\ 7233 /* index is inside current array */\ 7234 dArrayAt(a, UNIQVAR(idx)) = v;\ 7235 if (UNIQVAR(idx) < (a)->head) {\ 7236 /* update head since index is lower */\ 7237 (a)->head = UNIQVAR(idx);\ 7238 }\ 7239 }\ 7240 else {\ 7241 /* index is after last element */\ 7242 /* check if index is under maxCount */\ 7243 if (UNIQVAR(idx) >= dArrayMaxCount(a)) {\ 7244 /* resize array */\ 7245 dArrayResize(a, UNIQVAR(idx)+1);\ 7246 }\ 7247 dArrayAt(a, UNIQVAR(idx)) = v;\ 7248 /* update last since index is higher*/\ 7249 (a)->last = UNIQVAR(idx)+1;\ 7250 }\ 7251 }while(0) 7252 7253 /** 7254 * sparse set at index and resize dArray when index is greater then maxCount 7255 * dArraySparseSet allows using dArray as a sparse array 7256 * 7257 * head and last are not updated because there are empty regions in the sparse array 7258 * 7259 * the empty segments are marked with NULL in the a->buffers array 7260 * 7261 * after using dArraySparseSet only these macros are valid: 7262 * dArrayResize, dArrayElemType, dArrayElemPtrType, dArrayMaxCount, dArrayAt, dArrayPtr, dArrayFree 7263 */ 7264 #define dArraySparseSet(a, index, v) do{\ 7265 var UNIQVAR(idx) = index;\ 7266 var UNIQVAR(bIdx) = UNIQVAR(idx)>>dArrayBits;\ 7267 if (UNIQVAR(idx) >= dArrayMaxCount(a)) {\ 7268 /* sparse resize array - grow array */\ 7269 (a)->buffers = realloc((a)->buffers, (((UNIQVAR(bIdx)+1)>>dArrayBits)+1) * sizeof(void*));\ 7270 /* empty segments are marked with NULL */\ 7271 memset(&(a)->buffers[(a)->maxCount], 0, (UNIQVAR(bIdx)+1) - (a)->maxCount);\ 7272 (a)->maxCount = UNIQVAR(bIdx)+1;\ 7273 /* allocate new segment */\ 7274 (a)->buffers[UNIQVAR(bIdx)] = malloc(dArraySz * sizeof((a)->element));\ 7275 dArrayAt(a, UNIQVAR(idx)) = v;\ 7276 }\ 7277 else {\ 7278 /* check if the segment is already allocated */\ 7279 if (!(a)->buffers[UNIQVAR(bIdx)]) {\ 7280 /* allocate new segment */\ 7281 (a)->buffers[UNIQVAR(bIdx)] = malloc(dArraySz * sizeof((a)->element));\ 7282 }\ 7283 dArrayAt(a, UNIQVAR(idx)) = v;\ 7284 }\ 7285 }while(0) 7286 7287 /** 7288 * last element 7289 * 7290 * \param 7291 * a dynamic array 7292 */ 7293 #define dArrayLast(a) (*((typeof((a)->element)*)((a)->buffers[((a)->last-1)>>dArrayBits])+(((a)->last-1)&dArrayMask))) 7294 7295 /** 7296 * pointer to last element 7297 * 7298 * \param 7299 * a dynamic array 7300 */ 7301 #define dArrayLastPtr(a) ((typeof((a)->element)*)((a)->buffers[((a)->last-1)>>dArrayBits])+(((a)->last-1)&dArrayMask)) 7302 7303 /** 7304 * index of last element 7305 */ 7306 #define dArrayLastIndex(a) ((a)->last-1) 7307 7308 /** 7309 * direct access to the last element index variable for assignments 7310 */ 7311 #define dArrayLastIndexVar(a) ((a)->last) 7312 7313 /** 7314 * first element 7315 * 7316 * \param 7317 * a dynamic array 7318 */ 7319 #define dArrayFirst(a) (*((typeof((a)->element)*)((a)->buffers[((a)->head)>>dArrayBits])+((a)->head)&dArrayMask)) 7320 7321 /** 7322 * index of first element 7323 */ 7324 #define dArrayFirstIndex(a) ((a)->head) 7325 7326 /** 7327 * write the dArray content to filename file 7328 * No NULL checks are done on the parameters 7329 * 7330 * \param 7331 * filename file name string 7332 */ 7333 #define dArrayWriteFilename(a, filename) do {\ 7334 FILE *UNIQVAR(f) = fopen(filename, "w");\ 7335 if (UNIQVAR(f)) {\ 7336 range(UNIQVAR(i), (size_t)dArrayCount(a)) {\ 7337 typeof((a)->element) *firstElement = (a)->buffers[UNIQVAR(i)/dArraySz];\ 7338 fwrite(firstElement+(UNIQVAR(i)%dArraySz), 1, sizeof((a)->element), UNIQVAR(f));\ 7339 }\ 7340 fclose(UNIQVAR(f));\ 7341 }\ 7342 } while(0) 7343 7344 /** 7345 * write the dArray content to disk 7346 * No NULL checks are done on the parameters 7347 * 7348 * \param 7349 * file already opened file 7350 */ 7351 #define dArrayWrite(a, file) do {\ 7352 range(UNIQVAR(i), (size_t)dArrayCount(a)) {\ 7353 typeof((a)->element) *firstElement = (a)->buffers[UNIQVAR(i)/dArraySz];\ 7354 fwrite(firstElement+(UNIQVAR(i)%dArraySz), 1, sizeof((a)->element), file);\ 7355 }\ 7356 } while(0) 7357 7358 /** 7359 * read a dArray from filename file 7360 * No NULL checks are done on the parameters 7361 * 7362 * \param 7363 * filename file name string 7364 */ 7365 #define dArrayReadFilename(a, filename) do {\ 7366 if (fileExists(filename)) {\ 7367 size_t UNIQVAR(sz) = fileSize(filename);\ 7368 FILE *UNIQVAR(f) = fopen(filename, "r");\ 7369 if (UNIQVAR(f)) {\ 7370 range(UNIQVAR(i), UNIQVAR(sz)/sizeof((a)->element)) {\ 7371 dArrayPush(a);\ 7372 fread(dArrayLastPtr(a), 1, sizeof((a)->element), UNIQVAR(f));\ 7373 }\ 7374 fclose(UNIQVAR(f));\ 7375 }\ 7376 }\ 7377 } while(0) 7378 7379 /** 7380 * read a dArray from disk 7381 * No NULL checks are done on the parameters 7382 * 7383 * \param 7384 * file already opened file 7385 */ 7386 #define dArrayRead(a, file) do {\ 7387 fseek(file, 0 , SEEK_END);\ 7388 size_t UNIQVAR(sz) = ftell(file);\ 7389 fseek(file, 0 , SEEK_SET);\ 7390 range(UNIQVAR(i), UNIQVAR(sz)/sizeof((a)->element)) {\ 7391 dArrayPush(a);\ 7392 fread(dArrayLastPtr(a), 1, sizeof((a)->element), file);\ 7393 }\ 7394 } while(0) 7395 7396 /** 7397 * loop on dArray elements 7398 * element is a pointer to a value in the array 7399 * 7400 * dArrayForEach(&a, e) { 7401 * e->x = 0; 7402 * } 7403 */ 7404 #define dArrayForEach(name, element) \ 7405 ;size_t UNIQVAR(libsheepyInternalIndex) = (name)->head; \ 7406 for (dArrayElemPtrType(name) element = dArrayPtr(name, (name)->head) ; UNIQVAR(libsheepyInternalIndex) < (name)->last + 1 ; UNIQVAR(libsheepyInternalIndex)++, element = dArrayPtr(name, UNIQVAR(libsheepyInternalIndex))) 7407 7408 /** 7409 * enumerate dArray elements 7410 * index is the position of the element in the array 7411 * index is declared as size_t and is available after the loop 7412 * element is a pointer to a value in the array 7413 * 7414 * dArrayEnumerate(&a, i, e) { 7415 * e->x = 0; 7416 * printf("dArrayEnumerate %d\n", i); 7417 * } 7418 */ 7419 #define dArrayEnumerate(name, index, element) \ 7420 ; size_t index = (name)->head; \ 7421 for (dArrayElemPtrType(name) element = dArrayPtr(name, (name)->head) ; index < (name)->last + 1 ; index++, element = dArrayPtr(name, index)) 7422 7423 7424 7425 /* 7426 * end dynamic array 7427 */ 7428 7429 7430 /** 7431 * slab - dynamic array in one chunk of memory 7432 * 7433 * slab supports shrinking through slabResize, the slab is reset when head or last are outside the new size 7434 * slab has head and last indexes, this allows dequeuing from head elements fast 7435 * 7436 * this type of array has a dynamic element count 7437 * pushing elements into the array increases the element count 7438 * 7439 * no sanity checks are done 7440 * 7441 * usage examples: regular array, stack, lifo, fifo 7442 * 7443 * the prefix is slab 7444 * 7445 * Usage: 7446 * 7447 * to declare an array: 7448 * 7449 * slabT(typeName, type); 7450 * 7451 * typeName slab; 7452 * 7453 * slabInit(&slab); 7454 * or 7455 * slabInitCount(&slab, 17); 7456 * 7457 * slabAppend(&slab, value); 7458 * 7459 * // get an element 7460 * int a = slabAt(&slab, 0); 7461 * 7462 * set 7463 * slabAt(&slab, 1) = 3; 7464 * 7465 * slabFree(&slab); 7466 * 7467 * Slab variables: 7468 * slab.array: elements 7469 * slab.maxCount: maximum element count allowed 7470 * 7471 * Note: some functions are macros to be able to have structs as element and 7472 * access the struct members directly, for example: 7473 * slabLast(chan).a = 0; 7474 */ 7475 7476 /** number of elements added by slabAlloc */ 7477 #define slabSz 64 7478 7479 /** 7480 * declares type for dynamic array 7481 * 7482 * \param 7483 * typeName slab type name 7484 * \param 7485 * element type of elements (int, struct, pointer...) 7486 */ 7487 #define slabT(typeName, elementType)\ 7488 typedef struct {\ 7489 int64_t last;\ 7490 int64_t head;\ 7491 int64_t maxCount;\ 7492 elementType *array;\ 7493 } typeName 7494 7495 7496 #define createSlab(typeName, name) ;typeName name; slabInit(&name) 7497 7498 #define createSlabCount(typeName, name, count) ;typeName name; slabInitCount(&name, count) 7499 7500 /** 7501 * initialize dynamic array with minimum element count 7502 * 7503 * \param 7504 * a variable name for slab 7505 */ 7506 #define slabInit(a) do{\ 7507 (a)->last = (a)->head = 0;\ 7508 (a)->array = malloc(sizeof(*((a)->array)) * slabSz);\ 7509 (a)->maxCount = slabSz;\ 7510 }while(0) 7511 7512 7513 /** 7514 * initialize slab and count 7515 * 7516 * \param 7517 * a variable name for slab 7518 * \param 7519 * count initial element count for name type 7520 */ 7521 #define slabInitCount(a, count) do{\ 7522 var UNIQVAR(c) = count;\ 7523 (a)->last = (a)->head = 0;\ 7524 (a)->array = malloc(sizeof(*((a)->array)) * UNIQVAR(c));\ 7525 (a)->maxCount = UNIQVAR(c);\ 7526 }while(0) 7527 7528 #define slabResize(a, count) do{\ 7529 var UNIQVAR(c) = count;\ 7530 (a)->array = realloc((a)->array, sizeof(*((a)->array)) * UNIQVAR(c));\ 7531 (a)->maxCount = UNIQVAR(c);\ 7532 if (((a)->last >= (a)->maxCount) || ((a)->head >= (a)->maxCount)) {\ 7533 /* shrinking error - head or last outside the new array, reset to 0 */\ 7534 (a)->last = (a)->head = 0;\ 7535 }\ 7536 }while(0) 7537 7538 /** 7539 * free the internal buffers 7540 * 7541 * \param 7542 * a slab 7543 */ 7544 #define slabFree sliceFree 7545 7546 /** 7547 * element type in array 7548 */ 7549 #define slabElemType(name) typeof((name)->array[0]) 7550 7551 /** 7552 * element pointer type in array 7553 */ 7554 #define slabElemPtrType(name) typeof(&(name)->array[0]) 7555 7556 /** 7557 * Empty Array 7558 */ 7559 #define slabEmpty(name) do{\ 7560 (name)->last = (name)->head = 0;\ 7561 } while(0); 7562 7563 /** 7564 * is Array Empty 7565 */ 7566 #define slabIsEmpty(name) ((name)->head == (name)->last) 7567 7568 /** 7569 * return element count 7570 */ 7571 #define slabCount(name) ((name)->last - (name)->head) 7572 7573 /** 7574 * return max element count 7575 */ 7576 #define slabMaxCount vectorMaxCount 7577 7578 /** 7579 * allocate buffer for new elements 7580 * only when the slab is full 7581 * 7582 * \param 7583 * a dynamic array 7584 */ 7585 #define slabAlloc(a) do{\ 7586 if ((a)->last == slabMaxCount(a)) {\ 7587 (a)->maxCount += slabSz;\ 7588 slabResize(a, (a)->maxCount);\ 7589 }\ 7590 }while(0) 7591 7592 /** 7593 * push element and expand the slab 7594 * no data (random) is set in the new element 7595 * 7596 * \param 7597 * a slab 7598 */ 7599 #define slabPush(a) do{\ 7600 slabAlloc(a);\ 7601 (a)->last++;\ 7602 }while(0) 7603 7604 /** 7605 * append element and expand the slab 7606 * 7607 * \param 7608 * a slab 7609 * \param 7610 * v element to push 7611 */ 7612 #define slabAppend(a, v) do{\ 7613 slabAlloc(a);\ 7614 if ((a)->last < slabMaxCount(a)) {\ 7615 *( (a)->array + (a)->last ) = v;\ 7616 (a)->last++;\ 7617 }\ 7618 }while(0) 7619 7620 /** 7621 * pop element 7622 * the index of the last element is decreased 7623 * 7624 * NOTE: using comma operator to avoid warning 7625 * warning: operation on ‘b.head’ may be undefined [-Wsequence-point] 7626 * 7627 * 7628 * \param 7629 * a slab 7630 */ 7631 #define slabPop(a) ((a)->last--, *((a)->array + (a)->last)) 7632 7633 /** 7634 * delete the last element 7635 * useful for avoiding warning: right-hand operand of comma expression has no effect 7636 * when the poped value is not used 7637 */ 7638 #define slabDelLast(a) ((a)->last--) 7639 7640 /** 7641 * prepend element 7642 * 7643 * \param 7644 * a slab 7645 * \param 7646 * v element to prepend 7647 */ 7648 #define slabPrepend(a, v) do{\ 7649 if ((a)->head > 0) {\ 7650 (a)->head--;\ 7651 *( (a)->array + (a)->head ) = v;\ 7652 }\ 7653 }while(0) 7654 7655 /** 7656 * dequeue element 7657 * the index of the head element is increased 7658 * 7659 * NOTE: using comma operator to avoid warning 7660 * warning: operation on ‘b.head’ may be undefined [-Wsequence-point] 7661 * 7662 * 7663 * \param 7664 * a slab 7665 */ 7666 #define slabDequeue(a) ((a)->head++, *((a)->array + (a)->head -1)) 7667 7668 /** 7669 * delete the first element 7670 * useful for avoiding warning: right-hand operand of comma expression has no effect 7671 * when the dequeued value is not used 7672 */ 7673 #define slabDelFirst(a) ((a)->head++) 7674 7675 /** 7676 * get / set element at index 7677 * 7678 * \param 7679 * a slab 7680 * \param 7681 * index index in array 7682 */ 7683 #define slabAt sliceAt 7684 7685 /** 7686 * get pointer to element at index 7687 * 7688 * \param 7689 * a slab 7690 * \param 7691 * index index in array 7692 */ 7693 #define slabPtr slicePtr 7694 7695 /** 7696 * last element 7697 * 7698 * \param 7699 * a slab 7700 */ 7701 #define slabLast(a) (*((a)->array + (a)->last -1)) 7702 7703 /** 7704 * pointer to last element 7705 * 7706 * \param 7707 * a slab 7708 */ 7709 #define slabLastPtr(a) ((a)->array + (a)->last -1) 7710 7711 /** 7712 * index of last element 7713 */ 7714 #define slabLastIndex(a) ((a)->last-1) 7715 7716 /** 7717 * direct access to the last element index variable for assignments 7718 */ 7719 #define slabLastIndexVar(a) ((a)->last) 7720 7721 /** 7722 * first element 7723 * 7724 * \param 7725 * a slab 7726 */ 7727 #define slabFirst(a) (*((a)->array + (a)->head)) 7728 7729 /** 7730 * index of first element 7731 */ 7732 #define slabFirstIndex(a) ((a)->head) 7733 7734 /** 7735 * write the slab content to filename file 7736 * No NULL checks are done on the parameters 7737 * 7738 * \param 7739 * filename file name string 7740 */ 7741 #define slabWriteFilename(a, filename) do {\ 7742 FILE *UNIQVAR(f) = fopen(filename, "w");\ 7743 if (UNIQVAR(f)) {\ 7744 fwrite((a)->array + (a)->head, 1, sizeof(*((a)->array)) * slabCount(a), UNIQVAR(f));\ 7745 fclose(UNIQVAR(f));\ 7746 }\ 7747 } while(0) 7748 7749 /** 7750 * write the slab content to disk 7751 * No NULL checks are done on the parameters 7752 * 7753 * \param 7754 * file already opened file 7755 */ 7756 #define slabWrite(a, file) fwrite((a)->array + (a)->head, 1, sizeof(*((a)->array)) * slabCount(a), file) 7757 7758 /** 7759 * read a slab from filename file 7760 * No NULL checks are done on the parameters 7761 * 7762 * \param 7763 * filename file name string 7764 */ 7765 #define slabReadFilename(a, filename) do {\ 7766 if (fileExists(filename)) {\ 7767 size_t UNIQVAR(sz) = fileSize(filename);\ 7768 FILE *UNIQVAR(f) = fopen(filename, "r");\ 7769 if (UNIQVAR(f)) {\ 7770 range(UNIQVAR(i), UNIQVAR(sz)/sizeof(*((a)->array))) {\ 7771 slabPush(a);\ 7772 fread(slabLastPtr(a), 1, sizeof(*((a)->array)), UNIQVAR(f));\ 7773 }\ 7774 fclose(UNIQVAR(f));\ 7775 }\ 7776 }\ 7777 } while(0) 7778 7779 /** 7780 * read a slab from disk 7781 * No NULL checks are done on the parameters 7782 * 7783 * \param 7784 * file already opened file 7785 */ 7786 #define slabRead(a, file) do {\ 7787 fseek(file, 0 , SEEK_END);\ 7788 size_t UNIQVAR(sz) = ftell(file);\ 7789 fseek(file, 0 , SEEK_SET);\ 7790 range(UNIQVAR(i), UNIQVAR(sz)/sizeof(*((a)->array))) {\ 7791 slabPush(a);\ 7792 fread(slabLastPtr(a), 1, sizeof(*((a)->array)), file);\ 7793 }\ 7794 } while(0) 7795 7796 /** 7797 * loop on slab elements 7798 * element is a pointer to a value in the array 7799 * 7800 * slabForEach(&a, e) { 7801 * e->x = 0; 7802 * } 7803 */ 7804 #define slabForEach(name, element) \ 7805 ;size_t UNIQVAR(libsheepyInternalIndex) = (name)->head; \ 7806 for (slabElemPtrType(name) element = slabPtr(name, (name)->head) ; UNIQVAR(libsheepyInternalIndex) < (name)->last + 1 ; UNIQVAR(libsheepyInternalIndex)++, element = slabPtr(name, UNIQVAR(libsheepyInternalIndex))) 7807 7808 /** 7809 * enumerate slab elements 7810 * index is the position of the element in the array 7811 * index is declared as size_t and is available after the loop 7812 * element is a pointer to a value in the array 7813 * 7814 * slabEnumerate(&a, i, e) { 7815 * e->x = 0; 7816 * printf("slabEnumerate %d\n", i); 7817 * } 7818 */ 7819 #define slabEnumerate(name, index, element) \ 7820 ; size_t index = (name)->head; \ 7821 for (slabElemPtrType(name) element = slabPtr(name, (name)->head) ; index < (name)->last + 1 ; index++, element = slabPtr(name, index)) 7822 7823 7824 /* 7825 * end slab 7826 */ 7827 7828 7829 /** 7830 * static bitset 7831 * 7832 * no sanity checks are done 7833 * 7834 * Usage: 7835 * 7836 * staticBitsetT(typeName, u64 , 8); 7837 * 7838 * typeName bits; 7839 * 7840 * staticBitsetInit(&bits); 7841 * 7842 * staticBitset1(&bits, index); 7843 * 7844 * bool bit = staticBitsetGet(&bits, index); 7845 * 7846 */ 7847 7848 /** 7849 * typedef for staticBitset 7850 * 7851 * \param 7852 * typeName typedef name 7853 * \param 7854 * containerType element type in array: u8, u16, u32, u64... 7855 * \param 7856 * count bit count in array 7857 */ 7858 #define staticBitsetT(typeName, containerType, count)\ 7859 typedef struct {containerType map[BUCKETS(count, 8 * sizeof(containerType))];} typeName; 7860 7861 #define staticBitsetInit staticBitsetClear 7862 7863 /** bitset count */ 7864 #define staticBitsetCount(name) (sizeof((name)->map) * 8) 7865 7866 /** clear all bits in bitset */ 7867 #define staticBitsetClear(name) memset(name, 0, sizeof(*(name))); 7868 7869 /** bucket containing bit at given index */ 7870 #define staticBitsetBucket(name, index) (name)->map[index / (8 * sizeof((name)->map[0]))] 7871 7872 /** set 0 at index */ 7873 #define staticBitset0(name, index) do{\ 7874 var UNIQVAR(idx) = index;\ 7875 size_t byteOffset = UNIQVAR(idx) / (8 * sizeof((name)->map[0]));\ 7876 size_t bitOffset = UNIQVAR(idx) % (8 * sizeof((name)->map[0]));\ 7877 (name)->map[byteOffset] &= 0xFFFFFFFFFFFFFFFFUL ^ (1UL<<bitOffset);\ 7878 } while(0) 7879 7880 /** set 1 at index*/ 7881 #define staticBitset1(name, index) do{\ 7882 var UNIQVAR(idx) = index;\ 7883 size_t byteOffset = UNIQVAR(idx) / (8 * sizeof((name)->map[0]));\ 7884 size_t bitOffset = UNIQVAR(idx) % (8 * sizeof((name)->map[0]));\ 7885 (name)->map[byteOffset] |= 1UL<<bitOffset;\ 7886 } while(0) 7887 7888 /** set bit value at index*/ 7889 #define staticBitsetSet(name, index, value) do{\ 7890 var UNIQVAR(idx) = index;\ 7891 size_t byteOffset = UNIQVAR(idx) / (8 * sizeof((name)->map[0]));\ 7892 size_t bitOffset = UNIQVAR(idx) % (8 * sizeof((name)->map[0]));\ 7893 /* performance is about the same as the if version with gcc 6.3 on skylake cpu, use the less obscure version - (name)->map[byteOffset] = ( (name)->map[byteOffset] & ~(1UL<<bitOffset)) | (-(value) & (1UL<<bitOffset));*/\ 7894 if (!value)\ 7895 (name)->map[byteOffset] &= 0xFFFFFFFFFFFFFFFFUL ^ (1UL<<bitOffset);\ 7896 else\ 7897 (name)->map[byteOffset] |= 1UL<<bitOffset;\ 7898 } while(0) 7899 7900 /** invert bit at index */ 7901 #define staticBitsetInv(name, index) do{\ 7902 var UNIQVAR(idx) = index;\ 7903 size_t byteOffset = UNIQVAR(idx) / (8 * sizeof((name)->map[0]));\ 7904 size_t bitOffset = UNIQVAR(idx) % (8 * sizeof((name)->map[0]));\ 7905 (name)->map[byteOffset] ^= 1UL<<bitOffset;\ 7906 } while(0) 7907 7908 /** get bit at index */ 7909 #define staticBitsetGet(name, index) ({\ 7910 var UNIQVAR(idx) = index;\ 7911 size_t byteOffset = UNIQVAR(idx) / (8 * sizeof((name)->map[0]));\ 7912 size_t bitOffset = UNIQVAR(idx) % (8 * sizeof((name)->map[0]));\ 7913 ((name)->map[byteOffset] & (1UL<<bitOffset)) == 1UL<<bitOffset;\ 7914 }) 7915 7916 /** 7917 * end static bitset 7918 */ 7919 7920 /** 7921 * bitset 7922 * the underlying array is defined in the provided at macro or function 7923 * 7924 * no sanity checks are done 7925 * 7926 * a dynamic bitset can be created using slice and sliceAt 7927 */ 7928 7929 #define bitsetModulo 8 7930 7931 /** bucket containing bit at given index */ 7932 #define bitsetBucket(name, index) (name)->map[index / (bitsetModulo)] 7933 7934 /** set 0 at index 7935 * at must be macro or function taking 2 parameters: 7936 * at(name, intIndex) 7937 * and point to value at intIndex 7938 */ 7939 #define bitset0(name, at, index) do{\ 7940 var UNIQVAR(idx) = index;\ 7941 size_t byteOffset = UNIQVAR(idx) / (bitsetModulo);\ 7942 size_t bitOffset = UNIQVAR(idx) % (bitsetModulo);\ 7943 at(name, byteOffset) &= 0xFFFFFFFFFFFFFFFFUL ^ (1UL<<bitOffset);\ 7944 } while(0) 7945 7946 /** set 1 at index 7947 * at must be macro or function taking 2 parameters: 7948 * at(name, intIndex) 7949 * and point to value at intIndex 7950 */ 7951 #define bitset1(name, at, index) do{\ 7952 var UNIQVAR(idx) = index;\ 7953 size_t byteOffset = UNIQVAR(idx) / (bitsetModulo);\ 7954 size_t bitOffset = UNIQVAR(idx) % (bitsetModulo);\ 7955 at(name, byteOffset) |= 1UL<<bitOffset;\ 7956 } while(0) 7957 7958 /** set bit value at index 7959 * at must be macro or function taking 2 parameters: 7960 * at(name, intIndex) 7961 * and point to value at intIndex 7962 */ 7963 #define bitsetSet(name, at, index, value) do{\ 7964 var UNIQVAR(idx) = index;\ 7965 size_t byteOffset = UNIQVAR(idx) / (bitsetModulo);\ 7966 size_t bitOffset = UNIQVAR(idx) % (bitsetModulo);\ 7967 /* performance is about the same as the if version with gcc 6.3 on skylake cpu, use the less obscure version - at(name, byteOffset) = ( at(name, byteOffset) & ~(1UL<<bitOffset)) | (-(value) & (1UL<<bitOffset)); */\ 7968 if (!value)\ 7969 at(name, byteOffset) &= 0xFFFFFFFFFFFFFFFFUL ^ (1UL<<bitOffset);\ 7970 else\ 7971 at(name, byteOffset) |= 1UL<<bitOffset;\ 7972 } while(0) 7973 7974 /** invert bit at index 7975 * at must be macro or function taking 2 parameters: 7976 * at(name, intIndex) 7977 * and point to value at intIndex 7978 */ 7979 #define bitsetInv(name, at, index) do{\ 7980 var UNIQVAR(idx) = index;\ 7981 size_t byteOffset = UNIQVAR(idx) / (bitsetModulo);\ 7982 size_t bitOffset = UNIQVAR(idx) % (bitsetModulo);\ 7983 at(name, byteOffset) ^= 1UL<<bitOffset;\ 7984 } while(0) 7985 7986 /** 7987 * get bit at index 7988 * at must be macro or function taking 2 parameters: 7989 * at(name, intIndex) 7990 * and return the value at intIndex 7991 */ 7992 #define bitsetGet(name, at, index) ({\ 7993 var UNIQVAR(idx) = index;\ 7994 size_t byteOffset = UNIQVAR(idx) / (bitsetModulo);\ 7995 size_t bitOffset = UNIQVAR(idx) % (bitsetModulo);\ 7996 (at(name, byteOffset) & (1UL<<bitOffset)) == 1UL<<bitOffset;\ 7997 }) 7998 7999 /** 8000 * end bitset 8001 */ 8002 8003 /** 8004 * bitfield array 8005 * 8006 * a field is a group of bit representing an int stored in a larger int 8007 * 8008 * bitfield array is an array of fields (short int) similar to bitset 8009 * 8010 * Example: 8011 * 8012 * u64 v = 0; // field storage 8013 * FIELD_SET(v, 3, 1, 0); // field is 2 bits from bit 0 to bit 1, set value 3 8014 * 8015 * u8 field = FIELD_GET(v, 1, 0); // get value in field at bit 0 to 1 8016 * 8017 * // declare a bitfield array 8018 * // the array has 256 elements and each element is a 2 bit integer 8019 * BITFIELD_VAR(bitfields, 256, 2) = init0Var; 8020 * 8021 * // set value for element at index 255 8022 * BITFIELD_SET(bitfields, 255, 3, 2); 8023 * // get value for element at index 255 8024 * v = BITFIELD_GET(bitfields, 255, 2); 8025 * 8026 */ 8027 8028 /** 8029 * set bitfield value in destination (opposite of EXTRACT macro) 8030 * 8031 * only bits between msb and lsb are set in dst 8032 * 8033 * \param 8034 * dst destination, unsigned integer (u8, u16, u32, u64) 8035 * \param 8036 * val value to set, the value is shifted to lsb 8037 * \param 8038 * msb most significant bit in dst to be set 8039 * \param 8040 * lsb least significant bit in dst to be set 8041 */ 8042 #define FIELD_SET(dst, val, msb, lsb) dst = (/*clear field in dst*/ (dst) & ((0xFFFFFFFFFFFFFFFEUL << (msb)) | ((1UL<<(lsb))-1) )) | (/*clear highest bits in val and shift to field lsb*/(~(0xFFFFFFFFFFFFFFFEUL << ((msb)-(lsb))) & (val)) << (lsb)) 8043 8044 #define FIELD_GET EXTRACT 8045 8046 /** 8047 * set bitfield value in destination, given bitfield index and length 8048 * 8049 * (index+1)*len-1 must be lower or equal to 8*sizeof(dst), 8050 * otherwise val will be truncated 8051 * 8052 * \param 8053 * dst destination, unsigned integer (u8, u16, u32, u64) 8054 * \param 8055 * index index of the bitfield in dst (bit index*len is lsb) 8056 * \param 8057 * val value to set, the value is shifted to lsb 8058 * \param 8059 * len bitfield length in dst 8060 */ 8061 #define FIELD_SETL(dst, index, val, len) FIELD_SET(dst, val, ((index)+1)*(len)-1, (index)*(len)) 8062 8063 /** 8064 * set bitfield value in array of bitfields 8065 * the boundaries are not checked 8066 * 8067 * \param 8068 * array array of u64 8069 * \param 8070 * index index of the bitfield in array (bit index*len is lsb) 8071 * \param 8072 * val value to set, the value is shifted to the correct position 8073 * \param 8074 * len bitfield length in array, must divide 64 (2, 4, 8, 16, 32) 8075 */ 8076 #define BITFIELD_SET(array, index, val, len) FIELD_SET((array)[((index)*(len))/64], val, ((index)*(len))%64+(len)-1, ((index)*(len))%64) 8077 8078 /** 8079 * get bitfield value in array of bitfields 8080 * the boundaries are not checked 8081 * 8082 * \param 8083 * array array of u64 8084 * \param 8085 * index index of the bitfield in array (bit index*len is lsb) 8086 * \param 8087 * len bitfield length in array, must divide 64 (2, 4, 8, 16, 32) 8088 */ 8089 #define BITFIELD_GET(array, index, len) EXTRACT((array)[((index)*(len))/64], ((index)*(len))%64+(len)-1, ((index)*(len))%64) 8090 8091 /** 8092 * return number of u64 necessary to hold count bitfields of length len 8093 */ 8094 #define BITFIELD_SIZE(count, len, containerType) BUCKETS((count)*(len), 8 * sizeof(containerType)) 8095 8096 /** 8097 * declare an array to hold count bitfields of length len 8098 */ 8099 #define BITFIELD_VAR(array, count, len) u64 array[BITFIELD_SIZE(count, len, u64)] 8100 8101 /** 8102 * end bitfield 8103 */ 8104 8105 // get monotonic time in ns 8106 uint64_t getMonotonicTime(void) MUST_CHECK; 8107 8108 // sleep nanoseconds 8109 int nanoSleepF(uint64_t time) MUST_CHECK; 8110 #define nanoSleep(time) pError0(nanoSleepF(time)) 8111 8112 /** sleep nanoseconds */ 8113 #define nanoSleep(time) pError0(nanoSleepF(time)) 8114 8115 /** nanoSleep and error code */ 8116 #define nanoSleepE(time, cmd) pErrorCmd(nanoSleepF(time), == 0, cmd) 8117 8118 /** sleep microseconds */ 8119 #define usSleep(time) pError0(nanoSleepF(1000 * (uint64_t)time)) 8120 8121 /** sleep miliseconds */ 8122 #define msSleep(time) pError0(nanoSleepF(1000000 * (uint64_t)time)) 8123 8124 8125 #ifdef __GNUC__ 8126 #define UNUSED __attribute__ ((unused)) 8127 #define DEPRECATED __attribute__ ((deprecated)) 8128 #define PACKED __attribute__((__packed__)) 8129 8130 /** 8131 * cleanup calls a function when the variable is out of scope 8132 * 8133 * Also checkout the clean* macros using the cleanup attribute (cleanCharP, ...) 8134 * 8135 * Example: 8136 * void cleanUp(int *val) { 8137 * logVarG(*val); 8138 * } 8139 * int a CLEANUP(cleanUp) = 1; 8140 * a++; 8141 * 8142 * The cleanUp function is called when the variable a is out of scope 8143 * 8144 */ 8145 #define CLEANUP(func) __attribute__((cleanup(func))) 8146 8147 /** 8148 * suppress warning: this statement may fall through [-Wimplicit-fallthrough=] 8149 * 8150 * switch (cond) 8151 * { 8152 * case 1: 8153 * bar (0); 8154 * FALLTHRU; 8155 * default: 8156 * } 8157 */ 8158 #if __GNUC__ >= 7 8159 #define FALLTHRU __attribute__ ((fallthrough)) 8160 #else 8161 #define FALLTHRU 8162 #endif 8163 8164 /** always inline function */ 8165 #define AINLINE inline __attribute__ ((always_inline)) 8166 8167 /** never inline function */ 8168 #define NOINLINE __attribute__ ((noinline)) 8169 8170 /** 8171 * pure function (no effect on assembly code with gcc 10) 8172 * a pure function is one that has no side effects and whose return value reflects only 8173 * the function's parameters or nonvolatile global variables. 8174 * Any parameter or global variable access must be read-only 8175 */ 8176 //#define PURE __attribute__ ((pure)) 8177 8178 /** 8179 * const function (no effect on assembly code with gcc 10) 8180 * a const function is a pure function that cannot access global variables 8181 * and cannot take pointers as parameters. 8182 */ 8183 //#define CONST __attribute__ ((const)) 8184 8185 /** function that always terminate the program, the compile optimizes the caller code better */ 8186 #define NORETURN __attribute__ ((noreturn)) 8187 8188 /** function returning a pointer to a newly allocated buffer */ 8189 #define AMALLOC __attribute__ ((malloc)) 8190 8191 /** mark a function as used */ 8192 #define USED __attribute__ ((used)) 8193 8194 /** force alignment */ 8195 #define ALIGN(X) __attribute__ ((aligned, (x))) 8196 #define ALIGN_MAX __attribute__ ((aligned)) 8197 8198 /** branch anotation (use profile feedback-directed optimization instead) */ 8199 //#define likely(x) __builtin_expect (!!(x), 1) 8200 //#define unlikely(x) __builtin_expect (!!(x), 0) 8201 8202 #else 8203 #define UNUSED 8204 #define DEPRECATED 8205 #define PACKED 8206 #define CLEANUP 8207 #define FALLTHRU 8208 #define AINLINE 8209 #define NOINLINE 8210 #define PURE 8211 #define CONST 8212 #define NORETURN 8213 #define AMALLOC 8214 #define MUST_CHECK 8215 #define USED 8216 #define ALIGN(X) 8217 #define ALIGN_MAX 8218 #define likely(x) (x) 8219 #define unlikely(x) (x) 8220 #endif 8221 8222 #endif // _libsheepyH 8223 // vim: set expandtab ts=2 sw=2: