LTP GCOV extension - code coverage report
Current view: directory - src/base - pdf-time.c
Test: libgnupdf.info
Date: 2010-07-31 Instrumented lines: 345
Code covered: 89.3 % Executed lines: 308

       1                 : /* -*- mode: C -*-
       2                 :  *
       3                 :  *       File:         pdf-time.c
       4                 :  *       Date:         Mon Apr 28 23:23:04 2008
       5                 :  *
       6                 :  *       GNU PDF Library - Time Module source
       7                 :  *
       8                 :  */
       9                 : 
      10                 : /* Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. */
      11                 : 
      12                 : /* This program is free software: you can redistribute it and/or modify
      13                 :  * it under the terms of the GNU General Public License as published by
      14                 :  * the Free Software Foundation, either version 3 of the License, or
      15                 :  * (at your option) any later version.
      16                 :  *
      17                 :  * This program is distributed in the hope that it will be useful,
      18                 :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      19                 :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      20                 :  * GNU General Public License for more details.
      21                 :  *
      22                 :  * You should have received a copy of the GNU General Public License
      23                 :  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
      24                 :  */
      25                 : 
      26                 : #include <config.h>
      27                 : 
      28                 : #include <time.h>
      29                 : 
      30                 : #include <pdf-alloc.h>
      31                 : #include <pdf-types.h>
      32                 : #include <pdf-time-context.h>
      33                 : #include <pdf-time-string.h>
      34                 : #include <pdf-time.h>
      35                 : 
      36                 : 
      37                 : #define PDF_SECS_PER_DAY      86400
      38                 : #define PDF_SECS_PER_HOUR      3600
      39                 : #define PDF_SECS_PER_MIN         60
      40                 : #define PDF_MINS_PER_HOUR        60
      41                 : #define PDF_HOURS_PER_DAY        24
      42                 : #define PDF_MINS_PER_DAY       1440
      43                 : #define PDF_DAYS_IN_YEAR        365
      44                 : #define PDF_DAYS_IN_LEAP_YEAR   366
      45                 : #define PDF_MINIMUM_YEAR       1970
      46                 : 
      47                 : enum pdf_time_cal_type_e {
      48                 :   PDF_TIME_CAL_LOCAL,
      49                 :   PDF_TIME_CAL_UTC
      50                 : };
      51                 : 
      52                 : enum pdf_time_month_e {
      53                 :   PDF_TIME_JANUARY    = 1,
      54                 :   PDF_TIME_FEBRUARY   = 2,
      55                 :   PDF_TIME_MARCH      = 3,
      56                 :   PDF_TIME_APRIL      = 4,
      57                 :   PDF_TIME_MAY        = 5,
      58                 :   PDF_TIME_JUNE       = 6,
      59                 :   PDF_TIME_JULY       = 7,
      60                 :   PDF_TIME_AUGUST     = 8,
      61                 :   PDF_TIME_SEPTEMBER  = 9,
      62                 :   PDF_TIME_OCTOBER    = 10,
      63                 :   PDF_TIME_NOVEMBER   = 11,
      64                 :   PDF_TIME_DECEMBER   = 12,
      65                 :   PDF_TIME_NMONTHS
      66                 : };
      67                 : 
      68                 : /* Returns PDF_TRUE if the Olimpic Games [were/will be] celebrated in the given
      69                 :  *  year */
      70                 : static pdf_bool_t
      71                 : pdf_time_is_leap_year_p(pdf_u32_t year)
      72          778510 : {
      73                 :   /* A leap year is divisable by 4, but not by 100, except if divisable by
      74                 :    *  400 */
      75          778510 :   return (((year % 4 == 0) && \
      76                 :            ((year % 100 != 0) || \
      77                 :             (year % 400 == 0))) ? \
      78                 :           PDF_TRUE : PDF_FALSE);
      79                 : }
      80                 : 
      81                 : 
      82                 : /* Returns number of days in the given month */
      83                 : static pdf_u32_t
      84                 : pdf_time_get_days_in_month(const pdf_u32_t year,
      85                 :                            const enum pdf_time_month_e month)
      86         1516080 : {
      87         1516080 :   switch(month)
      88                 :   {
      89                 :     case PDF_TIME_JANUARY:
      90                 :     case PDF_TIME_MARCH:
      91                 :     case PDF_TIME_MAY:
      92                 :     case PDF_TIME_JULY:
      93                 :     case PDF_TIME_AUGUST:
      94                 :     case PDF_TIME_OCTOBER:
      95                 :     case PDF_TIME_DECEMBER:
      96          890967 :       return 31;
      97                 :     case PDF_TIME_APRIL:
      98                 :     case PDF_TIME_JUNE:
      99                 :     case PDF_TIME_SEPTEMBER:
     100                 :     case PDF_TIME_NOVEMBER:
     101          396848 :       return 30;
     102                 :     case PDF_TIME_FEBRUARY:
     103          228265 :       return (pdf_time_is_leap_year_p(year) ? 29 : 28);
     104                 :     default:
     105               0 :       return 0;
     106                 :   }
     107                 : }
     108                 : 
     109                 : 
     110                 : /* Returns number of days before the given month */
     111                 : static pdf_u32_t
     112                 : pdf_time_get_days_before_month(const pdf_u32_t year,
     113                 :                                const enum pdf_time_month_e month)
     114                 : {
     115          274747 :   enum pdf_time_month_e walk = PDF_TIME_JANUARY;
     116          274747 :   pdf_u32_t sum = 0;
     117         1689784 :   while(walk != month) {
     118         1415037 :     sum += pdf_time_get_days_in_month(year, walk++);
     119                 :   }
     120          274747 :   return sum;
     121                 : }
     122                 : 
     123                 : static pdf_bool_t
     124                 : pdf_time_is_valid_cal_p(const struct pdf_time_cal_s *p_cal_time)
     125           62611 : {
     126                 : /*
     127                 :   PDF_DEBUG_BASE("Calendar: %d/%d/%d %d:%d:%d off:%d",
     128                 :                  p_cal_time->year,
     129                 :                  p_cal_time->month,
     130                 :                  p_cal_time->day,
     131                 :                  p_cal_time->hour,
     132                 :                  p_cal_time->minute,
     133                 :                  p_cal_time->second,
     134                 :                  p_cal_time->gmt_offset);
     135                 : */  
     136           62611 :   return ( ( (p_cal_time == NULL) || \
     137                 :              (p_cal_time->year < PDF_MINIMUM_YEAR) || \
     138                 :              (p_cal_time->month < PDF_TIME_JANUARY) || \
     139                 :              (p_cal_time->month > PDF_TIME_DECEMBER) || \
     140                 :              (p_cal_time->day == 0) || \
     141                 :              (p_cal_time->day > pdf_time_get_days_in_month(p_cal_time->year,
     142                 :                                                            p_cal_time->month)) || \
     143                 :              (p_cal_time->hour >= PDF_HOURS_PER_DAY) || \
     144                 :              (p_cal_time->minute >= PDF_MINS_PER_HOUR) || \
     145                 :              (p_cal_time->second >= PDF_SECS_PER_MIN) ) ? PDF_FALSE : PDF_TRUE);
     146                 :   
     147                 : }
     148                 : 
     149                 : 
     150                 : /* Get Break-Down calendar from pdf_time_t */
     151                 : static pdf_status_t
     152                 : pdf_time_get_cal (const pdf_time_t time_var,
     153                 :                   const enum pdf_time_cal_type_e cal_type,
     154                 :                   struct pdf_time_cal_s *p_cal_time)
     155           26774 : {
     156                 :   /* Based on glibc's __offtime function */
     157                 : 
     158                 :   pdf_i32_t days;
     159                 :   pdf_i64_t aux64;
     160                 :   pdf_i32_t remaining;
     161                 :   pdf_i32_t years;
     162                 :   pdf_i32_t months;
     163                 :   pdf_time_t new_time_var;
     164           26774 :   pdf_status_t p_status = PDF_OK;
     165                 :   
     166                 :   /* Duplicate time var */
     167           26774 :   new_time_var = pdf_time_dup(time_var);
     168                 : 
     169                 :   /* pdf_time_t always stores the date & time in UTC timescale, so we only need
     170                 :    *  to modify the time_var IF gmt_offset is not zero, in order to move the
     171                 :    *  date & time from UTC to local time specified by the offset */
     172           26774 :   if( (cal_type == PDF_TIME_CAL_LOCAL) && \
     173                 :       (time_var->gmt_offset != 0) )
     174                 :     {
     175                 :       pdf_time_span_t delta;
     176                 :       /* Modify time in the time object */
     177           12543 :       delta = pdf_time_span_new();
     178           12543 :       pdf_time_span_set_from_i32(&delta, time_var->gmt_offset);
     179           12543 :       pdf_time_add_span(new_time_var, delta);
     180           12543 :       pdf_time_span_destroy(&delta);
     181                 :     }
     182                 :   
     183           26774 :   aux64 = pdf_i64_new(0,0);
     184                 : 
     185                 : 
     186                 :   /* Get date as days */
     187           26774 :   pdf_i64_div_i32_divisor(&aux64, new_time_var->seconds, PDF_SECS_PER_DAY, &p_status);
     188           26774 :   days = pdf_i64_to_i32(aux64);
     189                 :   /* Get time in seconds */
     190           26774 :   pdf_i64_mod_i32_divisor(&aux64, new_time_var->seconds, PDF_SECS_PER_DAY, &p_status);
     191           26774 :   remaining = pdf_i64_to_i32(aux64);
     192                 :   /* Get hours */
     193           26774 :   p_cal_time->hour = remaining / PDF_SECS_PER_HOUR;
     194                 :   /* Get remaining */
     195           26774 :   remaining = remaining % PDF_SECS_PER_HOUR;
     196                 :   /* Get minutes */
     197           26774 :   p_cal_time->minute = remaining / PDF_MINS_PER_HOUR;
     198                 :   /* Get seconds */
     199           26774 :   p_cal_time->second = remaining % PDF_MINS_PER_HOUR;
     200                 :   
     201                 :   /* Seems that Unix origin time was thursday */
     202           26774 :   p_cal_time->dow = ((days+4)%7);
     203                 :     
     204           26774 :   years = 1970;
     205                 : 
     206                 : 
     207           68913 :   while((days < 0) || \
     208                 :         (days >= (pdf_time_is_leap_year_p(years) ? \
     209                 :                   (PDF_DAYS_IN_YEAR+1) :  \
     210                 :                   (PDF_DAYS_IN_YEAR))))
     211                 :     {
     212                 :       pdf_i32_t yg;
     213           15365 :       yg = years;
     214                 : 
     215                 :       /* Compute number of years (assuming all years of 365 days) between the
     216                 :        *  origin and our date */
     217           15365 :       yg += (days / PDF_DAYS_IN_YEAR);
     218                 :       /* Get number of remaining days after having added the fixed-size years
     219                 :          If the number of remaining days is less than zero, go down 1 year */
     220           15365 :       yg -= ((days % PDF_DAYS_IN_YEAR) < 0);
     221                 : 
     222                 : 
     223                 : #define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
     224                 :       /* Remove number of days due to the leap years */
     225           15365 :       days -= (((yg - years)*PDF_DAYS_IN_YEAR) +        \
     226                 :                (LEAPS_THRU_END_OF (yg - 1)) - \
     227                 :                (LEAPS_THRU_END_OF (years - 1)));
     228           15365 :       years = yg;
     229                 :     }
     230                 : 
     231                 :   /* Set year */
     232           26774 :   p_cal_time->year = years;// - 1900;
     233                 :   
     234          212136 :   for (months = 11; \
     235          451046 :        days < pdf_time_get_days_before_month(p_cal_time->year,months); \
     236                 :        --months)
     237                 :     continue;
     238                 : 
     239           53548 :   days -= pdf_time_get_days_before_month(p_cal_time->year,months);
     240                 : 
     241                 :   /* Set month and day of month */
     242           26774 :   p_cal_time->month = months;
     243           26774 :   if (pdf_time_get_days_in_month(p_cal_time->year, p_cal_time->month) < days + 1){
     244            4711 :     p_cal_time->day = days + 1 - pdf_time_get_days_in_month(p_cal_time->year, p_cal_time->month);
     245            4711 :     p_cal_time->month+=1;
     246            4711 :     if (p_cal_time->month == 13) {
     247               0 :         p_cal_time->month = 1;
     248               0 :         p_cal_time->year+=1;
     249                 :     }
     250                 :   }
     251                 :   else 
     252           22063 :   p_cal_time->day = days + 1;
     253                 :   
     254                 :   /* Finally, set gmt offset */
     255           26774 :   p_cal_time->gmt_offset = new_time_var->gmt_offset;
     256                 :   
     257           26774 :   pdf_time_destroy(new_time_var);
     258                 :   
     259           26774 :   return (pdf_time_is_valid_cal_p(p_cal_time) ? PDF_OK : PDF_ERROR);
     260                 : }
     261                 : 
     262                 : 
     263                 : 
     264                 : /* Function to normalize a given date after having added YEARS */
     265                 : static void
     266                 : pdf_time_calendar_add_years(struct pdf_time_cal_s *p_calendar,
     267                 :                             const pdf_i32_t delta_years)
     268                 : {
     269                 :   /* ADD years */
     270            5102 :   p_calendar->year += delta_years;
     271                 : 
     272                 :   /* The only thing to normalize is in case we reach Feb.29 in a non-leap
     273                 :    *  year */
     274            5102 :   if( (!pdf_time_is_leap_year_p(p_calendar->year)) && \
     275                 :        (p_calendar->month == PDF_TIME_FEBRUARY) && \
     276                 :        (p_calendar->day == 29) )
     277                 :     {
     278               0 :       p_calendar->day = 28;
     279                 :     }
     280                 : }
     281                 : 
     282                 : /* Function to normalize a given date after having added MONTHS */
     283                 : static void
     284                 : pdf_time_calendar_add_months(struct pdf_time_cal_s *p_calendar,
     285                 :                              const pdf_i32_t delta_months)
     286            5102 : {
     287            5102 :   if(delta_months > 0)
     288                 :     {
     289            3440 :       p_calendar->month += delta_months;
     290            6880 :       while(p_calendar->month > 12)
     291                 :         {
     292               0 :           p_calendar->month -= 12;
     293               0 :           p_calendar->year++;
     294                 :         }
     295                 :     }
     296            1662 :   else if(delta_months < 0)
     297                 :     {
     298              24 :       p_calendar->month += delta_months;
     299              48 :       while(p_calendar->month < 1)
     300                 :         {
     301               0 :           p_calendar->month += 12;
     302               0 :           p_calendar->year--;
     303                 :         }
     304                 :     }
     305                 :   
     306                 :   /* After having added months, we could need to normalize the days */
     307            5102 :   if(pdf_time_get_days_in_month(p_calendar->year,
     308                 :                                 p_calendar->month) < p_calendar->day)
     309                 :     {
     310              25 :       p_calendar->day = pdf_time_get_days_in_month(p_calendar->year,
     311                 :                                                    p_calendar->month);
     312                 :     }
     313            5102 : }
     314                 : 
     315                 : /* Function to normalize a given date after having added DAYS */
     316                 : static void
     317                 : pdf_time_calendar_add_days(struct pdf_time_cal_s *p_calendar,
     318                 :                            const pdf_i32_t delta_days)
     319           20408 : {
     320           20408 :   pdf_i32_t delta = delta_days;
     321                 : 
     322                 :   /* ADD days */
     323           20408 :   if(delta_days > 0)
     324                 :     {
     325                 :       pdf_i32_t days_in_month;
     326                 :   
     327                 :       /* Initialize days in month */
     328            1820 :       days_in_month = pdf_time_get_days_in_month(p_calendar->year, \
     329                 :                                                  (enum pdf_time_month_e)p_calendar->month);
     330            3640 :       while(delta > (days_in_month - p_calendar->day))
     331                 :         {
     332                 :           /* Go to start of next month */
     333               0 :           p_calendar->day = 1;
     334               0 :           pdf_time_calendar_add_months(p_calendar, 1);
     335                 : 
     336                 :           /* Update remaining delta and new days_in_month */
     337               0 :           delta -= (days_in_month - p_calendar->day +1);
     338               0 :           days_in_month = pdf_time_get_days_in_month(p_calendar->year, \
     339                 :                                                      (enum pdf_time_month_e)p_calendar->month);
     340                 :         }
     341                 :       /* Add final delta, which doesn't require month change */
     342            1820 :       p_calendar->day += delta;
     343                 :     }
     344                 :   
     345                 :   /* SUBSTRACT days */
     346           18588 :   else if(delta_days < 0)
     347                 :     {
     348                 :       pdf_i32_t days_in_month;
     349                 :       
     350                 :       /* Initialize days in month */
     351               0 :       days_in_month = p_calendar->day - 1;
     352                 : 
     353               0 :       while(days_in_month <= (-delta))
     354                 :         {
     355                 :           /* Go to the begin of previous month */
     356               0 :           p_calendar->day = 1;
     357               0 :           pdf_time_calendar_add_months(p_calendar, -1);
     358                 :           
     359                 :           /* Update remaining delta and new days_in_month */
     360               0 :           delta += days_in_month;
     361               0 :           days_in_month = pdf_time_get_days_in_month(p_calendar->year, \
     362                 :                                                      (enum pdf_time_month_e)p_calendar->month);
     363                 :         }
     364                 :       /* Add final delta, which doesn't require month change */
     365               0 :       delta += days_in_month;
     366               0 :       p_calendar->day += delta;
     367                 :     }
     368           20408 : }
     369                 : 
     370                 : /* Function to normalize a given date after having added HOURS */
     371                 : static void
     372                 : pdf_time_calendar_add_hours(struct pdf_time_cal_s *p_calendar,
     373                 :                             const pdf_i32_t delta_hours)
     374           15306 : {
     375                 :   pdf_i32_t days;
     376                 :   pdf_i32_t remaining_hours;
     377                 : 
     378                 :   /* No real problem with hours, as 1 day is always 24h */
     379           15306 :   days = delta_hours / PDF_HOURS_PER_DAY;
     380           15306 :   remaining_hours = delta_hours % PDF_HOURS_PER_DAY;
     381                 : 
     382                 :   /* Add remaining hours */
     383           15306 :   p_calendar->hour += remaining_hours;
     384                 :   /* If we went back to the previous day, correct time and add 1 day more
     385                 :    * to remove */
     386                 :   if(p_calendar->hour < 0)
     387                 :     {
     388                 :       p_calendar->hour += PDF_HOURS_PER_DAY;
     389                 :       days--;
     390                 :     }
     391                 :   /* If we went forward to the next day, correct time and add 1 day more
     392                 :    * to add */
     393           15306 :   else if(p_calendar->hour >= PDF_HOURS_PER_DAY)
     394                 :     {
     395               0 :       p_calendar->hour -= PDF_HOURS_PER_DAY;
     396               0 :       days++;
     397                 :     }
     398                 : 
     399                 :   /* Add/Remove days... */
     400           15306 :   pdf_time_calendar_add_days(p_calendar, days);
     401           15306 : }
     402                 : 
     403                 : /* Function to normalize a given date after having added MINUTES */
     404                 : static void
     405                 : pdf_time_calendar_add_minutes(struct pdf_time_cal_s *p_calendar,
     406                 :                               const pdf_i32_t delta_minutes)
     407           10204 : {
     408                 :   pdf_i32_t hours;
     409                 :   pdf_i32_t remaining_minutes;
     410                 :   
     411                 :   /* No real problem with minutes, as 1 hour is always 60minutes */
     412           10204 :   hours = delta_minutes / PDF_MINS_PER_HOUR;
     413           10204 :   remaining_minutes = delta_minutes % PDF_MINS_PER_HOUR;
     414                 : 
     415                 :   /* Add remaining minutes */
     416           10204 :   p_calendar->minute += remaining_minutes;
     417                 : 
     418                 :   /* If we went back to the previous hour, correct time and add 1 hour more
     419                 :    * to remove */
     420                 :   if(p_calendar->minute < 0)
     421                 :     {
     422                 :       p_calendar->minute += PDF_MINS_PER_HOUR;
     423                 :       hours--;
     424                 :     }
     425                 :   /* If we went forward to the next day, correct time and add 1 hour more
     426                 :    * to add */
     427           10204 :   else if(p_calendar->minute >= PDF_MINS_PER_HOUR)
     428                 :     {
     429               0 :       p_calendar->minute -= PDF_MINS_PER_HOUR;
     430               0 :       hours++;
     431                 :     }
     432                 :   
     433                 :   /* Add/Remove hours... */
     434           10204 :   pdf_time_calendar_add_hours(p_calendar, hours);
     435           10204 : }
     436                 : 
     437                 : 
     438                 : /* Function to normalize a given date after having added SECONDS */
     439                 : static void
     440                 : pdf_time_calendar_add_seconds(struct pdf_time_cal_s *p_calendar,
     441                 :                               const pdf_i32_t delta_seconds)
     442                 : {
     443                 :   pdf_i32_t minutes;
     444                 :   pdf_i32_t remaining_seconds;
     445                 :   
     446                 :   /* No real problem with minutes, as 1 hour is always 60minutes */
     447            5102 :   minutes = delta_seconds / PDF_SECS_PER_MIN;
     448            5102 :   remaining_seconds = delta_seconds % PDF_SECS_PER_MIN;
     449                 :   
     450                 :   /* Add remaining seconds */
     451            5102 :   p_calendar->second += remaining_seconds;
     452                 :   
     453                 :   /* If we went back to the previous minute, correct time and add 1 minute more
     454                 :    * to remove */
     455                 :   if(p_calendar->second < 0)
     456                 :     {
     457                 :       p_calendar->second += PDF_SECS_PER_MIN;
     458                 :       minutes--;
     459                 :     }
     460                 :   /* If we went forward to the next minute, correct time and add 1 minute more
     461                 :    * to add */
     462            5102 :   else if(p_calendar->second >= PDF_SECS_PER_MIN)
     463                 :     {
     464               0 :       p_calendar->second -= PDF_SECS_PER_MIN;
     465               0 :       minutes++;
     466                 :     }
     467                 :   
     468                 :   /* Add/Remove minutes... */
     469            5102 :   pdf_time_calendar_add_minutes(p_calendar, minutes);
     470                 : }
     471                 : 
     472                 : 
     473                 : 
     474                 : 
     475                 : 
     476                 : 
     477                 : /* --------------------- Time Module Initialization ------------------------- */
     478                 : 
     479                 : /* Initialize Time module. Warning! Not thread-safe, must be used only once when
     480                 :  *  the program starts. It will be in charge of detecting currently configured
     481                 :  *  time zone (GMT offset) and so on. */
     482                 : pdf_status_t
     483                 : pdf_time_init(void)
     484             618 : {
     485                 :   /* Start Time context */
     486             618 :   return pdf_time_context_init();
     487                 : }
     488                 : 
     489                 : 
     490                 : /* --------------------- Time Creation and Destruction ---------------------- */
     491                 : 
     492                 : /* Create new pdf_time_t object */
     493                 : pdf_status_t
     494                 : pdf_time_new (pdf_time_t *element)
     495           35833 : {
     496                 :   /* Allocate object & Initialize all contents */
     497           35833 :   *element = (pdf_time_t) pdf_alloc (sizeof(struct pdf_time_s));
     498           35833 :   if (*element == NULL)
     499                 :     {
     500                 :       /* Not enough memory condition */
     501               0 :       return PDF_ENOMEM;
     502                 :     }
     503                 : 
     504                 :   /* Create pdf_i64_t */
     505           35833 :   (*element)->seconds = pdf_i64_new(0,0);
     506           35833 :   pdf_time_clear(*element);
     507                 : 
     508                 :   /* Success */
     509           35833 :   return PDF_OK;
     510                 : }
     511                 : 
     512                 : /* Duplicate pdf_time_t object */
     513                 : pdf_time_t
     514                 : pdf_time_dup (const pdf_time_t orig)
     515           31123 : {
     516                 :   pdf_time_t element;
     517                 : 
     518           31123 :   if((pdf_time_new (&element) == PDF_OK) &&
     519                 :      (pdf_time_copy(orig, element) != PDF_OK))
     520                 :     {
     521               0 :       pdf_time_destroy(element);
     522               0 :       element = NULL;
     523                 :     }
     524                 : 
     525           31123 :   return element;
     526                 : }
     527                 : 
     528                 : 
     529                 : /* Destroy pdf_time_t object */
     530                 : pdf_status_t
     531                 : pdf_time_destroy (pdf_time_t time_var)
     532           35801 : {
     533           35801 :   pdf_time_clear(time_var); /* Just in case additional contents are stored */
     534           35801 :   pdf_dealloc(time_var);
     535           35801 :   return PDF_OK;
     536                 : }
     537                 : 
     538                 : 
     539                 : /* Set time value with a 32-bit unsigned integer */
     540                 : pdf_status_t
     541                 : pdf_time_set_from_u32 (pdf_time_t time_var,
     542                 :                        pdf_u32_t seconds)
     543           21604 : {
     544                 :   pdf_status_t ret_code;
     545           21604 :   pdf_i64_assign(&(time_var->seconds), 0, seconds, &ret_code);
     546           21604 :   return ret_code;  
     547                 : }
     548                 : 
     549                 : 
     550                 : /* Set time value with a pdf_i64_t variable */
     551                 : pdf_status_t
     552                 : pdf_time_set_from_i64 (pdf_time_t time_var,
     553                 :                        pdf_i64_t  seconds)
     554               8 : {
     555                 :   pdf_status_t ret_code;
     556               8 :   pdf_i64_copy(seconds, &(time_var->seconds), &ret_code);
     557               8 :   return ret_code;
     558                 : }
     559                 : 
     560                 : #ifdef PDF_HOST_WIN32
     561                 : /* Windows-specific function to set the time with a FILETIME structure */
     562                 : pdf_status_t
     563                 : pdf_time_w32_set_from_filetime (pdf_time_t time_var,
     564                 :                                 const FILETIME *p_filetime)
     565                 : {
     566                 :   SYSTEMTIME systemtime;
     567                 : 
     568                 :   
     569                 :   /*
     570                 :     BOOL WINAPI
     571                 :     FileTimeToSystemTime(const FILETIME *lpFileTime,
     572                 :                          LPSYSTEMTIME lpSystemTime);
     573                 : 
     574                 :     If the function succeeds, the return value is nonzero.
     575                 : 
     576                 :     typedef struct _SYSTEMTIME {
     577                 :       WORD wYear;
     578                 :       WORD wMonth;        (1: january, 2: february...)
     579                 :       WORD wDayOfWeek;    (0:sunday, 1: monday...)
     580                 :       WORD wDay;
     581                 :       WORD wHour;
     582                 :       WORD wMinute;
     583                 :       WORD wSecond;
     584                 :       WORD wMilliseconds;
     585                 :     } SYSTEMTIME;
     586                 : 
     587                 :    */
     588                 : 
     589                 :   /* Convert filetime to systemtime calendar */
     590                 :   if(FileTimeToSystemTime(p_filetime,&systemtime)==0)
     591                 :     {
     592                 :       PDF_DEBUG_BASE("FileTimeToSystemTime failed...");
     593                 :       return PDF_ERROR;
     594                 :     }
     595                 :   else
     596                 :     {
     597                 :       /* Convert from systemtime calendar to our pdf_time_cal_s */
     598                 :       struct pdf_time_cal_s calendar;
     599                 : 
     600                 :       calendar.year = systemtime.wYear;
     601                 :       calendar.month = systemtime.wMonth;
     602                 :       calendar.day = systemtime.wDay;
     603                 :       calendar.hour = systemtime.wHour;
     604                 :       calendar.minute = systemtime.wMinute;
     605                 :       calendar.second = systemtime.wSecond;
     606                 :       /* Round seconds if milliseconds available */
     607                 :       if(systemtime.wMilliseconds >= 500)
     608                 :         {
     609                 :           calendar.second++;
     610                 :         }
     611                 :       calendar.gmt_offset = 0;
     612                 :       /* For us, sunday is 7 */
     613                 :       calendar.dow = (systemtime.wDayOfWeek == 0) ? 7: systemtime.wDayOfWeek;
     614                 :       
     615                 :       return pdf_time_from_cal(time_var,&calendar);
     616                 :     }
     617                 : }
     618                 : #endif
     619                 : 
     620                 : 
     621                 : 
     622                 : 
     623                 : 
     624                 : /* ------------------------- Managing Time Values --------------------------- */
     625                 : 
     626                 : /* Copy the contents of a given pdf_time_t object */
     627                 : pdf_status_t
     628                 : pdf_time_copy (const pdf_time_t orig,
     629                 :                pdf_time_t copy)
     630           31124 : {
     631           31124 :   pdf_status_t p_status = PDF_OK;
     632           31124 :   pdf_i64_copy (orig->seconds, &(copy->seconds), &p_status);
     633           31124 :   copy->gmt_offset = orig->gmt_offset;
     634           31124 :   return p_status;
     635                 : }
     636                 : 
     637                 : /* Clear contents of the pdf_time_t object */
     638                 : pdf_status_t
     639                 : pdf_time_clear (pdf_time_t time_var)
     640           75986 : {
     641           75986 :   pdf_status_t p_status = PDF_OK;
     642                 :   /* Set time as January 1st, 1970 */
     643           75986 :   pdf_i64_assign_quick(&time_var->seconds, 0, &p_status);
     644                 :   /* UTC */
     645           75986 :   time_var->gmt_offset = 0;
     646           75986 :   return p_status;
     647                 : }
     648                 : 
     649                 : 
     650                 : 
     651                 : /*
     652                 : *  Based on the work done by Perl guys in DateTime:
     653                 : *  http://search.cpan.org/dist/DateTime/lib/DateTime.pm#Adding_a_Duration_to_a_Datetime
     654                 : *
     655                 : *  "DateTime.pm always adds (or subtracts) days, then months, minutes, and then
     656                 : *   seconds and nanoseconds. If there are any boundary overflows, these are
     657                 : *   normalized at each step. For the days and months (the calendar) the local
     658                 : *   (not UTC) values are used. For minutes and seconds, the local values are
     659                 : *   used. This generally just works. 
     660                 : *
     661                 : *   This means that adding one month and one day to February 28, 2003 will
     662                 : *   produce the date April 1, 2003, not March 29, 2003."
     663                 : *
     664                 : * Thanks to S.Jansen for the link!
     665                 : */
     666                 : static pdf_status_t
     667                 : pdf_time_add_cal_span_with_sign (pdf_time_t time_var,
     668                 :                                  const struct pdf_time_cal_span_s *p_cal_span,
     669                 :                                  int sign)
     670            5102 : {
     671            5102 :   pdf_status_t status = PDF_ERROR;
     672                 : 
     673                 :   /* Check allowed sign values */
     674            5102 :   if( (sign == -1) || \
     675                 :       (sign == 1) )
     676                 :     {
     677                 :       struct pdf_time_cal_s calendar;
     678                 :       
     679                 :       /* Create Calendar type from the time object */
     680            5102 :       if(pdf_time_get_utc_cal (time_var, &calendar) == PDF_OK)
     681                 :         {
     682            5102 :           pdf_time_calendar_add_days(&calendar,     sign * p_cal_span->days);
     683            5102 :           pdf_time_calendar_add_months(&calendar,   sign * p_cal_span->months);
     684            5102 :           pdf_time_calendar_add_years(&calendar,    sign * p_cal_span->years);
     685            5102 :           pdf_time_calendar_add_hours(&calendar,    sign * p_cal_span->hours);
     686            5102 :           pdf_time_calendar_add_minutes(&calendar,  sign * p_cal_span->minutes);
     687            5102 :           pdf_time_calendar_add_seconds(&calendar,  sign * p_cal_span->seconds);
     688                 :           
     689            5102 :           status = pdf_time_from_cal(time_var, &calendar);
     690                 :         }
     691                 :     }
     692                 :   
     693            5102 :   return status;
     694                 : }
     695                 : 
     696                 : /* Add the time span represented by cal_span to the text object. */
     697                 : pdf_status_t
     698                 : pdf_time_add_cal_span (pdf_time_t time_var,
     699                 :                        const struct pdf_time_cal_span_s *p_cal_span)
     700            5072 : {
     701            5072 :   return pdf_time_add_cal_span_with_sign(time_var, p_cal_span, 1);
     702                 : }
     703                 : 
     704                 : /* Substract the time span represented by cal_span from the text object */
     705                 : pdf_status_t
     706                 : pdf_time_sub_cal_span (pdf_time_t time_var,
     707                 :                        const struct pdf_time_cal_span_s *p_cal_span)
     708              30 : {
     709              30 :   return pdf_time_add_cal_span_with_sign(time_var, p_cal_span, -1);
     710                 : }
     711                 : 
     712                 : /* Add the time span contained in time_span to time. As the time span is stored
     713                 :  * in seconds, the adding is direct. */
     714                 : pdf_status_t
     715                 : pdf_time_add_span (pdf_time_t time_var,
     716                 :                    const pdf_time_span_t time_span)
     717           13984 : {
     718           13984 :   pdf_status_t p_status = PDF_OK;
     719           13984 :   pdf_i64_add ((&time_var->seconds),
     720                 :                time_var->seconds,
     721                 :                time_span, &p_status);
     722           13984 :   return p_status;
     723                 : }
     724                 : 
     725                 : /* Subtract the time span contained in time_span to time. As the time span is
     726                 :  * stored in seconds. */
     727                 : pdf_status_t
     728                 : pdf_time_sub_span (pdf_time_t time_var,
     729                 :                    const pdf_time_span_t time_span)
     730           30258 : {
     731           30258 :   pdf_status_t p_status = PDF_OK;
     732           30258 :   pdf_i64_subtraction ((&time_var->seconds),
     733                 :                        time_var->seconds,
     734                 :                        time_span, &p_status);
     735           30258 :   return p_status;
     736                 : }
     737                 : 
     738                 : 
     739                 : /* Fill local_cal with the local calendar time of object. */
     740                 : pdf_status_t
     741                 : pdf_time_get_local_cal (const pdf_time_t time_var,
     742                 :                         struct pdf_time_cal_s *p_local_cal)
     743           12630 : {
     744           12630 :   return pdf_time_get_cal(time_var, PDF_TIME_CAL_LOCAL,
     745                 :                           p_local_cal);
     746                 : }
     747                 : 
     748                 : /* Get the UTC calendar time of a given time variable. */
     749                 : pdf_status_t
     750                 : pdf_time_get_utc_cal (const pdf_time_t time_var,
     751                 :                       struct pdf_time_cal_s *p_utc_cal)
     752            9824 : {
     753            9824 :   return pdf_time_get_cal(time_var, PDF_TIME_CAL_UTC,
     754                 :                           p_utc_cal);
     755                 : }
     756                 : 
     757                 : 
     758                 : /* Set the value of a time variable to a given calendar time. */
     759                 : pdf_status_t
     760                 : pdf_time_from_cal (pdf_time_t time_var,
     761                 :                    const struct pdf_time_cal_s *p_cal_time)
     762           35837 : {
     763                 :   pdf_i64_t aux;
     764                 :   pdf_i32_t walker;
     765           35837 :   pdf_status_t p_status = PDF_OK;
     766                 : 
     767           35837 :   if( (time_var == NULL) || \
     768                 :       (! pdf_time_is_valid_cal_p(p_cal_time)) )
     769                 :     {
     770                 :       PDF_DEBUG_BASE("Invalid arguments received");
     771               0 :       return PDF_EBADDATA;
     772                 :     }
     773                 :   
     774                 :   /* Initialize days to 0 */
     775           35837 :   aux = pdf_i64_new(0,0);
     776                 : 
     777                 :   /* Add days per year until the current year in the calendar */
     778           35837 :   walker = 1970;
     779          575868 :   while(walker < p_cal_time->year)
     780                 :     {
     781          504194 :       pdf_i64_add_i32(&aux, aux, \
     782                 :                       (pdf_time_is_leap_year_p(walker) ? \
     783                 :                        PDF_DAYS_IN_LEAP_YEAR : PDF_DAYS_IN_YEAR), &p_status);
     784          504194 :       walker++;
     785                 :     }
     786                 : 
     787                 :   /* Add days per month until the current month in the calendar */
     788           71674 :   pdf_i64_add_i32(&aux, aux, pdf_time_get_days_before_month(p_cal_time->year,
     789                 :                                                             p_cal_time->month), &p_status);
     790                 : 
     791                 :   /* Add days in current month until the current required day */
     792           35837 :   pdf_i64_add_i32(&aux, aux, p_cal_time->day -1, &p_status);
     793                 : 
     794                 :   /* Set date as seconds in the output variable */
     795           35837 :   pdf_i64_mult_i32(&(time_var->seconds), aux, PDF_SECS_PER_DAY, &p_status);
     796                 : 
     797                 :   /* Add hours as seconds */
     798           35837 :   pdf_i64_add_i32(&(time_var->seconds), \
     799                 :                   (time_var->seconds), \
     800                 :                   p_cal_time->hour * PDF_SECS_PER_HOUR, &p_status);
     801                 :   /* Add minutes as seconds */
     802           35837 :   pdf_i64_add_i32(&(time_var->seconds), \
     803                 :                   (time_var->seconds), \
     804                 :                   p_cal_time->minute * PDF_SECS_PER_MIN, &p_status);
     805                 :   /* Finally, add seconds */
     806           35837 :   pdf_i64_add_i32(&(time_var->seconds), \
     807                 :                   (time_var->seconds), \
     808                 :                   p_cal_time->second, &p_status);
     809                 :   
     810                 :   /* Set specific GMT offset if any */
     811           35837 :   if(p_cal_time->gmt_offset != 0)
     812                 :     {
     813                 :       /* Remove it from the time value (calendar comes in local time, so
     814                 :        *  we must remove the offset to get the pdf_time_t->seconds in UTC. */
     815           30255 :       pdf_time_span_t delta = pdf_time_span_new();
     816           30255 :       pdf_time_span_set_from_i32(&delta, p_cal_time->gmt_offset);
     817           30255 :       pdf_time_sub_span(time_var, delta);
     818           30255 :       pdf_time_span_destroy(&delta);
     819                 :     }
     820                 : 
     821                 :   /* Store the offset */
     822           35837 :   time_var->gmt_offset = p_cal_time->gmt_offset;
     823                 : 
     824           35837 :   return PDF_OK;
     825                 : }
     826                 : 
     827                 : /* Set the local time offset of time to the one used by the operating system. */
     828                 : pdf_status_t
     829                 : pdf_time_set_local_offset (pdf_time_t time_var)
     830              74 : {
     831                 :   /* Set local GMT offset */
     832              74 :   time_var->gmt_offset = pdf_time_context_get_gmt_offset();
     833              74 :   return PDF_OK;
     834                 : }
     835                 : 
     836                 : 
     837                 : /* ----------------------- Getting Time Intervals --------------------------- */
     838                 : 
     839                 : /* Get time interval as Calendar Span */
     840                 : pdf_status_t
     841                 : pdf_time_diff_cal (const pdf_time_t time1,
     842                 :                    const pdf_time_t time2,
     843                 :                    struct pdf_time_cal_span_s *p_cal_span)
     844            2160 : {
     845            2160 :   pdf_status_t ret_code = PDF_ERROR;
     846                 :   struct pdf_time_cal_s calendar1;
     847                 :   struct pdf_time_cal_s calendar2;
     848                 : 
     849            2160 :   if( (p_cal_span != NULL) && \
     850                 :       (pdf_time_get_cal(time1,
     851                 :                         PDF_TIME_CAL_UTC,
     852                 :                         &calendar1) == PDF_OK) && \
     853                 :       (pdf_time_get_cal(time2,
     854                 :                         PDF_TIME_CAL_UTC,
     855                 :                         &calendar2) == PDF_OK) )
     856                 :     {
     857                 :       struct pdf_time_cal_s *p_big;
     858                 :       struct pdf_time_cal_s *p_small;
     859                 :       pdf_i32_t aux;
     860                 : 
     861                 :       /* Check which of the dates is bigger */
     862            2160 :       if(pdf_time_cmp(time1, time2) > 0)
     863                 :         {
     864               0 :           p_cal_span->sign = PDF_TRUE;
     865               0 :           p_big = &calendar1;
     866               0 :           p_small = &calendar2;
     867                 :         }
     868                 :       else
     869                 :         {
     870            2160 :           p_cal_span->sign = PDF_FALSE;
     871            2160 :           p_big = &calendar2;
     872            2160 :           p_small = &calendar1;          
     873                 :         }
     874                 :       
     875                 :       /* Get diff of years directly (always + or 0) */
     876            2160 :       p_cal_span->years = p_big->year - p_small->year;
     877                 : 
     878                 : #define DIFF_AND_CORRECT(field,spanfield,spanupperfield) \
     879                 :   do { \
     880                 :       aux = p_big->field - p_small->field; \
     881                 :       if(aux < 0) { \
     882                 :           p_cal_span->spanupperfield--; \
     883                 :           p_cal_span->spanfield = (-1)*aux; \
     884                 :       } else { \
     885                 :         p_cal_span->spanfield = aux; \
     886                 :       } \
     887                 :   } while(0)
     888                 : 
     889                 :       /* Get diff of months (could be -) */
     890            2160 :       DIFF_AND_CORRECT(month,   months,   years);
     891                 :       /* Get diff of days (could be -) */
     892            2160 :       DIFF_AND_CORRECT(day,     days,     months);
     893                 :       /* Get diff of hours (could be -) */
     894            2160 :       DIFF_AND_CORRECT(hour,    hours,    days);
     895                 :       /* Get diff of minutes (could be -) */
     896            2160 :       DIFF_AND_CORRECT(minute,  minutes,  hours);
     897                 :       /* Get diff of seconds (could be -) */
     898            2160 :       DIFF_AND_CORRECT(second,  seconds,  minutes);
     899                 : 
     900                 : #undef DIFF_AND_CORRECT
     901                 : 
     902            2160 :       ret_code = PDF_OK;
     903                 :     }
     904                 : 
     905            2160 :   return ret_code;
     906                 : }
     907                 : 
     908                 : /* Get time interval as Span */
     909                 : pdf_status_t
     910                 : pdf_time_diff (const pdf_time_t time1,
     911                 :                const pdf_time_t time2,
     912                 :                pdf_time_span_t  *p_time_span)
     913            2881 : { 
     914            2881 :   pdf_status_t p_status = PDF_OK;
     915            2881 :   pdf_i64_subtraction(p_time_span, time1->seconds, time2->seconds, &p_status);
     916            2881 :   return p_status;
     917                 : }
     918                 : 
     919                 : 
     920                 : /* ---------------------------- Time comparison ----------------------------- */
     921                 : 
     922                 : /* Compares two times. */
     923                 : pdf_i32_t
     924                 : pdf_time_cmp (const pdf_time_t time1,
     925                 :               const pdf_time_t time2)
     926           25134 : {
     927           25134 :   return (pdf_i32_t)pdf_i64_cmp(time1->seconds, time2->seconds);
     928                 : }
     929                 : 
     930                 : 
     931                 : /* ---------------------- Time printing and parsing ------------------------- */
     932                 : 
     933                 : /* Create a string representation of a given time. */
     934                 : pdf_char_t *
     935                 : pdf_time_to_string (const pdf_time_t time_var,
     936                 :                     const enum pdf_time_format_e time_format,
     937                 :                     pdf_bool_t include_trailing_apostrophe)
     938           12471 : {
     939           12471 :   switch(time_format)
     940                 :   {
     941                 :     case PDF_TIME_FORMAT_PDF:
     942            4988 :       return pdf_time_to_string_pdf (time_var,
     943                 :                                      include_trailing_apostrophe);
     944                 :     case PDF_TIME_FORMAT_ISO_8601:
     945            2495 :       return pdf_time_to_string_iso8601(time_var);
     946                 :     case PDF_TIME_FORMAT_UTC_ASN1:
     947            2494 :       return pdf_time_to_string_utc_asn1(time_var);
     948                 :     case PDF_TIME_FORMAT_GENERALIZED_ASN1:
     949            2494 :       return pdf_time_to_string_generalized_asn1(time_var);
     950                 :     default:
     951               0 :       return NULL;
     952                 :   }
     953                 : }
     954                 : 
     955                 : 
     956                 : 
     957                 : /* Get a string containing a time specification in some format and fill a time
     958                 :  *  variable with the parsed values. */
     959                 : pdf_status_t
     960                 : pdf_time_from_string (pdf_time_t time_var,
     961                 :                       const pdf_char_t *time_str,
     962                 :                       const enum pdf_time_format_e time_format,
     963                 :                       pdf_bool_t require_trailing_apostrophe)
     964           23544 : {
     965           23544 :   switch(time_format)
     966                 :     {
     967                 :       case PDF_TIME_FORMAT_PDF:
     968            9260 :         return pdf_time_from_string_pdf(time_var, time_str, require_trailing_apostrophe);
     969                 :       case PDF_TIME_FORMAT_ISO_8601:
     970            4850 :         return pdf_time_from_string_iso8601(time_var, time_str);
     971                 :       case PDF_TIME_FORMAT_UTC_ASN1:
     972            4630 :         return pdf_time_from_string_utc_asn1(time_var, time_str);
     973                 :       case PDF_TIME_FORMAT_GENERALIZED_ASN1:
     974            4804 :         return pdf_time_from_string_generalized_asn1(time_var, time_str);
     975                 :       default:
     976               0 :         return PDF_ERROR;
     977                 :     }
     978                 : }
     979                 : 
     980                 : 
     981                 : /* ---------------------- Getting the Current Time -------------------------- */
     982                 : 
     983                 : /* Set the value of object to the current local time used by the operating
     984                 :  *  system. */
     985                 : pdf_status_t
     986                 : pdf_time_set_to_current_local_time (pdf_time_t time_var)
     987               2 : {
     988               2 :   if(pdf_time_set_to_current_utc_time(time_var) == PDF_OK)
     989                 :     {
     990                 :       /* And store offset in the gmt_offset */
     991               2 :       time_var->gmt_offset = pdf_time_context_get_gmt_offset();
     992               2 :       return PDF_OK;
     993                 :     }
     994                 :   else
     995                 :     {
     996               0 :       return PDF_ERROR;
     997                 :     }
     998                 : }
     999                 : 
    1000                 : 
    1001                 : /* Set the value of object to the current UTC time used by the operating
    1002                 :  *  system. */
    1003                 : pdf_status_t
    1004                 : pdf_time_set_to_current_utc_time (pdf_time_t time_var)
    1005            4633 : {
    1006            4633 :   pdf_status_t p_status = PDF_OK;
    1007            4633 :   time_t time_now = time(NULL);
    1008            4633 :   if(time_now != -1)
    1009                 :     {
    1010                 :       /* At least until 2038 this call will work correctly, even in systems with
    1011                 :        *  a 32bit time_t */
    1012            4633 :       pdf_i64_assign_quick(&(time_var->seconds), (pdf_i32_t)time_now, &p_status);
    1013            4633 :       time_var->gmt_offset = 0;
    1014                 :     }
    1015            4633 :   return p_status;
    1016                 : }
    1017                 : 
    1018                 : 
    1019                 : /* ----------------- Time Span Creation and Destruction --------------------- */
    1020                 : /* Note: It seems quite weird to manage the time span as any other pdf_X object,
    1021                 :  *  taking into account that it's just a typedef of pdf_i64_t, BUT, keeping the
    1022                 :  *  common interface would allow easy updates in the future if needed */
    1023                 : 
    1024                 : /* Create new time span object */
    1025                 : pdf_time_span_t
    1026                 : pdf_time_span_new (void)
    1027           45711 : {
    1028           45711 :   return pdf_i64_new(0,0);
    1029                 : }
    1030                 : 
    1031                 : 
    1032                 : /* Duplicate time span object */
    1033                 : pdf_time_span_t
    1034                 : pdf_time_span_dup (const pdf_time_span_t span)
    1035               1 : {
    1036                 :   pdf_time_span_t new_span;
    1037               1 :   new_span = pdf_time_span_new();
    1038               1 :   pdf_time_span_copy(span, &new_span);
    1039               1 :   return new_span;
    1040                 : }
    1041                 : 
    1042                 : 
    1043                 : /* Destroy time span object */
    1044                 : pdf_status_t
    1045                 : pdf_time_span_destroy (pdf_time_span_t *p_span)
    1046           45705 : {
    1047           45705 :   return PDF_OK;
    1048                 : }
    1049                 : 
    1050                 : 
    1051                 : /* --------------------- Managing Time Span Values -------------------------- */
    1052                 : 
    1053                 : /* Set the value of a time span from a 64 bits signed number */
    1054                 : pdf_status_t
    1055                 : pdf_time_span_set (pdf_time_span_t *p_span,
    1056                 :                    const pdf_i32_t high_value,
    1057                 :                    const pdf_u32_t low_value)
    1058              15 : {
    1059              15 :   pdf_status_t p_status = PDF_OK;
    1060              15 :   pdf_i64_assign(p_span, high_value, low_value, &p_status);
    1061              15 :   return p_status;
    1062                 : }
    1063                 : 
    1064                 : 
    1065                 : /* Set the value of a time span from a 32 bits signed number. */
    1066                 : pdf_status_t
    1067                 : pdf_time_span_set_from_i32 (pdf_time_span_t *p_span,
    1068                 :                             const pdf_i32_t seconds)
    1069           42810 : {
    1070           42810 :   pdf_status_t p_status = PDF_OK;
    1071           42810 :   pdf_i64_assign_quick(p_span, seconds, &p_status);
    1072           42810 :   return p_status;
    1073                 : }
    1074                 : 
    1075                 : 
    1076                 : /* Change sign of time span */
    1077                 : pdf_status_t
    1078                 : pdf_time_span_negate (pdf_time_span_t *p_span)
    1079               3 : {
    1080               3 :   pdf_status_t p_status = PDF_OK;
    1081               3 :   if (p_span == NULL)
    1082               1 :     return PDF_ERROR;
    1083               2 :   pdf_i64_neg(p_span, *p_span, &p_status);
    1084               2 :   return p_status;
    1085                 : }
    1086                 : 
    1087                 : 
    1088                 : /* Add two time spans and store the result in another time span. */
    1089                 : pdf_status_t
    1090                 : pdf_time_span_add (const pdf_time_span_t span1,
    1091                 :                    const pdf_time_span_t span2,
    1092                 :                    pdf_time_span_t *p_result)
    1093             722 : {
    1094             722 :   pdf_status_t p_status = PDF_OK;
    1095             722 :   pdf_i64_add((pdf_i64_t *)p_result, span1, span2, &p_status);
    1096             722 :   return p_status;
    1097                 : }
    1098                 : 
    1099                 : /* Copy the value of a time span into another time span. */
    1100                 : pdf_status_t
    1101                 : pdf_time_span_copy (const pdf_time_span_t orig,
    1102                 :                     pdf_time_span_t *p_dest)
    1103               3 : {
    1104               3 :   pdf_status_t p_status = PDF_OK;
    1105               3 :   pdf_i64_copy(orig, (pdf_i64_t *)p_dest, &p_status);
    1106               3 :   return p_status;
    1107                 : }
    1108                 : 
    1109                 : /* Difference two time spans and store the result (maybe negative) into another
    1110                 :  *  time span. */
    1111                 : pdf_status_t
    1112                 : pdf_time_span_diff (const pdf_time_span_t span1,
    1113                 :                     const pdf_time_span_t span2,
    1114                 :                     pdf_time_span_t *p_result)
    1115             722 : {
    1116             722 :   pdf_status_t p_status= PDF_OK;
    1117             722 :   pdf_i64_subtraction(p_result, span1, span2, &p_status);
    1118             722 :   return p_status;
    1119                 : }
    1120                 : 
    1121                 : /* Get the value of a time span in seconds. */
    1122                 : pdf_i64_t
    1123                 : pdf_time_span_to_secs (const pdf_time_span_t span)
    1124              12 : {
    1125              12 :   return span;
    1126                 : }
    1127                 : 
    1128                 : 
    1129                 : /* ------------------------- Time Span Comparison --------------------------- */
    1130                 : 
    1131                 : /* Compare two time spans */
    1132                 : pdf_i32_t
    1133                 : pdf_time_span_cmp (const pdf_time_span_t span1,
    1134                 :                    const pdf_time_span_t span2)
    1135               4 : {
    1136               4 :   return (pdf_i64_cmp(span1, span2));
    1137                 : }
    1138                 : 
    1139                 : 
    1140                 : /* ---------------------- Calendar Spans Management ------------------------- */
    1141                 : 
    1142                 : 
    1143                 : 
    1144                 : static pdf_status_t
    1145                 : pdf_time_span_from_cal_span(pdf_time_span_t *p_span,
    1146                 :                             const struct pdf_time_cal_span_s *p_cal_span,
    1147                 :                             const pdf_time_t base_time)
    1148            2880 : {
    1149            2880 :   pdf_status_t ret_code = PDF_ERROR;
    1150            2880 :   pdf_time_t new_time = NULL;
    1151                 : 
    1152                 :   /* Duplicate base object and add calendar span */
    1153            2880 :   new_time = pdf_time_dup(base_time);
    1154            2880 :   if( (new_time != NULL) &&
    1155                 :       (pdf_time_add_cal_span(new_time,p_cal_span) == PDF_OK) )
    1156                 :     {
    1157                 :       /* Get the difference in seconds */
    1158            2880 :       ret_code = pdf_time_diff(new_time, base_time, p_span);
    1159            2880 :       pdf_time_destroy(new_time);
    1160            2880 :       new_time = NULL;
    1161                 :     }
    1162                 : 
    1163                 :   /* Destroy allocated object, if any */
    1164            2880 :   if(new_time != NULL)
    1165                 :     {
    1166               0 :       pdf_time_destroy(new_time);
    1167                 :     }
    1168            2880 :   return ret_code;
    1169                 : }
    1170                 : 
    1171                 : 
    1172                 : static pdf_status_t
    1173                 : pdf_time_span_to_cal_span(struct pdf_time_cal_span_s *p_cal_span,
    1174                 :                           const pdf_time_span_t span,
    1175                 :                           const pdf_time_t base_time)
    1176            1440 : {
    1177            1440 :   pdf_status_t ret_code = PDF_ERROR;
    1178            1440 :   pdf_time_t new_time = NULL;
    1179                 :   
    1180                 :   /* Duplicate base object and add calendar span,
    1181                 :    *  and get both initial and new times as calendars
    1182                 :    */
    1183            1440 :   new_time = pdf_time_dup(base_time);
    1184            1440 :   if((new_time != NULL) && \
    1185                 :      (pdf_time_add_span(new_time,span) == PDF_OK))
    1186                 :     {
    1187                 :       /* Now, directly get calendar diff */
    1188            1440 :       ret_code = pdf_time_diff_cal(base_time, new_time, p_cal_span);
    1189                 :     }
    1190                 : 
    1191                 :   /* Destroy allocated object, if any */
    1192            1440 :   if(new_time != NULL)
    1193                 :     {
    1194            1440 :       pdf_time_destroy(new_time);
    1195                 :     }
    1196            1440 :   return ret_code; 
    1197                 : }
    1198                 : 
    1199                 : /* Add two calendar spans. Since the calendar spans are relative (some years
    1200                 :  *  has more days than another) the calendar spans are first resolved from a
    1201                 :  *  base time to get the number of seconds, and then that number is stored in
    1202                 :  *  the resulting calendar span */
    1203                 : pdf_status_t
    1204                 : pdf_time_add_cal_span_with_base (const struct pdf_time_cal_span_s *p_span1,
    1205                 :                                  const struct pdf_time_cal_span_s *p_span2,
    1206                 :                                  const pdf_time_t base_time,
    1207                 :                                  struct pdf_time_cal_span_s *p_result)
    1208             720 : {
    1209             720 :   pdf_status_t  ret_code = PDF_ERROR;
    1210                 :   pdf_time_span_t span_time_1;
    1211                 :   pdf_time_span_t span_time_2;
    1212                 :   
    1213             720 :   span_time_1 = pdf_time_span_new();
    1214             720 :   span_time_2 = pdf_time_span_new();
    1215                 :   
    1216             720 :   if( (p_span1 != NULL) && \
    1217                 :       (p_span2 != NULL) && \
    1218                 :       (pdf_time_span_from_cal_span(&span_time_1,
    1219                 :                                    p_span1,
    1220                 :                                    base_time) == PDF_OK) && \
    1221                 :       (pdf_time_span_from_cal_span(&span_time_2,
    1222                 :                                   p_span2,
    1223                 :                                   base_time) == PDF_OK) )
    1224                 :     {
    1225                 :       /* Now add two time spans */
    1226             720 :       pdf_time_span_add(span_time_1, span_time_2, &span_time_1);
    1227                 : 
    1228                 :       /* Get calendar span from the new result */
    1229             720 :       ret_code = pdf_time_span_to_cal_span(p_result,
    1230                 :                                            span_time_1,
    1231                 :                                            base_time);
    1232                 :     }
    1233                 : 
    1234             720 :   pdf_time_span_destroy(&span_time_1);
    1235             720 :   pdf_time_span_destroy(&span_time_2);
    1236             720 :   return ret_code;
    1237                 : }
    1238                 : 
    1239                 : /* Compare two calendar spans previously resolved with a given base time. */
    1240                 : pdf_i32_t
    1241                 : pdf_time_cal_span_cmp (const struct pdf_time_cal_span_s *p_span1,
    1242                 :                        const struct pdf_time_cal_span_s *p_span2,
    1243                 :                        const pdf_time_t base_time,
    1244                 :                        pdf_status_t *p_ret_code)
    1245              14 : {
    1246                 :   /* Probably the best way to do it is convert the cal spans into pdf_time_t
    1247                 :    * and then compare the pdf_time_ts */
    1248                 :   pdf_time_t time1;
    1249                 :   pdf_time_t time2;
    1250              14 :   pdf_i32_t cmp_ret = 0;
    1251              14 :   pdf_status_t  ret_code = PDF_ERROR;
    1252                 :   
    1253              14 :   time1 = pdf_time_dup(base_time);
    1254              14 :   time2 = pdf_time_dup(base_time);
    1255                 :   
    1256              14 :   if( (time1 != NULL) && \
    1257                 :       (time2 != NULL) && \
    1258                 :       (p_span1 != NULL) && \
    1259                 :       (p_span2 != NULL) && \
    1260                 :       (pdf_time_add_cal_span(time1, p_span1) == PDF_OK) && \
    1261                 :       (pdf_time_add_cal_span(time2, p_span2) == PDF_OK) )
    1262                 :     {
    1263              14 :       cmp_ret = pdf_time_cmp(time1, time2);
    1264              14 :       ret_code = PDF_OK;
    1265                 :     }
    1266                 :   
    1267              14 :   if(p_ret_code != NULL)
    1268                 :     {
    1269              14 :       *p_ret_code = ret_code;
    1270                 :     }
    1271                 : 
    1272              14 :   pdf_time_destroy(time1);
    1273              14 :   pdf_time_destroy(time2);
    1274              14 :   return cmp_ret;
    1275                 : }
    1276                 : 
    1277                 : /* Compute the difference between two calendar spans relative to a given base
    1278                 :  *  time and store it in a given calendar span. */
    1279                 : pdf_status_t
    1280                 : pdf_time_cal_span_diff (const struct pdf_time_cal_span_s *p_span1,
    1281                 :                         const struct pdf_time_cal_span_s *p_span2,
    1282                 :                         const pdf_time_t base_time,
    1283                 :                         struct pdf_time_cal_span_s *p_result)
    1284             720 : {
    1285             720 :   pdf_status_t  ret_code = PDF_ERROR;
    1286                 :   pdf_time_span_t span_time_1;
    1287                 :   pdf_time_span_t span_time_2;
    1288                 :   
    1289             720 :   span_time_1 = pdf_time_span_new();
    1290             720 :   span_time_2 = pdf_time_span_new();
    1291                 :   
    1292             720 :   if((p_span1 != NULL) && \
    1293                 :      (p_span2 != NULL) && \
    1294                 :      (pdf_time_span_from_cal_span(&span_time_1,
    1295                 :                                   p_span1,
    1296                 :                                   base_time) == PDF_OK) && \
    1297                 :      (pdf_time_span_from_cal_span(&span_time_2,
    1298                 :                                   p_span2,
    1299                 :                                   base_time) == PDF_OK) )
    1300                 :     {
    1301                 :       /* Now substract the two time spans */
    1302             720 :       pdf_time_span_diff(span_time_1, span_time_2, &span_time_1);
    1303                 :       
    1304                 :       /* Get calendar span from the new result */
    1305             720 :       ret_code = pdf_time_span_to_cal_span(p_result,
    1306                 :                                            span_time_1,
    1307                 :                                            base_time);
    1308                 :     }
    1309                 :   
    1310             720 :   pdf_time_span_destroy(&span_time_1);
    1311             720 :   pdf_time_span_destroy(&span_time_2);
    1312             720 :   return ret_code;
    1313                 : }
    1314                 : 
    1315                 : 
    1316                 : /* End of pdf-time.c */

Generated by: LTP GCOV extension version 1.6