<commit_before>//
//  src/tbd/tbd.cc
//  tbd
//
//  Created by inoahdev on 4/24/17.
//  Copyright © 2017 inoahdev. All rights reserved.
//

#include <mach-o/nlist.h>
#include <mach-o/swap.h>

#include <cerrno>
#include <cstdlib>

#include "group.h"
#include "tbd.h"

const char *tbd::platform_to_string(const enum tbd::platform &platform) noexcept {
    switch (platform) {
        case ios:
            return "ios";

        case macosx:
            return "macosx";

        case watchos:
            return "watchos";

        case tvos:
            return "tvos";

        default:
            return nullptr;
    }
}

enum tbd::platform tbd::string_to_platform(const char *platform) noexcept {
    if (strcmp(platform, "ios") == 0) {
        return platform::ios;
    } else if (strcmp(platform, "macosx") == 0) {
        return platform::macosx;
    } else if (strcmp(platform, "watchos") == 0) {
        return platform::watchos;
    } else if (strcmp(platform, "tvos") == 0) {
        return platform::tvos;
    }

    return (enum platform)-1;
}

enum tbd::version tbd::string_to_version(const char *version) noexcept {
    if (strcmp(version, "v1") == 0) {
        return tbd::version::v1;
    } else if (strcmp(version, "v2") == 0) {
        return tbd::version::v2;
    }

    return (enum tbd::version)-1;
}

tbd::tbd(const std::vector<std::string> &macho_files, const std::vector<std::string> &output_files, const enum tbd::platform &platform, const enum tbd::version &version, const std::vector<const NXArchInfo *> &architecture_overrides)
: macho_files_(macho_files), output_files_(output_files), platform_(platform), version_(version), architectures_(architecture_overrides) {
    this->validate();
}

void tbd::validate() const {
    const auto &architectures = architectures_;
    const auto &version = version_;

    const auto architectures_size = architectures.size();
    if (version == version::v2 && architectures_size != 0) {
        fputs("Overriding architectures is only supported on tbd-version v1\n", stderr);
        exit(1);
    }
}

