pdf-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[pdf-devel] libgnupdf ChangeLog src/base/pdf-time-string.c


From: Aleksander Morgado
Subject: [pdf-devel] libgnupdf ChangeLog src/base/pdf-time-string.c
Date: Sun, 13 Jul 2008 17:50:23 +0000

CVSROOT:        /cvsroot/pdf
Module name:    libgnupdf
Changes by:     Aleksander Morgado <aleksander_m>       08/07/13 17:50:23

Modified files:
        .              : ChangeLog 
        src/base       : pdf-time-string.c 

Log message:
        Implemented PDF date string handling

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libgnupdf/ChangeLog?cvsroot=pdf&r1=1.278&r2=1.279
http://cvs.savannah.gnu.org/viewcvs/libgnupdf/src/base/pdf-time-string.c?cvsroot=pdf&r1=1.4&r2=1.5

Patches:
Index: ChangeLog
===================================================================
RCS file: /cvsroot/pdf/libgnupdf/ChangeLog,v
retrieving revision 1.278
retrieving revision 1.279
diff -u -b -r1.278 -r1.279
--- ChangeLog   11 Jul 2008 15:41:26 -0000      1.278
+++ ChangeLog   13 Jul 2008 17:50:22 -0000      1.279
@@ -1,3 +1,10 @@
+2008-07-13  Aleksander Morgado Juez  <address@hidden>
+
+       * src/base/pdf-time-string.c (pdf_time_from_string_pdf): Function
+       implemented.
+       (pdf_time_to_string_pdf): Function implemented.
+       (pdf_time_to_string_iso8601): Bugfix to handle negative GMT offsets.
+
 2008-07-11  gerel  <address@hidden>
 
        * prmgt/check-api-doc-consistency.pl: added '-i' feature.

Index: src/base/pdf-time-string.c
===================================================================
RCS file: /cvsroot/pdf/libgnupdf/src/base/pdf-time-string.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- src/base/pdf-time-string.c  2 Jul 2008 20:28:41 -0000       1.4
+++ src/base/pdf-time-string.c  13 Jul 2008 17:50:23 -0000      1.5
@@ -31,7 +31,12 @@
 #include <pdf-time-string.h>
 
 
+/* Maximum length of strings, including trailing NUL */
 #define PDF_MAX_ISO8601_STR_LENGTH  30
+#define PDF_MAX_PDFDATE_STR_LENGTH  24
+
+
+/* Mask to check if a given expected character is actually a digit or not */
 
 
 
