/* * Copyright (c) 2023 Trackunit Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include "gnss_parse.h" #define GNSS_PARSE_NANO_KNOTS_IN_MMS (1943840LL) #define GNSS_PARSE_NANO (1000000000LL) #define GNSS_PARSE_MICRO (1000000LL) #define GNSS_PARSE_MILLI (1000LL) int gnss_parse_dec_to_nano(const char *str, int64_t *nano) { int64_t sum = 0; int8_t decimal = -1; int8_t pos = 0; int8_t start = 0; int64_t increment; __ASSERT(str != NULL, "str argument must be provided"); __ASSERT(nano != NULL, "nano argument must be provided"); /* Find decimal */ while (str[pos] != '\0') { /* Verify if char is decimal */ if (str[pos] == '.') { decimal = pos; break; } /* Advance position */ pos++; } /* Determine starting position based on decimal location */ pos = decimal < 0 ? pos - 1 : decimal - 1; /* Skip sign if it exists */ start = str[0] == '-' ? 1 : 0; /* Add whole value to sum */ increment = GNSS_PARSE_NANO; while (start <= pos) { /* Verify char is decimal */ if (str[pos] < '0' || str[pos] > '9') { return -EINVAL; } /* Add value to sum */ sum += (str[pos] - '0') * increment; /* Update increment */ increment *= 10; /* Degrement position */ pos--; } /* Check if decimal was found */ if (decimal < 0) { /* Set sign of sum */ sum = start == 1 ? -sum : sum; *nano = sum; return 0; } /* Convert decimal part to nano fractions and add it to sum */ pos = decimal + 1; increment = GNSS_PARSE_NANO / 10LL; while (str[pos] != '\0') { /* Verify char is decimal */ if (str[pos] < '0' || str[pos] > '9') { return -EINVAL; } /* Add value to micro_degrees */ sum += (str[pos] - '0') * increment; /* Update unit */ increment /= 10; /* Increment position */ pos++; } /* Set sign of sum */ sum = start == 1 ? -sum : sum; *nano = sum; return 0; } int gnss_parse_dec_to_micro(const char *str, uint64_t *micro) { int ret; __ASSERT(str != NULL, "str argument must be provided"); __ASSERT(micro != NULL, "micro argument must be provided"); ret = gnss_parse_dec_to_nano(str, micro); if (ret < 0) { return ret; } *micro = (*micro) / GNSS_PARSE_MILLI; return 0; } int gnss_parse_dec_to_milli(const char *str, int64_t *milli) { int ret; __ASSERT(str != NULL, "str argument must be provided"); __ASSERT(milli != NULL, "milli argument must be provided"); ret = gnss_parse_dec_to_nano(str, milli); if (ret < 0) { return ret; } (*milli) = (*milli) / GNSS_PARSE_MICRO; return 0; } int gnss_parse_atoi(const char *str, uint8_t base, int32_t *integer) { char *end; __ASSERT(str != NULL, "str argument must be provided"); __ASSERT(integer != NULL, "integer argument must be provided"); *integer = (int32_t)strtol(str, &end, (int)base); if ('\0' != (*end)) { return -EINVAL; } return 0; }