LCOV - code coverage report
Current view: top level - src - index.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 85 102 83.3 %
Date: 2019-01-29 11:06:41 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             : * Copyright (c) 1999-2002  Shane Hudson
       3             : * Copyright (c) 2006-2009  Pascal Georges
       4             : * Copyright (C) 2014-2016  Fulvio Benini
       5             : 
       6             : * This file is part of Scid (Shane's Chess Information Database).
       7             : *
       8             : * Scid is free software: you can redistribute it and/or modify
       9             : * it under the terms of the GNU General Public License as published by
      10             : * the Free Software Foundation.
      11             : *
      12             : * Scid is distributed in the hope that it will be useful,
      13             : * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             : * GNU General Public License for more details.
      16             : *
      17             : * You should have received a copy of the GNU General Public License
      18             : * along with Scid.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "index.h"
      22             : #include "namebase.h"
      23             : #include <cstring>
      24             : 
      25             : static constexpr char INDEX_MAGIC[8] = "Scid.si";
      26             : 
      27         128 : void Index::Init ()
      28             : {
      29         128 :     Header.numGames  = 0;
      30         128 :     Header.version   = SCID_VERSION;
      31         128 :     Header.baseType = 0;
      32         128 :     Header.autoLoad = 1;
      33         128 :     Header.description[0] = 0;
      34         128 :     std::memset(Header.customFlagDesc, 0, sizeof(Header.customFlagDesc));
      35         128 :     Header.dirty_ = false;
      36         128 :     FilePtr = NULL;
      37         128 :     fileMode_ = FMODE_Memory;
      38         128 :     nInvalidNameId_ = 0;
      39         128 :     seqWrite_ = 0;
      40         128 :     entries_.resize(0);
      41         128 : }
      42             : 
      43          78 : errorT Index::Clear ()
      44             : {
      45          78 :     errorT res = flush();
      46          78 :     delete FilePtr;
      47          78 :     Init();
      48          78 :     return res;
      49             : }
      50             : 
      51             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      52             : // Index::CreateIndexFile():
      53             : //      Creates and opens a new empty index file.
      54             : //
      55             : errorT
      56           6 : Index::Create(const char* filename)
      57             : {
      58           6 :     ASSERT(filename != 0);
      59             : 
      60           6 :     Clear();
      61           6 :     FilePtr = new Filebuf;
      62          12 :     std::string fname = filename;
      63           6 :     fname += INDEX_SUFFIX;
      64             :     //Check that the file does not exists and then create it
      65          12 :     if (FilePtr->Open(fname.c_str(), FMODE_ReadOnly) == OK ||
      66           6 :         FilePtr->Open(fname.c_str(), FMODE_Create) != OK) {
      67           0 :         delete FilePtr;
      68           0 :         FilePtr = NULL;
      69           0 :         return ERROR_FileOpen;
      70             :     }
      71           6 :     fileMode_ = FMODE_Both;
      72           6 :     return WriteHeader();
      73             : }
      74             : 
      75             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      76             : // Index::Open():
      77             : //      Open an index file and read the header.
      78             : //
      79             : errorT
      80           8 : Index::Open (const char* filename, fileModeT fmode)
      81             : {
      82           8 :     ASSERT(filename != 0);
      83             : 
      84           8 :     Clear();
      85           8 :     if (fmode == FMODE_WriteOnly) return ERROR_FileMode;
      86           7 :     FilePtr = new Filebuf;
      87          14 :     std::string fname = filename;
      88           7 :     fname += INDEX_SUFFIX;
      89             : 
      90           7 :     if (FilePtr->Open (fname.c_str(), fmode) != OK) {
      91           0 :         delete FilePtr;
      92           0 :         FilePtr = NULL;
      93           0 :         return ERROR_FileOpen;
      94             :     }
      95             : 
      96             :     char magic[8];
      97           7 :     FilePtr->sgetn(magic, 8);
      98           7 :     if (!std::equal(std::begin(magic), std::end(magic), std::begin(INDEX_MAGIC),
      99             :                     std::end(INDEX_MAGIC))) {
     100           0 :         delete FilePtr;
     101           0 :         FilePtr = NULL;
     102           0 :         return ERROR_BadMagic;
     103             :     }
     104             : 
     105           7 :     Header.version = FilePtr->ReadTwoBytes ();
     106           7 :     if (Header.version < SCID_OLDEST_VERSION || Header.version > SCID_VERSION) {
     107           0 :         delete FilePtr;
     108           0 :         FilePtr = NULL;
     109           0 :         return ERROR_FileVersion;
     110             :     }
     111           7 :     if (Header.version != SCID_VERSION && fmode != FMODE_ReadOnly) {
     112             :         //Old versions must be opened readonly
     113           0 :         delete FilePtr;
     114           0 :         FilePtr = NULL;
     115           0 :         return ERROR_FileMode;
     116             :     }
     117             : 
     118           7 :     Header.baseType = FilePtr->ReadFourBytes ();
     119           7 :     Header.numGames = FilePtr->ReadThreeBytes ();
     120           7 :     Header.autoLoad = FilePtr->ReadThreeBytes ();
     121           7 :     FilePtr->sgetn(Header.description, SCID_DESC_LENGTH + 1);
     122           7 :     Header.description[SCID_DESC_LENGTH] = 0;
     123           7 :     if (Header.version >= 400) {
     124          49 :         for (uint i = 0 ; i < CUSTOM_FLAG_MAX ; i++ ) {
     125          42 :             FilePtr->sgetn(Header.customFlagDesc[i], CUSTOM_FLAG_DESC_LENGTH + 1);
     126          42 :             Header.customFlagDesc[i][CUSTOM_FLAG_DESC_LENGTH] = 0;
     127             :         }
     128             :     } 
     129             : 
     130           7 :     fileMode_ = fmode;
     131           7 :     return OK;
     132             : }
     133             : 
     134             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     135             : // Index::WriteHeader():
     136             : //      Write the header to the open index file.
     137             : //
     138             : errorT
     139           9 : Index::WriteHeader ()
     140             : {
     141           9 :     ASSERT(FilePtr != NULL);
     142           9 :     if (FilePtr->pubseekpos(0) != std::streampos(0)) return ERROR_FileWrite;
     143             : 
     144           9 :     seqWrite_ = 0;
     145           9 :     std::streamsize n = 0;
     146           9 :     n += FilePtr->sputn(INDEX_MAGIC, 8);
     147           9 :     n += FilePtr->WriteTwoBytes (Header.version);
     148           9 :     n += FilePtr->WriteFourBytes (Header.baseType);
     149           9 :     n += FilePtr->WriteThreeBytes (Header.numGames);
     150           9 :     n += FilePtr->WriteThreeBytes (Header.autoLoad);
     151           9 :     n += FilePtr->sputn(Header.description, SCID_DESC_LENGTH + 1);
     152          63 :     for (size_t i = 0 ; i < CUSTOM_FLAG_MAX ; i++ ) {
     153          54 :         n += FilePtr->sputn(Header.customFlagDesc[i], CUSTOM_FLAG_DESC_LENGTH + 1);
     154             :     }
     155           9 :     if (n != INDEX_HEADER_SIZE || FilePtr->pubsync() == -1) return ERROR_FileWrite;
     156           9 :     Header.dirty_ = false;
     157           9 :     return OK;
     158             : }
     159             : 
     160       12018 : errorT Index::WriteEntry(const IndexEntry* ie, gamenumT idx)
     161             : {
     162       12018 :     if (idx > Header.numGames) return ERROR_BadArg;
     163       12018 :     if (fileMode_ == FMODE_ReadOnly) { return ERROR_FileMode; }
     164             : 
     165       12018 :     if (idx == Header.numGames) {
     166       10017 :         entries_.push_back(*ie);
     167       10017 :         Header.numGames++;
     168       10017 :         Header.dirty_ = true;
     169             :     } else {
     170        2001 :         IndexEntry* copyToMemory = &(entries_[idx]);
     171        2001 :         *copyToMemory = *ie;
     172             :     }
     173       12018 :     if (FilePtr == NULL) return OK;
     174             : 
     175        4000 :     if ((seqWrite_ == 0) || (idx != seqWrite_ + 1)) {
     176        1004 :         std::streampos pos = INDEX_ENTRY_SIZE * idx + INDEX_HEADER_SIZE;
     177        1004 :         if (FilePtr->pubseekpos(pos) != pos) {
     178           0 :             seqWrite_ = 0;
     179           0 :             return ERROR_FileWrite;
     180             :         }
     181             :     }
     182        4000 :     errorT res = ie->Write (FilePtr, Header.version);
     183        4000 :     seqWrite_ = (res == OK) ? idx : 0;
     184        4000 :     return res;
     185             : }
     186             : 
     187             : //////////////////////////////////////////////////////////////////////
     188             : //  EOF: index.cpp
     189             : //////////////////////////////////////////////////////////////////////
     190             : 

Generated by: LCOV version 1.13