Skip to content

nikita-sakharin/c-commons

Repository files navigation

arithmetic.h:

multiplyHigh (mulHi)
isMultipleOf, nextMultipleOf, prevMultipleOf
icopysign
isignbit (docs.gl, nvidia.com, khronos.org, numpy.org, opencl.org, vulkan.org)
ceilDivMod, euclidDivMod, floorDivMod

bit.h:

{bitCount|popCount}
rotateLeft, rotateRight
clear (reset), set, flip
getBit (testBit):

  • testAll (isAll, getAll, Ruby)
  • testAny (isAny, getAny, Ruby)
  • testNone (isNone, getNone, Ruby)

(are|have|has|is)SameSign[um]

ctype.h:

isAscii, toAscii

debug.h (check.h):

checkArray (checkPointer), checkIndexSize, checkLengthSize

error_handling.h:

Макрос EXIT_IF можно использовать в следующей ситуации: было выделено несколько ресурсов, далее произошла ошибка, GOTO_IF перекинул в место, где выделенные ресурсы освобождаются. Когда вызываем функцию для освобождения ресурса, то возвращаемое значение проверяем уже с помощью EXIT_IF, а не с помощью GOTO_IF. В данном случае напрашивается аналогия с C++ std::terminate, которая вызывается, если при обработке исключения, было выброшено еще одно. Возможно, в рамках данной аналогии, имеет смысл вместо функции exit, использовать _Exit, или даже abort. Но вариант, просто exit видится более органичным, более интуитивным, так как в точности копирует return в main (вызывает atexit и закрывает файловые дискрипторы). С другой стороны вариант с функцией abort ближе по семантике к std::terminate. Вариант при котором будет отдельно макрос с abort и отдельно с exit кажется откровенно спорным.

Так же имеет смысл рассмотреть макрос для вывода сообщений об ошибках в формате POSIX. Например:
dir: cannot access '42': No such file or directory,
где первый аргумент это argv[0], затем сообщение произвольного вида, затем perror.

Итого, получается нужно три макроса под три ситуации:

  1. Размотка стека;
  2. По форме POSIX;
  3. Если при обработке ошибки произошла еще одна.

Для GOTO_IF добавить вариант (или изменить имеющийся макрос?) который записывает текущее значение errno в lvalue (или по указателю?) переданное в макрос, затем зануляет errno (или просто оставляет без изменений?). Переданное lvalue может содержать side-effect. Есть ОЧЕНЬ плохой вариант DO_GOTO_IF с выполнением произвольного блока. Но данный вариант категорически ошибкоопасен и отвергается по понятным причинам.

ERR04-C. Choose an appropriate termination strategy
Baseline for Ed 2 of TR 24772
Errors
Error Messages

math.h:

fclampf, fclamp, fclampl, lerp, saturate
toDegrees, toRadians
DBL_1_PI, DBL_2_PI, DBL_2_SQRTPI, DBL_E, DBL_LN10, DBL_LN2, DBL_LOG10E, DBL_LOG2E, DBL_PHI, DBL_PI, DBL_PI_2, DBL_PI_4, DBL_SQRT1_2, DBL_SQRT2
comb (binomialCoefficient), perm (factorial)
ulp, nextDown, nextUp, union { uint32_t u32; flt f; }
random

numeric.h:

gcd, lcm, midpoint, fmidpoint, isqrt, icbrt

preprocessor.h:

Integer Properties

  • check_* (checked_*), is_*_overflow, is_*_undefined
  • wrapping_*, overflowing_*
  • saturating_*

string.h:
strFormat, strNFormat, strReverse, strNReverse

type_generic.h:
TYPE_GENERIC_POINTER

utility.h:

memSwap:

  • Если в двух файлах используется эта функция, в одном файле NDEBUG объявлен, а в другом нет, то это породит undefined behavior
  • изменить имена переменных s1 и s2 на src1 и src2 ???
  • изменить имя переменной n на size или length (контрпример: strn{cat,cmp,cpy,len}) ???
  • изменить имя переменной offset на step ???
  • сделать const-антной переменную size_t n. Вместо n -= offset использовать offset = min(LEVEL1_DCACHE_LINESIZE, (size_t) (end1 - s1)) ???
  • На данный момент используются разные реализации в зависимости от макроса NDEBUG. Будет лучше подставлять разные реализацию для inline и extern ???

Три уровня интерфейса:

  • Два указателя (mem*)
  • Элемент массива и указатель (elemGet, elemSet, elem*/elem*Mem) ???
  • Два элемента массива (arr*/arrElem*/array*/elem*Elem/arrayCompareMax)
  • Все элементы массива (arrMax/arrElemMax/arrayMax) ???

elemCompareEqual, elemCompareGreater, elemCompareGreaterEqual, elemCompareLess, elemCompareLessEqual, elemCompareNotEqual
memCompareEqual, memCompareGreater, memCompareGreaterEqual, memCompareLess, memCompareLessEqual, memCompareNotEqual
memReverse
memRotate (memExchange, memShift)
ptrRemoveConst (ptrConstCast), ptrRemoveConstVolatile (ptrConstVolatileCast), ptrRemoveVolatile (ptrVolatileCast)

Тестирование:

  • Два goal синонима друг другу: check и test.
  • Следуя практикам xUnit выделяются файлы являющиеся suit-ами и функции внутри этих файлов, являющиеся case-ами, которые тестируют функции из ./src и ./include.
  • Как должен называться файл содержащий тесты для функций находящихся в ./src/arithmetic.c и ./include/arithmetic.h? Существует два варианта:
    • ./test/arithmetic.test.c
    • ./test/arithmetic.c
  • Как должен называться исполняемый файл, скомпилированный из файлов предыдущего пункта? Опять же два варианта:
    • ./test/arithmetic.test.out
    • ./test/arithmetic.out
  • Каждый файл из папки ./test (т.е. suit) содержит функцию main в которой запускаети все тестовые функции (case).
  • Могут ли в папке ./test существовать кроме самих suit-ов еще и другие файлы? Если да, то потребуется продумать где лежат не только .c-файлы, но и местоположение .h-файлов. А это значит, что кроме папки ./include потребуется еще аналогичная папка для заголовочников, которые используются только в тестах. ОЧЕНЬ ПЛОХАЯ ИДЕЯ.