<commit_before>/*
 * Copyright (c) 2019 Roc authors
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "roc_core/parse_duration.h"
#include "roc_core/log.h"
#include "roc_core/stddefs.h"

namespace roc {
namespace core {

namespace {

const char* find_suffix(const char* str, size_t str_len, const char* suffix) {
    const size_t suffix_len = strlen(suffix);
    if (str_len < suffix_len) {
        return NULL;
    }
    if (strcmp(str + str_len - suffix_len, suffix) != 0) {
        return NULL;
    }
    return str + str_len - suffix_len;
}

} // namespace

bool parse_duration(const char* str, nanoseconds_t& result) {
    if (str == NULL) {
        roc_log(LogError, "parse duration: string is null");
        return false;
    }

    nanoseconds_t multiplier = 0;

    const size_t str_len = strlen(str);
    const char* suffix;

    if ((suffix = find_suffix(str, str_len, "ns"))) {
        multiplier = Nanosecond;
    } else if ((suffix = find_suffix(str, str_len, "us"))) {
        multiplier = Microsecond;
    } else if ((suffix = find_suffix(str, str_len, "ms"))) {
        multiplier = Millisecond;
    } else if ((suffix = find_suffix(str, str_len, "s"))) {
        multiplier = Second;
    } else if ((suffix = find_suffix(str, str_len, "m"))) {
        multiplier = Minute;
    } else if ((suffix = find_suffix(str, str_len, "h"))) {
        multiplier = Hour;
    } else {
        roc_log(LogError, "parse duration: no known suffix (ns, us, ms, s, m, h)");
        return false;
    }

    if (str == suffix || !isdigit(*str)) {
        roc_log(LogError, "parse duration: invalid format, expected <number><suffix>");
        return false;
    }

    char* number_end = NULL;
    long number = strtol(str, &number_end, 10);

    if (number == LONG_MAX || number == LONG_MIN || !number_end || number_end != suffix) {
        roc_log(LogError, "parse duration: invalid format, expected <number><suffix>");
        return false;
    }

    result = nanoseconds_t(number) * multiplier;
    return true;
}

} // namespace core
} // namespace roc<commit_msg>Allow negative numbers in parse_duration<commit_after>/*
 * Copyright (c) 2019 Roc authors
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "roc_core/parse_duration.h"
#include "roc_core/log.h"
#include "roc_core/stddefs.h"

namespace roc {
namespace core {

namespace {

const char* find_suffix(const char* str, size_t str_len, const char* suffix) {
    const size_t suffix_len = strlen(suffix);
    if (str_len < suffix_len) {
        return NULL;
    }
    if (strcmp(str + str_len - suffix_len, suffix) != 0) {
        return NULL;
    }
    return str + str_len - suffix_len;
}

} // namespace

bool parse_duration(const char* str, nanoseconds_t& result) {
    if (str == NULL) {
        roc_log(LogError, "parse duration: string is null");
        return false;
    }

    nanoseconds_t multiplier = 0;

    const size_t str_len = strlen(str);
    const char* suffix;

    if ((suffix = find_suffix(str, str_len, "ns"))) {
        multiplier = Nanosecond;
    } else if ((suffix = find_suffix(str, str_len, "us"))) {
        multiplier = Microsecond;
    } else if ((suffix = find_suffix(str, str_len, "ms"))) {
        multiplier = Millisecond;
    } else if ((suffix = find_suffix(str, str_len, "s"))) {
        multiplier = Second;
    } else if ((suffix = find_suffix(str, str_len, "m"))) {
        multiplier = Minute;
    } else if ((suffix = find_suffix(str, str_len, "h"))) {
        multiplier = Hour;
    } else {
        roc_log(LogError, "parse duration: no known suffix (ns, us, ms, s, m, h)");
        return false;
    }

    if (str == suffix) {
        roc_log(
            LogError,
            "parse duration: invalid format, missing number, expected <number><suffix>");
        return false;
    }

    if (!isdigit(*str) && *str != '-') {
        roc_log(
            LogError,
            "parse duration: invalid format, not a number, expected <number><suffix>");
        return false;
    }

    char* number_end = NULL;
    long number = strtol(str, &number_end, 10);

    if (number == LONG_MAX || number == LONG_MIN || !number_end || number_end != suffix) {
        roc_log(LogError,
                "parse duration: invalid format, can't parse number, expected "
                "<number><suffix>");
        return false;
    }

    result = nanoseconds_t(number) * multiplier;
    return true;
}

} // namespace core
} // namespace roc
{'fraction_non_alphanumeric': 0.1299163179916318, 'fraction_numerical': 0.00502092050209205, 'mean_word_length': 2.697602474864656, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '979844', 'n_tokens_mistral': 1627, 'n_tokens_neox': 1539, 'n_words': 462}