summaryrefslogtreecommitdiff
path: root/src/miav_config.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/miav_config.cc')
-rw-r--r--src/miav_config.cc489
1 files changed, 364 insertions, 125 deletions
diff --git a/src/miav_config.cc b/src/miav_config.cc
index f7d56ce..f59b6b3 100644
--- a/src/miav_config.cc
+++ b/src/miav_config.cc
@@ -31,6 +31,10 @@
/*
* $Log$
+ * Revision 1.11 2005/07/02 11:39:51 deva
+ * Added some audiocode.
+ * Moved libfame code out of mov_encoder
+ *
* Revision 1.10 2005/06/14 12:29:40 deva
* Incorporated the use of the Info object everywhere... also using the log functionality.
*
@@ -65,7 +69,7 @@ MiavConfig::MiavConfig(char *file, Info *i)
return;
}
fseek(fp, 0, SEEK_END);
- int fsz = ftell(fp);
+ int fsz = ftell(fp) + 1;
fseek(fp, 0, SEEK_SET);
char *raw = (char*)calloc(fsz, 1);
@@ -73,7 +77,8 @@ MiavConfig::MiavConfig(char *file, Info *i)
fclose(fp);
- parse(raw);
+ configs = parse(raw);
+
free(raw);
}
@@ -93,173 +98,384 @@ MiavConfig::~MiavConfig()
/**
* Prints a reasonable error message when a parse error occurres.
*/
-_cfg *MiavConfig::parseError(char* msg, char* line)
+void MiavConfig::parseError(char* msg, _cfg* cfg)
{
- if(info) info->error("Error parsing file %s at line:\n\t%s\n\t%s\n", filename.c_str(), line, msg);
- else fprintf(stderr, "Error parsing file %s at line:\n\t%s\n\t%s\n", filename.c_str(), line, msg);
- return NULL;
+ if(info) info->error("Error parsing file %s at line %d:\n\t%s\n\t%s\n",
+ filename.c_str(),
+ cfg->line,
+ cfg->orig,
+ msg);
+ else fprintf(stderr, "Error parsing file %s at line %d:\n\t%s\n\t%s\n",
+ filename.c_str(),
+ cfg->line,
+ cfg->orig,
+ msg);
}
-/**
- * Adds one configuration entry, from a single zero terminated line.
- */
-_cfg *MiavConfig::addConfig(_cfg *parent, char* conf)
+_cfg* MiavConfig::readLines(char* raw)
{
- // Check for wellformed input:
- // Check for =
- if(strstr(conf, "=") == 0) return parseError("Missing '='", conf);
- /*
- if(strstr(conf, "\"")) {
- if(strstr(conf, "=") > strstr(conf, "\""))
- return parseError("Missing '=', first occurrence inside string", conf);
- }
- */
+ int line = 1;
+
+ _cfg *first = (_cfg*)calloc(1, sizeof(_cfg));
+ _cfg *current = first;
+ _cfg *next = NULL;
- // Check for nonempty left side
- if(strstr(conf, "=") == conf) return parseError("Empty left side", conf);
+ char *nl = strchr(raw, '\n');
- // Check for nonempty right side
- if(strstr(conf, "=") == conf + strlen(conf) - 1) return parseError("Empty right side.", conf);
+ while(nl != NULL) {
+ int len = nl - raw;
- // Parse this wellformed input.
- _cfg *cfg;
+ current->line = line;
- cfg = (_cfg*) malloc(sizeof(_cfg));
- if(!parent) configs = cfg;
+ current->orig = (char*) calloc(len + 1, 1);
+ strncpy(current->orig, raw, len);
- int namelen = strchr(conf, '=') - conf;
- char* name = (char*)calloc(namelen + 1, 1);
- strncpy(name, conf, namelen);
+ // Find next newline
+ raw = nl+1;
+ nl = strchr(raw, '\n');
- int vallen = conf + strlen(conf) - (strchr(conf, '=') + 1);
- char* val = (char*)calloc(vallen + 1, 1);
- strncpy(val, conf + strlen(conf) - vallen, vallen);
+ line++;
- // TODO: Check valid rightside (true, false, number or "..")
+ // Add _cfg
+ if(nl != NULL) {
+ next = (_cfg*)calloc(1, sizeof(_cfg));
+ current->next = next;
+ current = next;
+ } else {
+ current->next = NULL;
+ }
+ }
- cfg->name = new string((const char*)name);
- free(name);
+ return first;
+}
- cfg->stringval = new string((const char*)val);
- cfg->intval = atoi(val);
- cfg->floatval = atof(val);
- cfg->boolval = atoi(val) != 0;
- free(val);
+_cfg* MiavConfig::parseLines(_cfg *cfg)
+{
+ if(cfg == NULL) return NULL;
- cfg->next = NULL;
+ char *l = cfg->left = (char*)calloc(1, strlen(cfg->orig));
+ char *r = cfg->right = (char*)calloc(1, strlen(cfg->orig));
- if(parent) parent->next = cfg;
- return cfg;
-}
+ char *p = cfg->orig;
-/**
- * Main parse function, iterates the lines of the file.
- */
-int MiavConfig::parse(char* raw)
-{
- // Strip the string
- char *conf = strip(raw);
- char *conf_end = conf + strlen(conf);
- char *start = conf;
- char *p;
-
- _cfg *cfg = NULL;
-
- // Iterate the lines in the string
- for(p = conf; p < conf_end; p++) {
- if(*p == '\n') {
- *p = '\0';
- if(!(cfg = addConfig(cfg, start))) return 1;
- start = p+1;
+ // Skip leftmost whitespace
+ while(p < cfg->orig + strlen(cfg->orig) && strchr("\t ", *p)) {
+ p++;
+ }
+
+ // Empty line, with whitespaces
+ if(p == cfg->orig + strlen(cfg->orig)) {
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ // Parse left side
+ while(p < cfg->orig + strlen(cfg->orig) && !strchr("\t ", *p)) {
+ if(strchr("#", *p)) {
+ if(l != cfg->left) parseError("Incomplete line.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ if(strchr("=", *p)) break;
+
+ if(strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_", *p)) {
+ *l = *p;
+ l++;
+ } else {
+ char buf[256];
+ sprintf(buf, "Invalid left hand side character at [%s].", p);
+ parseError(buf, cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
}
+
+ p++;
}
- // Allocated in strip
- free(conf);
- return 0;
-}
-/**
- * Strip all unwanted data from the string, initial to parsing.
- */
-char* MiavConfig::strip(char* conf)
-{
- // Freed in parse!!!
- char *stripped = (char*)calloc(strlen(conf) + 2, 1);
- char *r;
- char *w = stripped;
-
- bool instring = false;
- bool incomment = false;
-
- // Iterate over the characters in the input string.
- for(r = conf; r < conf + strlen(conf); r++) {
- if(strchr("#", *r)) incomment = true;
- if(strchr("\n", *r)) incomment = false;
-
- if(!incomment) {
- if(instring) {
- // When in a string, accept anything, except ".
- if(*r != '\"') {
- *w = *r;
- w++;
- }
- } else {
- // Only copy valid characters
- if(strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890-_,.=", *r)) {
- // Change comma into dot
- if(*r == ',') *r = '.';
- *w = *r;
- w++;
- }
- // We don't want double newlines and initial newline!
- if((*r == '\n') && (*(w-1) != '\n') && (w != stripped)) {
- *w = *r;
- w++;
- }
+ // Skip whitespace
+ while(p < cfg->orig + strlen(cfg->orig) && strchr("\t ", *p)) {
+ p++;
+ }
+
+ if(*p != '=') {
+ parseError("Expected '='.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+ p++; // Get past the '='
+
+ // Skip whitespace
+ while(p < cfg->orig + strlen(cfg->orig) && strchr("\t ", *p)) {
+ p++;
+ }
+
+ // Parse right hand side
+ int instring = 0;
+ while(p < cfg->orig + strlen(cfg->orig) && !(strchr("\t ", *p) && instring != 1)) {
+ if(*p == '\"') instring++;
+ if(instring > 2) {
+ parseError("Too many '\"'.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ if(instring == 1) {
+ // Accept all chars
+ *r= *p;
+ r++;
+ } else {
+ // Accept only those chars valid for the data types.
+ if(strchr("truefalseyesnoTRUEFALSEYESNO1234567890\",.-", *p)) {
+ if(*p == ',') *r= '.';
+ *r = *p;
+ r++;
+ } else if(!strchr("\n", *p)) {
+ char buf[256];
+ sprintf(buf, "Invalid right hand side character at [%s].", p);
+ parseError(buf, cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
}
+ if(*p == '#') break;
}
- if(strchr("\"", *r)) instring = !instring;
+ p++;
+ }
+
+ // Skip whitespace
+ while(p < cfg->orig + strlen(cfg->orig) && strchr("\t ", *p)) {
+ p++;
+ }
+
+ // Detect if whitespace ocurred inside righthand value.
+ if(p != cfg->orig + strlen(cfg->orig)) {
+ parseError("Invalid use of whitespace.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ // Check for instring (string not ended)
+ if(instring == 1) {
+ parseError("String not closed.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ // Check for empty line
+ if(l == cfg->left && r == cfg->right) {
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ // Check for empty left side.
+ if(l == cfg->left) {
+ parseError("Empty left side.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
}
- // If we are not ending on a newline, we better append one
- if(*(w-1) != '\n') {
- *w = '\n';
- w++;
+ // Check for empty right side.
+ if(r == cfg->right) {
+ parseError("Empty right side.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
}
- // Make sure we are nullterminated.
- *w = '\0';
+ cfg->next = parseLines(cfg->next);
+ return cfg;
+}
+
+
+_cfg *MiavConfig::createSemantics(_cfg *cfg) {
+ if(cfg == NULL) return NULL;
+
+ cfg->type = CONFIG_UNKNOWN;
+
+ // Boolean - true
+ if(strcasecmp(cfg->right, "yes") == 0 ||
+ strcasecmp(cfg->right, "true") == 0) {
+ cfg->type = CONFIG_BOOL;
+ cfg->boolval = true;
+ }
+
+ // Boolean - false
+ if(strcasecmp(cfg->right, "no") == 0 ||
+ strcasecmp(cfg->right, "false") == 0) {
+ cfg->type = CONFIG_BOOL;
+ cfg->boolval = false;
+ }
- return stripped;
+ // String
+ if(cfg->right[0] == '\"') {
+ cfg->type = CONFIG_STRING;
+ cfg->right[strlen(cfg->right) - 1] = '\0';
+ cfg->stringval = new string(cfg->right + 1);
+
+ }
+
+ // Number
+ bool number = true;
+ char *p = cfg->right;
+ while(p < cfg->right + strlen(cfg->right)) {
+ if(!strchr("01234567890.-", *p)) number = false;
+ p++;
+ }
+
+ // Integer
+ if(number && strstr(cfg->right, ".") == NULL ) {
+ cfg->type = CONFIG_INT;
+ cfg->intval = atoi(cfg->right);
+ }
+
+ // Float
+ if(number && strstr(cfg->right, ".") != NULL) {
+ cfg->type = CONFIG_FLOAT;
+ cfg->floatval = atof(cfg->right);
+ }
+
+ if(cfg->type == CONFIG_UNKNOWN) {
+ parseError("Unknown type (see 'man miav.conf' for valid right hand sides).", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return createSemantics(next);
+ }
+
+ // Create name
+ cfg->name = new string(cfg->left);
+
+ cfg->next = createSemantics(cfg->next);
+ return cfg;
+}
+
+
+_cfg* MiavConfig::parse(char* raw)
+{
+ _cfg *first = readLines(raw);
+ first = parseLines(first);
+
+ first = createSemantics(first);
+
+ /*
+ _cfg* cfg = first;
+ while(cfg) {
+ printf("Node:\n");
+ printf("\tLine: [%d]\n", cfg->line);
+ printf("\tOrig: [%s]\n", cfg->orig);
+ printf("\tLeft: [%s]\n", cfg->left);
+ printf("\tRight: [%s]\n", cfg->right);
+
+ switch(cfg->type) {
+ case CONFIG_INT:
+ printf("\tInt value: %d\n", cfg->intval);
+ break;
+ case CONFIG_BOOL:
+ printf("\tBool value: %d\n", cfg->boolval);
+ break;
+ case CONFIG_FLOAT:
+ printf("\tFloat value: %f\n", cfg->floatval);
+ break;
+ case CONFIG_STRING:
+ printf("\tString value: %s\n", cfg->stringval->c_str());
+ break;
+ case CONFIG_UNKNOWN:
+ printf("\tUnknown type: %s\n", cfg->right);
+ break;
+ }
+
+ cfg= cfg->next;
+ }
+ */
+ return first;
}
int MiavConfig::readInt(char *node)
{
_cfg* n = findNode(node);
- if(n) return n->intval;
- else return 0;
+ if(n) {
+ if(n->type == CONFIG_INT) return n->intval;
+ parseError("Expected integer.", n);
+ }
+ return 0;
}
bool MiavConfig::readBool(char *node)
{
- _cfg* n = findNode(node);
- if(n) return n->boolval;
- else return false;
+ _cfg* n = findNode(node);
+ if(n) {
+ if(n->type == CONFIG_BOOL) return n->boolval;
+ if(n->type == CONFIG_INT) return (n->intval != 0);
+ parseError("Expected boolean.", n);
+ }
+ return false;
}
string *MiavConfig::readString(char *node)
{
_cfg* n = findNode(node);
- if(n) return n->stringval;
- else return &emptyString;
+ if(n) {
+ if(n->type == CONFIG_STRING) return n->stringval;
+ parseError("Expected string.", n);
+ }
+ return &emptyString;
}
float MiavConfig::readFloat(char *node)
{
_cfg* n = findNode(node);
- if(n) return n->floatval;
- else return 0.0f;
+ if(n) {
+ if(n->type == CONFIG_FLOAT) return n->floatval;
+ if(n->type == CONFIG_INT) return (float)n->intval;
+ parseError("Expected float.", n);
+ }
+ return 0.0f;
}
_cfg *MiavConfig::findNode(char* node)
@@ -270,8 +486,31 @@ _cfg *MiavConfig::findNode(char* node)
if(!strcmp(node, cfg->name->c_str())) return cfg;
cfg = cfg->next;
}
- if(info) info->error("Request for nonexisting node \"%s\"!\n", node);
- else fprintf(stderr, "Request for nonexisting node \"%s\"!\n", node);
+ if(info) info->error("Missing line in configuration file: \"%s\"!\n", node);
+ else fprintf(stderr, "Missing line in configuration file: \"%s\"!\n", node);
return NULL;
}
+
+#ifdef __TEST_MIAV_CONFIG
+
+int main(int argc, char *argv[]) {
+ if(argc < 2) {
+ fprintf(stderr, "usage:\n\tmiav_config [filename]\n");
+ return 1;
+ }
+
+ MiavConfig cfg(argv[1]);
+ printf("Server user: [%s]\n", cfg.readString("server_user")->c_str());
+ printf("Resolution: [%f]\n", cfg.readFloat("screensize"));
+ printf("Resolution (as int): [%d]\n", cfg.readInt("screensize"));
+ printf("Width: [%d]\n", cfg.readInt("pixel_width"));
+ printf("Width (as float): [%f]\n", cfg.readFloat("pixel_width"));
+ printf("Frame quality: [%d]\n", cfg.readInt("frame_quality"));
+ printf("Skip frames: [%d]\n", cfg.readBool("player_skip_frames"));
+ printf("Skip frames (as int): [%d]\n", cfg.readInt("player_skip_frames"));
+ printf("Frame quality (as bool): [%d]\n", cfg.readBool("frame_quality"));
+
+}
+
+#endif/* __TEST_MIAV_CONFIG*/