Nimbin2git.christianimmanuel.de / Games / dvd / test_1.c

dvd files

last change 2026-09-04 (2 hours ago)

wget https://git.christianimmanuel.de/games/dvd/archive/dvd.tar.gz
test_1.c 7.6 KB · 223 lines raw
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>


// ANSI color codes
#define RESET   "\033[0m"
#define RED     "\033[31m"
#define GREEN   "\033[32m"
#define YELLOW  "\033[33m"
#define BLUE    "\033[34m"
#define MAGENTA "\033[35m"
#define CYAN    "\033[36m"
#define WHITE   "\033[37m"

#define MAX_LINE_LENGTH 1024
#define NUM_THREADS 4

// Define the struct to hold the parsed data for each line
typedef struct {
    char *titleId;         // Dynamically allocated
    int ordering;
    char *title;           // Dynamically allocated
    char *region;          // Dynamically allocated
    char *language;        // Dynamically allocated
    char *types;           // Dynamically allocated
    char *attributes;      // Dynamically allocated
    int isOriginalTitle;
} TitleLanguages;

typedef struct {
    FILE *fh;
    long start_offset;
    long end_offset;
    TitleLanguages **parsed_lines;
    int *line_count;
    int thread_id;
} ThreadArgs;

char *strdup(const char *s);

// Function to read and store all lines (as strings)
void *processAkaLinesThread(void *args) {

    ThreadArgs *thread_args = (ThreadArgs *)args;
    FILE *fh = thread_args->fh;
    long start_offset = thread_args->start_offset;
    long end_offset = thread_args->end_offset;
    TitleLanguages **parsed_lines = thread_args->parsed_lines;
    int *line_count = thread_args->line_count;

    printf(MAGENTA "┌──────────────────────────────────────\n└── " CYAN "Starting Thread" YELLOW " %d\n" RESET, thread_args->thread_id);
    // Set the file pointer to the start_offset position
    fseek(fh, start_offset, SEEK_SET);

    char line[MAX_LINE_LENGTH];  // Buffer for each line
    int alloc_size = 10;  // Initial memory allocation size
    *parsed_lines = malloc(alloc_size * sizeof(TitleLanguages));  // Allocate memory for the array of TitleLanguages structs

    if (!*parsed_lines) {
        perror("Memory allocation failed");
        return NULL;
    }

    // Read lines until we reach the end_offset
    while (ftell(fh) < end_offset && fgets(line, sizeof(line), fh)) {
        // Remove newline character from line
        line[strcspn(line, "\n")] = 0;

        // If we've reached the allocated size, reallocate more memory for TitleLanguages array
        if (*line_count >= alloc_size) {
            alloc_size *= 2;  // Double the allocated size
            *parsed_lines = realloc(*parsed_lines, alloc_size * sizeof(TitleLanguages));
            if (!*parsed_lines) {
                perror("Memory reallocation failed");
                return NULL;
            }
        }

        TitleLanguages *current_line = &(*parsed_lines)[*line_count];

        // Parse the fields from the line and directly store them into the struct
        current_line->titleId = strdup(strtok(line, "\t"));
        current_line->ordering = atoi(strtok(NULL, "\t"));
        current_line->title = strdup(strtok(NULL, "\t"));
        current_line->region = strdup(strtok(NULL, "\t"));
        current_line->language = strdup(strtok(NULL, "\t"));
        current_line->types = strdup(strtok(NULL, "\t"));
        current_line->attributes = strdup(strtok(NULL, "\t"));
        current_line->isOriginalTitle = atoi(strtok(NULL, "\t"));

        // If any memory allocation fails, free all previously allocated memory
        if (!current_line->titleId || !current_line->title || !current_line->region || 
            !current_line->language || !current_line->types || !current_line->attributes) {
            perror("Memory allocation failed");
            return NULL;
        }

        (*line_count)++;
    }

    return NULL;
}