void tbd::print_symbols(FILE *output_file, const flags &flags, std::vector<symbol> &symbols, symbols_type type) const noexcept {
    if (symbols.empty()) {
        return;
    }

    switch (type) {
        case symbols_type::reexports:
            fprintf(output_file, "%-4sre-exports:%7s", "", "");
            break;

        case symbols_type::symbols:
            fprintf(output_file, "%-4ssymbols:%10s", "", "");
            break;

        case symbols_type::weak_symbols:
            fprintf(output_file, "%-4sweak-def-symbols: ", "");
            break;

        case symbols_type::objc_classes:
            fprintf(output_file, "%-4sobjc-classes:%5s", "", "");
            break;

        case symbols_type::objc_ivars:
            fprintf(output_file, "%-4sobjc-ivars:%7s", "", "");
            break;
    }

    const auto is_valid_symbol = [](const symbol &symbol, symbols_type type) {
        const auto symbols_string = symbol.string();

        switch (type) {
            case symbols_type::reexports:
                return true;

            case symbols_type::symbols: {
                const auto symbols_string_is_objc_class = strncmp(symbols_string, "_OBJC_CLASS_$", 13) == 0;
                const auto symbols_string_is_objc_metaclass = symbols_string_is_objc_class ? false : strncmp(symbols_string, "_OBJC_METACLASS_$", 17) == 0;
                const auto symbols_string_is_objc_ivar = symbols_string_is_objc_class || symbols_string_is_objc_metaclass ? false : strncmp(symbols_string, "_OBJC_IVAR_$", 12) == 0;

                const auto symbol_is_weak = symbol.weak();

                return !symbols_string_is_objc_class && !symbols_string_is_objc_metaclass && !symbols_string_is_objc_ivar && !symbol_is_weak;
                break;
            }

            case symbols_type::weak_symbols:
                return symbol.weak();

            case symbols_type::objc_classes:
                return strncmp(symbols_string, "_OBJC_CLASS_$", 13) == 0 || strncmp(symbols_string, "_OBJC_METACLASS_$", 17) == 0;

            case symbols_type::objc_ivars:
                return strncmp(symbols_string, "_OBJC_IVAR_$", 12) == 0;
        }

        return false;
    };

    auto symbols_begin = symbols.begin();
    auto symbols_end = symbols.end();

    for (; symbols_begin < symbols_end; symbols_begin++) {
        const auto &symbol = *symbols_begin;
        const auto symbol_is_valid = is_valid_symbol(symbol, type);

        if (!symbol_is_valid) {
            continue;
        }

        const auto &symbol_flags = symbol.flags();
        if (symbol_flags != flags) {
            continue;
        }

        break;
    }

    if (symbols_begin == symbols_end) {
        return;
    }

    const auto parse_symbol_string = [](const char *symbol_string, symbols_type type) {
        switch (type) {
            case symbols_type::reexports:
            case symbols_type::symbols:
                return symbol_string;

            case symbols_type::objc_classes: {
                if (strncmp(symbol_string, "_OBJC_CLASS_$", 13) == 0) {
                    return &symbol_string[13];
                }

                if (strncmp(symbol_string, "_OBJC_METACLASS_$", 17) == 0) {
                    return &symbol_string[17];
                }

                return symbol_string;
            }

            case symbols_type::objc_ivars:
                return &symbol_string[12];

            default:
                break;
        }

        return symbol_string;
    };

    const auto line_length_max = 85;

    auto symbols_begin_string = symbols_begin->string();
    auto parsed_symbols_begin_string = parse_symbol_string(symbols_begin_string, type);

    fprintf(output_file, "[ %s", parsed_symbols_begin_string);<commit_msg>Print symbols after checking if symbols-vector contains any symbols of provided type<commit_after>//
//  src/tbd/tbd.cc
//  tbd
//
//  Created by inoahdev on 4/24/17.
//  Copyright © 2017 inoahdev. All rights reserved.
//

#include <mach-o/nlist.h>
#include <mach-o/swap.h>

#include <cerrno>
#include <cstdlib>

#include "group.h"
#include "tbd.h"

const char *tbd::platform_to_string(const enum tbd::platform &platform) noexcept {
    switch (platform) {
        case ios:
            return "ios";

        case macosx:
            return "macosx";

        case watchos:
            return "watchos";

        case tvos:
            return "tvos";

        default:
            return nullptr;
    }
}

enum tbd::platform tbd::string_to_platform(const char *platform) noexcept {
    if (strcmp(platform, "ios") == 0) {
        return platform::ios;
    } else if (strcmp(platform, "macosx") == 0) {
        return platform::macosx;
    } else if (strcmp(platform, "watchos") == 0) {
        return platform::watchos;
    } else if (strcmp(platform, "tvos") == 0) {
        return platform::tvos;
    }

    return (enum platform)-1;
}

enum tbd::version tbd::string_to_version(const char *version) noexcept {
    if (strcmp(version, "v1") == 0) {
        return tbd::version::v1;
    } else if (strcmp(version, "v2") == 0) {
        return tbd::version::v2;
    }

    return (enum tbd::version)-1;
}

tbd::tbd(const std::vector<std::string> &macho_files, const std::vector<std::string> &output_files, const enum tbd::platform &platform, const enum tbd::version &version, const std::vector<const NXArchInfo *> &architecture_overrides)
: macho_files_(macho_files), output_files_(output_files), platform_(platform), version_(version), architectures_(architecture_overrides) {
    this->validate();
}

void tbd::validate() const {
    const auto &architectures = architectures_;
    const auto &version = version_;

    const auto architectures_size = architectures.size();
    if (version == version::v2 && architectures_size != 0) {
        fputs("Overriding architectures is only supported on tbd-version v1\n", stderr);
        exit(1);
    }
}

void tbd::print_symbols(FILE *output_file, const flags &flags, std::vector<symbol> &symbols, symbols_type type) const noexcept {
    if (symbols.empty()) {
        return;
    }

    const auto is_valid_symbol = [](const symbol &symbol, symbols_type type) {
        const auto symbols_string = symbol.string();

        switch (type) {
            case symbols_type::reexports:
                return true;

            case symbols_type::symbols: {
                const auto symbols_string_is_objc_class = strncmp(symbols_string, "_OBJC_CLASS_$", 13) == 0;
                const auto symbols_string_is_objc_metaclass = symbols_string_is_objc_class ? false : strncmp(symbols_string, "_OBJC_METACLASS_$", 17) == 0;
                const auto symbols_string_is_objc_ivar = symbols_string_is_objc_class || symbols_string_is_objc_metaclass ? false : strncmp(symbols_string, "_OBJC_IVAR_$", 12) == 0;

                const auto symbol_is_weak = symbol.weak();

                return !symbols_string_is_objc_class && !symbols_string_is_objc_metaclass && !symbols_string_is_objc_ivar && !symbol_is_weak;
                break;
            }

            case symbols_type::weak_symbols:
                return symbol.weak();

            case symbols_type::objc_classes:
                return strncmp(symbols_string, "_OBJC_CLASS_$", 13) == 0 || strncmp(symbols_string, "_OBJC_METACLASS_$", 17) == 0;

            case symbols_type::objc_ivars:
                return strncmp(symbols_string, "_OBJC_IVAR_$", 12) == 0;
        }

        return false;
    };

    auto symbols_begin = symbols.begin();
    auto symbols_end = symbols.end();

    for (; symbols_begin < symbols_end; symbols_begin++) {
        const auto &symbol = *symbols_begin;
        const auto symbol_is_valid = is_valid_symbol(symbol, type);

        if (!symbol_is_valid) {
            continue;
        }

        const auto &symbol_flags = symbol.flags();
        if (symbol_flags != flags) {
            continue;
        }

        break;
    }

    if (symbols_begin == symbols_end) {
        return;
    }
    
    const auto parse_symbol_string = [](const char *symbol_string, symbols_type type) {
        switch (type) {
            case symbols_type::reexports:
            case symbols_type::symbols:
                return symbol_string;

            case symbols_type::objc_classes: {
                if (strncmp(symbol_string, "_OBJC_CLASS_$", 13) == 0) {
                    return &symbol_string[13];
                }

                if (strncmp(symbol_string, "_OBJC_METACLASS_$", 17) == 0) {
                    return &symbol_string[17];
                }

                return symbol_string;
            }

            case symbols_type::objc_ivars:
                return &symbol_string[12];

            default:
                break;
        }

        return symbol_string;
    };
    
    switch (type) {
        case symbols_type::reexports:
            fprintf(output_file, "%-4sre-exports:%7s", "", "");
            break;
            
        case symbols_type::symbols:
            fprintf(output_file, "%-4ssymbols:%10s", "", "");
            break;
            
        case symbols_type::weak_symbols:
            fprintf(output_file, "%-4sweak-def-symbols: ", "");
            break;
            
        case symbols_type::objc_classes:
            fprintf(output_file, "%-4sobjc-classes:%5s", "", "");
            break;
            
        case symbols_type::objc_ivars:
            fprintf(output_file, "%-4sobjc-ivars:%7s", "", "");
            break;
    }

    const auto line_length_max = 85;

    auto symbols_begin_string = symbols_begin->string();
    auto parsed_symbols_begin_string = parse_symbol_string(symbols_begin_string, type);

    fprintf(output_file, "[ %s", parsed_symbols_begin_string);
{'fraction_non_alphanumeric': 0.11880768905072403, 'fraction_numerical': 0.011347277500211703, 'mean_word_length': 2.394653636102328, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 23, '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': '1947133', 'n_tokens_mistral': 3848, 'n_tokens_neox': 3641, 'n_words': 770}