@@ -39,8 +44,171 @@
 pdf_time_from_string_pdf(pdf_time_t time_var,
                          const pdf_char_t *time_str)
 {
-  /* TODO */
-  return PDF_ERROR;
+  /*
+   * From PDF Reference 1.7: ( D:YYYYMMDDHHmmSSOHH'mm' )
+   * From ISO 32000:         ( D:YYYYMMDDHHmmSSOHH'mm  )
+   *
+   * Notes: Year is mandatory, all the other fields may appear if the preceding
+   *        also appear.
+   *
+   *  D:   = string "D:"
+   *  YYYY = four-digit year
+   *  MM   = two-digit month (01=January, etc.)
+   *  DD   = two-digit day of month (01 through 31)
+   *  HH   = two digits of hour (00 through 23)
+   *  mm   = two digits of minute (00 through 59)
+   *  SS   = two digits of second (00 through 59)
+   *  O    = either '+', '-' or 'Z'
+   *  HH   = two digits of hour (00 through 23) for the GMT offset
+   *  '    = string "'"
+   *  MM   = two digits of minute (00 through 59) for the GMT offset
+   *  '    = string "'"  (NOTE: Mandatory in 1.7, optional in ISO32000)
+   */
+  struct pdf_time_cal_s calendar;
+  pdf_char_t   duplicate_field[5];
+  pdf_status_t ret_code;
+  pdf_i32_t    gmt_offset = 0;
+  pdf_i32_t    i;
+  pdf_size_t   time_str_length = strlen((char *)time_str);
+  
+  /* Check minimum length      D:YYYY */
+  if(time_str_length < 6)
+    {
+      PDF_DEBUG_BASE("Invalid PDF time string (too short): '%s'",
+                     time_str);
+      return PDF_EBADDATA;
+    }
+  /* Check prefix */
+  if(strncmp((char *)time_str,"D:",2) != 0)
+    {
+      PDF_DEBUG_BASE("Invalid PDF time string (no prefix): '%s'",
+                    time_str);
+      return PDF_EBADDATA;
+    }
+
+  /* We need to check the input characters are digits when we expect digits and
+   *  the opposite as well. Remember that for unconvertable bytes, atoi returns
+   *  zero, so we must really be sure we pass digits to atoi */
+
+#define PDF_STRING_DIGIT_MASK  0x36FFFC /* 0011 0110 1111 1111 1111 1100 */
+
+  /* Don't really need to check again two first bytes, as already done before 
*/
+  i = 2;
+  while(i < time_str_length)
+    {
+      if(PDF_STRING_DIGIT_MASK & (1 << i))
+        {
+          /* Expected a digit at position 'i' */
+          if((time_str[i] < '0') || \
+              (time_str[i] > '9'))
+            {
+              PDF_DEBUG_BASE("Expected digit and found '%c' in '%s'",
+                              time_str[i], time_str);
+              return PDF_EBADDATA;
+            }
+        }
+      /* Update index */
+      i++;
+    }
+
+  /* Check time zone definer */
+  if((time_str_length >=16) && \
+     (time_str[16] != 'Z') && \
+     (time_str[16] != '+') && \
+     (time_str[16] != '-'))
+    {
+      PDF_DEBUG_BASE("Invalid time zone definer '%c' found in '%s'",
+                    time_str[16], time_str);
+      return PDF_EBADDATA;
+    }
+
+  /* Check additional ' characters. Remember that the last ' character is
+   * mandatory in PDF Ref 1.7 but optional in ISO32000*/
+  if(((time_str_length >= 19) && \
+      (time_str[19] != '\'')) || \
+     ((time_str_length >= 22) && \
+      (time_str[22] != '\'')))
+    {
+      PDF_DEBUG_BASE("Invalid separator found ('%c' or '%c') in '%s'",
+                    time_str[19], time_str[22], time_str);
+      return PDF_EBADDATA;
+    }
+
+
+  /* Reset calendar (all integers to zero) */
+  memset(&calendar, 0, sizeof(calendar));
+
+
+#define __GET_FIELD(str,start,length,dest) do { \
+  memcpy(&duplicate_field[0], &str[start], length); \
+  duplicate_field[length]=0; \
+  dest += atoi((char *)&duplicate_field[0]); \
+} while(0)
+
+  
+  /* Get year */
+  __GET_FIELD(time_str, 2, 4, calendar.year);
+  /* Get month */
+  if(time_str_length >= 8) /* D:YYYYMM */
+    {
+      __GET_FIELD(time_str, 6, 2, calendar.month);
+      /* Get day */
+      if(time_str_length >= 10) /* D:YYYYMMDD */
+        {
+          __GET_FIELD(time_str, 8, 2, calendar.day);
+          /* Get hour */
+          if(time_str_length >= 12) /* D:YYYYMMDDHH */
+            {
+              __GET_FIELD(time_str, 10, 2, calendar.hour);
+              /* Get minutes */
+              if(time_str_length >= 14) /* D:YYYYMMDDHHmm */
+                {
+                  __GET_FIELD(time_str, 12, 2, calendar.minute);
+                  /* Get seconds */
+                  if(time_str_length >= 16) /* D:YYYYMMDDHHmmSS */
+                    {
+                      __GET_FIELD(time_str, 14, 2, calendar.second);
+                      /* Get time zone offset hours */
+                      if(time_str_length >= 19) /* D:YYYYMMDDHHmmSS0HH */
+                        {
+                          __GET_FIELD(time_str, 17, 2, calendar.gmt_offset);
+                          /* And convert it in minutes */
+                          calendar.gmt_offset *= 60;
+
+                          /* Get time zone offset minutes */
+                          if(time_str_length >= 22) /* D:YYYYMMDDHHmmSS0HH'MM 
*/
+                            {
+                              __GET_FIELD(time_str, 20, 2, 
calendar.gmt_offset);
+                              /* And convert it in minutes */
+                              calendar.gmt_offset *= 60;
+                            }
+
+                          /* Convert from minutes to seconds */
+                          calendar.gmt_offset *= 60;
+
+                          /* Set proper sign */
+                          if(time_str[16]=='-')
+                            {
+                              calendar.gmt_offset *= (-1);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+#undef __GET_FIELD
+  
+  /* Get time value from break-down UTC calendar !*/
+  ret_code = pdf_time_from_cal(time_var, &calendar);
+  if(ret_code == PDF_OK)
+    {
+      /* Now set GMT offset in pdf_time_t */
+      time_var->gmt_offset = gmt_offset;
+    }
+
+  return ret_code;
 }
 
 pdf_status_t
@@ -94,7 +262,7 @@
   pdf_char_t *duplicate;
   pdf_char_t *walker;
   pdf_status_t ret_code;
-  pdf_i32_t    gmt_offset;
+  pdf_i32_t    gmt_offset = 0;
   pdf_size_t time_str_length = strlen((char *)time_str);
   
   /* Check minimum length */
@@ -183,22 +351,6 @@
   /* Set calendar as if it were UTC */
   calendar.gmt_offset = 0;
 
-/*
-   pdf_char_t *str = (pdf_char_t 
*)pdf_alloc(PDF_MAX_ISO8601_STR_LENGTH*sizeof(pdf_char_t));
-   pdf_i32_t offset_hours = calendar.gmt_offset / 3600;
-   pdf_i32_t offset_minutes = calendar.gmt_offset % 3600;
-   sprintf((char *)str, "%4d-%s%d-%s%dT%s%d:%s%d:%s%d.00+%s%d:%s%d", \
-   calendar.year,
-   (calendar.month < 10 ? "0" : ""), calendar.month,
-   (calendar.day < 10 ? "0" : ""), calendar.day,
-   (calendar.hour < 10 ? "0" : ""), calendar.hour,
-   (calendar.minute < 10 ? "0" : ""), calendar.minute,
-   (calendar.second < 10 ? "0" : ""), calendar.second,
-   (offset_hours < 10 ? "0" : ""), offset_hours,
-   (offset_minutes < 10 ? "0" : ""), offset_minutes);
-   PDF_DEBUG_BASE("Intermediate calendar: %s", str);
-*/
-  
   /* Get time value from break-down UTC calendar !*/
   ret_code = pdf_time_from_cal(time_var, &calendar);
   if(ret_code == PDF_OK)
@@ -215,7 +367,53 @@
 pdf_char_t *
 pdf_time_to_string_pdf(const pdf_time_t time_var)
 {
-  return NULL;
+  pdf_char_t *str;
+  struct pdf_time_cal_s calendar;
+  
+  str = (pdf_char_t *)pdf_alloc(PDF_MAX_PDFDATE_STR_LENGTH*sizeof(pdf_char_t));
+  if(str != NULL)
+    {
+      /* D:YYYYMMDDHHmmSSOHH'mm' */
+      if(pdf_time_get_local_cal(time_var, &calendar) == PDF_OK)
+        {
+          if(calendar.gmt_offset != 0)
+            {
+              pdf_i32_t offset_hours;
+              pdf_i32_t offset_minutes;
+
+              offset_hours = (((calendar.gmt_offset < 0) ? (-1) : (1)) * 
calendar.gmt_offset) / 3600;
+              offset_minutes = (((calendar.gmt_offset < 0) ? (-1) : (1)) * 
calendar.gmt_offset) % 3600;
+              sprintf((char *)str, "D:%4d%s%d%s%d%s%d%s%d%s%d%c%s%d'%s%d'", \
+                      calendar.year,
+                      (calendar.month < 10 ? "0" : ""), calendar.month,
+                      (calendar.day < 10 ? "0" : ""), calendar.day,
+                      (calendar.hour < 10 ? "0" : ""), calendar.hour,
+                      (calendar.minute < 10 ? "0" : ""), calendar.minute,
+                      (calendar.second < 10 ? "0" : ""), calendar.second,
+                      ((calendar.gmt_offset < 0) ? '-' : '+'),
+                      (offset_hours < 10 ? "0" : ""), offset_hours,
+                      (offset_minutes < 10 ? "0" : ""), offset_minutes);
+            }
+          else
+            {
+              sprintf((char *)str, "D:%4d%s%d%s%d%s%d%s%d%s%dZ", \
+                      calendar.year,
+                      (calendar.month < 10 ? "0" : ""), calendar.month,
+                      (calendar.day < 10 ? "0" : ""), calendar.day,
+                      (calendar.hour < 10 ? "0" : ""), calendar.hour,
+                      (calendar.minute < 10 ? "0" : ""), calendar.minute,
+                      (calendar.second < 10 ? "0" : ""), calendar.second);
+            }
+        }
+      else
+        {
+          PDF_DEBUG_BASE("Could not get local calendar from pdf_time_t...");
+          pdf_dealloc(str);
+          str = NULL;
+        }
+    }
+  
+  return str;
 }
 
 
@@ -246,20 +444,37 @@
       /* YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00) */
       if(pdf_time_get_local_cal(time_var, &calendar) == PDF_OK)
         {
-          pdf_i32_t offset_hours = calendar.gmt_offset / 3600;
-          pdf_i32_t offset_minutes = calendar.gmt_offset % 3600;
-          sprintf((char *)str, "%4d-%s%d-%s%dT%s%d:%s%d:%s%d.00+%s%d:%s%d", \
+          if(calendar.gmt_offset != 0)
+            {
+              pdf_i32_t offset_hours;
+              pdf_i32_t offset_minutes;
+
+              offset_hours = (((calendar.gmt_offset < 0) ? (-1) : (1)) * 
calendar.gmt_offset) / 3600;
+              offset_minutes = (((calendar.gmt_offset < 0) ? (-1) : (1)) * 
calendar.gmt_offset) % 3600;
+              sprintf((char *)str, 
"%4d-%s%d-%s%dT%s%d:%s%d:%s%d.00%c%s%d:%s%d", \
                   calendar.year,
                   (calendar.month < 10 ? "0" : ""), calendar.month,
                   (calendar.day < 10 ? "0" : ""), calendar.day,
                   (calendar.hour < 10 ? "0" : ""), calendar.hour,
                   (calendar.minute < 10 ? "0" : ""), calendar.minute,
                   (calendar.second < 10 ? "0" : ""), calendar.second,
+                      ((calendar.gmt_offset < 0) ? '-' : '+'),
                   (offset_hours < 10 ? "0" : ""), offset_hours,
                   (offset_minutes < 10 ? "0" : ""), offset_minutes);
         }
       else
         {
+              sprintf((char *)str, "%4d-%s%d-%s%dT%s%d:%s%d:%s%d.00Z", \
+                      calendar.year,
+                      (calendar.month < 10 ? "0" : ""), calendar.month,
+                      (calendar.day < 10 ? "0" : ""), calendar.day,
+                      (calendar.hour < 10 ? "0" : ""), calendar.hour,
+                      (calendar.minute < 10 ? "0" : ""), calendar.minute,
+                      (calendar.second < 10 ? "0" : ""), calendar.second);
+            }
+        }
+      else
+        {
           PDF_DEBUG_BASE("Could not get local calendar from pdf_time_t...");
           pdf_dealloc(str);
           str = NULL;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]