<commit_before>#include <stdio.h>
#include <string.h>
#include <glib.h>
#include <math.h>

#include "sizes.h"

#define INT_FLOAT_EPS 1e-5
#define INT_EQ_FLOAT(i, f) (ABS ((f) - (i)) < INT_FLOAT_EPS)
#define INT_LT_FLOAT(i, f) (((i) - (f)) < INT_FLOAT_EPS)
#define INT_GT_FLOAT(i, f) (((i) - (f)) > INT_FLOAT_EPS)

#define NUM_PREFIXES 7
static gchar const * const size_prefixes[NUM_PREFIXES] = {"", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei"};

GQuark bd_utils_size_error_quark (void)
{
    return g_quark_from_static_string ("g-bd-utils-size-error-quark");
}

/**
 * get_unit_prefix_power: (skip)
 *
 * Returns: power of the @prefix or %NUM_PREFIXES if not found
 */
static guint8 get_unit_prefix_power (gchar *prefix) {
    guint i = 0;

    for (i = 0; size_prefixes[i]; i++)
        if (g_str_has_prefix (size_prefixes[i], prefix))
            return i;

    return NUM_PREFIXES;
}

/**
 * bd_utils_size_human_readable:
 * @size: size to get human readable representation of
 *
 * Returns: human readable representation of the given @size
 */
gchar* bd_utils_size_human_readable (guint64 size) {
    guint8 i = 0;
    gdouble value = (gdouble) size;
    gdouble prev_value = (gdouble) value;

    for (i=0; i < NUM_PREFIXES && INT_LT_FLOAT(1024, value); i++) {
        prev_value = value;
        value = value / 1024.0;
    }

    if (INT_GT_FLOAT(10, value)) {
        value = prev_value;
        i = i - 1;
    }

    if (INT_EQ_FLOAT (value, (guint64) value))
        return g_strdup_printf ("%"G_GUINT64_FORMAT" %sB", (guint64) value, size_prefixes[i]);
    else
        return g_strdup_printf ("%.2f %sB", value, size_prefixes[i]);
}

/**
 * bd_utils_size_from_spec:
 * @spec: human readable size specification (e.g. "512 MiB")
 * @error: (out): place to store error (if any)
 *
 * Returns: number of bytes equal to the size specification rounded to bytes, if
 * 0, @error) may be set in case of error
 */
guint64 bd_utils_size_from_spec (gchar *spec, GError **error) {
    gchar const * const pattern = "^\\s*(\\d+\\.?\\d*)\\s*([kmgtpeKMGTPE]i?)[bB]";
    gchar const * const zero_pattern = "^\\s*0\\.?0*\\s*$";
    GRegex *regex = NULL;
    GRegex *zero_regex = NULL;<commit_msg>Zero size may have some units specified<commit_after>#include <stdio.h>
#include <string.h>
#include <glib.h>
#include <math.h>

#include "sizes.h"

#define INT_FLOAT_EPS 1e-5
#define INT_EQ_FLOAT(i, f) (ABS ((f) - (i)) < INT_FLOAT_EPS)
#define INT_LT_FLOAT(i, f) (((i) - (f)) < INT_FLOAT_EPS)
#define INT_GT_FLOAT(i, f) (((i) - (f)) > INT_FLOAT_EPS)

#define NUM_PREFIXES 7
static gchar const * const size_prefixes[NUM_PREFIXES] = {"", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei"};

GQuark bd_utils_size_error_quark (void)
{
    return g_quark_from_static_string ("g-bd-utils-size-error-quark");
}

/**
 * get_unit_prefix_power: (skip)
 *
 * Returns: power of the @prefix or %NUM_PREFIXES if not found
 */
static guint8 get_unit_prefix_power (gchar *prefix) {
    guint i = 0;

    for (i = 0; size_prefixes[i]; i++)
        if (g_str_has_prefix (size_prefixes[i], prefix))
            return i;

    return NUM_PREFIXES;
}

/**
 * bd_utils_size_human_readable:
 * @size: size to get human readable representation of
 *
 * Returns: human readable representation of the given @size
 */
gchar* bd_utils_size_human_readable (guint64 size) {
    guint8 i = 0;
    gdouble value = (gdouble) size;
    gdouble prev_value = (gdouble) value;

    for (i=0; i < NUM_PREFIXES && INT_LT_FLOAT(1024, value); i++) {
        prev_value = value;
        value = value / 1024.0;
    }

    if (INT_GT_FLOAT(10, value)) {
        value = prev_value;
        i = i - 1;
    }

    if (INT_EQ_FLOAT (value, (guint64) value))
        return g_strdup_printf ("%"G_GUINT64_FORMAT" %sB", (guint64) value, size_prefixes[i]);
    else
        return g_strdup_printf ("%.2f %sB", value, size_prefixes[i]);
}

/**
 * bd_utils_size_from_spec:
 * @spec: human readable size specification (e.g. "512 MiB")
 * @error: (out): place to store error (if any)
 *
 * Returns: number of bytes equal to the size specification rounded to bytes, if
 * 0, @error) may be set in case of error
 */
guint64 bd_utils_size_from_spec (gchar *spec, GError **error) {
    gchar const * const pattern = "^\\s*(\\d+\\.?\\d*)\\s*([kmgtpeKMGTPE]i?)[bB]";
    gchar const * const zero_pattern = "^\\s*0\\.?0*\\s*([kmgtpeKMGTPE]i?)?[bB]?$";
    GRegex *regex = NULL;
    GRegex *zero_regex = NULL;
{'fraction_non_alphanumeric': 0.15511775362318841, 'fraction_numerical': 0.017210144927536232, 'mean_word_length': 3.548918640576725, 'pattern_counts': {'":': 0, '<': 17, '<?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': '2834875', 'n_tokens_mistral': 1790, 'n_tokens_neox': 1687, 'n_words': 439}