Libsheepy User Guide

Libsheepy is a generic C library handling text files, strings, json and more.

For an introduction, see libsheepy.

Libsheepy has a build tool called sheepy which runs C programs like scripts

This document shows how to use libsheepy for a user perspective. There is a detailed documentation at https://spartatek.se/libsheepy/ where each function has a description.

Sheepy setup

Install

git clone https://spartatek.se/git/sheepy.git
cd sheepy

sudo -H ./install.sh

First Sheepy Program

Create program with sheepy and run:

sheepy -n example

# run:
./example.c

Overview

Libsheepy has a few concepts and conventions described in the libsheepy overview page in the doxygen documentation:

It is also helpful to look at the examples.

libsheepy.h is the API operating on basic data types.

The doxygen documentation is more detailed than this userguide and the source code is available to browse.

Defines

Name Description
LIBSHEEPY_VERSION current libsheepy version, libsheepy can be updated independently of sheepy
internal or local alias for static
var let the compiler choose the variable type: var c = TRUE;
boolS(boolVar) convert bool value to const char*
XSUCCESS, XFAILURE and exitFailure(data) exit the program
init0Var initialize array or struct to zero
typ typedef
ret return
elif else if
cast(type, casted, toCast) define variable and cast pointer
EVA(var, func) Evaluate, assign result from func and return result using the comma operator
charToS(dst, c) convert char to string by declaring string dst with c in it
put print an empty line
toUpper(c) upper case and store the result in c and return the result
toLower(c) lower case and store the result in c and return the result
orS(string, alternative) return string if non empty, alternative string when string is empty
orBlankS(string, alternative) return string if non blank, alternative string when string is blank (empty or only white spaces)
nS(string) null String - replace null string with "" string (empty string)
and && (iso646.h)
or || (iso646.h)
not ! (iso646.h)
UNIQVAR(name) create a unique variable name by appending the line number (for declaring variables in macros)
_ """
UNUSED set gcc attribute unused on a variable or function parameter
DEPRECATED set gcc attribute deprecated on a symbol

Example code:

local bool abool = false;            // static bool
puts(boolS(abool));                  // convert bool value to string
put                                  // new line
typ struct { u32 a; char *s;} datat; // typedef
datat data = init0Var;

if (not abool or !data.s) {
  data.s = strdup("string");
  toUpper(data.s[0]);
  ret;
}
elif (data.s and eqG(data.s, "Quit")) { // else if
  XSUCCESS;                             // exit(0);
}

void func(int a UNUSED, int b UNUSED) {
  ret;
}

Integer And Float Types

Libsheepy type Standard C type
i8 int8_t
i16 int16_t
i32 int32_t
i64 int64_t
u8 uint8_t
u16 uint16_t
u32 uint32_t
u64 uint64_t
f32 float
f64 double

Macros

Name Description
MAX(a, b) return max value (a and b are evaluted multiple times)
MIN(a, b) return min value (a and b are evaluted multiple times)
MAX3(a, b, c) return max value (a, b and c are evaluted multiple times)
MIN3(a, b, c) return min value (a, b and c are evaluted multiple times)
ABS(a) return absolute value
CLAMP(x, low, high) return x when low <= x <= high, return low when x < low and return high when x > high (x, high and low are evaluted multiple times)
COUNT_ELEMENTS(arr) or ARRAY_SIZE(arr) return element count in a static array: char *arr[100]; logVarG(COUNT_ELEMENTS(arr));
EXTRACT(x, msb, lsb) extract a bit field (the bit field starts at bit 0)
CMP(a, b) compare a to b, return 0 when a equals b, -1 when a is less than b, 1 when a is more than b
BUCKETS(count, divider) divide count by divider and add one when remainder is not zero. this is used in segmented arrays to count the number of buckets from the element count
swapV(a, b) swap a and b, a and b should have the same type
setMax(result, a, b) max a,b and store result in result, a and b are evaluated only once
setMin(result, a, b) min a,b and store result in result, a and b are evaluated only once
maxV(a, b) max a,b and return result, a and b are evaluated only once
minV(a, b) min a,b and return result, a and b are evaluated only once
absV(a) absV return absolute value for a, a is evaluated only once
FIELD_SIZEOF(t, f) get the size of a struct's field
freen(ptr) free pointer and set it to NULL
QSORT(N, LESS, SWAP) traditional Quicksort implementation
BSEARCH(RESULT_INDEX, SEARCH_ELEMENT, B_N, B_LESS, B_EQUAL) binary search
emptyS(string) assign empty string to string pointer
bEmptyS(string) string buffer empty - set 0 at index 0
listEmptyS(list) assign empty list (char * *) to list pointer
newPtr(name, type) create name variable and allocate it on heap
new0Ptr(name, type) create name variable and calloc it on heap
allocAPtr(name) allocate struct on heap and assign address
callocAPtr(name) calloc struct on heap and assign address
newArray(name, type, count) create name variable and allocate array of type on heap
new0Array(name, type, count) reate name variable and calloc array of type on heap
allocArray(name, count) allocate array
allocAArray(name, count) allocate and assign array
callocArray(name, count) calloc array
callocAArray(name, count) calloc and assign array
reallocArray(name, count) realloc array
toUnsignedType(var) convert a variable number type to unsigned type, to declare a new variable or cast a value

Error Reporting

The error reporting macros print an error message and the backtrace (glibc only).

Name Description
pFuncError print function name and system error (errno string)
pStrError(str) print string and system error
shPrintError print error with line number, function name and file name to stderr
shEPrintfS(const char *fmt, ...) printf to stderr
pError(func) print error when function failed. The error code must be -1
pError0(func) print error when function failed. The error code must be 0
pErrorNot0(func) print error when function failed. The error code must be not 0
pErrorNULL(func) print error when function failed. The error code must be NULL
pErrorValue(func, errorValue) print error when function failed. The error code must be -1
pTestError(test) print error when test is true
pTestErrorCmd(test, cmd) print error and run command when test is true
pErrorCmd(func, test, cmd) print error and run cmd when test is true
pErrorResult(result, func, test) print error when test is true and return func result in result
pErrorResultCmd(result, func, test, cmd) print error and run cmd when test is true and return func result in result
logE(fmt, ...) log error

Logging

Variables

There are a few macros logging variable name and their values, mainly for debugging:

int a = 1;

Log:

a=1
Name Description
logVarG(var) generic for logging any basic type and libsheepy objects
logVar(var, format) log variable and its value. format is the variable type: %d, %c...
logMVar(mask, var, format) log variable and its value. format is the variable type: %d, %c... this log is maskable, see Mask section below for more information about masks
logBoolVar(var) log bool variable by printing the value as TRUE or FALSE
logMBoolVar(mask, var) maskable log bool
logPtr(pointer) log pointer value
logMPtr(mask, pointer) maskable log pointer

Configuration

The logs are printed to the stdout by default, use setLogFile(char *filename) to set a log file or multiple log files (max 15). When initLibsheepy is called, the log files are closed at program exit, use closeLogFiles(void) to explicitly close the log files.

The log mode configuration controls which information (date, function, program,...) is printed in the log, there are 8 modes:

Name Description
LOG_VERBOSE log symbol, filename, function, line, date [CRITICAL] _pLogT() (libsheepyTest.c:173) at Wed Apr 24 03:58:45 2019
LOG_CONCISE log symbol [!] pLog test
LOG_DATE log symbol and date [!] 19-04-24 03:58:45 pLog test
LOG_FUNC log symbol and function [!] _pLogT 195: pLog test
LOG_PROG log symbol and program name [!] progname: pLog test
LOG_PROGNDATE log symbol, program name and date [!] progname 19-04-24 03:58:45: pLog test
LOG_VOID log message only pLog test
LOG_UTF8 UTF8 symbols and concise [x]pLog test

Use setLogMode(int mode) to configure a log mode and getLogMode(void) to get current log mode.

The log symbols indicate the log level and are printed at the beginning of the first line. The log symbols can be set independently of the log mode, use getLogSymbols(void) to get current log mode for symbols and setLogSymbols(int mode) to set log symbols, choose 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 (!*+->~).

The short path configuration (setLogShortPath(bool shortPath) and getLogShortPath(void)) controls the length of the filename in the LOG_VERBOSE mode.

The max log level configuration (setMaxLogLevel(int logLevel) and getMaxLogLevel(void)) allows skipping the higher log level or completely disable all logs at runtime.

To disable logs at compile time anywhere in the code (local to the source file), undefine the pLog macro:

/* enable/disable logging */
#undef pLog
#define pLog(...)

To disable the logs at runtime, run:

setMaxLogLevel(LOG_DISABLE);

The libsheepy functions print log messages when errors are encountered, these logs are disabled with the disableLibsheepyErrorLogs macro:

// Mask libsheepy error logs
disableLibsheepyErrorLogs;
Name Description
setLogFile(char *filename) add a log file, maximum 15 files
closeLogFiles(void) close logfiles opened with setLogFile (not needed when initLibsheepy is called)
setLogMode(int mode) set log mode LOG_VERBOSE, LOG_CONCISE, ...
getLogMode(void) get current log mode (LOG_VERBOSE, LOG_CONCISE, ...)
setLogSymbols(int mode) 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 (!*+->~)
getLogSymbols(void) current log symbols
setLogShortPath(bool shortPath) set log long/short file path value for VERBOSE mode
getLogShortPath(void) get current log long/short path value, default is TRUE (short paths)
setMaxLogLevel(int logLevel) set max log level, logs above logMaxLevel are skipped
getMaxLogLevel(void) current max log level
disableLibsheepyErrorLogs; disable log prints from libsheepy
btraceEnable(void) enable backtrace in error messages
btraceDisable(void) disable backtrace in error messages
btraceConfig(void) get current backtrace configuration

Functions

There are 5 log levels: critical, error, warning, pass and info. The functions for the log level end with the first letter of the log level: logC for critical, logI for info...

Name Description
logI(fmt,...) info level
logP(fmt,...) pass level
logW(fmt,...) warning level
logE(fmt,...) error level
logC(fmt,...) critical level
AT; log line number, function name and filename
logSI(fmt,string) info level, log string and free: logSI("The list: %s", catS("1", "2"));
logSP(fmt,string) pass level, log string and free
logSW(fmt,string) warning level, log string and free
logSE(fmt,string) error level, log string and free
logSC(fmt,string) critical level, log string and free
logSystem(cmd) or logExec(cmd) log cmd and run
char** logSystemOut(cmd) or char** logExecOut(cmd) log cmd, run and return stdout lines
logSystemf(fmt, ...) or logExecf(fmt, ...) build command with format fmt, log commad and run
logSystemOutf(fmt, ...) or logExecOutf(fmt, ...) build command with format fmt, log commad, run and return stdout lines
logBtrace; log backtrace
logG(self) log array or dictionary, one line per element
loghex(const void *buf, size_t len) print buffer as hexadecimal string

Mask

The logM macros are maskable at runtime. The mask configuration is stored in the logMask variable and libsheepy uses bit 63 (libsheepyErrorMask) in logMask.

showLogsInMask(mask) and hideLogsInMask(mask) shows or hides logs in a mask.

To disable the logM macros at compile time, undefine pLogMask:

#undef pLogMask
#define pLogMask(...)

For example:

#define group1 0x03
#define group11 0x01
#define group12 0x02
#define group2 0x04

showLogsInMask(group11);
logMI(group1, "is shown when logMask has bit 0 or 1 set");
logMI(group11, "is shown when logMask has bit 0 set");
logMI(group12, "is shown when logMask has bit 1 set");
logMI(group2, "is shown when logMask has bit 2 set");
Name Description
logMI(mask, ...) info level mask
logMP(mask, ...) pass level mask
logMW(mask, ...) warning level mask
logME(mask, ...) error level mask
logMC(mask, ...) critical level mask
logSMI(mask, ...) info level mask, log string and free: logSMI(0x1, "The list: %s", catS("1", "2"));
logSMP(mask, ...) pass level mask, log string and free
logSMW(mask, ...) warning level mask, log string and free
logSME(mask, ...) error level mask, log string and free
logSMC(mask, ...) critical level mask, log string and free
showLogsInMask(mask) set bits in logMask
hideLogsInMask(mask) unset bits in logMask

Loops

Libsheepy has a loop breaker system that breaks possible infinite loops. loopBreakerInit initializes the loop breaker before the loop, loopBreakerReset resets the loop breaker for the next loop and loopBreaker(breakCount) breaks the loop after breakCount loops.

Usage:

loopBreakerInit;
forever {
  loopBreaker(20);
}
if (didBreak) logE("infinite loop detected");
loopBreakerReset;
forever {
  loopBreaker(100);
}
if (didBreak) logE("infinite loop detected");
Loop Name Description
forever forever loop
range(index, maxCount) range loop
rangeInf(index) increase the index infinitly
rangeDown(index, maxCount) range down loop, index is ssize_t
rangeDownTo(index, maxCount, to) range down loop to to index, index is ssize_t
rangeFrom(index, from, maxCount) range loop starting at value from
arange(index, array) loop on the elements of C static array of any type. Example: u32 array[20]; arange(i, array) {}
arangeDown(index, array) loop on the elements of C static array of any type from highest index down to 0
arangeDownTo(index, array, to) loop on the elements of C static array of any type from highest index down to index 'to'
arangeFrom(index, from, array) loop on the elements of C static array of any type starting at index 'from'
circular(index, from, maxCount) range from value from to maxCount-1 then from 0 to from-1
circularDown(index, from, maxCount) range from value from down to 0 then from maxCount-1 to from+1
rangeStep(index, maxCount, step) range step loop
rangeDownStep(index, maxCount, step) range down setp loop, index is int64_t
rangeFromStep(index, from, maxCount, step) range step loop starting at value from
loop(maxCount) loops without index
loopDownTo(maxCount, to) loop to to index
loopFrom(from, maxCount) loop starting at value from
loopStep(maxCount, step) step loop
loopFromStep(from, maxCount, step) step loop starting at value from
forEachCharP(list, element) forEach - loop macro on char** list. To access the element in the loop, use *element
forEachS(list, element) forEach - loop macro on char** list. To access the element in the loop, use element
forEachType(type, list, element) forEach - loop macro on type** list. To access the element in the loop, use *element
enumerateCharP(list, element, index) enumerate char** list. To access the element in the loop, use *element
enumerateS(list, element, index) enumerate char** list. To access the element in the loop, use element
enumerateType(type, list, element, index) enumerate type** list. To access the element in the loop, use *element
lForEach(node, startNode) loop for linked lists from startNode to last
lForEachDown(node, startNode) or lForEachPrev(node, startNode) loop for linked lists from startNode to head
loopBreakerInit; declare and reset loop breaker variables
loopBreakerReset; reset loop breaker
loopBreaker(breakCount) break loop after count, the didBreak variable is set to true

There are also iterators for the libsheepy objects implementing the iterator interface. The libsheepy classes with iterator interfaces are: smallArrayt, smallDictt and smallJsont

For example:

var array = createSA("1", "2", "3");
iter(array, elem) {
  logVarG(elem);
}
Iterator Name Description
iter(obj, element) Loop on obj elements
iterLast(obj, element) Loop from last element to first element
iterFrom(obj, index, element) Loop on obj elements starting at index
iterFromStep(obj, index, step, element) Loop on obj elements starting at index incrementing index by step
iterType(type, obj, element) Loop on obj elements and cast element to type
iterTypeLast(type, obj, element) Loop from last element to first element and cast element to type
iterTypeFrom(type, obj, index, element) Loop on obj elements starting at index and cast element to type
iterTypeFromStep(type, obj, index, step, element) Loop on obj elements starting at index incrementing index by step and cast element to type
iterK(obj, key) Loop on obj elements and set element key (use getG to get the element)
iterIndexG(self) Current index
iterKeyG(self) Current key

Printf

Specifiers

The specifiers are available when libsheepy is compiled against glibc.

Name Description
%k foreground hex color. Example: printf("%k%KRGB color" RST, 0x99EEFF, 0x666666);
%K background hex color
%b print bool as FALSE/TRUE
%m print baset objects

Terminal Colors And Effects

The terminal colors can be added in any string that will be printed in a terminal. The string part with the effect starts with the chosen effect, for example BLD and ends with RST to cancel the effect. Terminal colors and effects are allowed to be combined: BLD RED "bold red" RST.

For example:

char *s = "This " BLD"color"RST " is " RED"red"RST ".";

- This and is have normal color
- color is bold
- red is red
Name Description
RST reset
BLD bold
FNT faint
UDL underline
INV inverse
COC conceal/hidden
CRD crossed
BLK foreground black
RED foreground red
GRN foreground green
YLW foreground yellow
BLU foreground blue
MGT foreground magenta
CYN foreground cyan
WHT foreground white
BGBLK background black
BGRED background red
BGGRN background green
BGYLW background yellow
BGBLU background blue
BGMGT background magenta
BGCYN background cyan
BGWHT background white

Use stripCtrlS to remove terminal colors from a string.

When libsheepy is linked to glibc, it is possible to print RGB colors with %k and %K, the colors are coded as hexadecimal RGB:

logI("%k%KRGB color" RST, 0x99EEFF, 0x666666);

Stopwatch And Timer

Name Description
timeNs(func) print how long time (in nanoseconds) was spent in func
timeUs(func) time a function in microseconds
timeMs(func) time a function in miliseconds
timeSec(func) time a function in seconds
stopwatchStart start the stopwatch
stopwatchLog print stopwatch value in ns since last start (in nanoseconds)
stopwatchLogUs print stopwatch value in microseconds since last start
stopwatchLogMs print stopwatch value in milliseconds since last start
stopwatchLogSec print stopwatch value in seconds since last start

For example:

stopwatchStart;
... code ...
stopwatchLogUs; // log time spent in code section

Naming conventions

Name Description
ending with O macro calling an object method
ending with G generic for libsheepy objects
ending with S function operating on char*
ending with UTF8 UTF8 function operating on char*
starting with b function operating on char* returning the result in the first parameter: the caller allocates the buffer
starting with bL function operating on char* returning the result in the first parameter: the caller allocates the buffer and gives the buffer size
starting with ic ignore case function
starting with i in place function that reallocates char* buffers
starting with list and ending with S function operating on char**
starting with list function operating on void**

Libsheepy Classes

All classes in libsheepy inherit from the baset class, the baset methods are: free, terminate, toString, duplicate.

All classes have a set of functions for creating and destroying objects:

These function names end with either: SmallArray, SmallBool, SmallBytes, SmallContainer, SmallDict, SmallDouble, SmallInt, SmallJson, SmallString, Undefined

For example: createSmallJson(jsonObject) declares a local json object. freeG(jsonObject) frees the internal buffers.

The class name are: smallArrayt, smallBoolt, smallBytest, smallContainert, smallDictt, smallDoublet, smallIntt, smallJsont, smallStringt, undefinedt

Objects of type:

Use sheepy -C classname to generate your own baset class from templates.

Generics

The macros create* and createAllocate* declare and initialize new object:

createAllocteSmallArray(array);
createSmallDict(dict);

Objects can be declared like other variables and then initialized with initiateG or allocG

smallArrayt *array;
smallDict dict;
smallStringt *string;

initiateG(&array);
initiateG(&dict);
string = allocG("new string");

The regular generic call format is:

methodG(object, other parameters...);

result = method2G(object, other parameters...);

To get the value in smallBool, smallDouble, smallInt, smallString use getValG(self).

To get a value in smallArrayt, smallDictt or smallJsont use getG(self, returnType, key).

To set a value in smallBool, smallDouble, smallInt, smallString use setFromG(self, value).

To set a value in smallArrayt, smallDictt or smallJsont use setG(self, returnType, key).

getG and setG support smallBool, smallDouble, smallInt, smallString types by setting returnType to unusedV.

The generics support these types where it makes sense:

For type char* and char**, the functions in lisheepy.h are called.

The generics returning a value have a returnType parameter, the possible values for returnType are:

For example getG(dict, rtBool, "a") returns a bool and with rtBoolP it returns a pointer to a bool.

Name Description
initiateG(self) give the address of the object to initialize (smallArrayt or smallArrayt*)
allocG(value) allocate a smallObject corresponding to value type and assign value to the object
freeG(self) free smallObject, char** and any pointer type
freeManyG(paramType, ...) free baset objects
terminateG(obj) free baset container and internal buffers, for objects allocated on the head only
terminateManyG free containers and internal buffers
isOTypeG(obj, className) test obj type
isOSmallArray(obj) test if obj type is smallArray
isOSmallBool(obj) test if obj type is smallBool
isOSmallBytes(obj) test if obj type is smallBytes
isOSmallContainer(obj) test if obj type is smallContainer
isOSmallDict(obj) test if obj type is smallDictt
isOSmallDouble(obj) test if obj type is smallDouble
isOSmallInt(obj) test if obj type is smallInt
isOSmallJson(obj) test if obj type is smallJson
isOSmallString(obj) test if obj type is smallString
isOUndefined(obj) test if obj type is undefined
getOType(obj) return obj type in a string
duplicateG(obj) create a copy of obj
smashG(obj) free object and keep data
smashManyO(paramType, ...) smash many baset objects
finishG(obj) free container only
finishManyG(paramType, ...) finish many baset objects
getValG get the value in smallBool, smallDouble, smallInt, smallString
getPG(self) get pointer to value in smallBool, smallDouble, smallInt
setFromG(self, value) set value in smallBool, smallDouble, smallInt, smallString
setTopG(self, value) set top value in smallJson or set value in smallBool, smallDouble, smallInt, smallString
setTopNFreeG(self, value) set top value in smallJson and free container
getTopG(self, returnType) get top object in smallJson
pushG(self, value) add value at the end of the object, char literals are accepted. When self is char* or char** give &self in first parameter because self might be reallocated
pushNFreeG(self, value) push and free container. When self is char* or char** give &self in first parameter because self might be reallocated
setG(self, key, value) set value at key
setNFreeG(self, key, value) set value at key and free container
setPG(self, key, value) set smallObject pointer at key (more info about memory management on libsheepy overview)
setNFreePG(self, key, value) set smallObject pointer at key and free container
getG(self, returnType, key) get value of type returnType at key
getNDupG(self, returnType, key) get and duplicate value of type returnType at key
getNumG(self, key) get a double value
appendG(self, obj) append an object of type self. When self is char* or char** give &self in first parameter because self might be reallocated
appendNSmashG(self, obj) append object and free array/dict keeping the elements. When self is char* or char** give &self in first parameter because self might be reallocated
prependG(self, value) prepend an object of type self. When self is char* or char** give &self in first parameter because self might be reallocated
prependNFreeG(self, obj) prepend an object of type self and free array keeping the elements. When self is char* or char** give &self in first parameter because self might be reallocated
delG(self, start, end) delete elements between start and end. When self is a smallArray, the remaining elements keep their indexes, the deleted elements are set to NULL, use compactG to remove these NULL elements
delElemG(self, index) delete the element at index. When self is a smallArray, the remaining elements keep their indexes, the deleted element is set to NULL, use compactG to remove the NULL element
popG(self, returnType) return and remove last element
dequeueG(self, returnType) return and remove first element
getRealProgPathG(returnType) get program path
systemG(cmd) run cmd
systemNFreeG(cmd) run and free cmd
getModificationTimeG(path) get modification time for path
setModificationTimeG(path, mtime) set modification time for path
equalModificationTimesG(path1, path2) return true when path1 and path2 have equal modification times
timeToSG(returnType, t) convect time_t to string
shDirnameG(path) dirname
expandHomeG(path) expand home ~/
normalizePathG(path) normalize path
getCwdG(returnType) get current working directory
chDirG(path) change directory
isDirG(path) true when path is directory
isLinkG(path) true when path is symbolic link
fileExistsG(path) file and dir exists
fileChmodG(path, mode) chmod "721": fileChmodG(path, 0721 /*octal*/);
fileSizeG(path) file size
readFileG(self, path) read file, when self is smallJson, json and yml files are parsed. . For char* or char**, self specifies the return type: char *content = NULL; content = readFileG(content, "filename");
readTextG(self, path) read text file, each line is an array element
writeFileG(self, path) write file, when self is smallJson, json and yml files are generated
writeTextG(self, path) write text file
zipG(self, keys, values) merge key,value pairs to self. keys and values are arrays
walkDirG(returnType, path) walkDir lists files only
walkDirDirG(returnType, path) walkDirDir lists directories
readDirG(returnType, path) readDir lists files in a directory
readDirDirG(returnType, path) readDirDir lists directories in a directory
walkDirAllG(returnType, path) walkDirAll lists files and directories
readDirAllG(returnType, path) readDirAll lists files and directories in a directory
mkdirParentsG(path) recursive mkdir
rmAllG(path) delete files and directories
copyG(path1, path2) copy files recursively
randomSG(returnType, length) generate random string
randomAlphaNumSG(returnType, length) generate random alpha numerical string
readG(returnType) read user input (one line) as a string
readLineG(returnType, fp) read line in a text file
dupG(self) duplicate object or char* string
replaceG(self, olds, news, max) replace
icReplaceG(self, olds, news, max) ignore case replace
eqG(self, obj) equality (all libsheepy types)
icEqG(self, obj) ignore case equality (all libsheepy types)
eqIG(self, obj, index) equality at index
startsWithG(self, obj) look for obj at self start
endsWithG(self, obj) look for obj at self end
countG(self, obj) count number of (non-overlapping) occurrences of obj
icStartsWithG(self, obj) ignore case startsWith
icEndsWithG(self, obj) ignore case endsWith
icCountG(self, obj) ignore case count
isNumberG(self) true when string is a number (integer or float)
isIntG(self) true when string is an integer
parseIntG(self) convert string to int
intToG(self, n) convert int to string
parseDoubleG(self) convert string to double
doubleToG(self, n) convert double to string
lenG(self) length
upperG(self) uppercase
lowerG(self) lowercase
trimG(self) remove space at right and left
lTrimG(self) left trim
rTrimG(self) right trim
uniqG(self, c) remove successive repetitions of char c
icUniqG(self, c) ignore case uniq
sliceG(self, start, end) slice string
copyRngG(self, start, end) copy range from start to end and duplicate elements
insertG(self, index, toInsert) insert object of type self at index
insertNSmashG(self, index, toInsert) insert object of type self at index and free array keeping the elements
injectG(self, index, value) insert an element at index
injectNFreeG(self, index, value) insert an element at index and free container
findG(self, needle) find
hasG(self, needle) true when self has needle
indexOfG(self, needle) index of needle
keyByG(self, needle) key for needle
icFindG(self, needle) ignore case find
icHasG(self, needle) ignore case has
icIndexOfG(self, needle) ignore case indexOf
icKeyByG(self, needle) ignore case keyBy
emptyG(self) empty self
isEmptyG(self) true when self is empty
isBlankG(self) true when self has only white spaces or is empty
fromArrayG(self, array, size) set strings from array of size size
splitG(self, delim) split
icSplitG(self, delim) ignore case split
joinG(self, delim) join
joinSG(self, delim) join and return value of type char*
extractG(self, delim1, delim2) extract string between delim1 and delim2
icExtractG(self, delim1, delim2) ignore case extract
reverseG(self) reverse
addG(self, list) append
sortG(self) sort
binarySearchG(self, string) binary search
icSortG(self) ignore case sort
icBinarySearchG(self, string) ignore case binary search
compactG(self) remove blank elements
parseG(self, input) parse json string, smallJson only
parseYMLG(self, input) parse yml string, smallJson only
execG(cmd, out, err) run cmd and return stdout lines in out
renameG(src, dst) rename
moveG(src, dst) move files recursively
logG(self) print self, one line per element
catG(self, ...) append smallObjects
catSG(self, ...) append char* strings
pushManyG(self, ...) push objects
pushManySG(self, ...) push char* strings
pushNFreeManyG(self, ...) push and free containers
pushNFreeManySG(self, ...) push and free char* strings
pushBufferG(self, data, size) smallBytes pushBuffer
disposeG(self) free sObject index but not elements, self becomes empty
helpG(self) print class help
resetG(self) remove reference to internal sObject, set NULL and free the iterator. This function is useful for object not allocated on the heap to free the iterator element when the object is not used anymore
getsoG(self) get the sobject, data in the container
setsoG(self, so) set the sobject, data in the container, the iterator is reset
mirrorG(self) allocate a new container for the sobject, the iterator state is copied. After this function is executed, there are 2 containers for one sobject, only one container should be freed or terminated, the other one should be finished
fromArrayNFreeG(self, array, size) fromArray and free array
ssGet(obj) get char* from object (must be smallStringt)
sjGet(obj) get char* from object (must be smallJsont)
replaceManyG(self, olds, ...) replace many
icReplaceManyG(self, olds, ...) ignore case replace many
toStringG(obj) convert data in obj to string
putsG(obj) print obj

System Functions

Name Description
initLibsheepy(progPath) initialize segfault handler, prog path, thread pool, register printf specifiers
int64_t getStackLimit(void); get current stack limit - returns 0 when error
int setStackLimit(int64_t stackSize); set stack limit (-1 for unlimited) - returns 0 when error
smallDictt *shSysinfo(void); Sheepy sysinfo. The keys are: uptime, loads, totalram, freeram, sharedram, bufferram, totalswap, freeswap, procs
const char *getProgName(void); get program name
bool setProgName(const char *name); set program name
void setDefaultProgName(void); set default program name
const char *getProgPath(void); or smallStringt *getRealProgPathO(void); get program path as given in the shell
const char *getRealProgPath(void); or smallStringt *getRealProgPathO(void); get real program path, allocates path string internally
void freeRealProgPath(void); free real program path
int systemO(smallStringt *command); run system command in a smallString
systemNFree(char *command) orsystemNFreeO(smallStringt *command) run system command and free command buffer
int execO(const char *cmd, smallArrayt *out, smallArrayt *err); or int execSmallStringO(smallStringt *cmd, smallArrayt *out, smallArrayt *err); execute command and return stdout from cmd in *out
char **execOut(const char *cmd); or char **systemOut(const char *cmd); run command and return stdout
char **execOutf(const char *fmt, ...); or char **systemOutf(const char *fmt, ...); system command with formatting and return stdout
int execf(const char *fmt, ...); or int systemf(const char *fmt, ...); system command with formatting
time_t getCurrentUnixTime(void); get current unix time
time_t strToUnixTime(const char *date, const char *format); convert date string to unix time
char *timeToS(const time_t t); or smallStringt *timeToSO(const time_t t); convert unix time to string
char *timeToYMDS(const time_t t); convert unix time to Y-m-d H:M:S string
char *getCurrentDate(void); get current date in ctime format
char *getCurrentDateYMD(void); get current date in Y-m-d H:M:S format
int randomUrandomOpen(void); open /dev/urandom in libsheepy
uint64_t randomWord(void); return random 64 bit unsigned integer
uint64_t randomWordFromHW(void); return random 64 bit unsigned integer from the cpu
uint64_t randomChoice(uint64_t range); return a random value between 0 and range 0<=value<range
char *randomS(uint64_t length); generate random string
char *randomAlphaNumS(uint64_t length); generate random alpha numerical string
char *readS(void); read user input (one line) as a string
char *readPasswordS(void); read hidden password as a string - like getpass
bool zeroS(char *string); write zero to all bytes in string with memset, for clearing password buffers
bool zeroBuf(void *buf, size_t len); write zero to all bytes in buffer with memset
void *memdup(const void *buf, size_t size); allocate and copy buffer
void readEnter(void); wait until press the enter key
uint64_t getMonotonicTime(void); get monotonic time in ns
nanoSleep(time) sleep nanoseconds
nanoSleepE(time, cmd) nanoSleep and run cmd when there is an error
usSleep(time) sleep microseconds
msSleep(time) sleep miliseconds

File Functions

Name Description
time_t getModificationTime(const char *path); get modification time for path
int setModificationTime(const char *path, time_t mtime); set modification time for path
bool isReadable(const char *path); true when path is readable
bool isWritable(const char *path); true when path is writable
bool isExecutable(const char *path); true when path is executable
bool equalModificationTimes(const char *path1, const char *path2); compare modification times for path1 and path2
char *shDirname(const char *path); dirname
char *expandHome(const char *path); expand home ~/
char *normalizePath(const char *path); normalize path
char *relPath(const char *path, const char *start); relative path
char *getHomePath(void); get home path
char *getCwd(void); get current working directory
int chDir(const char *path); change directory
bool isDir(const char *path); true when path is directory
char *shReadlink(const char *path); read link to a new string
char *endlink(const char *path); read link chain to the end to a new string
bool isLink(const char *path); true when path is symbolic link
bool fileExists(const char *filePath); or bool isPath(const char *filePath); file and dir exists
bool fileChmod(const char *filePath, mode_t mode); chmod "721": fileChmod(path, 0721 /*octal*/);
ssize_t fileSize(const char *filePath); or ssize_t fileSizeFP(FILE *fp); file size
void *readFileToS(const char *filePath); read file
int writeFileS(const char *filePath, const char *string); write file
bool appendFileS(const char *filePath, const char *string); append string to file
char **walkDir(const char* dirPath); walkDir lists files only
char **walkDirDir(const char* dirPath); walkDirDir lists directories
char **readDir(const char *dirPath); readDir lists files in a directory
char **readDirDir(const char *dirPath); readDirDir lists directories in a directory
char **walkDirAll(const char* dirPath); walkDirAll lists files and directories
char **readDirAll(const char *dirPath); readDirAll lists files and directories in a directory
mode_t getumask(void); get umask
mode_t getCurrentPermissions(void); get current permissions for creating directories
int mkdirParents(const char* path); recursive mkdir
int rmAll(const char* path); delete files and directories
int copy(const char* src, const char* dst); copy files recursively
int shRename(const char* src, const char* dst); rename file
int shMove(const char* src, const char* dst); move files recursively
char *readLine(FILE *fp); readLine

String Functions

Name Description
void *readFileToS(const char *filePath); read file
ssize_t readFile(const char *filePath, void **buffer); read file
void *readStreamToS(FILE *fp); read file
int writeFileS(const char *filePath, const char *string); write file
int writeFile(const char *filePath, void *buffer, size_t len); write file
int writeStreamS(FILE *fp, const char *string); write file
int writeLStream(FILE *fp, void *buffer, size_t len); write file
bool appendFileS(const char *filePath, const char *string); append string to file
char *randomS(uint64_t length); generate random string
char *randomAlphaNumS(uint64_t length); generate random alpha numerical string
char *readS(void); read user input (one line) as a string
char *readPasswordS(void); read hidden password as a string - like getpass
bool zeroS(char *string); write zero to all bytes in string with memset, for clearing password buffers
freeManyS(...) free many char*
char *dupS(const char *string); duplicate string
void shPrintfS(const char *fmt, ...); print like printf, the formating can be NULL
void shEPrintfS(const char *fmt, ...); stderr printf, the formating can be NULL
void logNFree(char *s); print and free s
void loghex(const void *buf, size_t len); print buf as hexadecimal
char *toHexS(const void *buf, size_t len); create a string with bytes in buf converted to hex strings: 0xff,
char *toHexSepS(const void *buf, size_t len, const char *separator); create a string with bytes in buf converted to hex strings separated by separator: 0xffSEP
char *toHexHeadSepS(const void *buf, size_t len, const char *head, const char *separator); create a string with bytes in buf converted to hex strings separated by separator and with head string in front of earch byte: HEADffSEP
put; print new line
char *strCpy(char *dst, const char *src); copy src to dst
char *strNCpy(char *dst, const char *src, size_t srcSize); copy string to buffer given string length: strNCpy(buffer, string, lenS(string));
char *strLCpy(char *dst, size_t dstSize, const char *src); copy string
char *strCat(char *dst, const char *src); concatenate src to dst
char *strNCat(char *dst, const char *src, size_t srcLen); concatenate src to dst
char *strLCat(char *dst, size_t dstSize, const char *src); concatenate src to dst
char *strLNCat(char *dst, size_t dstSize, const char *src, size_t srcLen); concatenate src to dst
catS(...) cat: catS("qwd ", str," werr ", str2)
iCatS(dst, ...) cat and copy result to dst buffer
char *formatS(const char *fmt, ...); allocate and format string using asprintf
char *appendS(const char *string1, const char *string2); append strings
char *prependS(const char *string1, const char *string2); prepend string
char *replaceS(const char *s, const char *olds, const char *news, size_t max); string replace
replaceManyS(s, ...) string replace many olds with news (s, olds1, news1, olds2, news2,...)
char *icReplaceS(const char *s, const char *olds, const char *news, size_t max); ignore case string replace
bool eqS(const char *string1, const char *string2); string equal (compare content)
bool eqIS(const char *string1, const char *string2, intmax_t index); string equal at index (compare content)
bool startsWithS(const char *string1, const char *string2); look for string2 at string1 start
bool endsWithS(const char *string1, const char *string2); look for string2 at string1 end
ssize_t countS(const char *s, const char *needle); count number of (non-overlapping) occurrences of a substring
bool icEqS(const char *string1, const char *string2); ignore case string equal (compare content)
bool icEqIS(const char *string1, const char *string2, intmax_t index); ignore case string equal at index (compare content)
bool icStartsWithS(const char *string1, const char *string2); ignore case and look for string2 at string1 start
bool icEndsWithS(const char *string1, const char *string2); ignore case look for string2 at string1 end
ssize_t icCountS(const char *s, const char *needle); ignore case and count number of (non-overlapping) occurrences of a substring
bool hasCtrlChar(const char *string); has terminal control char (for example colors)
char *stripCtrlS(const char *string); remove terminal control char from string
bool isNumber(const char *string); true when string is a number (integer or float)
bool isInt(const char *string); true when string is an integer
intmax_t parseInt(const char *string); parseInt
double parseDouble(const char *string); parseDouble
uint64_t parseHex(const char *string); parse hexadecimal string: 0xff
char *intToS(intmax_t n); convert int to string
char *doubleToS(double n); convert double to string
size_t lenS(const char *string); length
char *upperS(const char *string); duplicate and upper case
char *lowerS(const char *string); duplicate and lower case
char *trimS(const char *string); duplicate and trim
char *lTrimS(const char *string); left trim
char *rTrimS(const char *string); right trim
char *uniqS(const char *string, char c); remove successive repetitions of char c
uniqSlash(s) remove successive repetitions of /
char *icUniqS(const char *string, char c); ignore case and remove successive repetitions of char c
char *repeatS(const char *string, size_t count); repeat string count times
ssize_t repeatLenS(const char *string, size_t count); length of string repeated count times
char *ellipsisStartS(const char *string, size_t targetLength, const char *ellipsisString); ellipsisStart string
ssize_t ellipsisLenS(const char *string, size_t targetLength, const char *ellipsisString); length of string after ellipsis
char *ellipsisEndS(const char *string, size_t targetLength, const char *ellipsisString); ellipsisEnd string
char *padStartS(const char *string, size_t targetLength, const char *padString); padStart string
ssize_t padStartLenS(const char *string, size_t targetLength, const char *padString); length of string after padStart
char *padEndS(const char *string, size_t targetLength, const char *padString); padEnd string
ssize_t padEndLenS(const char *string, size_t targetLength, const char *padString); length of string after padEnd
char getS(const char *string, intmax_t index); get char at python index
char *setS(char *string, intmax_t index, char c); set char at python index
char *swapS(char *string, intmax_t index1, intmax_t index2); swap characters in a string
char *sliceS(const char *string, intmax_t start, intmax_t end); slice string, function to slice parts of a string [1:10] - python style indexes 0..len-1 -1..-len+1
char *insertS(const char *string, intmax_t index, const char *toInsert); insert string in string
char *injectS(const char *string, intmax_t index, char toInject); inject a char in string
char *delS(const char *string, intmax_t start, intmax_t end); del string, function to delete parts of a string [1:10] - python style indexes 0..len-1 -1..-len+1
char *delElemS(const char *string, intmax_t index); del a character in string
char *findS(const char *string, const char *needle); find substring
ssize_t indexOfS(const char *string, const char *needle); index of substring
bool hasS(const char *string, const char *needle); true when needle is found
char *icFindS(const char *string, const char *needle); ignore case find substring
ssize_t icIndexOfS(const char *string, const char *needle); ignore case index of substring
bool icHasS(const char *string, const char *needle); ignore case, true when needle is found
char *tokS(const char *s, const char *delim, char **saveptr); parse s string with delim - works like strtok_r from stdlib
char *icTokS(const char *s, const char *delim, char **saveptr); ignore case and parse s string with delim - work like strtok_r from stdlib
emptyS(string) create empty string
bool isEmptyS(const char *string); is empty string
orS(string, alternative) orS - if string is empty, the value is alternative
bool isBlankS(const char *string); true when string is empty or white spaces
orBlankS(string, alternative) if string is blank(white spaces) or empty, the value is alternative
nS(string) nS - null String - replace null string with "" string (empty string)
ssize_t intIndex(intmax_t index, intmax_t length); convert python index (int, positive and negative) to always positive index (uint), this function is more generic than listIntIndexS

UTF8

Name Description
typedef int rune; rune is a 32 bit unicode integer
size_t lenUTF8(const char *s); character length of UTF-8 encoded string
bool isUTF8(const char * string); is string valid UTF-8 encoded string
bool isCodeUTF8(const char *code); is string a valid UTF-8 code point
codeSizeUTF8(utf8) size in bytes of UTF-8 code point
nextCodeUTF8(utf8) move pointer to next UTF-8 code point, no checks are done, the utf8 pointer parameter is unchanged
nxtCodeUTF8(utf8) change the utf8 pointer parameter to next UTF-8 code point, like char *s; s++;
char *nextUTF8(const char *utf8); next code point, works only when utf8 points to a valid code point
char *findNextUTF8(const char *string, size_t utf8Size, const char *utf8); find next code point even when utf8 points inside a code point
char *prevUTF8(const char *utf8); previous code point, undefined behavior when utf8 points to the start of the string
char *bPrevUTF8(const char *string, const char *utf8); previous code point
char *idx2PtrUTF8(const char *utf8, intmax_t index); character index to pointer
intmax_t ptr2IdxUTF8(const char *utf8, const char *pos); pointer to character index
char *makeValidUTF8(const char *utf8); make new valid UTF-8 encoded string

Arrays, Vector, Slice, Indexer, Slab, Bitsets

slice, staticSlice, vector, dVector, staticArray, dArray, slab, staticBitset, bitset are data structures defined in libsheepy.h.

They are arrays of user defined element type with counters and the other properties not available with C arrays.

The elements are accessed directly like regular C arrays with the At macros: vectorAt(&vectr, 1) = 3;.

Name Description
slice dynamic array in one chunk of memory with element count (similar to vector and slab), the array is realloced when adding elements
staticSlice C array with variable element count
vector dynamic array in one chunk of memory with element count and maximum element count (similar to slab below)
dVector dynamic segmented vector, the elements are stored in segments, adding elements adds new mallocated segments
staticArray this type of array has a static maximum element count (fixed), head and last indexes, this allows dequeuing from head elements fast. It is used as a circular buffer, queue, fifo...
dArray dynamic segmented array with maximum element count, head and last indexes, adding elements adds new mallocated segments
slab dynamic array in one chunk of memory with maximum element count, head and last indexes
staticBitset static bitset holding a fixed bit count
bitset bitset macros for creating dynamic bitsets using slice

The indexer allows seperating the data from the maximum count, head and last indexes. The indexer macros operate on a struct holding count, head and last indexes.

slice, staticSlice, vector, dVector, staticArray, dArray, slab are prefixes for the macros operating on the data structures. The macros define the types and handle the elements.

Name Description
*T declare type, for example sliceT(mysliceType, char*);
create*(typeName, name) declare variable name and call *Init
create*Count(typeName, name, count) declare variable name and initialize count
create*ClearCount(typeName, name, count) declare variable name, calloc array and initialize count
createAllocate*(typeName, name) declare variable name pointer and initialize
createAllocate*Count(typeName, name, count) declare variable name pointer and initialize count
createAllocate*ClearCount(typeName, name, count) declare variable name pointer, calloc array and initialize count
*Terminate(name) free elements and name pointer
*Init(name) initialize array
*InitCount(name, countInt) initialize array and count
*Calloc(name, countInt) initialize array and count and set elements to 0
*Resize(name, countInt) resize array
*ClearResize(name, countInt) resize array and clear new elements with memset
*Free(name) free internal buffers
*ElemType(name) element type
*ElemPtrType(name) element type pointer
*Dup(name) duplicate
*CreateNDup(name, dest) declare variable dest and duplicate name
*BDup(name, dest) duplicate to already declared dest of type name
*Data(name) direct access to underlying array
*From(name, array, countInt) copy data from array
*Mirror(name, start, end) mirror a range and return struct, the data is not copied to dest, to copy data see *Copy or *BCopy
*BMirror(name, dest, start, end) mirror a range o already declared dest of type name, the data is not copied to dest, to copy data see *Copy or *BCopy
*MirrorFrom(name, array, countInt) mirror from array, the data is not copied to dest
*Clear(name) set 0 in elements
*ClearRange(name, start, end) set 0 in a range of elements
*Empty(name) set count to 0
*IsEmpty(name) true when array is empty
*Fit(name) reallac to fit element count
*Count(name) return element count
*MaxCount(name) return max count
*ElemSize(name) element size
*Alloc(name) allocate an element, only when the array is full
*ClearElem(name, index) clear (set 0) in element at index
*Push(name) push element and expand the array, no data is set in the new element
*Append(name, v) append element and expand the array
*ClearPush(name) push element and expand the array, the new element is cleared
*Pop(name) pop element, return last element and decrease the element count
*DelLast(name) delete the last element
*Set(name, index, v) set value at index and clearResize array when index is outside array count
*At(name, index) get / set element at index (direct access to element)
*Ptr(name, index) get pointer to element at index
*Last(name) last element
*LastPtr(name) pointer to last element
*LastIndex(name) index of last element
*First(name) first element
*WriteFilename(name, filename) write the array content to filename file
*Write(name, file) write the array content to disk
*ReadFilename(name, filename) read an array from filename file
*Read(name, file) read an array from disk
forEachV(name, index) loop on indexes of slice, staticSlice, vector and dVector
*Inject(name, index) insert an element at index
*Prepend(name, v) prepend element
*Dequeue(name) return and remove first element
*DelFirst(name) delete first element in array
*DelElem(name, index) delete an element in array
*Del(name, start, end) delete range in array
*VAppend(name, slice) append slice to array name, the data is copied
*AppendFrom(name, array, countInt) append array to array name, the data is copied
*VPrepend(name, slice) prepend array to array name, the data in array name is moved and the data in slice is copied to array name
*PrependFrom(name, array, countInt) prepend array to array name, the data in slice is moved and the data in array is copied to array name
*Insert(name, index, slice) insert slice at position index, the data in array name is moved and the data in slice is copied to array name
*InsertFrom(name, index, array, countInt) insert array at position index, the data in array name is moved and the data in array is copied to array name
*Slice(name, start, end) slice array name, keep only elements between start and end, start must be between 0 and last index, end must be between 1 and count, the slice is returned
*Copy(name, start, end) copy array name elements between start and end to a new array, start must be between 0 and last index, end must be between 1 and count, the new array is returned and must be freed with sliceTerminate
*BCopy(name, dest, start, end) copy elements between start and end to dest
*Sort(name, compareFunction) sort array
*Eq(name, slice, eqFunction) array equality
*Has(name, value, eqFunction) return true when array name has value
*IndexOf(name, value, eqFunction) return index (ssize_t) of value in array name
*BinarySearch(name, value, less, equal) binary search
*Uniq(name, eqFunction) Uniquify elements

Bitset macros:

Name Description
*staticBitset0(name, index) or bitset0(name, at, index) set 0 at index
*staticBitset1(name, index) or bitset1(name, at, index) set 1 at index
*staticBitsetInv(name, index) or bitsetInv(name, at, index) invert bit at index
*staticBitsetGet(name, index) or bitsetGet(name, at, index) get bit at index

Examples:

sliceT(typeName, type);
typeName slce;
sliceInit(&slce);
// or
sliceInitCount(&slce, 17);
sliceAppend(&slce, value);
// get an element
int a                = sliceAt(&slce, 0);
// set
sliceAt(&slce, 1) = 3;
sliceFree(&slce);

staticSliceT(typeName, type, 10);
typeName slce;
staticSliceInit(&slce);
staticSliceAppend(&slce, value);
// get an element
int a                = staticSliceAt(&slce, 0);
// set
staticSliceAt(&slce, 1) = 3;
staticSliceFree(&slce);

vectorT(typeName, type);
typeName vectr;
vectorInit(&vectr);
// or
vectorInitCount(&vectr, 17);
vectorAppend(&vectr, value);
// get an element
int a                = vectorAt(&vectr, 0);
// set
vectorAt(&vectr, 1) = 3;
vectorFree(&vectr);

dVectorT(typeName, type);
typeName dvector;
dVectorInit(&dvector);
// or
dVectorInitCount(&dvector, 17);
dVectorAppend(&dvector, value);
// get an element
int a                = dVectorAt(&dvector, 0);
// set
dVectorAt(&dvector, 1) = 3;
dVectorFree(&dvector);

typedef struct {
  int a;
  char *key;
} element;
staticArrayT(typeName, element, 10);
typeName array;
staticArrayInit(array);
staticArrayPush(array);
staticArrayLast(array).a = fork();
val = staticArrayLast(array).a;
staticArrayPop(array);

char array[10][5];
// declare an indexer with smaller counters (default is int64_t):
indexerT(typeName, i8);
typeName indx;
indexerInit(indx, 10);
indexerPush(indx);
array[indexerLast(indx)][0] = '0';
// or
indexerPush(indx);
array[indx.last][0] = '0';
indexerPop(indx);
// accessing the first/head element
char c = array[indexerFirst(indx)][0];
char c = array[indx.head][0];

dArrayT(typeName, type);
typeName darray;
dArrayInit(&darray);
// or
dArrayInitCount(&darray, 17);
dArrayAppend(&darray, value);
// get an element
int a                = dArrayAt(&darray, 0);
// set
dArrayAt(&darray, 1) = 3;
dArrayFree(&darray);

slabT(typeName, type);
typeName slab;
slabInit(&slab);
// or
slabInitCount(&slab, 17);
slabAppend(&slab, value);
// get an element
int a                = slabAt(&slab, 0);
// set
slabAt(&slab, 1) = 3;
slabFree(&slab);

Thread Pool

The thread pool is initialized by initLibsheepy and the prefix for the thread pool is tpool.

The thread pool runs functions of type void f(void *p) where p is a pointer of your choice.

The functions are added to the thread pool queue using tpoolAdd and the first available thread runs the first function in the queue.

There is one thread per core and the threads are started with CPU affinity so they always run on the same core.

tpollWait waits until all the functions in the thread pool queue are finished.

tpool.h is the header for the thread pool and is included in libsheepyObject.h.

Thread pool function list:

Name Description
tpoolAdd(task, args) add a function to the thread pool queue
tpoolWait; wait until all functions in the thread pool are finished
tpoolKill; stop/kill the thread pool
tpoolPause; pause the thread pool
tpoolResume; resume the thread pool
tpoolNum; show number of working threads

Example:

int i = 0;

void emptyTask() {
  puts("the empty task");
}

void incTask(void *p) {
  int *i = (int*)p;
  sleep(1);
  (*i)++;
}

int main(int ARGC, char** ARGV) {
  initLibsheepy(ARGV[0]);
  tpoolAdd(emptyTask, NULL);
  tpoolAdd(incTask, &i);
  puts("Threads are running");
  tpoolWait;
  puts("All functions are finished");
}

Further Information