hmml_to_youtube.c: Handle unsupported chars [#9]

This commit is contained in:
Matt Mascarenhas 2017-04-11 00:47:46 +01:00
parent 5d495a9997
commit da4c64f5d6
2 changed files with 192 additions and 124 deletions

View File

@ -1,6 +1,6 @@
#if 0 #if 0
ctime -begin ${0%.*}.ctm ctime -begin ${0%.*}.ctm
clang -g -fsanitize=address $0 -o ${0%.*} hmml.a gcc -g -fsanitize=address $0 -o ${0%.*} hmml.a
ctime -end ${0%.*}.ctm ctime -end ${0%.*}.ctm
exit exit
#endif #endif
@ -8,6 +8,7 @@ exit
#include "hmmlib.h" #include "hmmlib.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h>
#ifndef bool #ifndef bool
typedef unsigned int bool; typedef unsigned int bool;
@ -34,28 +35,36 @@ StringLength(char *String)
return i; return i;
} }
bool char
StringsDiffer(char A[], char B[]) ToLower(char Char)
{ {
char APtr, BPtr; if(Char >= 'A' && Char <= 'Z')
while(*A)
{ {
APtr = *A++; Char += 'a' - 'A';
BPtr = *B++;
if(APtr >= 'A' && APtr <= 'Z')
{
APtr += 32;
}
if(BPtr >= 'A' && BPtr <= 'Z')
{
BPtr += 32;
}
if(APtr != BPtr)
{
return TRUE;
}
} }
return FALSE; return Char;
}
int
StringsDiffer(char *A, char *B)
{
while(*A && *B && ToLower(*A) == ToLower(*B))
{
++A, ++B;
}
return *A - *B;
}
__attribute__ ((format (printf, 2, 3)))
void
CopyStringToBuffer(buffer *Dest, char *Format, ...)
{
va_list Args;
va_start(Args, Format);
int Length = vsprintf(Dest->Ptr, Format, Args);
va_end(Args);
Dest->Ptr += Length;
} }
int int
@ -88,7 +97,6 @@ main(int ArgC, char **Args)
// Buffers and Pointers // Buffers and Pointers
char *InPtr; // Associated buffer is allocated by hmml_parse_file() char *InPtr; // Associated buffer is allocated by hmml_parse_file()
buffer Temp; // Temp.Ptr may be used independently of Temp.Location
buffer Out; buffer Out;
//printf("Reading %s\n", Args[FileIndex]); //printf("Reading %s\n", Args[FileIndex]);
@ -101,12 +109,12 @@ main(int ArgC, char **Args)
Out.Size = 1024*16; Out.Size = 1024*16;
ClaimedMemory += Out.Size; ClaimedMemory += Out.Size;
bool WritingChat = TRUE;
char *Member = HMML.metadata.twitch ? char *Member = HMML.metadata.twitch ?
HMML.metadata.twitch : HMML.metadata.twitch :
HMML.metadata.member; HMML.metadata.member;
bool WritingChat = TRUE;
for(int BuildPass = 0; BuildPass < 2; ++BuildPass) for(int BuildPass = 0; BuildPass < 2; ++BuildPass)
{ {
if(WritingChat == FALSE) if(WritingChat == FALSE)
@ -115,111 +123,90 @@ main(int ArgC, char **Args)
} }
Out.Ptr = Out.Location; Out.Ptr = Out.Location;
HMML_Annotation *Anno;
for(int AnnotationIndex = 0; AnnotationIndex < HMML.annotation_count; ++AnnotationIndex) for(int AnnotationIndex = 0; AnnotationIndex < HMML.annotation_count; ++AnnotationIndex)
{ {
if(HMML.annotations[AnnotationIndex].author && !WritingChat) Anno = HMML.annotations + AnnotationIndex;
if(Anno->author && !WritingChat)
{ {
goto skip; goto skip;
} }
InPtr = HMML.annotations[AnnotationIndex].time; CopyStringToBuffer(&Out, "%s ", Anno->time);
while(*InPtr) InPtr = Anno->text;
if(Anno->author)
{ {
*Out.Ptr++ = *InPtr++; CopyStringToBuffer(&Out, "Chat comment: \"");
} }
*Out.Ptr++ = ' ';
InPtr = HMML.annotations[AnnotationIndex].text; int MarkerIndex = 0, RefIndex = 0, InOffset = 0;
while(*InPtr || RefIndex < Anno->reference_count)
// TODO(matt): Get this logic correct
if(HMML.annotations[AnnotationIndex].author)
{ {
Temp.Location = "Chat comment: \""; if(MarkerIndex < Anno->marker_count &&
Temp.Ptr = Temp.Location; InPtr - Anno->text == Anno->markers[MarkerIndex].offset)
while(*Temp.Ptr)
{ {
*Out.Ptr++ = *Temp.Ptr++; char *Readable = Anno->markers[MarkerIndex].parameter
} ? Anno->markers[MarkerIndex].parameter
: Anno->markers[MarkerIndex].marker;
if(*HMML.annotations[AnnotationIndex].text) if(Anno->markers[MarkerIndex].type == HMML_MEMBER && (!StringsDiffer(Anno->markers[MarkerIndex].marker, Member)))
{
InPtr = HMML.annotations[AnnotationIndex].text;
if(!StringsDiffer(Member, InPtr))
{ {
InPtr += StringLength(Member); InPtr += StringLength(Readable);
while(*InPtr && while(*InPtr &&
!(*InPtr >= '0' && *InPtr <= '9') && ( *InPtr == ','
!(*InPtr >= 'A' && *InPtr <= 'Z') && || *InPtr == ':'
!(*InPtr >= 'a' && *InPtr <= 'z')) || *InPtr == ' '
)
)
{ {
++InPtr; ++InPtr;
} }
if(InPtr - Anno->text > 0 && !InOffset)
if(*InPtr && *InPtr >= 'a' && *InPtr <= 'z')
{ {
*InPtr -= 32; InOffset = InPtr - Anno->text;
} }
} }
++MarkerIndex;
} }
}
if(HMML.annotations[AnnotationIndex].reference_count) if(RefIndex < Anno->reference_count &&
{ InPtr - Anno->text == Anno->references[RefIndex].offset)
for(int RefIndex = 0; RefIndex < HMML.annotations[AnnotationIndex].reference_count; ++RefIndex)
{ {
while(InPtr - HMML.annotations[AnnotationIndex].text < HMML.annotations[AnnotationIndex].references[RefIndex].offset) if(Anno->references[RefIndex].offset == InOffset)
{ {
*Out.Ptr++ = *InPtr++;
}
if(HMML.annotations[AnnotationIndex].references[RefIndex].offset == 0)
{
if(HMML.annotations[AnnotationIndex].references[RefIndex].page)
{
Temp.Ptr = HMML.annotations[AnnotationIndex].references[RefIndex].page;
}
else if(HMML.annotations[AnnotationIndex].references[RefIndex].site)
{
Temp.Ptr = HMML.annotations[AnnotationIndex].references[RefIndex].site;
}
else if(HMML.annotations[AnnotationIndex].references[RefIndex].title)
{
Temp.Ptr = HMML.annotations[AnnotationIndex].references[RefIndex].title;
}
if(Out.Ptr[-1] != '"' && Out.Ptr[-1] != ' ') if(Out.Ptr[-1] != '"' && Out.Ptr[-1] != ' ')
{ {
*Out.Ptr++ = ' '; *Out.Ptr++ = ' ';
} }
while(*Temp.Ptr) if(Anno->references[RefIndex].page)
{ {
*Out.Ptr++ = *Temp.Ptr++; CopyStringToBuffer(&Out, "%s", Anno->references[RefIndex].page);
}
else if(Anno->references[RefIndex].site)
{
CopyStringToBuffer(&Out, "%s", Anno->references[RefIndex].site);
}
else if(Anno->references[RefIndex].title)
{
CopyStringToBuffer(&Out, "%s", Anno->references[RefIndex].title);
} }
} }
if(HMML.annotations[AnnotationIndex].references[RefIndex].url) if(Anno->references[RefIndex].url)
{ {
Temp.Ptr = HMML.annotations[AnnotationIndex].references[RefIndex].url; if(Anno->references[RefIndex].offset < StringLength(Anno->text) ||
RefIndex < Anno->reference_count-1)
if(HMML.annotations[AnnotationIndex].references[RefIndex].offset < StringLength(HMML.annotations[AnnotationIndex].text) ||
RefIndex < HMML.annotations[AnnotationIndex].reference_count-1)
{ {
if(Out.Ptr[-1] != ' ') if(Out.Ptr[-1] != ' ')
{ {
*Out.Ptr++ = ' '; *Out.Ptr++ = ' ';
} }
*Out.Ptr++ = '-';
*Out.Ptr++ = ' '; CopyStringToBuffer(&Out, "- %s -", Anno->references[RefIndex].url);
while(*Temp.Ptr)
{
*Out.Ptr++ = *Temp.Ptr++;
}
*Out.Ptr++ = ' ';
*Out.Ptr++ = '-';
} }
else else
{ {
@ -229,24 +216,36 @@ main(int ArgC, char **Args)
} }
if(InPtr[-3] != ':') if(InPtr[-3] != ':')
{ {
*Out.Ptr++ = ':'; CopyStringToBuffer(&Out, ": ");
*Out.Ptr++ = ' ';
}
while(*Temp.Ptr)
{
*Out.Ptr++ = *Temp.Ptr++;
} }
CopyStringToBuffer(&Out, "%s", Anno->references[RefIndex].url);
} }
} }
++RefIndex;
} }
if(*InPtr)
{
switch(*InPtr)
{
case '<':
CopyStringToBuffer(&Out, "&lt;");
break;
case '>':
CopyStringToBuffer(&Out, "&gt;");
break;
case '#':
break;
default:
*Out.Ptr++ = *InPtr;
break;
}
++InPtr;
}
} }
while(*InPtr) if(Anno->author &&
{
*Out.Ptr++ = *InPtr++;
}
if(HMML.annotations[AnnotationIndex].author &&
WritingChat == TRUE) WritingChat == TRUE)
{ {
*Out.Ptr++ = '\"'; *Out.Ptr++ = '\"';
@ -256,22 +255,9 @@ main(int ArgC, char **Args)
skip: {}; skip: {};
} }
Temp.Location = MemoryArena + ClaimedMemory; CopyStringToBuffer(&Out, "\nAnnotated by %s - https://handmade.network/m/%s\n",
Temp.Size = 256;
ClaimedMemory += Temp.Size;
Temp.Ptr = Temp.Location;
sprintf(Temp.Location, "\nAnnotated by %s - https://handmade.network/m/%s\n",
HMML.metadata.annotator, HMML.metadata.annotator); HMML.metadata.annotator, HMML.metadata.annotator);
while(*Temp.Ptr)
{
*Out.Ptr++ = *Temp.Ptr++;
}
*Temp.Location = '\0';
ClaimedMemory -= Temp.Size;
if(Out.Ptr - Out.Location > 5000) if(Out.Ptr - Out.Location > 5000)
{ {
WritingChat = FALSE; WritingChat = FALSE;
@ -291,23 +277,17 @@ skip: {};
hmml_free(&HMML); hmml_free(&HMML);
// NOTE(matt): Open a file for writing out to // NOTE(matt): Open a file for writing out to
Temp.Location = MemoryArena + ClaimedMemory; char Filename[StringLength(Args[FileIndex]) + 5];
Temp.Size = StringLength(Args[FileIndex]) + 5; sprintf(Filename, "%s.txt", Args[FileIndex]);
ClaimedMemory += Temp.Size; //printf("Writing to %s\n", Filename);
sprintf(Temp.Location, "%s.txt", Args[FileIndex]);
//printf("Writing to %s\n", Temp.Location);
FILE *OutFile; FILE *OutFile;
if(!(OutFile = fopen(Temp.Location, "w"))) if(!(OutFile = fopen(Filename, "w")))
{ {
perror(Args[0]); perror(Args[0]);
free(MemoryArena); free(MemoryArena);
return 1; return 1;
} }
*Temp.Location = '\0';
ClaimedMemory -= Temp.Size;
fwrite(Out.Location, Out.Ptr - Out.Location, 1, OutFile); fwrite(Out.Location, Out.Ptr - Out.Location, 1, OutFile);
fclose(OutFile); fclose(OutFile);
} }

88
hmml_to_youtube/hmmlib.h Normal file
View File

@ -0,0 +1,88 @@
#ifndef HMML_H_
#define HMML_H_
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h>
// Data structures
typedef struct {
char* member;
char* twitch;
char* project;
char* title;
char* platform;
char* id;
char* annotator;
} HMML_VideoMetaData;
typedef struct {
char* site;
char* page;
char* url;
char* title;
char* article;
char* author;
char* editor;
char* publisher;
char* isbn;
int offset;
} HMML_Reference;
typedef enum {
HMML_CATEGORY,
HMML_MEMBER,
HMML_PROJECT,
HMML_MARKER_COUNT,
} HMML_MarkerType;
typedef struct {
HMML_MarkerType type;
char* marker;
char* parameter;
int offset;
} HMML_Marker;
typedef struct {
int id;
char* author;
} HMML_Quote;
typedef struct {
int line;
char* time;
char* text;
char* author;
HMML_Reference* references;
size_t reference_count;
HMML_Marker* markers;
size_t marker_count;
HMML_Quote quote;
bool is_quote;
} HMML_Annotation;
typedef struct {
int line;
char* message;
} HMML_Error;
typedef struct {
bool well_formed;
HMML_VideoMetaData metadata;
HMML_Annotation* annotations;
size_t annotation_count;
HMML_Error error;
} HMML_Output;
// Functions
HMML_Output hmml_parse_file (FILE* file);
void hmml_dump (HMML_Output* output);
void hmml_free (HMML_Output* output);
#endif