LCOV - code coverage report
Current view: top level - src - date.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 48 48 100.0 %
Date: 2019-01-29 11:06:41 Functions: 7 8 87.5 %

          Line data    Source code
       1             : //////////////////////////////////////////////////////////////////////
       2             : //
       3             : //  FILE:       date.h
       4             : //              Date format and inline date functions.
       5             : //
       6             : //  Part of:    Scid (Shane's Chess Information Database)
       7             : //  Version:    1.9
       8             : //
       9             : //  Notice:     Copyright (c) 1999  Shane Hudson.  All rights reserved.
      10             : //
      11             : //  Author:     Shane Hudson (sgh@users.sourceforge.net)
      12             : //
      13             : //////////////////////////////////////////////////////////////////////
      14             : 
      15             : 
      16             : #ifndef SCID_DATE_H
      17             : #define SCID_DATE_H
      18             : 
      19             : #include "common.h"
      20             : #include <algorithm>
      21             : #include <cstdlib>
      22             : 
      23             : // DATE STORAGE FORMAT:
      24             : // In memory, dates are stored in a 32-bit (4-byte) uint, of which only
      25             : // the lowest 3 bytes need be used, with the lowest 5 bits for the
      26             : // day, the next highest 4 bits for the month and the highest bits for
      27             : // the year. This makes date comparisons easy: a bigger date value is
      28             : // a more recent date.  If a field is unknown, its value is set to zero.
      29             : // On disk, the date is stored in 3 bytes.
      30             : 
      31             : 
      32             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      33             : //  CONSTANTS and MACROS:
      34             : 
      35             : const dateT ZERO_DATE = 0;
      36             : 
      37             : const uint  YEAR_SHIFT  = 9;
      38             : const uint  MONTH_SHIFT = 5;
      39             : const uint  DAY_SHIFT   = 0;
      40             : 
      41             : // DAY (31 days) 5 bits (32) , MONTH (12 months) 4 bits (16)
      42             : 
      43             : const uint YEAR_MAX = 2047;  // 2^11 - 1
      44             : 
      45             : #define DATE_MAKE(y,m,d) (((y) << YEAR_SHIFT) | ((m) << MONTH_SHIFT) | (d))
      46             : 
      47             : 
      48             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      49             : // date_GetYear():
      50             : //      Get the year from a date.
      51             : inline uint
      52     2586251 : date_GetYear (dateT date)
      53             : {
      54     2586251 :     return (uint) (date >> YEAR_SHIFT);
      55             : }
      56             : 
      57             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      58             : // date_GetMonth():
      59             : //      Get the month from a date.
      60             : inline uint
      61      510494 : date_GetMonth (dateT date)
      62             : {
      63      510494 :     return (uint) ((date >> MONTH_SHIFT) & 15);
      64             : }
      65             : 
      66             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      67             : //### date_GetDay():
      68             : //      Get the day of the month from a date.
      69             : inline uint
      70      510494 : date_GetDay (dateT date)
      71             : {
      72      510494 :     return (uint) (date & 31);
      73             : }
      74             : 
      75             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      76             : //### date_GetMonthDay():
      77             : //      Get the month and day; used to check for year-only dates. S.A
      78             : inline uint
      79             : date_GetMonthDay (dateT date)
      80             : {
      81             :     return (uint) (date & 511);
      82             : }
      83             : 
      84             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      85             : // date_DecodeToString(): convert date to PGN tag string.
      86             : inline void
      87        2109 : date_DecodeToString (dateT date, char * str)
      88             : {
      89        2109 :     ASSERT(str != NULL);
      90             :     uint year, month, day;
      91             : 
      92        2109 :     year = date_GetYear (date);
      93        2109 :     month = date_GetMonth (date);
      94        2109 :     day = date_GetDay (date);
      95             : 
      96        2109 :     if (year == 0) {
      97        2011 :         *str++ = '?'; *str++ = '?'; *str++ = '?'; *str++ = '?';
      98             :     } else {
      99          98 :         *str++ = '0' + (year / 1000);
     100          98 :         *str++ = '0' + (year % 1000) / 100;
     101          98 :         *str++ = '0' + (year % 100) / 10;
     102          98 :         *str++ = '0' + (year % 10);
     103             :     }
     104        2109 :     *str++ = '.';
     105             : 
     106        2109 :     if (month == 0) {
     107        2017 :         *str++ = '?'; *str++ = '?';
     108             :     } else {
     109          92 :         *str++ = '0' + (month / 10);
     110          92 :         *str++ = '0' + (month % 10);
     111             :     }
     112        2109 :     *str++ = '.';
     113             : 
     114        2109 :     if (day == 0) {
     115        2026 :         *str++ = '?'; *str++ = '?';
     116             :     } else {
     117          83 :         *str++ = '0' + (day / 10);
     118          83 :         *str++ = '0' + (day % 10);
     119             :     }
     120        2109 :     *str = 0;
     121        2109 : }
     122             : 
     123             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     124             : // date_EncodeFromString(): convert PGN tag string to date.
     125             : //      The date string format is: "yyyy.mm.dd".
     126             : inline dateT
     127             : date_EncodeFromString (const char * str)
     128             : {
     129             :     // Do checks on str's validity as a date string:
     130             :     ASSERT(str != NULL);
     131             : 
     132             :     dateT date;
     133             :     uint year, month, day;
     134             : 
     135             :     // convert year:
     136             :     year = std::strtoul(str, NULL, 10);
     137             :     if (year > YEAR_MAX) { year = 0; }
     138             :     date = year << YEAR_SHIFT;
     139             :     while (*str != 0  &&  *str != '.') { str++; }
     140             :     if (*str == '.') { str++; }
     141             : 
     142             :     // convert month:
     143             :     month = std::strtoul(str, NULL, 10);
     144             :     if (month > 12) { return date; }
     145             :     date |= (month << MONTH_SHIFT);
     146             :     while (*str != 0  &&  *str != '.') { str++; }
     147             :     if (*str == '.') { str++; }
     148             : 
     149             :     // convert day:
     150             :     day = std::strtoul(str, NULL, 10);
     151             :     if (day > 31) { return date; }
     152             :     date |= (day << DAY_SHIFT);
     153             : 
     154             :     return date;
     155             : }
     156             : 
     157             : /**
     158             :  * Creates a dateT object from a PGN tag value string.
     159             :  * "The Date tag value field always uses a standard ten character format:
     160             :  * "YYYY.MM.DD". If the any of the digit fields are not known, then question
     161             :  * marks are used in place of the digits."
     162             :  * @param str: pointer to the memory containing the tag value.
     163             :  * @param len: length of the tag value.
     164             :  * @returns the dateT object corresponding to @e str.
     165             :  */
     166        2116 : inline dateT date_parsePGNTag(const char* str, size_t len) {
     167        2116 :         char tmp[10] = {0};
     168       23235 :         std::transform(str, str + std::min<size_t>(len, 10), tmp, [](char ch) {
     169       21119 :                 return (ch >= '0' && ch <= '9') ? ch - '0' : 0;
     170       21119 :         });
     171             : 
     172        2116 :         uint32_t year = tmp[0] * 1000 + tmp[1] * 100 + tmp[2] * 10 + tmp[3];
     173        2116 :         uint32_t month = tmp[5] * 10 + tmp[6];
     174        2116 :         uint32_t day = tmp[8] * 10 + tmp[9];
     175             : 
     176        2116 :         if (year > YEAR_MAX)
     177           1 :                 year = 0;
     178             : 
     179        2116 :         if (month > 12)
     180           3 :                 month = 0;
     181             : 
     182        2116 :         constexpr unsigned char days[] = {31, 31, 28, 31, 30, 31, 30,
     183             :                                           31, 31, 30, 31, 30, 31};
     184        2116 :         if (day > days[month]) {
     185          12 :                 if (day != 29 || year % 4 || (year % 100 == 0 && year % 400)) {
     186           9 :                         day = 0;
     187             :                 }
     188             :         }
     189             : 
     190        2116 :         return (year << YEAR_SHIFT) | (month << MONTH_SHIFT) | (day << DAY_SHIFT);
     191             : }
     192             : 
     193        2075 : inline dateT date_parsePGNTag(std::pair<const char*, const char*> str) {
     194        2075 :         return date_parsePGNTag(str.first, std::distance(str.first, str.second));
     195             : }
     196             : 
     197             : #endif   // #ifndef SCID_DATE_H
     198             : 
     199             : //////////////////////////////////////////////////////////////////////
     200             : //  EOF: date.h
     201             : //////////////////////////////////////////////////////////////////////
     202             : 

Generated by: LCOV version 1.13