<commit_before>/*
 * Copyright (c) 2012-2019, The University of Oxford
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of the University of Oxford nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "settings/oskar_option_parser.h"
#include "binary/oskar_binary.h"
#include "binary/private_binary.h"
#include "log/oskar_log.h"
#include "mem/oskar_binary_read_mem.h"
#include "utility/oskar_get_binary_tag_string.h"
#include "utility/oskar_get_error_string.h"
#include "utility/oskar_version_string.h"

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <string>

static void print_log(const char* filename, oskar_Log* log, int* status)
{
    int tag_not_present = 0;
    oskar_Binary* h = oskar_binary_create(filename, 'r', status);
    if (*status)
    {
        oskar_binary_free(h);
        return;
    }
    oskar_Mem* temp = oskar_mem_create(OSKAR_CHAR, OSKAR_CPU, 0, status);
    oskar_binary_read_mem(h, temp, OSKAR_TAG_GROUP_RUN,
            OSKAR_TAG_RUN_LOG, 0, &tag_not_present);
    oskar_mem_realloc(temp, oskar_mem_length(temp) + 1, status);
    oskar_mem_char(temp)[oskar_mem_length(temp) - 1] = 0; /* Null-terminate. */
    if (tag_not_present)
        oskar_log_error(log, "Run log not found");
    else
        printf("%s\n", oskar_mem_char(temp));
    oskar_mem_free(temp, status);
    oskar_binary_free(h);
}

static void print_settings(const char* filename, oskar_Log* log, int* status)
{
    int tag_not_present = 0;
    oskar_Binary* h = oskar_binary_create(filename, 'r', status);
    if (*status)
    {
        oskar_binary_free(h);
        return;
    }
    oskar_Mem* temp = oskar_mem_create(OSKAR_CHAR, OSKAR_CPU, 0, status);
    oskar_binary_read_mem(h, temp, OSKAR_TAG_GROUP_SETTINGS,
            OSKAR_TAG_SETTINGS, 0, &tag_not_present);
    oskar_mem_realloc(temp, oskar_mem_length(temp) + 1, status);
    oskar_mem_char(temp)[oskar_mem_length(temp) - 1] = 0; /* Null-terminate. */
    if (tag_not_present)
        oskar_log_error(log, "Settings data not found");
    else
        printf("%s\n", oskar_mem_char(temp));
    oskar_mem_free(temp, status);
    oskar_binary_free(h);
}

