Ejemplo n.º 1
0
bool TDBCSV::OpenDB(PGLOBAL g)
  {
  bool    rc = false;
  PCOLDEF cdp;
  PDOSDEF tdp = (PDOSDEF)To_Def;

  if (Use != USE_OPEN && (Columns || Mode == MODE_UPDATE)) {
    // Allocate the storage used to read (or write) records
    int     i, len;
    PCSVCOL colp;

    if (!Fields)              // May have been set in TABFMT::OpenDB
      if (Mode != MODE_UPDATE && Mode != MODE_INSERT) {
        for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next)
          if (!colp->IsSpecial() && !colp->IsVirtual())
            Fields = MY_MAX(Fields, (int)colp->Fldnum);

        if (Columns)
          Fields++;           // Fldnum was 0 based

      } else
        for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext())
          if (!cdp->IsVirtual())
            Fields++;

    Offset = (int*)PlugSubAlloc(g, NULL, sizeof(int) * Fields);
    Fldlen = (int*)PlugSubAlloc(g, NULL, sizeof(int) * Fields);

    if (Mode == MODE_INSERT || Mode == MODE_UPDATE) {
      Field = (PSZ*)PlugSubAlloc(g, NULL, sizeof(PSZ) * Fields);
      Fldtyp = (bool*)PlugSubAlloc(g, NULL, sizeof(bool) * Fields);
      } // endif Mode

    for (i = 0; i < Fields; i++) {
      Offset[i] = 0;
      Fldlen[i] = 0;

      if (Field) {
        Field[i] = NULL;
        Fldtyp[i] = false;
        } // endif Field

      } // endfor i

    if (Field)
      // Prepare writing fields
      if (Mode != MODE_UPDATE) {
        for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next)
          if (!colp->IsSpecial() && !colp->IsVirtual()) {
            i = colp->Fldnum;
            len = colp->GetLength();
            Field[i] = (PSZ)PlugSubAlloc(g, NULL, len + 1);
            Field[i][len] = '\0';
            Fldlen[i] = len;
            Fldtyp[i] = IsTypeNum(colp->GetResultType());
            } // endif colp

      } else     // MODE_UPDATE
        for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext())
          if (!cdp->IsVirtual()) {
            i = cdp->GetOffset() - 1;
            len = cdp->GetLength();
            Field[i] = (PSZ)PlugSubAlloc(g, NULL, len + 1);
            Field[i][len] = '\0';
            Fldlen[i] = len;
            Fldtyp[i] = IsTypeNum(cdp->GetType());
            } // endif cdp

    } // endif Use

  if (Header) {
    // Check that the Lrecl is at least equal to the header line length
    int     headlen = 0;
    PCOLDEF cdp;
    PDOSDEF tdp = (PDOSDEF)To_Def;

    for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext())
      headlen += strlen(cdp->GetName()) + 3;  // 3 if names are quoted

    if (headlen > Lrecl) {
      Lrecl = headlen;
      Txfp->Lrecl = headlen;
      } // endif headlen

    } // endif Header

  Nerr = 0;
  rc = TDBDOS::OpenDB(g);

  if (!rc && Mode == MODE_UPDATE && To_Kindex)
    // Because KINDEX::Init is executed in mode READ, we must restore
    // the Fldlen array that was modified when reading the table file.
    for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext())
      Fldlen[cdp->GetOffset() - 1] = cdp->GetLength();

  return rc;
  } // end of OpenDB
