LCOV - code coverage report
Current view: top level - src - index.cpp (source / functions) Hit Total Coverage
Test: test_coverage.info Lines: 125 142 88.0 %
Date: 2017-06-21 14:32:49 Functions: 7 7 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         135 : void Index::Init ()
      26             : {
      27         135 :     strCopy (Header.magic, INDEX_MAGIC);
      28         135 :     Header.numGames  = 0;
      29         135 :     Header.version   = SCID_VERSION;
      30         135 :     Header.baseType = 0;
      31         135 :     Header.autoLoad = 1;
      32         135 :     Header.description[0] = 0;
      33         270 :     std::memset(Header.customFlagDesc, 0, sizeof(Header.customFlagDesc));
      34         135 :     Header.dirty_ = false;
      35         135 :     FilePtr = NULL;
      36         135 :     fileMode_ = FMODE_Memory;
      37         135 :     nInvalidNameId_ = 0;
      38         135 :     seqWrite_ = 0;
      39         135 :     entries_.resize(0);
      40         135 : }
      41             : 
      42          82 : errorT Index::Clear ()
      43             : {
      44          82 :     errorT res = flush();
      45          82 :     delete FilePtr;
      46          82 :     Init();
      47          82 :     return res;
      48             : }
      49             : 
      50             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      51             : // Index::CreateIndexFile():
      52             : //      Creates and opens a new empty index file.
      53             : //
      54             : errorT
      55           9 : Index::Create(const char* filename)
      56             : {
      57           9 :     ASSERT(filename != 0);
      58             : 
      59           9 :     Clear();
      60          18 :     FilePtr = new Filebuf;
      61          36 :     std::string fname = filename;
      62           9 :     fname += INDEX_SUFFIX;
      63             :     //Check that the file does not exists and then create it
      64          27 :     if (FilePtr->Open(fname.c_str(), FMODE_ReadOnly) == OK ||
      65          18 :         FilePtr->Open(fname.c_str(), FMODE_Create) != OK) {
      66           0 :         delete FilePtr;
      67           0 :         FilePtr = NULL;
      68           0 :         return ERROR_FileOpen;
      69             :     }
      70           9 :     fileMode_ = FMODE_Both;
      71           9 :     return WriteHeader();
      72             : }
      73             : 
      74             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      75             : // Index::Open():
      76             : //      Open an index file and read the header.
      77             : //
      78             : errorT
      79          12 : Index::Open (const char* filename, fileModeT fmode)
      80             : {
      81          12 :     ASSERT(filename != 0);
      82             : 
      83          12 :     Clear();
      84          12 :     if (fmode == FMODE_WriteOnly) return ERROR_FileMode;
      85          22 :     FilePtr = new Filebuf;
      86          33 :     std::string fname = filename;
      87          11 :     fname += INDEX_SUFFIX;
      88             : 
      89          11 :     if (FilePtr->Open (fname.c_str(), fmode) != OK) {
      90           0 :         delete FilePtr;
      91           0 :         FilePtr = NULL;
      92           0 :         return ERROR_FileOpen;
      93             :     }
      94             : 
      95          22 :     FilePtr->sgetn(Header.magic, 8);
      96          11 :     Header.magic[8] = 0;
      97          11 :     if (strCompare (Header.magic, INDEX_MAGIC) != 0) {
      98           0 :         delete FilePtr;
      99           0 :         FilePtr = NULL;
     100           0 :         return ERROR_BadMagic;
     101             :     }
     102             : 
     103          22 :     Header.version = FilePtr->ReadTwoBytes ();
     104          11 :     if (Header.version < SCID_OLDEST_VERSION || Header.version > SCID_VERSION) {
     105           0 :         delete FilePtr;
     106           0 :         FilePtr = NULL;
     107           0 :         return ERROR_FileVersion;
     108             :     }
     109          11 :     if (Header.version != SCID_VERSION && fmode != FMODE_ReadOnly) {
     110             :         //Old versions must be opened readonly
     111           0 :         delete FilePtr;
     112           0 :         FilePtr = NULL;
     113           0 :         return ERROR_FileMode;
     114             :     }
     115             : 
     116          22 :     Header.baseType = FilePtr->ReadFourBytes ();
     117          22 :     Header.numGames = FilePtr->ReadThreeBytes ();
     118          22 :     Header.autoLoad = FilePtr->ReadThreeBytes ();
     119          22 :     FilePtr->sgetn(Header.description, SCID_DESC_LENGTH + 1);
     120          11 :     Header.description[SCID_DESC_LENGTH] = 0;
     121          11 :     if (Header.version >= 400) {
     122         143 :         for (uint i = 0 ; i < CUSTOM_FLAG_MAX ; i++ ) {
     123         132 :             FilePtr->sgetn(Header.customFlagDesc[i], CUSTOM_FLAG_DESC_LENGTH + 1);
     124          66 :             Header.customFlagDesc[i][CUSTOM_FLAG_DESC_LENGTH] = 0;
     125             :         }
     126             :     } 
     127             : 
     128          11 :     fileMode_ = fmode;
     129          11 :     return OK;
     130             : }
     131             : 
     132             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     133             : // Index::ReadEntireFile():
     134             : //      Reads in the entire index into memory.
     135             : //
     136             : errorT
     137          11 : Index::ReadEntireFile (NameBase* nb, const Progress& progress)
     138             : {
     139          11 :     ASSERT (FilePtr != NULL);
     140          11 :     ASSERT (entries_.size() == 0);
     141             : 
     142          11 :     if (fileMode_ == FMODE_WriteOnly) { return ERROR_FileMode; }
     143          11 :     entries_.resize(Header.numGames);
     144             : 
     145             :     idNumberT maxIdx[NUM_NAME_TYPES];
     146          99 :     for (nameT nt = NAME_PLAYER; nt < NUM_NAME_TYPES; nt++) {
     147          44 :         maxIdx[nt] = nb->GetNumNames(nt);
     148             :     }
     149             : 
     150             :     gamenumT gNum = 0;
     151       16051 :     for (; FilePtr->sgetc() != EOF; gNum++) {
     152        5343 :         if (gNum == Header.numGames) return ERROR_CorruptData;
     153             : 
     154        5343 :         if ((gNum % 10000) == 0) {
     155          16 :             if (!progress.report(gNum, Header.numGames)) return ERROR_UserCancel;
     156             :         }
     157             : 
     158       10686 :         IndexEntry* ie = &(entries_[gNum]);
     159        5343 :         errorT err = ie->Read(FilePtr, Header.version);
     160        5343 :         if (err != OK) return err;
     161             : 
     162        5343 :         if (ie->GetWhite() >= maxIdx[NAME_PLAYER]) {
     163           1 :             ie->SetWhiteName(nb, "?");
     164           1 :             nInvalidNameId_++;
     165             :         }
     166        5343 :         if (ie->GetBlack() >= maxIdx[NAME_PLAYER]) {
     167           1 :             ie->SetBlackName(nb, "?");
     168           1 :             nInvalidNameId_++;
     169             :         }
     170        5343 :         if (ie->GetEvent() >= maxIdx[NAME_EVENT] ) {
     171           1 :             ie->SetEventName(nb, "?");
     172           1 :             nInvalidNameId_++;
     173             :         }
     174        5343 :         if (ie->GetSite()  >= maxIdx[NAME_SITE]  ) {
     175           1 :             ie->SetSiteName(nb, "?");
     176           1 :             nInvalidNameId_++;
     177             :         }
     178        5343 :         if (ie->GetRound() >= maxIdx[NAME_ROUND] ) {
     179           1 :             ie->SetRoundName(nb, "?");
     180           1 :             nInvalidNameId_++;
     181             :         }
     182             : 
     183        5343 :         eloT eloW = ie->GetWhiteElo();
     184        6554 :         if (eloW > 0) nb->AddElo (ie->GetWhite(), eloW);
     185        5343 :         eloT eloB = ie->GetBlackElo();
     186        6435 :         if (eloB > 0) nb->AddElo (ie->GetBlack(), eloB);
     187             :     }
     188          11 :     progress.report(1,1);
     189             : 
     190          11 :     if (gNum != Header.numGames) return ERROR_FileRead;
     191          11 :     if (nInvalidNameId_ != 0) return ERROR_NameDataLoss;
     192          10 :     return OK;
     193             : }
     194             : 
     195             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     196             : // Index::WriteHeader():
     197             : //      Write the header to the open index file.
     198             : //
     199             : errorT
     200          25 : Index::WriteHeader ()
     201             : {
     202          25 :     ASSERT(FilePtr != NULL);
     203          75 :     if (FilePtr->pubseekpos(0) != std::streampos(0)) return ERROR_FileWrite;
     204             : 
     205          25 :     seqWrite_ = 0;
     206          25 :     size_t n = 0;
     207          50 :     n += FilePtr->sputn(Header.magic, 8);
     208          25 :     n += FilePtr->WriteTwoBytes (Header.version);
     209          25 :     n += FilePtr->WriteFourBytes (Header.baseType);
     210          25 :     n += FilePtr->WriteThreeBytes (Header.numGames);
     211          25 :     n += FilePtr->WriteThreeBytes (Header.autoLoad);
     212          50 :     n += FilePtr->sputn(Header.description, SCID_DESC_LENGTH + 1);
     213         175 :     for (size_t i = 0 ; i < CUSTOM_FLAG_MAX ; i++ ) {
     214         300 :         n += FilePtr->sputn(Header.customFlagDesc[i], CUSTOM_FLAG_DESC_LENGTH + 1);
     215             :     }
     216          50 :     if (n != INDEX_HEADER_SIZE || FilePtr->pubsync() == -1) return ERROR_FileWrite;
     217          25 :     Header.dirty_ = false;
     218          25 :     return OK;
     219             : }
     220             : 
     221       16041 : errorT Index::write (const IndexEntry* ie, gamenumT idx)
     222             : {
     223       16041 :     if (idx > Header.numGames) return ERROR_BadArg;
     224       16041 :     if (idx >= MAX_GAMES) return ERROR_IndexFull;
     225       16041 :     if (fileMode_ == FMODE_ReadOnly) { return ERROR_FileMode; }
     226             : 
     227       16041 :     if (idx == Header.numGames) {
     228       24078 :         entries_.push_back(*ie);
     229       12039 :         Header.numGames++;
     230       12039 :         Header.dirty_ = true;
     231             :     } else {
     232        8004 :         IndexEntry* copyToMemory = &(entries_[idx]);
     233        4002 :         *copyToMemory = *ie;
     234             :     }
     235       16041 :     if (FilePtr == NULL) return OK;
     236             : 
     237        6004 :     if ((seqWrite_ == 0) || (idx != seqWrite_ + 1)) {
     238        4016 :         std::streampos pos = INDEX_ENTRY_SIZE * idx + INDEX_HEADER_SIZE;
     239        6024 :         if (FilePtr->pubseekpos(pos) != pos) {
     240           0 :             seqWrite_ = 0;
     241           0 :             return ERROR_FileWrite;
     242             :         }
     243             :     }
     244        6004 :     errorT res = ie->Write (FilePtr, Header.version);
     245        6004 :     seqWrite_ = (res == OK) ? idx : 0;
     246        6004 :     return res;
     247             : }
     248             : 
     249             : //////////////////////////////////////////////////////////////////////
     250             : //  EOF: index.cpp
     251             : //////////////////////////////////////////////////////////////////////
     252             : 

Generated by: LCOV version 1.12