Added documentation via doxygen
This commit is contained in:
parent
c6605630b5
commit
0a1a4e8803
5 changed files with 3045 additions and 66 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -6,3 +6,4 @@ test/*
|
|||
*.a
|
||||
*.so
|
||||
*.core
|
||||
doc
|
9
Makefile
9
Makefile
|
@ -53,7 +53,10 @@ static: $(staticlib)
|
|||
$(staticlib): $(objs)
|
||||
$(AR) rcs $@ $?
|
||||
|
||||
clean:
|
||||
rm -rf $(objs) $(staticlib)
|
||||
docs: Doxyfile $(hdrs)
|
||||
doxygen
|
||||
|
||||
.PHONY: all clean
|
||||
clean:
|
||||
rm -rf $(objs) $(staticlib) doc
|
||||
|
||||
.PHONY: all docs clean
|
||||
|
|
|
@ -17,18 +17,25 @@ int lineBufferInit(lineBuffer *lb) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
gemtextParser* gemtextParserInit(FILE *stream) {
|
||||
gemtextParser *parser = calloc(1, sizeof(gemtextParser));
|
||||
if (parser == NULL)
|
||||
return NULL;
|
||||
int gemtextParserInit(gemtextParser *parser, FILE *stream) {
|
||||
int ret = 0;
|
||||
|
||||
parser->stream = stream;
|
||||
parser->mode = normalMode;
|
||||
parser->state = lineStart;
|
||||
if (lineBufferInit(&parser->buffer) != 0) {
|
||||
parser->linkUrl = NULL;
|
||||
ret = lineBufferInit(&parser->buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
gemtextParser* gemtextParserNew(FILE *stream) {
|
||||
gemtextParser *parser = calloc(1, sizeof(gemtextParser));
|
||||
if (parser == NULL)
|
||||
return NULL;
|
||||
if (gemtextParserInit(parser, stream) != 0) {
|
||||
free(parser);
|
||||
return NULL;
|
||||
}
|
||||
parser->linkUrl = NULL;
|
||||
return parser;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
/** \file gemtext-parser.h
|
||||
* \brief A fast Gemtext markup parser
|
||||
*/
|
||||
#ifndef GEMTEXT_PARSER_H
|
||||
#define GEMTEXT_PARSER_H 1
|
||||
|
||||
|
@ -5,95 +8,238 @@
|
|||
#include <stddef.h> // size_t
|
||||
#include <stdio.h> // FILE
|
||||
|
||||
#define LBUF_SIZE 512
|
||||
#define LBUF_SIZE 512 ///< The default size of a lineBuffer
|
||||
|
||||
/** The main modes which the parser can operate in */
|
||||
typedef enum {
|
||||
normalMode,
|
||||
preformattedMode,
|
||||
quoteMode,
|
||||
linkMode,
|
||||
h1Mode,
|
||||
h2Mode,
|
||||
h3Mode,
|
||||
listMode,
|
||||
normalMode, /**< A normal text line is being parsed, or the parser is
|
||||
still determining the line type */
|
||||
preformattedMode, ///< A Preformatted block is being parsed
|
||||
quoteMode, ///< A Quote block is being parsed
|
||||
linkMode, ///< A hyperlink is being parsed
|
||||
h1Mode, ///< An H1 heading is being parsed
|
||||
h2Mode, ///< An H2 heading is being parsed
|
||||
h3Mode, ///< An H3 heading is being parsed
|
||||
listMode, ///< A list member is being parsed
|
||||
} gemtextParserMode;
|
||||
|
||||
/** An enumeration representing the state of the parsing action. These values
|
||||
* are to be taken in context with the current gemtextParserMode */
|
||||
typedef enum {
|
||||
lineStart,
|
||||
lineEnd,
|
||||
firstLinkChar,
|
||||
linkDisplayStart,
|
||||
linkDisplay,
|
||||
firstHashChar,
|
||||
secondHashChar,
|
||||
thirdHashChar,
|
||||
firstBacktickChar,
|
||||
secondBacktickChar,
|
||||
thirdBacktickChar,
|
||||
preformattedAlt,
|
||||
trimStart,
|
||||
normalState,
|
||||
lineStart, ///< The cursor is at the start of a new line
|
||||
lineEnd, ///< The cursor is at the end of a line
|
||||
firstLinkChar, ///< The first link character was the previous character
|
||||
linkDisplayStart, /**< The url of a link has been parsed and the cursor is at the
|
||||
beginning of the display element */
|
||||
linkDisplay, ///< The link's display element is being parsed
|
||||
firstHashChar, ///< A Single '#' character has been encountered
|
||||
secondHashChar, ///< Two '#' characters have been encountered sequentially
|
||||
thirdHashChar, ///< Three '#' characters have been encountered sequentially
|
||||
firstBacktickChar, ///< A single '`' character has been encountered
|
||||
secondBacktickChar, ///< Two '`' characters have been encountered sequentially
|
||||
thirdBacktickChar, ///< Three '`' characters have been encountered sequentially
|
||||
preformattedAlt, ///< A Preformatted block's alt text is being parsed
|
||||
trimStart, ///< The *mode* is known and leading whitespace is being trimmed
|
||||
normalState, ///< The *mode* is known and normal parsing is occurring
|
||||
} gemtextParserState;
|
||||
|
||||
/**
|
||||
* An enum type representing the various line types in gemtext markup
|
||||
*/
|
||||
typedef enum {
|
||||
normalLine,
|
||||
linkLine,
|
||||
listLine,
|
||||
h1Line,
|
||||
h2Line,
|
||||
h3Line,
|
||||
preformattedLine,
|
||||
quoteLine,
|
||||
endOfStream,
|
||||
normalLine, ///< A normal text line
|
||||
linkLine, ///< A link line
|
||||
listLine, ///< A list member
|
||||
h1Line, ///< An H1 heading
|
||||
h2Line, ///< An H2 heading
|
||||
h3Line, ///< An H3 heading
|
||||
preformattedLine, ///< A preformatted text block
|
||||
quoteLine, ///< A Quote block
|
||||
endOfStream, /**< Notifies the receiver that the stream is over and no
|
||||
more lines are to be expected */
|
||||
} gemtextLineType;
|
||||
|
||||
/**
|
||||
* A growable byte array
|
||||
*/
|
||||
typedef struct {
|
||||
size_t capacity;
|
||||
size_t len;
|
||||
char *cursor;
|
||||
char *buf;
|
||||
size_t capacity; ///< The current capacity of the internal buffer
|
||||
size_t len; ///< The actual number of bytes currently in use
|
||||
char *cursor; ///< A pointer to the next byte to be used in the internal buffer
|
||||
char *buf; ///< A Pointer to the beginning of the internal buffer
|
||||
} lineBuffer;
|
||||
|
||||
/**
|
||||
* A Gemtext link element
|
||||
*/
|
||||
typedef struct {
|
||||
char *url;
|
||||
char *display;
|
||||
char *url; ///< The url of the gemtext link
|
||||
char *display; ///< Optional text to be displayed in lieu of the url
|
||||
} gemtextLink;
|
||||
|
||||
/**
|
||||
* A block of preformatted text
|
||||
*/
|
||||
typedef struct {
|
||||
char *altText;
|
||||
char *body;
|
||||
char *altText; /**< Some descriptive text to be read by screen readers if
|
||||
this is ascii art */
|
||||
char *body; ///< The body of the preformatted block
|
||||
} preformattedNode;
|
||||
|
||||
/**
|
||||
* The main Gemtext parser
|
||||
*/
|
||||
typedef struct {
|
||||
FILE *stream;
|
||||
gemtextParserMode mode;
|
||||
gemtextParserState state;
|
||||
lineBuffer buffer;
|
||||
FILE *stream; /**< A stream of bytes to read gemtext from */
|
||||
gemtextParserMode mode; /**< The current parsing mode */
|
||||
gemtextParserState state; /**< The state of the parser within each mode */
|
||||
lineBuffer buffer; /**< The internal buffer used to store bytes until
|
||||
a gemtextLine is ready to be sent */
|
||||
union {
|
||||
char *linkUrl;
|
||||
char *altText;
|
||||
char *linkUrl; /**< The url portion of a linkLine */
|
||||
char *altText; /**< The alt text associated with a preformatted block */
|
||||
};
|
||||
} gemtextParser;
|
||||
|
||||
struct _gemtextLine {
|
||||
struct _gemtextLine *next;
|
||||
struct _gemtextLine *prev;
|
||||
gemtextLineType lineType;
|
||||
struct _gemtextLine *next; ///< The next line in the queue
|
||||
struct _gemtextLine *prev; ///< The previous line in the queue
|
||||
gemtextLineType lineType; ///< Identifies the type of line
|
||||
union {
|
||||
char *str;
|
||||
gemtextLink *link;
|
||||
preformattedNode *node;
|
||||
char *str; ///< The text body of most line types
|
||||
gemtextLink *link; ///< The body of a link line
|
||||
preformattedNode *node; ///< The body and alt text of a preformatted block
|
||||
};
|
||||
};
|
||||
|
||||
/** A Gemtext node */
|
||||
typedef struct _gemtextLine gemtextLine;
|
||||
|
||||
/**
|
||||
* A fifo queue used to pass gemtextLine elements from the worker thread to the
|
||||
* rendering thread.
|
||||
*/
|
||||
typedef struct {
|
||||
pthread_cond_t cond;
|
||||
size_t count;
|
||||
pthread_mutex_t mutex;
|
||||
gemtextLine *head;
|
||||
gemtextLine *tail;
|
||||
pthread_cond_t cond; ///< Signals the rendering thread to wait for an incoming line
|
||||
size_t count; ///< The number of elements currently in the queue
|
||||
pthread_mutex_t mutex; ///< The lock ensuring exclusive access
|
||||
gemtextLine *head; ///< The oldest line in the queue
|
||||
gemtextLine *tail; ///< The newest line in the queue
|
||||
} gemtextLineQueue;
|
||||
|
||||
/**
|
||||
* Initialize a lineBuffer struct to it's default values.
|
||||
* ### Return values
|
||||
* Returns 0 for success, 2 if memory allocation fails.
|
||||
* \param lb A pointer to an already allocated lineBuffer
|
||||
*/
|
||||
int lineBufferInit(lineBuffer *lb);
|
||||
|
||||
/**
|
||||
* Initialize a gemtextParser to it's default values.
|
||||
* ### Return values
|
||||
* Returns 0 upon success, 2 if memory allocation for the internal
|
||||
* buffer fails.
|
||||
* \param parser A pointer to an already allocated gemtextParser
|
||||
* \param stream A FILE which we whose bytes will be read and parsed as gemtext lines
|
||||
*/
|
||||
int gemtextParserInit(gemtextParser *parser, FILE *stream);
|
||||
|
||||
/**
|
||||
* Creates a new gemtextParser and initializes it to default values.
|
||||
* If memory allocation fails a NULL pointer will be returned.
|
||||
* \param stream The FILE stream which we will read and parse as gemtext lines
|
||||
*/
|
||||
gemtextParser* gemtextParserNew(FILE *stream);
|
||||
|
||||
/**
|
||||
* Frees all memory associated with this gemtextParser.
|
||||
* \param parser The gemtextParser to be freed
|
||||
*/
|
||||
void gemtextParserDeinit(gemtextParser *parser);
|
||||
|
||||
/**
|
||||
* Initializes a gemtextLineQueue with default values.
|
||||
* ### Return values
|
||||
* Returns 0 on success. If there is a failure initializing the internal
|
||||
* mutex or condition variable, an error code is returned instead.
|
||||
* \param queue The already allocated gemtextLineQueue
|
||||
*/
|
||||
int gemtextLineQueueInit(gemtextLineQueue *queue);
|
||||
|
||||
/**
|
||||
* Pushes a gemtextLine into the queue. This function will not fail, but
|
||||
* can block if another thread holds the gemtextQueue's internal mutex.
|
||||
* \param queue The queue which will receive the gemtext line
|
||||
* \param line The gemtextLine to be queued
|
||||
*/
|
||||
void gemtextLineQueuePush(gemtextLineQueue *queue, gemtextLine *line);
|
||||
|
||||
/**
|
||||
* Gets the oldest line inserted in the queue. This function will either
|
||||
* return a valid gemtextLine or block until one becomes available.
|
||||
* \param lq The queue from which we are attempting to pop a line
|
||||
*/
|
||||
gemtextLine* gemtextLineQueuePop(gemtextLineQueue *lq);
|
||||
|
||||
/**
|
||||
* Extends the LineBuffer lb by len bytes.
|
||||
* ### Return values
|
||||
* Returns 0 upon success, or 2 if memory allocation fails.
|
||||
* \param lb The buffer to be extended
|
||||
* \param len The number of bytes to extend the buffer by
|
||||
*/
|
||||
int lineBufferExtend(lineBuffer *lb, size_t len);
|
||||
|
||||
/**
|
||||
* Appends a character c to the lineBuffer lb. If there is no space left in the
|
||||
* internal buffer, it will be re-allocated first.
|
||||
* ### Return values
|
||||
* Returns 0 for success, or 2 if memory allocation fails.
|
||||
* \param lb The buffer we are appending to
|
||||
* \param c The character to be appended to this buffer
|
||||
*/
|
||||
int lineBufferAppendChar(lineBuffer *lb, char c);
|
||||
|
||||
/**
|
||||
* Appends a character c to the lineBuffer c without checking if there is space
|
||||
* available first.
|
||||
* > **Warning!** Due to the fact that this function is unchecked, it should
|
||||
* > only be called if you are absolutely certain that there is space remaining
|
||||
* > in the internal buffer, such as after calling lineBufferRewind to move the
|
||||
* > cursor back by one character. Failure to follow this warning may result in
|
||||
* > *buffer overflow* memory access violation.
|
||||
*/
|
||||
void lineBufferAppendCharUnchecked(lineBuffer *lb, char c);
|
||||
|
||||
/**
|
||||
* Appends a string beginning at the pointer *c of len bytes to lineBuffer lb.
|
||||
* ### Return values
|
||||
* Returns 0 on success, or 2 for memory allocation errors.
|
||||
* \param lb The buffer we are appending to
|
||||
* \param c A pointer to an array of chars
|
||||
* \param len The number of bytes to append from c
|
||||
*/
|
||||
int lineBufferAppendString(lineBuffer *lb, char *c, size_t len);
|
||||
|
||||
/**
|
||||
* Rewinds the internal cursor pointer and count for lineBuffer lb by 1.
|
||||
*/
|
||||
void lineBufferRewind(lineBuffer *lb);
|
||||
|
||||
/**
|
||||
* Resets the internal count of lineBuffer lb to 0 and moves it's cursor back
|
||||
* to the start of the internal buffer.
|
||||
*/
|
||||
void lineBufferReset(lineBuffer *lb);
|
||||
|
||||
/**
|
||||
* Parses gemtext into a series of nodes to be places in the gemtextLineQueue lq.
|
||||
* ### Return values
|
||||
* Returns 0 on success, any other number is an error code
|
||||
* \param parser A gemtextParser struct used to maintain state while parsing
|
||||
* \param lq A gemtextLineQueue which will receive gemtextLine elements as they are parsed
|
||||
*/
|
||||
int parseGemtext(gemtextParser *parser, gemtextLineQueue *lq);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue