/* vi: set ts=2: +-------------------+ Enno Rehling | Eressea PBEM host | Christian Schlittchen | (c) 1998 - 2008 | Katja Zedel +-------------------+ This program may not be used, modified or distributed without prior permission by the authors of Eressea. */ #include #include "config.h" #include "textstore.h" #include "save.h" #include "version.h" #include #include #include #include #include #include #define NULL_TOKEN '@' static int txt_w_brk(struct storage *store) { putc('\n', (FILE *) store->userdata); return 1; } static int txt_w_id(struct storage *store, int arg) { return fprintf((FILE *) store->userdata, "%s ", itoa36(arg)); } static int txt_r_id(struct storage *store) { char id[8]; fscanf((FILE *) store->userdata, "%7s", id); return atoi36(id); } static int txt_w_int(struct storage *store, int arg) { return fprintf((FILE *) store->userdata, "%d ", arg); } static int txt_r_int(struct storage *store) { int result; fscanf((FILE *) store->userdata, "%d", &result); return result; } static int txt_w_flt(struct storage *store, float arg) { return fprintf((FILE *) store->userdata, "%f ", arg); } static float txt_r_flt(struct storage *store) { double result; fscanf((FILE *) store->userdata, "%lf", &result); return (float)result; } static int txt_w_tok(struct storage *store, const char *tok) { int result; if (tok == NULL || tok[0] == 0) { result = fputc(NULL_TOKEN, (FILE *) store->userdata); } else { #ifndef NDEBUG const char *find = strchr(tok, ' '); if (!find) find = strchr(tok, NULL_TOKEN); assert(!find || !"reserved character in token"); #endif assert(tok[0] != ' '); result = fputs(tok, (FILE *) store->userdata); } fputc(' ', (FILE *) store->userdata); return result; } static char *txt_r_tok(struct storage *store) { char result[256]; fscanf((FILE *) store->userdata, "%256s", result); if (result[0] == NULL_TOKEN || result[0] == 0) { return NULL; } return strdup(result); } static void txt_r_tok_buf(struct storage *store, char *result, size_t size) { char format[16]; if (result && size > 0) { format[0] = '%'; sprintf(format + 1, "%us", size); fscanf((FILE *) store->userdata, format, result); if (result[0] == NULL_TOKEN) { result[0] = 0; } } else { /* trick to skip when no result expected */ fscanf((FILE *) store->userdata, "%*s"); } } static int txt_w_str(struct storage *store, const char *str) { int result = fwritestr((FILE *) store->userdata, str); fputc(' ', (FILE *) store->userdata); return result + 1; } static char *txt_r_str(struct storage *store) { char buffer[DISPLAYSIZE]; /* you should not use this */ freadstr((FILE *) store->userdata, store->encoding, buffer, sizeof(buffer)); return strdup(buffer); } static void txt_r_str_buf(struct storage *store, char *result, size_t size) { freadstr((FILE *) store->userdata, store->encoding, result, size); } static int txt_open(struct storage *store, const char *filename, int mode) { const char *modes[] = { 0, "rt", "wt", "at" }; FILE *F = fopen(filename, modes[mode]); store->userdata = F; if (F) { const unsigned char utf8_bom[4] = { 0xef, 0xbb, 0xbf }; if (mode == IO_READ) { char token[8]; /* recognize UTF8 BOM */ store->r_tok_buf(store, token, sizeof(token)); if (memcmp(token, utf8_bom, 3) == 0) { if (enc_gamedata != XML_CHAR_ENCODING_UTF8) { log_warning(("Found UTF-8 BOM, assuming unicode game data.\n")); store->encoding = XML_CHAR_ENCODING_UTF8; } store->version = atoi(token + 3); } else { if (store->encoding == XML_CHAR_ENCODING_NONE) { store->encoding = XML_CHAR_ENCODING_8859_1; log_warning(("No BOM, assuming 8859-1 game data.\n")); } store->version = atoi(token); } } else if (store->encoding == XML_CHAR_ENCODING_UTF8) { fputs((const char *)utf8_bom, F); fprintf(F, "%d\n", RELEASE_VERSION); } } return (F == NULL); } static int txt_w_bin(struct storage *store, void *arg, size_t size) { assert(!"not implemented!"); return 0; } static void txt_r_bin(struct storage *store, void *result, size_t size) { assert(!"not implemented!"); } static int txt_close(struct storage *store) { return fclose((FILE *) store->userdata); } const storage text_store = { txt_w_brk, txt_w_int, txt_r_int, txt_w_flt, txt_r_flt, txt_w_id, txt_r_id, txt_w_tok, txt_r_tok, txt_r_tok_buf, txt_w_str, txt_r_str, txt_r_str_buf, txt_w_bin, txt_r_bin, txt_open, txt_close, 0, 0, NULL };