static void scan_file(const char* filename, oskar_Log* log, int* status)
{
    int extended_tags = 0, depth = -4, i;
    const char p = 'M';
    oskar_Mem* temp;
    oskar_Binary* h = oskar_binary_create(filename, 'r', status);
    if (*status)
    {
        oskar_binary_free(h);
        return;
    }

    /* Log file header data. */
    const int num_chunks = oskar_binary_num_tags(h);
    oskar_log_section(log, p, "File header in '%s'", filename);
    oskar_log_message(log, p, 0, "File contains %d chunks.", num_chunks);

    /* Iterate all tags in index. */
    oskar_log_section(log, p, "Standard tags:");
    oskar_log_message(log, p, -1, "[%3s] %-23s %5s.%-3s : %-10s (%s)",
            "ID", "TYPE", "GROUP", "TAG", "INDEX", "BYTES");
    oskar_log_message(log, p, depth, "CONTENTS");
    oskar_log_line(log, p, '-');
    for (i = 0; i < num_chunks; ++i)
    {
        size_t num_items = 0;
        if (h->extended[i])
        {
            extended_tags++;
            continue;
        }
        const char group   = (char) (h->id_group[i]);
        const char tag     = (char) (h->id_tag[i]);
        const char type    = (char) (h->data_type[i]);
        const int idx      = h->user_index[i];
        const size_t bytes = h->payload_size_bytes[i];

        /* Display tag data. */
        oskar_log_message(log, p, -1,
                "[%3d] %-23s %5d.%-3d : %-10d (%ld bytes)",
                i, oskar_mem_data_type_string(type), group, tag, idx, bytes);

        /* Display more info if available. */
        const char* label = oskar_get_binary_tag_string(group, tag);
        temp = oskar_mem_create(type, OSKAR_CPU, 0, status);
        if (bytes <= 512 || type == OSKAR_CHAR)
            oskar_binary_read_mem(h, temp, group, tag, idx, status);
        const int precision = oskar_type_precision((int)type);
        num_items = oskar_mem_length(temp);
        if (oskar_type_is_complex(type)) num_items *= 2;
        if (oskar_type_is_matrix(type)) num_items *= 4;
        switch (precision)
        {
        case OSKAR_CHAR:
        {
            size_t c = 0;
            char* data = oskar_mem_char(temp);
            const int max_string_length = 40;
            const char* fmt = "%s: %.*s";
            for (c = 0; c < bytes && c < oskar_mem_length(temp); ++c)
                if (data[c] < 32) data[c] = ' ';
            if (bytes > max_string_length) fmt = "%s: %.*s ...";
            oskar_log_message(log, p, depth, fmt, label,
                    max_string_length, oskar_mem_char(temp));
            break;
        }
        case OSKAR_INT:
        {
            const int* data = oskar_mem_int_const(temp, status);
            switch (num_items)
            {
            case 0:
                oskar_log_message(log, p, depth, "%s", label);
                break;
            case 1:
                oskar_log_message(log, p, depth, "%s: %d", label, data[0]);<commit_msg>Ensure nulls are not overwritten.<commit_after>/*
 * Copyright (c) 2012-2019, The University of Oxford
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of the University of Oxford nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "settings/oskar_option_parser.h"
#include "binary/oskar_binary.h"
#include "binary/private_binary.h"
#include "log/oskar_log.h"
#include "mem/oskar_binary_read_mem.h"
#include "utility/oskar_get_binary_tag_string.h"
#include "utility/oskar_get_error_string.h"
#include "utility/oskar_version_string.h"

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <string>

static void print_log(const char* filename, oskar_Log* log, int* status)
{
    int tag_not_present = 0;
    oskar_Binary* h = oskar_binary_create(filename, 'r', status);
    if (*status)
    {
        oskar_binary_free(h);
        return;
    }
    oskar_Mem* temp = oskar_mem_create(OSKAR_CHAR, OSKAR_CPU, 0, status);
    oskar_binary_read_mem(h, temp, OSKAR_TAG_GROUP_RUN,
            OSKAR_TAG_RUN_LOG, 0, &tag_not_present);
    oskar_mem_realloc(temp, oskar_mem_length(temp) + 1, status);
    oskar_mem_char(temp)[oskar_mem_length(temp) - 1] = 0; /* Null-terminate. */
    if (tag_not_present)
        oskar_log_error(log, "Run log not found");
    else
        printf("%s\n", oskar_mem_char(temp));
    oskar_mem_free(temp, status);
    oskar_binary_free(h);
}

static void print_settings(const char* filename, oskar_Log* log, int* status)
{
    int tag_not_present = 0;
    oskar_Binary* h = oskar_binary_create(filename, 'r', status);
    if (*status)
    {
        oskar_binary_free(h);
        return;
    }
    oskar_Mem* temp = oskar_mem_create(OSKAR_CHAR, OSKAR_CPU, 0, status);
    oskar_binary_read_mem(h, temp, OSKAR_TAG_GROUP_SETTINGS,
            OSKAR_TAG_SETTINGS, 0, &tag_not_present);
    oskar_mem_realloc(temp, oskar_mem_length(temp) + 1, status);
    oskar_mem_char(temp)[oskar_mem_length(temp) - 1] = 0; /* Null-terminate. */
    if (tag_not_present)
        oskar_log_error(log, "Settings data not found");
    else
        printf("%s\n", oskar_mem_char(temp));
    oskar_mem_free(temp, status);
    oskar_binary_free(h);
}

static void scan_file(const char* filename, oskar_Log* log, int* status)
{
    int extended_tags = 0, depth = -4, i;
    const char p = 'M';
    oskar_Mem* temp;
    oskar_Binary* h = oskar_binary_create(filename, 'r', status);
    if (*status)
    {
        oskar_binary_free(h);
        return;
    }

    /* Log file header data. */
    const int num_chunks = oskar_binary_num_tags(h);
    oskar_log_section(log, p, "File header in '%s'", filename);
    oskar_log_message(log, p, 0, "File contains %d chunks.", num_chunks);

    /* Iterate all tags in index. */
    oskar_log_section(log, p, "Standard tags:");
    oskar_log_message(log, p, -1, "[%3s] %-23s %5s.%-3s : %-10s (%s)",
            "ID", "TYPE", "GROUP", "TAG", "INDEX", "BYTES");
    oskar_log_message(log, p, depth, "CONTENTS");
    oskar_log_line(log, p, '-');
    for (i = 0; i < num_chunks; ++i)
    {
        size_t num_items = 0;
        if (h->extended[i])
        {
            extended_tags++;
            continue;
        }
        const char group   = (char) (h->id_group[i]);
        const char tag     = (char) (h->id_tag[i]);
        const char type    = (char) (h->data_type[i]);
        const int idx      = h->user_index[i];
        const size_t bytes = h->payload_size_bytes[i];

        /* Display tag data. */
        oskar_log_message(log, p, -1,
                "[%3d] %-23s %5d.%-3d : %-10d (%ld bytes)",
                i, oskar_mem_data_type_string(type), group, tag, idx, bytes);

        /* Display more info if available. */
        const char* label = oskar_get_binary_tag_string(group, tag);
        temp = oskar_mem_create(type, OSKAR_CPU, 0, status);
        if (bytes <= 512 || type == OSKAR_CHAR)
            oskar_binary_read_mem(h, temp, group, tag, idx, status);
        const int precision = oskar_type_precision((int)type);
        num_items = oskar_mem_length(temp);
        if (oskar_type_is_complex(type)) num_items *= 2;
        if (oskar_type_is_matrix(type)) num_items *= 4;
        switch (precision)
        {
        case OSKAR_CHAR:
        {
            size_t c = 0;
            char* data = oskar_mem_char(temp);
            const int max_string_length = 40;
            const char* fmt = "%s: %.*s";
            for (c = 0; c < bytes && c < oskar_mem_length(temp); ++c)
                if (data[c] < 32 && data[c] != 0) data[c] = ' ';
            if (bytes > max_string_length) fmt = "%s: %.*s ...";
            oskar_log_message(log, p, depth, fmt, label,
                    max_string_length, oskar_mem_char(temp));
            break;
        }
        case OSKAR_INT:
        {
            const int* data = oskar_mem_int_const(temp, status);
            switch (num_items)
            {
            case 0:
                oskar_log_message(log, p, depth, "%s", label);
                break;
            case 1:
                oskar_log_message(log, p, depth, "%s: %d", label, data[0]);
{'fraction_non_alphanumeric': 0.11328185328185328, 'fraction_numerical': 0.009189189189189189, 'mean_word_length': 2.877544910179641, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 25, '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': '7541534', 'n_tokens_mistral': 4526, 'n_tokens_neox': 4245, 'n_words': 1219}