/* See LICENSE file for copyright and license details. */ #include "common.h" enum libsyscalls_error libsyscalls_parse_signed_integer(unsigned long long int value_in, enum libsyscalls_datatype_sign_representation representation, size_t bits, unsigned long long int *value_out, int *negative_out) { unsigned long long int value = value_in, mask; int negative = 0; if (!bits || bits > sizeof(value) / sizeof(char) * CHAR_BIT) return LIBSYSCALLS_E_INVAL; switch (representation) { case LIBSYSCALLS_SIGN_UNDETERMINED: break; case LIBSYSCALLS_SIGN_TWOS_COMPLEMENT: if (value >> (bits - 1U)) { mask = (1ULL << (bits - 1U)) - 1ULL; value = ~value & mask; value += 1ULL; negative = 1; } break; case LIBSYSCALLS_SIGN_ONES_COMPLEMENT: if (value >> (bits - 1U)) { mask = (1ULL << (bits - 1U)) - 1ULL; value = ~value & mask; negative = 1; } break; case LIBSYSCALLS_SIGN_SIGN_MAGNITUDE: if (value >> (bits - 1U)) { value ^= 1ULL << (bits - 1U); negative = 1; } break; case LIBSYSCALLS_SIGN_EXCESS_HALF: if (value >> (bits - 1U)) { value ^= 1ULL << (bits - 1U); } else { value = (1ULL << (bits - 1U)) - value; negative = 1; } break; default: return LIBSYSCALLS_E_INVAL; } if (value_out) *value_out = value; if (negative_out) *negative_out = negative; return LIBSYSCALLS_E_OK; }