diff options
author | Thomas White <taw@bitwiz.org.uk> | 2012-08-14 23:58:16 +0200 |
---|---|---|
committer | Thomas White <taw@bitwiz.org.uk> | 2012-08-14 23:58:16 +0200 |
commit | 3d0d122d46ff38c47adbe3d4960440aaefc5705c (patch) | |
tree | 29c451423a03d7b5b1520e0ced6ce9652166fed4 | |
parent | 2fd37a95bd5fe109a62917eca483b36a18a74777 (diff) |
First bits of StoryCode parser
-rw-r--r-- | src/storycode.c | 171 | ||||
-rw-r--r-- | src/storycode.h | 9 | ||||
-rw-r--r-- | tests/storycode_test.c | 13 |
3 files changed, 189 insertions, 4 deletions
diff --git a/src/storycode.c b/src/storycode.c index 446d277..4adfe1b 100644 --- a/src/storycode.c +++ b/src/storycode.c @@ -27,19 +27,186 @@ #include <assert.h> #include <stdlib.h> +#include <string.h> #include "storycode.h" #include "presentation.h" -struct frame *unpack_storycode(const char *sc) +struct _scblocklist +{ + int n_blocks; + char **blocks; + int max_blocks; +}; + + +struct _scblocklistiterator +{ + int pos; +}; + + +static int allocate_blocks(SCBlockList *bl) +{ + char **blocks_new; + + blocks_new = realloc(bl->blocks, bl->max_blocks*sizeof(char *)); + if ( blocks_new == NULL ) { + return 1; + } + + bl->blocks = blocks_new; + + return 0; +} + + +SCBlockList *sc_block_list_new() +{ + SCBlockList *bl; + + bl = calloc(1, sizeof(SCBlockList)); + if ( bl == NULL ) return NULL; + + bl->n_blocks = 0; + bl->max_blocks = 64; + bl->blocks = NULL; + if ( allocate_blocks(bl) ) { + free(bl); + return NULL; + } + + return bl; +} + + + +void sc_block_list_free(SCBlockList *bl) +{ + free(bl->blocks); + free(bl); +} + + +char *sc_block_list_first(SCBlockList *bl, SCBlockListIterator **piter) +{ + SCBlockListIterator *iter; + + if ( bl->n_blocks == 0 ) return NULL; + + iter = calloc(1, sizeof(SCBlockListIterator)); + if ( iter == NULL ) return NULL; + + iter->pos = 0; + *piter = iter; + + return bl->blocks[0]; +} + + +char *sc_block_list_next(SCBlockList *bl, SCBlockListIterator *iter) +{ + iter->pos++; + if ( iter->pos == bl->n_blocks ) { + free(iter); + return NULL; + } + + return bl->blocks[iter->pos]; +} + + +static int sc_block_list_add(SCBlockList *bl, char *text) +{ + if ( bl->n_blocks == bl->max_blocks ) { + bl->max_blocks += 64; + if ( allocate_blocks(bl) ) return 1; + } + + bl->blocks[bl->n_blocks] = text; + bl->n_blocks++; + return 0; +} + + +SCBlockList *sc_find_blocks(const char *sc, const char *blockname) +{ + SCBlockList *bl; + const char *pos; + char label[1024]; + + bl = sc_block_list_new(); + if ( bl == NULL ) return NULL; + + if ( strlen(blockname) > 1021 ) { + fprintf(stderr, "Block name '%s' too long.\n", blockname); + return NULL; + } + + strcat(label, "\\"); + strcat(label, blockname); + strcat(label, "{"); + + pos = sc; + do { + + pos = strstr(pos, label); + + if ( pos != NULL ) { + + int i; + int bct = 1; + int found = 0; + int ml = strlen(pos); + + pos += strlen(label); + + for ( i=0; i<ml; i++ ) { + if ( pos[i] == '{' ) { + bct++; + } else if ( pos[i] == '}' ) { + bct--; + } + if ( bct == 0 ) { + found = 1; + break; + } + } + + if ( (!found) || (bct != 0) ) { + fprintf(stderr, "Parse error while looking for" + " block '%s'\n", blockname); + sc_block_list_free(bl); + return NULL; + } + + if ( sc_block_list_add(bl, strndup(pos, i)) ) { + fprintf(stderr, "Failed to add block.\n"); + sc_block_list_free(bl); + return NULL; + } + + pos += i+1; + printf("Remaining text '%s'\n", pos); + + } + + } while ( pos != NULL ); + + return bl; +} + + +/* Unpack level 2 StoryCode (content + subframes) into frames */ +struct frame *sc_unpack(const char *sc) { struct frame *fr; fr = calloc(1, sizeof(struct frame)); if ( fr == NULL ) return NULL; - + return fr; } diff --git a/src/storycode.h b/src/storycode.h index 6e106e3..240900d 100644 --- a/src/storycode.h +++ b/src/storycode.h @@ -27,8 +27,13 @@ #include <config.h> #endif +typedef struct _scblocklist SCBlockList; +typedef struct _scblocklistiterator SCBlockListIterator; -extern char *sc_get_final_font(const char *sc); -extern char *sc_get_final_text_colour(const char *sc); +char *sc_block_list_first(SCBlockList *bl, SCBlockListIterator **piter); +char *sc_block_list_next(SCBlockList *bl, SCBlockListIterator *iter); + +extern SCBlockList *sc_find_blocks(const char *sc, const char *blockname); +extern void sc_block_list_free(SCBlockList *bl); #endif /* STORYCODE_H */ diff --git a/tests/storycode_test.c b/tests/storycode_test.c index 4ff4977..4ffc08c 100644 --- a/tests/storycode_test.c +++ b/tests/storycode_test.c @@ -32,6 +32,19 @@ int main(int argc, char *argv[]) { + SCBlockList *bl; + SCBlockListIterator *iter; + char *b; + + bl = sc_find_blocks("\\bg{wibble \\f{wobble}}\\bg{rwawr}Wobble", "bg"); + + for ( b = sc_block_list_first(bl, &iter); + b != NULL; + b = sc_block_list_next(bl, iter) ) + { + printf("'%s'\n", b); + } + sc_block_list_free(bl); return 0; } |