Ejemplo n.º 2
0
bool DBFFAM::AllocateBuffer(PGLOBAL g)
  {
  char c;
  int  rc;
  MODE mode = Tdbp->GetMode();

  Buflen = Blksize;
  To_Buf = (char*)PlugSubAlloc(g, NULL, Buflen);

  if (mode == MODE_INSERT) {
#if defined(WIN32)
    /************************************************************************/
    /*  Now we can revert to binary mode in particular because the eventual */
    /*  writing of a new header must be done in binary mode to avoid        */
    /*  translating 0A bytes (LF) into 0D0A (CRLF) by Windows in text mode. */
    /************************************************************************/
    if (_setmode(_fileno(Stream), _O_BINARY) == -1) {
      sprintf(g->Message, MSG(BIN_MODE_FAIL), strerror(errno));
      return true;
      } // endif setmode
#endif   // WIN32

    /************************************************************************/
    /*  If this is a new file, the header must be generated.                */
    /************************************************************************/
    int len = GetFileLength(g);

    if (!len) {
      // Make the header for this DBF table file
      struct tm  *datm;
      int         hlen, n = 0;
      ushort      reclen = 1;
      time_t      t;
      DBFHEADER  *header;
      DESCRIPTOR *descp;
      PCOLDEF     cdp;
      PDOSDEF     tdp = (PDOSDEF)Tdbp->GetDef();

      // Count the number of columns
      for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext())
        if (!(cdp->Flags & U_SPECIAL)) {
          reclen += cdp->GetLong();
          n++;
          } // endif Flags

      if (Lrecl != reclen) {
        sprintf(g->Message, MSG(BAD_LRECL), Lrecl, reclen);
        return true;
        } // endif Lrecl

      hlen = HEADLEN * (n + 1) + 2;
      header = (DBFHEADER*)PlugSubAlloc(g, NULL, hlen);
      memset(header, 0, hlen);
      header->Version = DBFTYPE;
      t = time(NULL) - (time_t)DTVAL::GetShift();
      datm = gmtime(&t);
      header->Filedate[0] = datm->tm_year - 100;
      header->Filedate[1] = datm->tm_mon + 1;
      header->Filedate[2] = datm->tm_mday;
      header->Headlen = (ushort)hlen;
      header->Reclen = (ushort)reclen;
      descp = (DESCRIPTOR*)header;

      // Currently only standard Xbase types are supported
      for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext())
        if (!(cdp->Flags & U_SPECIAL)) {
          descp++;
      
          switch ((c = *GetFormatType(cdp->GetType()))) {
            case 'S':           // Short integer
            case 'L':           // Large (big) integer
            case 'T':           // Tiny integer
              c = 'N';          // Numeric
            case 'N':           // Numeric (integer)
            case 'F':           // Float (double)
              descp->Decimals = (uchar)cdp->F.Prec;
            case 'C':           // Char
            case 'D':           // Date
              break;
            default:            // Should never happen
              sprintf(g->Message, "Unsupported DBF type %c for column %s",
                                  c, cdp->GetName());
              return true;
            } // endswitch c
      
          strncpy(descp->Name, cdp->GetName(), 11);
          descp->Type = c;
          descp->Length = (uchar)cdp->GetLong();
          } // endif Flags

      *(char*)(++descp) = EOH;

      //  Now write the header
      if (fwrite(header, 1, hlen, Stream) != (unsigned)hlen) {
        sprintf(g->Message, MSG(FWRITE_ERROR), strerror(errno));
        return true;
        } // endif fwrite

      Records = 0;
      Headlen = hlen;
    } else if (len < 0)
      return true;            // Error in GetFileLength

    /************************************************************************/
    /*  For Insert the buffer must be prepared.                             */
    /************************************************************************/
    memset(To_Buf, ' ', Buflen);
    Rbuf = Nrec;                     // To be used by WriteDB
  } else if (UseTemp) {
    // Allocate a separate buffer so block reading can be kept
    Dbflen = Nrec;
    DelBuf = PlugSubAlloc(g, NULL, Blksize);
  } // endif's

  if (!Headlen) {
    /************************************************************************/
    /*  Here is a good place to process the DBF file header                 */
    /************************************************************************/
    DBFHEADER header;

    if ((rc = dbfhead(g, Stream, Tdbp->GetFile(g), &header)) == RC_OK) {
      if (Lrecl != (int)header.Reclen) {
        sprintf(g->Message, MSG(BAD_LRECL), Lrecl, header.Reclen);
        return true;
        } // endif Lrecl

      Records = (int)header.Records;
      Headlen = (int)header.Headlen;
    } else if (rc == RC_NF) {
      Records = 0;
      Headlen = 0;
    } else              // RC_FX
      return true;                  // Error in dbfhead

    } // endif Headlen

  /**************************************************************************/
  /*  Position the file at the begining of the data.                        */
  /**************************************************************************/
  if (Tdbp->GetMode() == MODE_INSERT)
    rc = fseek(Stream, 0, SEEK_END);
  else
    rc = fseek(Stream, Headlen, SEEK_SET);

  if (rc) {
    sprintf(g->Message, MSG(BAD_DBF_FILE), Tdbp->GetFile(g));
    return true;
    } // endif fseek

  return false;
  } // end of AllocateBuffer