login

#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>

#define BUFSZ 256

typedef struct Line {
    uint32_t on, off;
    char *text;
} Line;

typedef struct Subtitles {
    int bulk;
    int count;
    Line *lines;
} Subtitles;

uint32_t
ts2ms(const char *ts)
{
    uint32_t ms = 0;
    ms += atoi(ts) * 60 * 60 * 1000;
    ms += atoi(ts + 3) * 60 * 1000;
    ms += atoi(ts + 6) * 1000;
    ms += atoi(ts + 9);
    return ms;
}

void
ms2ts(char *buffer, size_t bufsiz, uint32_t ms)
{
    unsigned h, m, s;
    h = ms / (60 * 60 * 1000);
    ms %= 60 * 60 * 1000;
    m = ms / (60 * 1000);
    ms %= 60 * 1000;
    s = ms / (1000);
    ms %= 1000;
    snprintf(buffer, bufsiz, "%02u:%02u:%02u,%03u", h, m, s, ms);
}

Subtitles *
load_subs(const char *path)
{
    Subtitles *subs;
    FILE *fp;
    char buffer[BUFSZ];
    char text[4*BUFSZ];
    char *ret = buffer;

    fp = fopen(path, "r");
    if (!fp)
        return NULL;
    subs = malloc(sizeof(*subs));
    subs->bulk = 256;
    subs->count = 0;
    subs->lines = malloc(subs->bulk * sizeof(*subs->lines));
    while (1) {
        Line line;
        /* Discard blank lines; get index or EOF. */
        strcpy(buffer, "");
        while (ret && strlen(buffer) <= 2)
            ret = fgets(buffer, BUFSZ, fp);
        if (!ret)
            break;
        assert(atoi(buffer) == subs->count + 1);
        /* Get time stamps. */
        fgets(buffer, BUFSZ, fp);
        line.on = ts2ms(buffer);
        line.off = ts2ms(buffer + 17);
        /* Get text. */
        fgets(text, BUFSZ, fp);
        while (1) {
            ret = fgets(buffer, BUFSZ, fp);
            if (ret && strlen(buffer) > 2)
                strcat(text, buffer);
            else
                break;
        }
        line.text = malloc(strlen(text) + 1);
        strcpy(line.text, text);
        /* Add line to subtitles. */
        if (subs->count == subs->bulk) {
            subs->bulk += subs->bulk >> 1;
            subs->lines = realloc(subs->lines, subs->bulk * sizeof(*subs->lines));
        }
        subs->lines[subs->count++] = line;
    }
    fclose(fp);
    return subs;
}

void
save_subs(Subtitles *subs, const char *path)
{
    FILE *fp;
    char bufon[13], bufoff[13];
    int i;

    fp = fopen(path, "w");
    if (!fp)
        return;
    for (i = 0; i < subs->count; i++) {
        Line line = subs->lines[i];
        fprintf(fp, "%d\r\n", i + 1);
        ms2ts(bufon, 13, line.on);
        ms2ts(bufoff, 13, line.off);
        fprintf(fp, "%s --> %s\r\n", bufon, bufoff);
        fprintf(fp, "%s\r\n", line.text);
    }
    fclose(fp);
}

void
free_subs(Subtitles **subs)
{
    int i;

    for (i = 0; i < (*subs)->count; i++)
        free((*subs)->lines[i].text);
    free((*subs)->lines);
    free(*subs);
    *subs = NULL;
}

int
main(int argc, char *argv[])
{
    Subtitles *subs;
    assert(argc == 2);
    subs = load_subs(argv[1]);
    save_subs(subs, "test.srt");
    free_subs(&subs);
    return 0;
}