LCOV - code coverage report
Current view: top level - src - codec_scid4.h (source / functions) Hit Total Coverage
Test: test_coverage.info Lines: 49 52 94.2 %
Date: 2017-06-21 14:32:49 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2016-2017  Fulvio Benini
       3             : 
       4             :  * This file is part of Scid (Shane's Chess Information Database).
       5             :  *
       6             :  * Scid is free software: you can redistribute it and/or modify
       7             :  * it under the terms of the GNU General Public License as published by
       8             :  * the Free Software Foundation.
       9             :  *
      10             :  * Scid is distributed in the hope that it will be useful,
      11             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             :  * GNU General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU General Public License
      16             :  * along with Scid.  If not, see <http://www.gnu.org/licenses/>.
      17             :  *
      18             :  */
      19             : 
      20             : /** @file
      21             :  * Implements the CodecScid4 class, which manages the databases encoded
      22             :  * in Scid format version 4.
      23             :  */
      24             : 
      25             : #ifndef CODEC_SCID4_H
      26             : #define CODEC_SCID4_H
      27             : 
      28             : #include "codec_memory.h"
      29             : #include "common.h"
      30             : #include "filebuf.h"
      31             : 
      32             : #if !CPP11_SUPPORT
      33             : #define override
      34             : #endif
      35             : 
      36             : /**
      37             :  * This class manages databases encoded in Scid format v4.
      38             :  */
      39         126 : class CodecScid4 : public CodecMemory {
      40             :         std::string filename_;
      41             :         FilebufAppend gfile_;
      42             :         char gamecache_[128*1024];
      43             : 
      44             : public:
      45           3 :         Codec getType() override { return ICodecDatabase::SCID4; }
      46             : 
      47             :         /**
      48             :          * Returns the full path of the three files (index, namebase and gamefile)
      49             :          * used by the database.
      50             :          */
      51          10 :         std::vector<std::string> getFilenames() override {
      52          10 :                 std::vector<std::string> res;
      53          30 :                 res.push_back(filename_ + INDEX_SUFFIX);
      54          30 :                 res.push_back(filename_ + NameBase::Suffix());
      55          30 :                 res.push_back(filename_ + ".sg4");
      56          10 :                 return res;
      57             :         };
      58             : 
      59        8000 :         const byte* getGameData(uint32_t offset, uint32_t length) override {
      60       16000 :                 if (offset >= gfile_.size())
      61             :                         return NULL;
      62        8000 :                 if (length > sizeof(gamecache_))
      63             :                         return NULL;
      64             : 
      65        8000 :                 if (gfile_.pubseekpos(offset) == -1)
      66             :                         return NULL;
      67       16000 :                 if (gfile_.sgetn(gamecache_, length) != std::streamsize(length))
      68             :                         return NULL;
      69             : 
      70        8000 :                 return reinterpret_cast<const byte*>(gamecache_);
      71             :         }
      72             : 
      73           9 :         errorT flush() override {
      74           9 :                 errorT err = CodecMemory::flush();
      75             :                 if (err != OK) return err;
      76             : 
      77           9 :                 err = idx_->flush();
      78           9 :                 if (err == OK) {
      79             :                         // *** Compatibility ***
      80             :                         // Even if name's frequency is no longer used, it's necessary to
      81             :                         // keep the compatibility with older Scid versions, forcing a
      82             :                         // recalculation.
      83           9 :                         nb_->hackedNameFreq();
      84           9 :                         err = nb_->flush(idx_);
      85             :                 }
      86          18 :                 errorT errGfile = (gfile_.pubsync() == 0) ? OK : ERROR_FileWrite;
      87             : 
      88           9 :                 return (err == OK) ? errGfile : err;
      89             :         }
      90             : 
      91             : protected:
      92          18 :         errorT dyn_open(fileModeT fMode, const char* filename,
      93             :                         const Progress& progress, Index* idx,
      94             :                         NameBase* nb) override {
      95          18 :                 if (filename == 0 || idx == 0 || nb == 0) return ERROR;
      96             : 
      97          36 :                 errorT err = CodecMemory::dyn_open(FMODE_Memory, 0, progress, idx, nb);
      98          18 :                 if (err != OK) return err;
      99             : 
     100          36 :                 filename_ = filename;
     101          36 :                 if (filename_.empty()) return ERROR_FileOpen;
     102             : 
     103          34 :                 err = gfile_.open(filename_ + ".sg4", fMode);
     104          17 :                 if (err != OK) return err;
     105             : 
     106          16 :                 if (fMode == FMODE_Create) {
     107           7 :                         err = idx->Create(filename);
     108           7 :                         if (err == OK) err = nb->Create(filename);
     109             :                 } else {
     110           9 :                         err = idx->Open(filename, fMode);
     111           9 :                         if (err == OK) err = nb->ReadEntireFile(filename);
     112           9 :                         if (err == OK) err = idx->ReadEntireFile(nb, progress);
     113             :                 }
     114             : 
     115             :                 return err;
     116             :         }
     117             : 
     118        6000 :         std::pair<errorT, uint32_t> dyn_addGameData(const byte* src,
     119             :                                                     size_t length) override {
     120        6000 :                 ASSERT(src != 0);
     121        6000 :                 const char* data = reinterpret_cast<const char*>(src);
     122             : 
     123             :                 // The Scid4 format uses 32-bits to store games' offset.
     124       12000 :                 size_t offset = gfile_.size();
     125             :                 static const uint32_t MAXSZ = std::numeric_limits<uint32_t>::max();
     126        6000 :                 if (offset >= MAXSZ || length >= MAXSZ - offset)
     127           0 :                         return std::make_pair(ERROR_Full, 0);
     128             : 
     129             :                 // The Scid4 format stores games into blocks of 128KB.
     130             :                 // If the current block does not have enough space, we fill it with
     131             :                 // random data and use the next one.
     132             :                 static const size_t GF_BLOCK = 128 * 1024;
     133        6000 :                 if (length > GF_BLOCK)
     134           0 :                         return std::make_pair(ERROR_Full, 0);
     135        6000 :                 size_t blockSpace = GF_BLOCK - (offset % GF_BLOCK);
     136        6000 :                 if (blockSpace < length) {
     137        1280 :                         errorT err = gfile_.append(data, blockSpace);
     138        1280 :                         if (err != OK)
     139           0 :                                 return std::make_pair(err, 0);
     140        1280 :                         offset += blockSpace;
     141             :                 }
     142             : 
     143        6000 :                 errorT err = gfile_.append(data, length);
     144        6000 :                 return std::make_pair(err, uint32_t(offset));
     145             :         }
     146             : };
     147             : 
     148             : #if !CPP11_SUPPORT
     149             : #undef override
     150             : #endif
     151             : 
     152             : #endif

Generated by: LCOV version 1.12