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

📄 xmlio.cpp

📁 FastDb是高效的内存数据库系统
💻 CPP
📖 第 1 页 / 共 2 页
字号:

#include "StdAfx.h"
#include "fastdb.h"
#include "symtab.h"
#include "compiler.h"
#include "database.h"
#include "hashtab.h"
#include "ttree.h"
#include "xmlio.h"

inline int dbXmlScanner::get
  ()
{
  int ch = getc(in);

  if (ch == '\n')
  {
    pos = 0;
    line += 1;
  }
  else if (ch == '\t')
  {
    pos = DOALIGN(pos + 1, 8);
  }
  else
  {
    pos += 1;
  }

  return ch;
}

inline void dbXmlScanner::unget(int ch)
{
  if (ch != EOF)
  {
    if (ch != '\n')
    {
      pos -= 1;
    }
    else
    {
      line -= 1;
    }

    ungetc(ch, in);
  }
}


dbXmlScanner::token dbXmlScanner::scan()
{
  int ch, i, pos;
  bool floatingPoint;

retry:

  do
  {
    if ((ch = get
                ()) == EOF)
      {
        return xml_eof;
      }
  }
  while (ch <= ' ');

  switch (ch)
  {

  case '<':

    ch = get
           ();

    if (ch == '?')
    {
      while ((ch = get
                     ()) != '?')
        {
          if (ch == EOF)
          {
            return xml_error;
          }
        }

      if ((ch = get
                  ()) != '>')
        {
          return xml_error;
        }

      goto retry;
    }

    if (ch != '/')
    {
      unget(ch);
      return xml_lt;
    }

    return xml_lts;

  case '>':
    return xml_gt;

  case '/':

    ch = get
           ();

    if (ch != '>')
    {
      unget(ch);
      return xml_error;
    }

    return xml_gts;

  case '=':
    return xml_eq;

  case '"':
    i = 0;

    while (true)
    {

      ch = get
             ();

      switch (ch)
      {

      case EOF:
        return xml_error;

      case '&':

        switch (get
                ())
        {

        case 'a':

          if (get
              () != 'm' || get
                () != 'p' || get
                  () != ';')
              {
                return xml_error;
              }

          ch = '&';
          break;

        case 'l':

          if (get
              () != 't' || get
                () != ';')
            {
              return xml_error;
            }

          ch = '<';
          break;

        case 'g':

          if (get
              () != 't' || get
                () != ';')
            {
              return xml_error;
            }

          ch = '>';
          break;

        case 'q':

          if (get
              () != 'u' || get
                () != 'o' || get
                  () != 't' || get
                    () != ';')
                {
                  return xml_error;
                }

          ch = '"';
          break;

        default:
          return xml_error;
        }

        break;

      case '"':
        slen = i;
        sconst[i] = 0;
        return xml_sconst;
      }

      if ((size_t)i+1 >= size)
      {
        char* newBuf = new char[size *= 2];
        memcpy(newBuf, sconst, slen);
        sconst = newBuf;
      }

      sconst[i++] = (char)ch;
    }

  case '-':

  case '+':

  case '0':

  case '1':

  case '2':

  case '3':

  case '4':

  case '5':

  case '6':

  case '7':

  case '8':

  case '9':
    i = 0;
    floatingPoint = false;

    while (true)
    {
      if ((size_t)i == size)
      {
        return xml_error;
      }

      if (!isdigit(ch) && ch != '-' && ch != '+' && ch != '.' && ch != 'E')
      {
        unget(ch);
        sconst[i] = '\0';

        if (floatingPoint)
        {
          return sscanf(sconst, "%lf%n", &fconst, &pos) == 1 && pos == i
                 ? xml_fconst : xml_error;
        }
        else
        {
          return sscanf(sconst, INT8_FORMAT "%n", &iconst, &pos) == 1 && pos == i
                 ? xml_iconst : xml_error;
        }
      }

      sconst[i++] = (char)ch;

      if (ch == '.')
      {
        floatingPoint = true;
      }

      ch = get
             ();
    }

  default:
    i = 0;

    while (isalnum(ch) || ch == '-' || ch == ':' || ch == '_')
    {
      if (i == MaxIdentSize)
      {
        return xml_error;
      }

      ident[i++] = (char)ch;

      ch = get
             ();
    }

    unget(ch);

    if (i == MaxIdentSize || i == 0)
    {
      return xml_error;
    }

    ident[i] = '\0';
    return xml_ident;
  }
}

#define EXPECT(x) scanner.expect(__LINE__, x)

dbXmlIo::dbXmlIo(dbDatabase* db) : m_db(db)
{}

dbXmlIo::~dbXmlIo()
{}



bool skipElement(dbXmlScanner& scanner)
{
  int depth = 1;

  do
  {
    switch (scanner.scan())
    {

    case dbXmlScanner::xml_lt:
      depth += 1;
      continue;

    case dbXmlScanner::xml_lts:
      depth -= 1;

      if (depth < 0 || !EXPECT(dbXmlScanner::xml_ident) || !EXPECT(dbXmlScanner::xml_gt))
      {
        return false;
      }

      break;

    case dbXmlScanner::xml_gts:
      depth -= 1;
      break;

    default:
      continue;
    }
  }
  while (depth != 0);

  return true;
}

bool dbXmlIo::importRecord(char* terminator, dbFieldDescriptor* fieldList, byte* rec, dbXmlScanner& scanner)
{
  dbXmlScanner::token tkn;

  while ((tkn = scanner.scan()) != dbXmlScanner::xml_lts)
  {
    if (tkn != dbXmlScanner::xml_lt || !EXPECT(dbXmlScanner::xml_ident)
        || !EXPECT(dbXmlScanner::xml_gt))
    {
      return false;
    }

    char* fieldName = scanner.getIdentifier();

    dbSymbolTable::add
      (fieldName, tkn_ident, FASTDB_CLONE_ANY_IDENTIFIER);

    dbFieldDescriptor* fd = fieldList;

    while (true)
    {
      if (fd->name == fieldName)
      {
        if (!importField(fd->name, fd, rec, scanner))
        {
          return false;
        }

        break;
      }

      if ((fd = fd->next) == fieldList)
      {
        if (!skipElement(scanner))
        {
          return false;
        }

        break;
      }
    }
  }

  return EXPECT(terminator) && EXPECT(dbXmlScanner::xml_gt);
}

#define HEX_DIGIT(ch) ((ch) >= 'a' ? ((ch) - 'a' + 10) : (ch) >= 'A' ? (((ch) - 'A' + 10)) : ((ch) - '0'))

bool dbXmlIo::importField(char* terminator, dbFieldDescriptor* fd, byte* rec, dbXmlScanner& scanner)
{
  dbXmlScanner::token tkn;
  int i;
  long id;
  byte* dst = rec + fd->appOffs;

  switch (fd->type)
  {

  case dbField::tpStructure:
    return importRecord(terminator, fd->components, rec, scanner);

  case dbField::tpArray:
    {
      int arrSize = 8;
      int elemSize = fd->components->appSize;
      byte* arr = (byte*)tmpAlloc.alloc(elemSize*arrSize);
      memset(arr, 0, elemSize*arrSize);

      for (i = 0; (tkn = scanner.scan()) == dbXmlScanner::xml_lt; i++)
      {
        if (!EXPECT("array-element")
            || !EXPECT(dbXmlScanner::xml_gt))
        {
          return false;
        }

        if (i == arrSize)
        {
          arrSize *= 2;
          byte* newArr = (byte*)tmpAlloc.alloc(elemSize*arrSize);
          memcpy(newArr, arr, i*elemSize);
          memset(newArr + i*elemSize, 0, i*elemSize);
          arr = newArr;
        }

        importField("array-element", fd->components, arr + i*elemSize, scanner);
      }

      dbAnyArray::arrayAllocator((dbAnyArray*)dst, arr, i);
      return tkn == dbXmlScanner::xml_lts
             && EXPECT(terminator)
             && EXPECT(dbXmlScanner::xml_gt);
    }

  case dbField::tpReference:

    if (!EXPECT(dbXmlScanner::xml_lt)
        || !EXPECT("ref")
        || !EXPECT("id")
        || !EXPECT(dbXmlScanner::xml_eq)
        || !EXPECT(dbXmlScanner::xml_sconst)
        || sscanf(scanner.getString(), "%ld", &id) != 1
        || !EXPECT(dbXmlScanner::xml_gts))
    {
      return false;
    }

    *(oid_t*)dst = mapId(id);
    break;

  case dbField::tpBool:

    switch (scanner.scan())
    {

    case dbXmlScanner::xml_iconst:
      *(bool*)dst = scanner.getInt() != 0;
      break;

    case dbXmlScanner::xml_fconst:
      *(bool*)dst = scanner.getReal() != 0.0;
      break;

    default:
      fprintf(stderr, "Failed to convert field '%s'\n", fd->name);
    }

    break;

  case dbField::tpInt1:

    switch (scanner.scan())
    {

    case dbXmlScanner::xml_iconst:
      *(int1*)dst = (int1)scanner.getInt();
      break;

    case dbXmlScanner::xml_fconst:
      *(int1*)dst = (int1)scanner.getReal();
      break;

    default:
      fprintf(stderr, "Failed to convert field '%s'\n", fd->name);
    }

    break;

  case dbField::tpInt2:

    switch (scanner.scan())
    {

    case dbXmlScanner::xml_iconst:
      *(int2*)dst = (int2)scanner.getInt();
      break;

    case dbXmlScanner::xml_fconst:
      *(int2*)dst = (int2)scanner.getReal();
      break;

⌨️ 快捷键说明

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