hmml_to_youtube.c: Handle unsupported chars [#9]
This commit is contained in:
parent
5d495a9997
commit
da4c64f5d6
|
@ -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, "<");
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
CopyStringToBuffer(&Out, ">");
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue