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

📄 xmlio.cpp

📁 FastDb是高效的内存数据库系统
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    default:
      fprintf(stderr, "Failed to convert field '%s'\n", fd->name);
    }

    break;

  case dbField::tpInt4:

    switch (scanner.scan())
    {

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

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

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

    break;

  case dbField::tpInt8:

    switch (scanner.scan())
    {

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

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

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

    break;

  case dbField::tpReal4:

    switch (scanner.scan())
    {

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

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

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

    break;

  case dbField::tpReal8:

    switch (scanner.scan())
    {

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

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

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

    break;

  case dbField::tpString:

    switch (scanner.scan())
    {

    case dbXmlScanner::xml_iconst:

    case dbXmlScanner::xml_sconst:

    case dbXmlScanner::xml_fconst:
      {
        char* str = (char*)tmpAlloc.alloc((scanner.getStringLength()+1));
        memcpy(str, scanner.getString(), scanner.getStringLength());
        str[scanner.getStringLength()] = '\0';
        *(char**)dst = str;
        break;
      }

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

    break;

  case dbField::tpRawBinary:
    {
      char* src = scanner.getString();
      int len = scanner.getStringLength() >> 1;

      if (fd->appSize != (size_t)len)
      {
        fprintf(stderr, "Length of raw binary field '%s' was changed\n", fd->name);
      }
      else
      {
        while (--len >= 0)
        {
          *dst++ = (HEX_DIGIT(src[0]) << 4) | HEX_DIGIT(src[1]);
          src += 2;
        }
      }

      break;
    }

#ifdef USE_STD_STRING

  case dbField::tpStdString:
    ((std::string*)dst)->assign(scanner.getString(), scanner.getStringLength());
    break;
#endif

  }

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

oid_t dbXmlIo::mapId(long id)
{
  oid_t oid;

  if (id == 0)
  {
    return 0;
  }

  if ((oid_t)id >= oidMapSize)
  {
    oid_t* newOidMap = new oid_t[id*2];
    memcpy(newOidMap, oidMap, oidMapSize*sizeof(oid_t));
    memset(newOidMap + oidMapSize, 0, (id*2-oidMapSize)*sizeof(oid_t));
    oidMapSize = id*2;
    oidMap = newOidMap;
  }

  oid = oidMap[id];

  if (oid == 0)
  {
    oid = m_db->allocateId();
    oidMap[id] = oid;
  }

  return oid;
}

void dbXmlIo::insertRecord(dbTableDescriptor* desc, oid_t oid, void const* record)
{
  dbFieldDescriptor* fd;
  byte* src = (byte*)record;
  size_t size = desc->columns->calculateRecordSize(src, desc->fixedSize);
  m_db->allocateRow(desc->tableId, oid, size);
  byte* dst = (byte*)m_db->getRow(oid);
  desc->columns->storeRecordFields(dst, src, desc->fixedSize, true);

  dbTable* table = (dbTable*)m_db->getRow(desc->tableId);
#ifdef AUTOINCREMENT_SUPPORT

  desc->autoincrementCount = table->count;
#endif

  int nRows = table->nRows;

  for (fd = desc->hashedFields; fd != NULL; fd = fd->nextHashedField)
  {
    dbHashTable::insert(m_db, fd->hashTable, oid, fd->type, fd->dbsSize, fd->dbsOffs, nRows);
  }

  for (fd = desc->indexedFields; fd != NULL; fd = fd->nextIndexedField)
  {
    dbTtree::insert(m_db, fd->tTree, oid, fd->type, fd->dbsSize, fd->comparator, fd->dbsOffs);
  }
}

bool dbXmlIo::importDatabase(FILE* in, bool append)
{
  dbXmlScanner scanner(in);
  dbXmlScanner::token tkn;

  if (!EXPECT(dbXmlScanner::xml_lt) ||
      !EXPECT("database") ||
      !EXPECT(dbXmlScanner::xml_gt))
  {
    return false;
  }

  oidMapSize = dbDefaultInitIndexSize;
  oidMap = new oid_t[oidMapSize];
  memset(oidMap, 0, oidMapSize*sizeof(oid_t));

  m_db->beginTransaction(dbDatabase::dbExclusiveLock);

  dbTableDescriptor* desc;

  if (!append)
  {
    for (desc=m_db->tables; desc != NULL; desc=desc->nextDbTable)
    {
      if (desc->tableId != dbMetaTableId)
      {
        m_db->deleteTable(desc);
      }
    }
  }

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

    desc = m_db->findTableByName(scanner.getIdentifier());

    if (desc == NULL)
    {
      fprintf(stderr, "Table '%s' not found\n", scanner.getIdentifier());
    }

    if (!EXPECT("id")
        || !EXPECT(dbXmlScanner::xml_eq)
        || !EXPECT(dbXmlScanner::xml_sconst)
        || !EXPECT(dbXmlScanner::xml_gt))
    {
      return false;
    }

    if (desc != NULL)
    {
      long id;

      if (sscanf(scanner.getString(), "%ld", &id) != 1)
      {
        return false;
      }

      oid_t oid = mapId(id);
      byte *record = (byte*)tmpAlloc.alloc(desc->appSize);
      memset(record, 0, desc->appSize);

      if (!importRecord(desc->name, desc->columns, record, scanner))
      {
        tmpAlloc.reset();
        return false;
      }

      insertRecord(desc, oid, record);
      tmpAlloc.reset();
    }
    else
    { // skip record

      if (!skipElement(scanner))
      {
        return false;
      }
    }
  }

  return EXPECT("database") && EXPECT(dbXmlScanner::xml_gt);
}


void exportString(FILE* out, char* src, int len)
{
  fprintf(out, "\"");

  while (--len > 0)
  {
    byte b = (byte)*src++;

    switch (b)
    {

    case '&':
      fprintf(out, "&amp;");
      break;

    case '<':
      fprintf(out, "&lt;");
      break;

    case '>':
      fprintf(out, "&gt;");
      break;

    case '"':
      fprintf(out, "&quot;");
      break;

    default:
      fprintf(out, "%c", b);
    }
  }

  fprintf(out, "\"");
}

void exportBinary(FILE* out, byte* src, int len)
{
  fprintf(out, "\"");

  while (--len >= 0)
  {
    fprintf(out, "%02X", *src++);
  }

  fprintf(out, "\"");
}

void exportRecord(dbFieldDescriptor* fieldList, FILE* out, byte* src, int indent)
{
  int i;
  dbFieldDescriptor* fd = fieldList;

  do
  {
    byte* ptr = src + fd->dbsOffs;

    for (i = indent; --i >= 0;)
    {
      fprintf(out, " ");
    }

    char* fieldName = fd->name;

    if (strcmp(fieldName, "[]") == 0)
    {
      fieldName = "array-element";
    }

    fprintf(out, "<%s>", fieldName);

    switch (fd->type)
    {

    case dbField::tpBool:
      fprintf(out, "%d", *(bool*)ptr);
      break;

    case dbField::tpInt1:
      fprintf(out, "%d", *(int1*)ptr);
      break;

    case dbField::tpInt2:
      fprintf(out, "%d", *(int2*)ptr);
      break;

    case dbField::tpInt4:
      fprintf(out, "%d", *(int4*)ptr);
      break;

    case dbField::tpInt8:
      fprintf(out, INT8_FORMAT, *(db_int8*)ptr);
      break;

    case dbField::tpReal4:
      fprintf(out, "%.8G", *(real4*)ptr);
      break;

    case dbField::tpReal8:
      fprintf(out, "%.16G", *(real8*)ptr);
      break;

    case dbField::tpRawBinary:
      exportBinary(out, src+fd->dbsOffs, fd->dbsSize);
      break;

    case dbField::tpString:
      exportString(out, (char*)(src + ((dbVarying*)ptr)->offs), ((dbVarying*)ptr)->size);
      break;

    case dbField::tpArray:
      {
        int nElems = ((dbVarying*)ptr)->size;
        byte* srcElem = src + ((dbVarying*)ptr)->offs;
        dbFieldDescriptor* element = fd->components;
        fprintf(out, "\n");

        while (--nElems >= 0)
        {
          exportRecord(element, out, srcElem, indent+1);
          srcElem += element->dbsSize;
        }

        for (i = indent; --i >= 0;)
        {
          fprintf(out, " ");
        }

        break;
      }

    case dbField::tpReference:
      fprintf(out, "<ref id=\"%ld\"/>", (long)*(oid_t*)ptr);
      break;

    case dbField::tpStructure:
      fprintf(out, "\n");
      exportRecord(fd->components, out, src, indent+1);

      for (i = indent; --i >= 0;)
      {
        fprintf(out, " ");
      }

      break;
    }

    fprintf(out, "</%s>\n", fieldName);
  }
  while ((fd = fd->next) != fieldList);
}

void dbXmlIo::exportDatabase(FILE* out, bool schema)
{
  fprintf(out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<database>\n");

  for (dbTableDescriptor* desc=m_db->tables; desc != NULL; desc=desc->nextDbTable)
  {
    if (desc->tableId != dbMetaTableId)
    {
      dbTable* table = (dbTable*)m_db->getRow(desc->tableId);
      oid_t oid = table->firstRow;
      int n = table->nRows;
      int percent = 0;

      if (schema)
      {
        int i;
        fprintf(out, " <%s id=\"x\">\n", desc->name);
        dbFieldDescriptor* fd = desc->columns;

        do
        {
          for (i = 2; --i >= 0;)
            fprintf(out, " ");

          char* fieldName = fd->name;

          fprintf(out, "<%s>", fieldName);

          if (fd->type== dbField::tpArray)
          {
            fprintf(out, "\n");

            for (i = 4; --i >= 0;)
              fprintf(out, " ");

            fprintf(out, "<array-element></array-element>\n");
          }

          fprintf(out, "</%s>\n", fieldName);
        }
        while ((fd = fd->next) != desc->columns);

        fprintf(out, " </%s>\n", desc->name);
      }
      else
      {
        for (int i = 0; oid != 0; i++)
        {
          dbRecord* rec = m_db->getRow(oid);
          fprintf(out, " <%s id=\"%d\">\n", desc->name, oid);
          exportRecord(desc->columns, out, (byte*)rec, 2);
          fprintf(out, " </%s>\n", desc->name);
          oid = rec->next;
          int p = (i+1)*100/n;

          if (p != percent)
          {
            fprintf(stderr, "Exporting table %s: %d%%\r", desc->name, p);
            fflush(stderr);
            percent = p;
          }
        }
      }

      fputc('\n', stderr);
    }
  }

  fprintf(out, "</database>\n");
}


⌨️ 快捷键说明

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