// Function to read the Akas file and process lines
int readAkas(TitleLanguages **languages) {
    FILE *fh = NULL;

    // Open the file specified by the constant FILENAME
    fh = fopen("imdb/title.akas.tsv", "r");
    if (!fh) {
        perror("Error opening file");
        return 1;
    }

    // Get the file size to divide the file into chunks for threads
    fseek(fh, 0, SEEK_END);
    long file_size = ftell(fh);
    fclose(fh);

    // Create threads to process file chunks
    pthread_t threads[NUM_THREADS];
    ThreadArgs thread_args[NUM_THREADS];
    long chunk_size = file_size / NUM_THREADS;

    TitleLanguages *merged_languages = NULL;
    int merged_line_count = 0;

    for (int i = 0; i < NUM_THREADS; i++) {
        thread_args[i].fh = fopen("imdb/title.akas.tsv", "r");
        thread_args[i].start_offset = i * chunk_size;
        thread_args[i].end_offset = (i == NUM_THREADS - 1) ? file_size : (i + 1) * chunk_size;
        thread_args[i].parsed_lines = malloc(sizeof(TitleLanguages *));
        if (!thread_args[i].parsed_lines) {
            perror("Memory allocation failed for thread_args[i].parsed_lines"); exit(1); }
        thread_args[i].line_count = malloc(sizeof(int));
        if (!thread_args[i].line_count) {
            perror("Memory allocation failed for thread_args[i].line_count"); exit(1); }
        *thread_args[i].line_count = 0;
        thread_args[i].thread_id = i;

        pthread_create(&threads[i], NULL, processAkaLinesThread, &thread_args[i]);
    }

    // Join threads and combine results
    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);

        // Merge thread results into the final languages array
        for (int j = 0; j < *thread_args[i].line_count; j++) {
            merged_languages = realloc(merged_languages, (merged_line_count + 1) * sizeof(TitleLanguages));
            if (!merged_languages) {
                perror("Memory reallocation failed");
                return 1;
            }

            merged_languages[merged_line_count] = (*thread_args[i].parsed_lines)[j];
            merged_line_count++;
        }

        // Clean up thread-specific memory
        free(thread_args[i].parsed_lines);
        free(thread_args[i].line_count);
        fclose(thread_args[i].fh);
    }

    printf("Processing complete. Total lines read: %d\n", merged_line_count);

    // Assign the merged languages back to the caller
    *languages = merged_languages;

    return merged_line_count;
}

int main(void) {
    TitleLanguages *languages = NULL;
    int line_count = 0;

    // Pass the address of languages to readAkas
    line_count = readAkas(&languages);

    // Print the first 4 lines and last 4 lines of the struct array
    printf("First and last 4 lines processed:\n");
    for (int i = 0; i < line_count; i++) {
        // Print first 4 lines
        if (i < 4) {
            printf("Line %d: %s, %d, %s, %s, %s, %s, %d\n", i + 1, 
                   languages[i].titleId, 
                   languages[i].ordering, 
                   languages[i].title, 
                   languages[i].region, 
                   languages[i].language, 
                   languages[i].types, 
                   languages[i].isOriginalTitle);
        }
        // Print last 4 lines
        if (i >= line_count - 4) {
            printf("Line %d: %s, %d, %s, %s, %s, %s, %d\n", i + 1, 
                   languages[i].titleId, 
                   languages[i].ordering, 
                   languages[i].title, 
                   languages[i].region, 
                   languages[i].language, 
                   languages[i].types, 
                   languages[i].isOriginalTitle);
        }
    }

    // Clean up the array of structs and the dynamically allocated strings
    for (int i = 0; i < line_count; i++) {
        free(languages[i].titleId);
        free(languages[i].title);
        free(languages[i].region);
        free(languages[i].language);
        free(languages[i].types);
        free(languages[i].attributes);
    }
    free(languages);

    return 0;
}