⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parse.cc

📁 该文件是包含了机器人足球比赛中的整个系统的代码
💻 CC
字号:
#include "Parse.h"

#include <iostream>
using namespace std;

Parse::Parse() {
  // hmm !
}

// Detects both CR and LF characters
bool Parse::IsTerminator(const char c) {
  if (c == char(13) || c == (char)10)
    return true;
  return false;
}

// Only DOS has these.
bool Parse::IsLF(const char c) {
  if (c == (char)13)
    return true;
  return false;
}

// Detects spaces AND tab characters.
bool Parse::IsSpace(const char c) {
  if (c == ' ' || c == '\t')
    return true;
  return false;
}

void Parse::WriteFile(const char* filename, const char* buffer, int buffersize) {
  printf("Config: Writing %s.\n",filename);
  FILE* f = fopen("/ms/open-r/mw/test.t","wb");
  if (f != NULL) { 
    fwrite(buffer,1,buffersize,f);
    fclose(f);
  } else {
    cout << "Parse: unable to open file for writing" << endl << flush;
  }
}

// This code is dirty, but it seems to be indestructible. I haven't found anything
//   that can crash it outright.
// It parses the specified file as a config file, looking for key,value pairs. These
//   are stored in a vector using RegisterPair().
void Parse::ParseFile(const char* filename) {
  printf("Config: Loading %s.\n", filename);
  FILE* f = fopen(filename,"rb");
  if (f == NULL) {
    printf("Config: Unable to open file %s.\n",filename);
    return;
  }
  fseek(f,0,SEEK_END);
  long filesize = ftell(f);
  rewind(f);
  char* filebuffer = (char*) malloc(filesize);
  if (filebuffer == NULL) {
    printf("Config: Unable to malloc %d bytes required to parse %s.\n",(int)filesize,filename);
    return;
  }

  fread(filebuffer,1,filesize,f);
  fclose(f);

  int i = 0;
  int linenumber=0;
  while (i < filesize) {
    char* keystring = (char*)malloc(MAX_KEYLENGTH);
    char* valstring = (char*)malloc(MAX_VALLENGTH);

    linenumber++;
    int k = 0;
    // ignore opening spaces
    while (i < filesize && IsSpace(filebuffer[i])) i++;
    // read up to =
    while (filebuffer[i] != '=' && IsTerminator(filebuffer[i]) == false && i < filesize && k < MAX_KEYLENGTH) {
      keystring[k] = filebuffer[i];
      k++;
      i++;
    }

    // if keystring is empty or starts with a [, # or //, we ignore this line.
    if (k == 0 || keystring[0] == '[' || keystring[0] == '#' || (k > 1 && keystring[0] == '/' && keystring[1] == '/')) {
      // ignore line !
      while (i < filesize && IsTerminator(filebuffer[i]) == false) i++;
      i++;
      if (IsLF(filebuffer[i-1])) i++;
      free(keystring);
      free(valstring);
      continue;
    }

    // check for non-empty key, with NO equals. if this wasn't caught above, then we have an invalid line !
    if (filebuffer[i] != '=' || k >= MAX_KEYLENGTH) {
      while (i < filesize && IsTerminator(filebuffer[i]) == false) i++;
      i++;
      // did anyone ever understand this?
      if (IsLF(filebuffer[i-1])) i++;
      printf("Config: Error on line %d of file %s - ",linenumber,filename);
      if (k >= MAX_KEYLENGTH) {
        printf("Key too long.\n");
      } else printf("Missing equals.\n");
      free(keystring);
      free(valstring);
      continue;
    }

    // remove trailing spaces
    while (k > 0 && IsSpace(keystring[k-1])) k--;

    keystring[k]='\0';
    
    k=0;
    // ignore =
    i++;
    // ignore whitespace after =
    while (i < filesize && IsSpace(filebuffer[i])) i++;

    // read till end of line.
    while (i < filesize && IsTerminator(filebuffer[i]) == false && k < MAX_VALLENGTH) {
      valstring[k] = filebuffer[i];
      k++;
      i++;
    }
    if (k >= MAX_VALLENGTH) {
      while (i < filesize && IsTerminator(filebuffer[i]) == false) i++;
      i++;
      if (IsLF(filebuffer[i-1])) i++;
      printf("Config: Error on line %d of file %s - ",linenumber,filename);
      printf("Value was too long.\n");
      continue;
    }
    i++;
    // make sure we really did hit the end of the line... need to be in the right place for next read. this is dos's fault !
    if (IsLF(filebuffer[i-1])) i++;

    // remove trailing spaces
    while (k > 0 && IsSpace(valstring[k-1])) k--;
    valstring[k]='\0';

    RegisterPair(keystring,valstring);
  }
  free(filebuffer);
}

// store the specified key,value pair in our vector.
// if the key already exists, it is overwritten (with a warning)
void Parse::RegisterPair(char* k,char* v) {
  Pair* p = FindPairFailFast(k);
  // key, value pair already exists
  if (p != NULL) {
    // value changed when we reloaded it ! warn user.
    if (strcmpi(p->val,v)!=0) {
      printf("Config: WARNING! Pair (%s,%s) is now (%s,%s).\n",p->key,p->val, k, v);
    }
    free(p->val);
    p->val = v;
    return;
  }
  Pair newp;
  newp.key = k;
  newp.val = v;
  keyValuePairs.push_back(newp);
  if (strlen(v) != 0) {
    printf("Config: Registered (%s,%s).\n",newp.key,newp.val);
  } else {
    printf("Config: Registered (%s,%s) (Value field empty!).\n",newp.key,newp.val);
  }

}

Pair* Parse::FindPair(const char* k) {
  for (unsigned int i = 0; i < keyValuePairs.size(); i++) {
    if (strcmpi(keyValuePairs[i].key,k)==0) {
      return &keyValuePairs[i];
    }
  }
  printf("Config: Unable to find key %s.\n",k);
  return NULL;
}

Pair* Parse::FindPairFailFast(const char* k) {
  for (unsigned int i = 0; i < keyValuePairs.size(); i++) {
    if (strcmpi(keyValuePairs[i].key,k)==0) {
      return &keyValuePairs[i];
    }
  }
  return NULL;
}


int Parse::GetAsInt(const char* k) {
  Pair* p = FindPair(k);
  if (p != NULL) {
    return atoi(p->val);
  }
  return -1;
}

double Parse::GetAsDouble(const char* k) {
  Pair* p = FindPair(k);
  if (p != NULL) {
    return atof(p->val);
  }
  return -1.0;
}

// Use with care !
char* Parse::GetAsString(const char* k) {
  Pair* p = FindPair(k);
  if (p != NULL) {
    return p->val;
  }
  return NULL;
}

bool Parse::GetAsBool(const char* k) {
  Pair* p = FindPair(k);
  if (p != NULL) {
    // nb strcmpi is not ANSI C !
    if (strcmpi(p->val,"on")==0) {
      return true;
    } else if (strcmpi(p->val,"true") == 0) {
      return true;
    }
  }
  return false;
}

int main() {
  Parse p;
  p.ParseFile("test.cfg");
  char* test = p.GetAsString("test");
  p.RegisterPair("test","hello");
  test = p.GetAsString("test");
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -