LCOV - code coverage report
Current view: top level - src - index.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 27 49 55.1 %
Date: 2019-01-29 11:06:41 Functions: 8 16 50.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             : #ifndef SCID_INDEX_H
      22             : #define SCID_INDEX_H
      23             : 
      24             : #include "common.h"
      25             : #include "containers.h"
      26             : #include "date.h"
      27             : #include "indexentry.h"
      28             : #include "filebuf.h"
      29             : #include "hfilter.h"
      30             : #include <array>
      31             : #include <string>
      32             : #include <vector>
      33             : #include <cstring>
      34             : 
      35             : class NameBase;
      36             : 
      37             : //////////////////////////////////////////////////////////////////////
      38             : //  Index:  Constants
      39             : 
      40             : const char         INDEX_SUFFIX[]     = ".si4";
      41             : const char         OLD_INDEX_SUFFIX[] = ".si3";
      42             : 
      43             : // Descriptions can be up to 107 bytes long.
      44             : const uint  SCID_DESC_LENGTH = 107;
      45             : const uint  CUSTOM_FLAG_DESC_LENGTH = 8;
      46             : const uint  CUSTOM_FLAG_MAX = 6;
      47             : 
      48             : // Header on-disk size: magic=8, version=2, numGames=3, baseType=4, autoLoad=3
      49             : // Description length = 111 bytes including trailing '\0'.
      50             : // Custom flag desc length = 9 bytes including trailing '\0'.
      51             : // So total is 128 bytes + 9*6 = 182 bytes for the whole header.
      52             : const uint  INDEX_HEADER_SIZE = 8 + 2 + 3 + 4 + 3 + SCID_DESC_LENGTH + 1 + (CUSTOM_FLAG_DESC_LENGTH+1) * CUSTOM_FLAG_MAX;
      53             : const uint  OLD_INDEX_HEADER_SIZE = INDEX_HEADER_SIZE - (CUSTOM_FLAG_DESC_LENGTH+1) * CUSTOM_FLAG_MAX;
      54             : 
      55             : //////////////////////////////////////////////////////////////////////
      56             : //  Index:  Class Definition
      57             : 
      58             : class Index
      59             : {
      60             : private:
      61             :     // The complete index will be loaded in memory and can be pretty huge.
      62             :     // To avoid the slow reallocation when adding games we split the data in chunks.
      63             :     // CHUNKSHIFT is the base-2 logarithm of the number of index entries allocated as one chunk.
      64             :     // i.e 16 = 2^16 = 65536 (total size of one chunk: 65536*48 = 3MB)
      65             :     VectorChunked<IndexEntry, 16> entries_; // A two-level array of the entire index.
      66             :     Filebuf*     FilePtr;       // filehandle for opened index file.
      67             :     fileModeT    fileMode_;     // Mode: e.g. FILE_WRITEONLY
      68             :     int nInvalidNameId_;
      69             :     gamenumT seqWrite_;
      70             : 
      71             :     struct { // one at the start of the index file.
      72             :         versionT    version;     // version number. 2 bytes.
      73             :         uint        baseType;    // Type, e.g. tournament, theory, etc.
      74             :         gamenumT    numGames;    // number of games in file.
      75             :         gamenumT    autoLoad;    // game number to autoload: 0=none, 1=1st, >numGames=last
      76             :         // description is a fixed-length string describing the database.
      77             :         char        description [SCID_DESC_LENGTH + 1];
      78             :         // short description (8 chars) for the CUSTOM_FLAG_MAX bits for CUSTOM flags
      79             :         char        customFlagDesc [CUSTOM_FLAG_MAX][CUSTOM_FLAG_DESC_LENGTH+1] ;
      80             :         bool        dirty_;      // If true, Header needs rewriting to disk.
      81             :     } Header;
      82             : 
      83             :     friend class CodecSCID4;
      84             : 
      85             : public:
      86          50 :     Index()  { Init(); }
      87             :     Index(const Index&);
      88             :     Index& operator=(const Index&);
      89          50 :     ~Index() { Clear(); }
      90             : 
      91             :     errorT Open(const char* filename, fileModeT fmode);
      92             :     errorT Create(const char* filename);
      93          14 :     errorT Close() { return Clear(); }
      94             : 
      95     1126406 :     const IndexEntry* GetEntry (gamenumT g) const {
      96     1126406 :         ASSERT(g < GetNumGames());
      97     1105286 :         return &(entries_[g]);
      98             :     }
      99             : 
     100             :     /**
     101             :      * GetBadNameIdCount() - return the number of invalid name handles.
     102             :      *
     103             :      * To save space, avoiding duplicates, the index keep handles
     104             :      * to strings stored in the namebase file.
     105             :      * If one of the two files is corrupted, the index may have
     106             :      * handles to strings that do not exists.
     107             :      * This functions returns the number of invalid name handles.
     108             :      */
     109           0 :     int GetBadNameIdCount() const { return nInvalidNameId_; }
     110             : 
     111             :     /**
     112             :      * Counts how many times every names contained in @e nb is used.
     113             :      * @param nb: the NameBase linked to this Index
     114             :      * @returns an array of std::vectors containing the count of each name.
     115             :      */
     116             :     std::array<std::vector<int>, NUM_NAME_TYPES>
     117          12 :     calcNameFreq(const NameBase& nb) const {
     118          12 :         std::array<std::vector<int>, NUM_NAME_TYPES> resVec;
     119          60 :         for (nameT n = NAME_PLAYER; n < NUM_NAME_TYPES; n++) {
     120          48 :             resVec[n].resize(nb.GetNumNames(n), 0);
     121             :         }
     122        4012 :         for (gamenumT i = 0, n = GetNumGames(); i < n; i++) {
     123        4000 :             const IndexEntry* ie = GetEntry(i);
     124        4000 :             resVec[NAME_PLAYER][ie->GetWhite()] += 1;
     125        4000 :             resVec[NAME_PLAYER][ie->GetBlack()] += 1;
     126        4000 :             resVec[NAME_EVENT][ie->GetEvent()] += 1;
     127        4000 :             resVec[NAME_SITE][ie->GetSite()] += 1;
     128        4000 :             resVec[NAME_ROUND][ie->GetRound()] += 1;
     129             :         }
     130          12 :         return resVec;
     131             :     }
     132             : 
     133             :     /**
     134             :      * Header getter functions
     135             :      */
     136     1149330 :     gamenumT    GetNumGames ()    const { return Header.numGames; }
     137           0 :     uint        GetType ()        const { return Header.baseType; }
     138           0 :     versionT    GetVersion ()     const { return Header.version; }
     139           0 :     const char* GetDescription () const { return Header.description; }
     140           0 :     const char* GetCustomFlagDesc (byte c) const {
     141           0 :         if (c < IndexEntry::IDX_FLAG_CUSTOM1 || c > IndexEntry::IDX_FLAG_CUSTOM6) return 0;
     142           0 :         return Header.customFlagDesc[c - IndexEntry::IDX_FLAG_CUSTOM1];
     143             :     }
     144           0 :     gamenumT GetAutoLoad () const {
     145           0 :         return (Header.autoLoad <= Header.numGames) ? Header.autoLoad : Header.numGames;
     146             :     }
     147             : 
     148             :     /**
     149             :      * Header setter functions
     150             :      */
     151           0 :     errorT copyHeaderInfo(const Index& src) {
     152           0 :         if (fileMode_ == FMODE_ReadOnly) return ERROR_FileMode;
     153           0 :         Header.baseType = src.Header.baseType;
     154           0 :         Header.autoLoad = src.Header.autoLoad;
     155           0 :         std::memcpy(Header.description, src.Header.description, sizeof Header.description);
     156           0 :         std::memcpy(Header.customFlagDesc, src.Header.customFlagDesc, sizeof Header.customFlagDesc);
     157           0 :         Header.dirty_ = true;
     158           0 :         return flush();
     159             :     }
     160             :     errorT SetType (uint t) {
     161             :         if (fileMode_ == FMODE_ReadOnly) return ERROR_FileMode;
     162             :         Header.baseType = t;
     163             :         Header.dirty_ = true;
     164             :         return flush();
     165             :     }
     166             :     errorT SetDescription (const char* str) {
     167             :         if (fileMode_ == FMODE_ReadOnly) return ERROR_FileMode;
     168             :         strncpy(Header.description, str, SCID_DESC_LENGTH);
     169             :         Header.description[SCID_DESC_LENGTH] = 0;
     170             :         Header.dirty_ = true;
     171             :         return flush();
     172             :     }
     173             :     errorT SetCustomFlagDesc (byte c, const char* str) {
     174             :         if (fileMode_ == FMODE_ReadOnly) return ERROR_FileMode;
     175             :         if (c < IndexEntry::IDX_FLAG_CUSTOM1 || c > IndexEntry::IDX_FLAG_CUSTOM6) return ERROR_BadArg;
     176             :         char* flagDesc = Header.customFlagDesc[c - IndexEntry::IDX_FLAG_CUSTOM1];
     177             :         strncpy(flagDesc, str, CUSTOM_FLAG_DESC_LENGTH);
     178             :         flagDesc[CUSTOM_FLAG_DESC_LENGTH] = 0;
     179             :         Header.dirty_ = true;
     180             :         return flush();
     181             :     }
     182           0 :     errorT SetAutoLoad (gamenumT gnum) {
     183           0 :         if (fileMode_ == FMODE_ReadOnly) return ERROR_FileMode;
     184           0 :         Header.autoLoad = gnum;
     185           0 :         Header.dirty_ = true;
     186           0 :         return flush();
     187             :     }
     188             : 
     189             :     /**
     190             :      * FetchEntry() - return a modifiable pointer to a game's IndexEntry
     191             :      *
     192             :      * The pointer returned by this function allow to modify the IndexEntry
     193             :      * informations of a game. If modified, the IndexEntry object must be
     194             :      * passed to WriteEntry() to write the changes to the disks.
     195             :      * This functions is very error prone. For example:
     196             :      * IndexEntry* ie = FetchEntry(0);
     197             :      * ie->SetWhiteName(nb, "New player with white");
     198             :      * oops(); // the function oops() may call GetEntry(0) and get a messy object.
     199             :      * ie->SetBlackName(nb, "New player with black");
     200             :      *
     201             :      * A safer alternative is to create a temporary copy of the IndexEntry object
     202             :      * returned by GetEntry() and then write all the changes in a single step
     203             :      */
     204        4339 :     IndexEntry* FetchEntry (gamenumT g) {
     205        4339 :         ASSERT(g < GetNumGames());
     206        4339 :         return &(entries_[g]);
     207             :     }
     208             : 
     209             :     /**
     210             :      * WriteEntry() - modify a game in the Index
     211             :      */
     212             :     errorT WriteEntry(const IndexEntry* ie, gamenumT idx);
     213             : 
     214             :     /**
     215             :      * flush() - writes all cached data to the file
     216             :      */
     217          84 :     errorT flush() {
     218          84 :         if (FilePtr == 0) return OK;
     219          19 :         errorT errHeader = (Header.dirty_) ? WriteHeader() : OK;
     220          19 :         errorT errSync = (FilePtr->pubsync() != 0) ? ERROR_FileWrite : OK;
     221          19 :         return (errHeader == OK) ? errSync : errHeader;
     222             :     }
     223             : 
     224             : private:
     225             :     void Init ();
     226             :     errorT Clear ();
     227             :     errorT WriteHeader ();
     228             : };
     229             : 
     230             : 
     231             : #endif  // #ifdef SCID_INDEX_H
     232             : 
     233             : //////////////////////////////////////////////////////////////////////
     234             : //  EOF: index.h
     235             : //////////////////////////////////////////////////////////////////////
     236             : 

Generated by: LCOV version 1.13