Adaptive Framework  0.9.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
afw_time.c
Go to the documentation of this file.
1 // See the 'COPYING' file in the project root for licensing information.
2 /*
3  * Adaptive Framework Time Support
4  *
5  * Copyright (c) 2010-2023 Clemson University
6  *
7  */
8 
14 #include "afw_internal.h"
15 
16 #define IMPL_IS_DIGIT(n) ((n) >= '0' && (n) <= '9')
17 
18 #define IMPL_SAFE_DIGIT(c, to, error) \
19 do { \
20  to = c - '0'; \
21  if (to < 0 || to > 9) goto error; \
22 } while (0)
23 
24 #define IMPL_MAX_TIME_ZONE_LEN sizeof("-01:00") - 1
25 
26 #define IMPL_MAX_DATE_SEPARATE_LEN sizeof("-2147483648-01-01") - 1
27 
28 #define IMPL_MAX_DATE_LEN IMPL_MAX_DATE_SEPARATE_LEN + IMPL_MAX_TIME_ZONE_LEN
29 
30 #define IMPL_MAX_TIME_SEPARATE_LEN sizeof("12:34:56.000000") - 1
31 
32 #define IMPL_MAX_TIME_LEN IMPL_MAX_TIME_SEPARATE_LEN + IMPL_MAX_TIME_ZONE_LEN
33 
34 #define IMPL_MAX_DATE_TIME_LEN \
35  IMPL_MAX_DATE_SEPARATE_LEN + 1 + \
36  IMPL_MAX_TIME_SEPARATE_LEN + \
37  IMPL_MAX_TIME_ZONE_LEN
38 
39 
40 /* Get now time as dateTime in specified pool. */
41 AFW_DEFINE_STATIC_INLINE(void)
42 impl_dateTime_tm_set(
43  afw_dateTime_t *dateTime, apr_time_exp_t *tm, afw_xctx_t *xctx)
44 {
45  /* Make sure any sluff is cleared. */
46  memset(dateTime, 0, sizeof(*dateTime));
47 
48  /* Fill in dateTime. */
49  dateTime->date.year = 1900 + tm->tm_year;
50  dateTime->date.month = tm->tm_mon + 1;
51  dateTime->date.day = tm->tm_mday;
52  dateTime->time.hour = tm->tm_hour;
53  dateTime->time.minute = tm->tm_min;
54  dateTime->time.second = tm->tm_sec;
55  dateTime->time.microsecond = tm->tm_usec;
56  dateTime->time_zone.hours = tm->tm_gmtoff / 3600;
57  dateTime->time_zone.minutes = abs(tm->tm_gmtoff / 60 % 60);
58 }
59 
60 
61 /* Get now time as time only in specified pool. */
62 AFW_DEFINE_STATIC_INLINE(void)
63 impl_time_tm_set(
64  afw_time_t *time, apr_time_exp_t *tm, afw_xctx_t *xctx)
65 {
66  /* Make sure any sluff is cleared. */
67  memset(time, 0, sizeof(*time));
68 
69  /* Fill in time. */
70  time->time.hour = tm->tm_hour;
71  time->time.minute = tm->tm_min;
72  time->time.second = tm->tm_sec;
73  time->time.microsecond = tm->tm_usec;
74  time->time_zone.hours = tm->tm_gmtoff / 3600;
75  time->time_zone.minutes = abs(tm->tm_gmtoff / 60 % 60);
76 }
77 
78 
79 AFW_DEFINE_STATIC_INLINE(void)
82  int year,
83  int month,
84  int day,
85  afw_xctx_t *xctx)
86 {
87  if (year < 0 AFW_INT32_MIN || year > AFW_INT32_MAX) {
88  AFW_THROW_ERROR_Z(general,
89  "year must be between "
91  " and "
93  xctx);
94  }
95 
96  if (month < 1 || month > 12) {
97  AFW_THROW_ERROR_Z(general,
98  "month must be between 1 and 12",
99  xctx);
100  }
101 
103  if (day < 1 || day > 31) {
104  AFW_THROW_ERROR_Z(general,
105  "day must be between 1 and 31",
106  xctx);
107  }
108 
109  date->year = (afw_int32_t)year;
110  date->month = (afw_uint8_t)month;
111  date->day = (afw_uint8_t)day;
112 }
113 
114 
115 AFW_DEFINE_STATIC_INLINE(void)
116 impl_set_time_no_time_zone(
118  int hour,
119  int minute,
120  int second,
121  int microsecond,
122  afw_xctx_t *xctx)
123 
124 {
125  if (hour < 0 || hour > 24) {
126  AFW_THROW_ERROR_Z(general,
127  "hour must be between 0 and 24",
128  xctx);
129  }
130 
131  if (hour == 24 && minute != 0 && second != 0 && microsecond != 0) {
132  AFW_THROW_ERROR_Z(general,
133  "if hour is 24, minute, second, and microsecond must be 0",
134  xctx);
135  }
136 
137  if (minute < 0 || minute > 59) {
138  AFW_THROW_ERROR_Z(general,
139  "minute must be between 0 and 59",
140  xctx);
141  }
142 
143  if (second < 0 || second > 255) {
144  AFW_THROW_ERROR_Z(general,
145  "second must be between 0 and 255",
146  xctx);
147  }
148 
149  if (microsecond < 0 || microsecond > 999999) {
150  AFW_THROW_ERROR_Z(general,
151  "microsecond must be between 0 and 999999",
152  xctx);
153  }
154 
155  time->hour = (afw_uint8_t)hour;
156  time->minute = (afw_uint8_t)minute;
157  time->second = (afw_uint8_t)second;
158  time->microsecond = (afw_uint32_t)microsecond;
159 }
160 
161 
162 AFW_DEFINE_STATIC_INLINE(void)
163 impl_set_time_zone(
164  afw_time_zone_t *time_zone,
165  int tz_hours_offset,
166  int tz_minutes_offset,
167  afw_xctx_t *xctx)
168 {
169  if (tz_hours_offset < -14 || tz_hours_offset > 14) {
170  AFW_THROW_ERROR_Z(general,
171  "tz_hours_offset must be between -14 and 14",
172  xctx);
173  }
174 
175  if (tz_hours_offset == -14 || tz_hours_offset == 14) {
176  if (tz_minutes_offset != 0) {
177  AFW_THROW_ERROR_Z(general,
178  "if tz_hours_offset is -14 or 14, "
179  "tz_minutes_offset must be 0",
180  xctx);
181  }
182  }
183 
184  if (tz_minutes_offset < -1 || tz_minutes_offset > 59) {
185  AFW_THROW_ERROR_Z(general,
186  "tz_minutes_offset must be between -1 and 59",
187  xctx);
188  }
189 
190  time_zone->hours = (afw_int8_t)tz_hours_offset;
191  time_zone->minutes = (afw_int8_t)tz_minutes_offset;
192 }
193 
194 
195 /* Set afw_date_t from parts. */
196 AFW_DEFINE(void)
198  afw_date_t *date,
199  int year,
200  int month,
201  int day,
202  int tz_hours_offset,
203  int tz_minutes_offset,
204  afw_xctx_t *xctx)
205 {
207  &date->date,
208  year, month, day,
209  xctx);
210  impl_set_time_zone(
211  &date->time_zone,
212  tz_hours_offset, tz_minutes_offset,
213  xctx);
214 }
215 
216 
217 /* Create afw_date_t from parts in specific pool. */
218 AFW_DEFINE(const afw_date_t *)
220  int year,
221  int month,
222  int day,
223  int tz_hours_offset,
224  int tz_minutes_offset,
225  const afw_pool_t *p,
226  afw_xctx_t *xctx)
227 {
228  afw_date_t *result;
229 
230  result = afw_pool_calloc_type(p, afw_date_t, xctx);
232  year, month, day,
233  tz_hours_offset, tz_minutes_offset,
234  xctx);
235  return result;
236 }
237 
238 
239 /*
240  * @brief Set afw_dateTime_t from parts.
241  * @param xctx of caller.
242  */
243 AFW_DEFINE(void)
245  afw_dateTime_t *dateTime,
246  int year,
247  int month,
248  int day,
249  int hour,
250  int minute,
251  int second,
252  int microsecond,
253  int tz_hours_offset,
254  int tz_minutes_offset,
255  afw_xctx_t *xctx)
256 {
258  &dateTime->date,
259  year, month, day,
260  xctx);
261  impl_set_time_no_time_zone(
262  &dateTime->time,
263  hour, minute, second, microsecond,
264  xctx);
265  impl_set_time_zone(
266  &dateTime->time_zone,
267  tz_hours_offset, tz_minutes_offset,
268  xctx);
269 }
270 
271 
272 /* Create afw_dateTime_t from parts in specific pool. */
273 AFW_DEFINE(const afw_dateTime_t *)
275  int year,
276  int month,
277  int day,
278  int hour,
279  int minute,
280  int second,
281  int microsecond,
282  int tz_hours_offset,
283  int tz_minutes_offset,
284  const afw_pool_t *p,
285  afw_xctx_t *xctx)
286 {
287  afw_dateTime_t *result;
288 
289  result = afw_pool_calloc_type(p, afw_dateTime_t, xctx);
291  year, month, day,
292  hour, minute, second, microsecond,
293  tz_hours_offset, tz_minutes_offset,
294  xctx);
295  return result;
296 }
297 
298 
299 
300 
301 
302 /* Set afw_dateTime_t from apr_time. */
303 AFW_DECLARE(void)
305  afw_dateTime_t *dateTime,
306  apr_time_t apr_time,
307  afw_xctx_t *xctx)
308 {
309  apr_status_t rv;
310  apr_time_exp_t tm;
311 
312  rv = apr_time_exp_lt(&tm, apr_time);
313  if (rv != APR_SUCCESS) {
314  AFW_THROW_ERROR_RV_Z(general, apr, rv, "apr_time_exp_lt() failed",
315  xctx);
316  }
317  impl_dateTime_tm_set(dateTime, &tm, xctx);
318 }
319 
320 
321 
322 /* Create afw_dateTime_t from apr time.*/
325  apr_time_t apr_time,
326  const afw_pool_t *p,
327  afw_xctx_t *xctx)
328 {
329  afw_dateTime_t *result;
330 
331  result = afw_pool_calloc_type(p, afw_dateTime_t, xctx);
332  afw_dateTime_set_from_apr_time(result, apr_time, xctx);
333  return result;
334 }
335 
336 
337 
338 /* Set afw_dayTimeDuration_t from parts. */
339 AFW_DEFINE(void)
341  afw_dayTimeDuration_t *dayTimeDuration,
342  afw_boolean_t is_positive,
343  int days,
344  int hours,
345  int minutes,
346  int seconds,
347  int microseconds,
348  afw_xctx_t *xctx)
349 {
350  if (days < 0 || days > AFW_INT32_MAX) {
351  AFW_THROW_ERROR_Z(general,
352  "days parameter must be between 0 and "
354  xctx);
355  }
356 
357  if (hours < 0 || hours > AFW_INT32_MAX) {
358  AFW_THROW_ERROR_Z(general,
359  "hours parameter must be between 0 and "
361  xctx);
362  }
363 
364  if (minutes < 0 || minutes > AFW_INT32_MAX) {
365  AFW_THROW_ERROR_Z(general,
366  "minutes parameter must be between 0 and "
368  xctx);
369  }
370 
371  if (seconds < 0 || seconds > AFW_INT32_MAX) {
372  AFW_THROW_ERROR_Z(general,
373  "seconds parameter must be between 0 and "
375  xctx);
376  }
377 
378  if (microseconds < 0 || microseconds > AFW_INT32_MAX) {
379  AFW_THROW_ERROR_Z(general,
380  "microseconds parameter must be between 0 and "
382  xctx);
383  }
384 
385  if (is_positive) {
386  dayTimeDuration->days = (afw_int32_t)days;
387  dayTimeDuration->hours = (afw_int32_t)hours;
388  dayTimeDuration->minutes = (afw_int32_t)minutes;
389  dayTimeDuration->seconds = (afw_int32_t)seconds;
390  dayTimeDuration->microseconds = (afw_int32_t)microseconds;
391  }
392  else {
393  dayTimeDuration->days = -(afw_int32_t)days;
394  dayTimeDuration->hours = -(afw_int32_t)hours;
395  dayTimeDuration->minutes = -(afw_int32_t)minutes;
396  dayTimeDuration->seconds = -(afw_int32_t)seconds;
397  dayTimeDuration->microseconds = -(afw_int32_t)microseconds;
398  }
399 }
400 
401 
402 /* Create afw_dayTimeDuration_t from parts in specific pool. */
405  afw_boolean_t is_positive,
406  afw_int32_t days,
407  afw_int32_t hours,
408  afw_int32_t minutes,
409  afw_int32_t seconds,
410  afw_int32_t microseconds,
411  const afw_pool_t *p,
412  afw_xctx_t *xctx)
413 {
414  afw_dayTimeDuration_t *result;
415 
416  result = afw_pool_calloc_type(p, afw_dayTimeDuration_t, xctx);
417  afw_dayTimeDuration_set_from_parts(result, is_positive,
418  days, hours, minutes, seconds, microseconds, xctx);
419  return result;
420 }
421 
422 
423 /* Set afw_time_t from parts. */
424 AFW_DEFINE(void)
426  afw_time_t *time,
427  int hour,
428  int minute,
429  int second,
430  int microsecond,
431  int tz_hours_offset,
432  int tz_minutes_offset,
433  afw_xctx_t *xctx)
434 {
435  impl_set_time_no_time_zone(
436  &time->time,
437  hour, minute, second, microsecond,
438  xctx);
439  impl_set_time_zone(
440  &time->time_zone,
441  tz_hours_offset, tz_minutes_offset,
442  xctx);
443 }
444 
445 
446 /* Create afw_time_t from parts in specific pool. */
447 AFW_DEFINE(const afw_time_t *)
449  int hour,
450  int minute,
451  int second,
452  int microsecond,
453  int tz_hours_offset,
454  int tz_minutes_offset,
455  const afw_pool_t *p,
456  afw_xctx_t *xctx)
457 {
458  afw_time_t *result;
459 
460  result = afw_pool_calloc_type(p, afw_time_t, xctx);
462  hour, minute, second, microsecond,
463  tz_hours_offset, tz_minutes_offset,
464  xctx);
465  return result;
466 }
467 
468 
469 /* Set afw_yearMonthDuration_t from parts. */
470 AFW_DEFINE(void)
472  afw_yearMonthDuration_t *yearMonthDuration,
473  afw_boolean_t is_positive,
474  int years,
475  int months,
476  afw_xctx_t *xctx)
477 {
478  if (years < 0 || years > AFW_INT32_MAX) {
479  AFW_THROW_ERROR_Z(general,
480  "years parameter must be between 0 and "
482  xctx);
483  }
484 
485  if (months < 0 || months > AFW_INT32_MAX) {
486  AFW_THROW_ERROR_Z(general,
487  "months parameter must be between 0 and "
489  xctx);
490  }
491 
492  if (is_positive) {
493  yearMonthDuration->years = (afw_int32_t)years;
494  yearMonthDuration->months = (afw_int32_t)months;
495  }
496  else {
497  yearMonthDuration->years = -(afw_int32_t)years;
498  yearMonthDuration->months = -(afw_int32_t)months;
499  }
500 }
501 
502 
503 /* Create afw_yearMonthDuration_t from parts in specific pool. */
506  afw_boolean_t is_positive,
507  afw_int32_t years,
508  afw_int32_t months,
509  const afw_pool_t *p,
510  afw_xctx_t *xctx)
511 {
512  afw_yearMonthDuration_t *result;
513 
515  afw_yearMonthDuration_set_from_parts(result, is_positive,
516  years, months, xctx);
517  return result;
518 }
519 
520 
521 /* Get now time as dateTime in specified pool. */
522 AFW_DEFINE(void)
524  afw_dateTime_t *dateTime_local, afw_dateTime_t *dateTime_utc,
525  afw_xctx_t *xctx)
526 {
527  apr_status_t rv;
528  apr_time_exp_t tm;
529  apr_time_t now;
530 
531  /* Make sure both will get same time. */
532  now = apr_time_now();
533 
534  /* If requested, set local dateTime to now. */
535  if (dateTime_local) {
536  rv = apr_time_exp_lt(&tm, now);
537  if (rv != APR_SUCCESS) {
538  AFW_THROW_ERROR_RV_Z(general, apr, rv, "apr_time_exp_lt() failed",
539  xctx);
540  }
541  impl_dateTime_tm_set(dateTime_local, &tm, xctx);
542  }
543 
544  /* If requested, set utc dateTime to now. */
545  if (dateTime_utc) {
546  rv = apr_time_exp_gmt(&tm, now);
547  if (rv != APR_SUCCESS) {
548  AFW_THROW_ERROR_RV_Z(general, apr, rv, "apr_time_exp_gmt() failed",
549  xctx);
550  }
551  impl_dateTime_tm_set(dateTime_utc, &tm, xctx);
552  }
553 }
554 
555 
556 /* Get now time as time only in specified pool. */
557 AFW_DEFINE(void)
559  afw_time_t *time_local, afw_time_t *time_utc,
560  afw_xctx_t *xctx)
561 {
562  apr_status_t rv;
563  apr_time_exp_t tm;
564  apr_time_t now;
565 
566  /* Make sure both will get same time. */
567  now = apr_time_now();
568 
569  /* If requested, set local time. */
570  if (time_local) {
571  rv = apr_time_exp_lt(&tm, now);
572  if (rv != APR_SUCCESS) {
573  AFW_THROW_ERROR_RV_Z(general, apr, rv, "apr_time_exp_lt() failed",
574  xctx);
575  }
576  impl_time_tm_set(time_local, &tm, xctx);
577  }
578 
579  /* If requested, set utc time. */
580  if (time_utc) {
581  rv = apr_time_exp_gmt(&tm, now);
582  if (rv != APR_SUCCESS) {
583  AFW_THROW_ERROR_RV_Z(general, apr, rv, "apr_time_exp_gmt() failed",
584  xctx);
585  }
586  impl_time_tm_set(time_utc, &tm, xctx);
587  }
588 }
589 
590 
591 /* Get now time as dateTime in specified pool. */
592 AFW_DEFINE(const afw_dateTime_t *)
594  const afw_pool_t *p, afw_xctx_t *xctx)
595 {
596  afw_dateTime_t *dateTime;
597 
598  dateTime = afw_pool_calloc(p, sizeof(afw_dateTime_t), xctx);
599  afw_dateTime_set_now(NULL, dateTime, xctx);
600  return dateTime;
601 }
602 
603 
604 /* Get now time as time only in specified pool. */
605 AFW_DEFINE(const afw_time_t *)
607  const afw_pool_t *p, afw_xctx_t *xctx)
608 {
609  afw_time_t *time;
610 
611  time = afw_pool_calloc(p, sizeof(afw_time_t), xctx);
612  afw_time_set_now(NULL, time, xctx);
613  return time;
614 }
615 
616 
617 /* Get now local time as time only in specified pool. */
618 AFW_DEFINE(void)
619 afw_time_set_now_local(
620  afw_time_t *time, afw_xctx_t *xctx)
621 {
622  apr_status_t rv;
623  apr_time_exp_t tm;
624 
625  /* Explode now time. */
626  rv = apr_time_exp_lt(&tm, apr_time_now());
627  if (rv != APR_SUCCESS) {
628  AFW_THROW_ERROR_RV_Z(general, apr, rv, "apr_time_exp_gmt() failed",
629  xctx);
630  }
631 
632  /* Set time. */
633  impl_time_tm_set(time, &tm, xctx);
634 }
635 
636 
637 /* Get now local time as dateTime in specified pool. */
638 AFW_DEFINE(const afw_dateTime_t *)
640  const afw_pool_t *p, afw_xctx_t *xctx)
641 {
642  afw_dateTime_t *dateTime;
643 
644  dateTime = afw_pool_calloc(p, sizeof(afw_dateTime_t), xctx);
645  afw_dateTime_set_now(dateTime, NULL, xctx);
646  return dateTime;
647 }
648 
649 
650 /* Get now local time as time only in specified pool. */
651 AFW_DEFINE(const afw_time_t *)
653  const afw_pool_t *p, afw_xctx_t *xctx)
654 {
655  afw_time_t *time;
656 
657  time = afw_pool_calloc(p, sizeof(afw_time_t), xctx);
658  afw_time_set_now_local(time, xctx);
659  return time;
660 }
661 
662 
663 /* Convert time normalize to utc to microseconds. */
666  const afw_time_t *time, afw_xctx_t *xctx)
667 {
668  afw_integer_t result;
669 
670  result = AFW_TIME_HOURS_TO_MICROSECONDS(time->time.hour) +
671  AFW_TIME_MINUTES_TO_MICROSECONDS(time->time.minute) +
672  AFW_TIME_SECONDS_TO_MICROSECONDS(time->time.second) +
673  time->time.microsecond;
674 
675  if (time->time_zone.minutes != -1) {
676  result -= AFW_TIME_HOURS_TO_MICROSECONDS(time->time_zone.hours) +
677  AFW_TIME_MINUTES_TO_MICROSECONDS(time->time_zone.minutes);
678  }
679 
680  return result;
681 }
682 
683 
684 static afw_size_t
685 impl_set_internal_to_utf8_date(const afw_date_no_time_zone_t *date,
686  afw_utf8_octet_t *to, afw_xctx_t *xctx)
687 {
688  afw_utf8_octet_t *c;
689  int len;
690  afw_int32_t year;
691 
692  /* [-]yyyyyyyyyy-mm-dd. Year must be at least 4 digits. */
693  if (date->year <= 9999 && date->year >= -9999) {
694  c = to;
695  year = date->year;
696  if (date->year < 0) {
697  year = -year;
698  *c++ = '-';
699  }
700  *c++ = (char)(year / 1000) + '0';
701  *c++ = (char)((year % 1000) / 100) + '0';
702  *c++ = year % 100 / 10 + '0';
703  *c++ = year % 10 + '0';
704  }
705  else {
706  len = snprintf(to, IMPL_MAX_DATE_SEPARATE_LEN, "%d", date->year);
707  if (len < 0 || len >= IMPL_MAX_DATE_SEPARATE_LEN) {
708  AFW_THROW_ERROR_Z(general, "Internal error", xctx);
709  }
710  c = to + len;
711  }
712  *c++ = '-';
713  *c++ = date->month % 100 / 10 + '0';
714  *c++ = date->month % 10 + '0';
715  *c++ = '-';
716  *c++ = date->day % 100 / 10 + '0';
717  *c++ = date->day % 10 + '0';
718 
719  /* Return len of date. */
720  return (afw_size_t)(c - to);
721 }
722 
723 
724 static afw_size_t
725 impl_set_internal_to_utf8_time(
726  const afw_time_no_time_zone_t *time,
727  afw_utf8_octet_t *to, afw_xctx_t *xctx)
728 {
729  afw_utf8_octet_t *c;
730  apr_int32_t x;
731 
732  c = to;
733  *c++ = time->hour % 100 / 10 + '0';
734  *c++ = time->hour % 10 + '0';
735  *c++ = ':';
736  *c++ = time->minute % 100 / 10 + '0';
737  *c++ = time->minute % 10 + '0';
738  *c++ = ':';
739  *c++ = time->second % 100 / 10 + '0';
740  *c++ = time->second % 10 + '0';
741  do {
742  if (time->microsecond == 0) break;
743  *c++ = '.';
744  *c++ = time->microsecond % 1000000 / 100000 + '0';
745  x = time->microsecond % 100000;
746  if (x == 0) break;
747  *c++ = x / 10000 + '0';
748  x = time->microsecond % 10000;
749  if (x == 0) break;
750  *c++ = x / 1000 + '0';
751  x = time->microsecond % 1000;
752  if (x == 0) break;
753  *c++ = x / 100 + '0';
754  x = time->microsecond % 100;
755  if (x == 0) break;
756  *c++ = x / 10 + '0';
757  x = time->microsecond % 10;
758  if (x == 0) break;
759  *c++ = x + '0';
760  } while (0);
761 
762  /* Return len of time. */
763  return (afw_size_t)(c - to);
764 }
765 
766 
767 static afw_size_t
768 impl_set_internal_to_utf8_time_zone(
769  const afw_time_zone_t *tz,
770  afw_utf8_octet_t *to, afw_xctx_t *xctx)
771 {
772  afw_utf8_octet_t *c;
773  afw_int8_t hours;
774 
775  c = to;
776 
777  /* If minutes is negative, there is no time zone. */
778  if (tz->minutes < 0) return 0;
779 
780  /* If hours and minutes is 0, time zone is 'Z'. */
781  if (tz->hours == 0 && tz->minutes == 0) {
782  *to = 'Z';
783  return 1;
784  }
785 
786  /* Sign of time zone is sign of hours. */
787  if (tz->hours < 0) {
788  *c++ = '-';
789  hours = -tz->hours;
790  }
791  else {
792  *c++ = '+';
793  hours = tz->hours;
794  }
795 
796  /* hh:mm */
797  *c++ = hours % 100 / 10 + '0';
798  *c++ = hours % 10 + '0';
799  *c++ = ':';
800  *c++ = tz->minutes % 100 / 10 + '0';
801  *c++ = tz->minutes % 10 + '0';
802 
803  /* Return len of time zone. */
804  return (afw_size_t)(c - to);
805 }
806 
807 
808 static afw_size_t
809 impl_utf8_date_set_internal(
810  const afw_utf8_octet_t *from, afw_size_t len,
812 {
813  const afw_utf8_octet_t *s;
814  afw_boolean_t is_negative;
815 
816  /* Clear any sluff in result and initialize locals. */
817  memset(to, 0, sizeof(*to));
818  s = from;
819  is_negative = false;
820 
821  /* Error if not minimal size. */
822  if (len < sizeof("1-23-45") - 1) goto error;
823 
824  /* Can begin with a '-' (not '+' by specification) */
825  if (*s == '-') {
826  is_negative = true;
827  s++;
828  }
829 
830  /*
831  * Convert year.
832  *
833  * Note: This only throws an error if there is not at least one digit.
834  * This is intentional. The specification requires at least 4.
835  * to_utf8() will produce at least 4, but it seems ok to allow
836  * less than 4 on input.
837  */
838  if (*s < '0' || *s > '9') goto error;
839  for (; (afw_size_t)(s - from) < len; s++) {
840  if (*s < '0' || *s > '9') break;
841  to->year = to->year * 10 + (*s - '0');
842  if (to->year < 0) goto error;
843  }
844  if (is_negative) to->year = -to->year;
845 
846  /*
847  * A 0 year is an error.
848  *
849  * This error is commented out. 3.2.7 of XML Schema Part 2 says that
850  * 0000 is not allowed, but they intend to allow it. 0000 will represent
851  * year 1 BC.
852  *
853  * if (to->year == 0) goto error;
854  */
855 
856  /* If not enough left for month and day, it's an error. */
857  if (len - (s - from) < sizeof("-01-10") - 1) goto error;
858 
859  /* Next should be '-'. */
860  if (*s++ != '-') goto error;
861 
862  /* Next should be MM (01-12). */
863  if (*s != '0' && *s != '1') goto error;
864  to->month = (*s++ - '0') * 10;
865  if (*s < '0' || *s > '9') goto error;
866  to->month += (*s++ - '0');
867  if (to->month < 1 || to->month > 12) goto error;
868 
869  /* Next should be '-'. */
870  if (*s++ != '-') goto error;
871 
872  /* Next should be DD (01-12). */
873  if (*s < '0' || *s > '3') goto error;
874  to->day = (*s++ - '0') * 10;
875  if (*s < '0' || *s > '9') goto error;
876  to->day += (*s++ - '0');
877  if (to->day < 1) goto error;
878 
879  /* Check days in month. */
880  switch (to->month) {
881 
882  case 2: /* February */
883  if (to->day <= 28) break;
884  if (to->day > 29) goto error;
885  if (to->year % 4 != 0 || (to->year % 100 == 0 && to->year % 400 != 0))
886  goto error;
887  break;
888 
889  case 4: /* April */
890  case 6: /* June */
891  case 9: /* September */
892  case 11: /* November */
893  if (to->day > 30) goto error;
894  break;
895 
896  default: /* Other months. */
897  if (to->day > 31) goto error;
898  }
899 
900  /* Return length remaining. */
901  return len - (afw_size_t)(s - from);
902 
903 error:
904  AFW_THROW_ERROR_Z(general, "date invalid", xctx);
905 }
906 
907 static afw_size_t
908 impl_set_utf8_time_to_internal(
909  const afw_utf8_octet_t *from, afw_size_t len,
911 {
912  const afw_utf8_octet_t *s;
913  char d1, d2;
914 
915  memset(to, 0, sizeof(*to));
916  s = from;
917 
918  /* hh[:mm[:ss[.nnnnnn]]][Z | (+|-)hh:mm] */
919 
920  /* hh[[:mm]:ss] */
921  if (len < 2) goto error;
922  len -= 2;
923  IMPL_SAFE_DIGIT(*s++, d1, error);
924  IMPL_SAFE_DIGIT(*s++, d2, error);
925  to->hour = d1 * 10 + d2;
926  if (len < 3 || *s == '+' || *s == '-' || *s == 'Z') goto finish_up;
927  if (*s++ != ':') goto error;
928  IMPL_SAFE_DIGIT(*s++, d1, error);
929  IMPL_SAFE_DIGIT(*s++, d2, error);
930  len -= 3;
931  to->minute = d1 * 10 + d2;
932  if (len < 3 || *s == '+' || *s == '-' || *s == 'Z') goto finish_up;
933  if (*s++ != ':') goto error;
934  IMPL_SAFE_DIGIT(*s++, d1, error);
935  IMPL_SAFE_DIGIT(*s++, d2, error);
936  len -= 3;
937  to->second = d1 * 10 + d2;
938  if (len <= 0) goto finish_up;
939 
940  /* Optional [.nnnnnn] */
941  if (*s == '.') do {
942  s++; len--;
943  if (len <= 0 || !IMPL_IS_DIGIT(*s)) goto error;
944  len--;
945  to->microsecond = (*s++ - '0') * 100000;
946  if (len <= 0 || !IMPL_IS_DIGIT(*s)) break;
947  len--;
948  to->microsecond += (*s++ - '0') * 10000;
949  if (len <= 0 || !IMPL_IS_DIGIT(*s)) break;
950  len--;
951  to->microsecond += (*s++ - '0') * 1000;
952  if (len <= 0 || !IMPL_IS_DIGIT(*s)) break;
953  len--;
954  to->microsecond += (*s++ - '0') * 100;
955  if (len <= 0 || !IMPL_IS_DIGIT(*s)) break;
956  len--;
957  to->microsecond += (*s++ - '0') * 10;
958  if (len <= 0 || !IMPL_IS_DIGIT(*s)) break;
959  len--;
960  to->microsecond += (*s++ - '0');
961  } while (0);
962 
963  /* Return length used. */
964 finish_up:
965 
966  /* Handle special case of 24:00:00. */
967  if (to->hour == 24) {
968  if (to->minute != 0 || to->second != 0 || to->microsecond != 0) {
969  goto error;
970  }
971  }
972 
973  /* If not hour 24, make sure rest of time is within bounds. */
974  else if (to->hour > 24 || to->minute >= 60 || to->second >= 60) {
975  goto error;
976  }
977 
978  /* Return length remaining. */
979  return len;
980 
981 error:
982  AFW_THROW_ERROR_Z(general, "time invalid", xctx);
983 }
984 
985 
986 static afw_size_t
987 impl_set_utf8_time_zone_to_internal(
988  const afw_utf8_octet_t *from, afw_size_t len,
989  afw_time_zone_t *to, afw_xctx_t *xctx)
990 {
991  const afw_utf8_octet_t *s;
992  char d1, d2;
993  afw_boolean_t negative;
994 
995  negative = false;
996  to->hours = 0;
997  to->minutes = -1; /* Assume on time zone */
998  s = from;
999 
1000  /* If len is 0, just return. */
1001  if (len <= 0) return len;
1002 
1003  /* Optional [Z | (+|-)hh:mm] */
1004  if (*s == 'Z') {
1005  if (len != 1) goto error;
1006  to->minutes = 0;
1007  return len - 1;
1008  }
1009  if (len < 3) goto finish_up;
1010  if (*s == '+') negative = false;
1011  else if (*s == '-') negative = true;
1012  else goto finish_up;
1013  s++;
1014  IMPL_SAFE_DIGIT(*s++, d1, error);
1015  IMPL_SAFE_DIGIT(*s++, d2, error);
1016  len -= 3;
1017  to->hours = d1 * 10 + d2;
1018  if (*s != ':') goto finish_up;
1019  s++;
1020  if (len < 3) goto error;
1021  IMPL_SAFE_DIGIT(*s++, d1, error);
1022  IMPL_SAFE_DIGIT(*s++, d2, error);
1023  len -= 3;
1024  to->minutes = d1 * 10 + d2;
1025 
1026  /* Check result and return length remaining. */
1027 finish_up:
1028  if (to->hours > 14 || to->minutes > 59 ||
1029  (to->hours == 14 && to->minutes != 0))
1030  {
1031  goto error;
1032  }
1033  if (negative) to->hours = -to->hours;
1034  return len;
1035 
1036 error:
1037  AFW_THROW_ERROR_Z(general, "time zone invalid. "
1038  "(('+' | '-') hh ':' mm) | 'Z'. "
1039  "hh 00-14, mm 00-59 or 00 if hh is 14", xctx);
1040 }
1041 
1042 
1043 /* Convert internal date to utf8 xml schema date in specified pool. */
1044 AFW_DEFINE(const afw_utf8_t *)
1046  const afw_date_t *date, const afw_pool_t *p, afw_xctx_t *xctx)
1047 {
1048  afw_utf8_octet_t to[IMPL_MAX_DATE_LEN];
1049  afw_size_t len;
1050 
1051  len = impl_set_internal_to_utf8_date(&date->date, &to[0], xctx);
1052  len += impl_set_internal_to_utf8_time_zone(&date->time_zone, &to[len],
1053  xctx);
1054 
1055  return afw_utf8_create_copy(&to[0], len, p, xctx);
1056 }
1057 
1058 
1059 /* Convert utf8 xml schema date to internal and set. */
1060 AFW_DEFINE(void)
1062  const afw_utf8_t *utf8, afw_date_t *internal, afw_xctx_t *xctx)
1063 {
1064  afw_size_t len;
1065  const afw_utf8_octet_t *s;
1066 
1067  s = utf8->s;
1068  len = utf8->len;
1069  len = impl_utf8_date_set_internal(s, len, &internal->date, xctx);
1070  s += utf8->len - len;
1071  len = impl_set_utf8_time_zone_to_internal(s, len, &internal->time_zone,
1072  xctx);
1073  if (len != 0) {
1074  AFW_THROW_ERROR_Z(general, "date invalid", xctx);
1075  }
1076 }
1077 
1078 
1079 /* Convert internal dateTime to utf8 xml schema dateTime in specified pool. */
1080 AFW_DEFINE(const afw_utf8_t *)
1082  const afw_dateTime_t *dateTime, const afw_pool_t *p, afw_xctx_t *xctx)
1083 {
1084  afw_utf8_octet_t to[IMPL_MAX_DATE_TIME_LEN];
1085  afw_size_t len;
1086 
1087  len = impl_set_internal_to_utf8_date(&dateTime->date, &to[0], xctx);
1088  to[len++] = 'T';
1089  len += impl_set_internal_to_utf8_time(&dateTime->time, &to[len], xctx);
1090  len += impl_set_internal_to_utf8_time_zone(&dateTime->time_zone, &to[len],
1091  xctx);
1092 
1093  return afw_utf8_create_copy(&to[0], len, p, xctx);
1094 }
1095 
1096 
1097 /* Convert utf8 xml schema dateTime to internal and set. */
1098 AFW_DEFINE(void)
1100  const afw_utf8_t *utf8, afw_dateTime_t *internal, afw_xctx_t *xctx)
1101 {
1102  afw_size_t len, prev;
1103  const afw_utf8_octet_t *s;
1104 
1105  s = utf8->s;
1106  len = utf8->len;
1107  len = impl_utf8_date_set_internal(s, len, &internal->date, xctx);
1108  s += utf8->len - len;
1109  if (len-- < 1 || *s++ != 'T') goto error;
1110  prev = len;
1111  len = impl_set_utf8_time_to_internal(s, len, &internal->time, xctx);
1112  s += prev - len;
1113  len = impl_set_utf8_time_zone_to_internal(s, len, &internal->time_zone,
1114  xctx);
1115  if (len != 0) goto error;
1116 
1117  return;
1118 
1119 error:
1120  AFW_THROW_ERROR_Z(general, "dateTime invalid", xctx);
1121 }
1122 
1123 
1124 /* Convert internal dayTimeDuration to utf8 xml schema dayTimeDuration. */
1125 AFW_DEFINE(const afw_utf8_t *)
1127  const afw_dayTimeDuration_t *dayTimeDuration,
1128  const afw_pool_t *p, afw_xctx_t *xctx)
1129 {
1130  afw_utf8_octet_t wa[
1131  sizeof("-P2147483648DT2147483648H2147483648M2147483648.999999S") - 1];
1132  afw_utf8_octet_t *s, *c, *end;
1133  afw_int32_t x;
1134  afw_integer_t days, hours, minutes, seconds, microseconds;
1135 
1136  /* Initialize locals. */
1137  c = s = &wa[0];
1138  end = &wa[sizeof(wa)];
1139 
1140  /* If negative duration, start with '-' and use negative of all members. */
1141  if (dayTimeDuration->days < 0 ||
1142  dayTimeDuration->hours < 0 ||
1143  dayTimeDuration->minutes < 0 ||
1144  dayTimeDuration->seconds < 0 ||
1145  dayTimeDuration->microseconds < 0)
1146  {
1147  days = -dayTimeDuration->days;
1148  hours = -dayTimeDuration->hours;
1149  minutes = -dayTimeDuration->minutes;
1150  seconds = -dayTimeDuration->seconds;
1151  microseconds = -dayTimeDuration->microseconds;
1152  *c++ = '-';
1153  }
1154 
1155  /* If positive duration, use members asis. */
1156  else {
1157  days = dayTimeDuration->days;
1158  hours = dayTimeDuration->hours;
1159  minutes = dayTimeDuration->minutes;
1160  seconds = dayTimeDuration->seconds;
1161  microseconds = dayTimeDuration->microseconds;
1162  }
1163 
1164  /* Next is always 'P'. */
1165  *c++ = 'P';
1166 
1167  /* If hours, put number of hours followed by 'H'. */
1168  if (days != 0) {
1169  c += afw_number_integer_set_u8(days, c, end - c,
1170  xctx);
1171  *c++ = 'D';
1172  }
1173 
1174  /* Time portion required a 'T' */
1175  if (hours != 0 || minutes != 0 || seconds != 0 || microseconds != 0) {
1176  *c++ = 'T';
1177  }
1178 
1179  /* If hours, put number of hours followed by 'H'. */
1180  if (hours != 0) {
1181  c += afw_number_integer_set_u8(hours, c, end - c,
1182  xctx);
1183  *c++ = 'H';
1184  }
1185 
1186  /* If minutes, put number of minutes followed by 'H'. */
1187  if (minutes != 0) {
1188  c += afw_number_integer_set_u8(minutes, c, end - c,
1189  xctx);
1190  *c++ = 'M';
1191  }
1192 
1193  /*
1194  * If seconds or microseconds, put number of seconds, followed by
1195  * fractional seconds if there are microseconds, ending by 'S'.
1196  */
1197  if (seconds != 0 || microseconds != 0) {
1198  if (seconds == 0) {
1199  *c++ = '0';
1200  }
1201  else {
1202  c += afw_number_integer_set_u8(seconds,
1203  c, end - c, xctx);
1204  }
1205  if (microseconds != 0) do {
1206  *c++ = '.';
1207  *c++ = (afw_utf8_octet_t)(microseconds % 1000000 / 100000 + '0');
1208  x = microseconds % 100000;
1209  if (x == 0) break;
1210  *c++ = (afw_utf8_octet_t)(x / 10000 + '0');
1211  x = microseconds % 10000;
1212  if (x == 0) break;
1213  *c++ = (afw_utf8_octet_t)(x / 1000 + '0');
1214  x = microseconds % 1000;
1215  if (x == 0) break;
1216  *c++ = (afw_utf8_octet_t)(x / 100 + '0');
1217  x = microseconds % 100;
1218  if (x == 0) break;
1219  *c++ = (afw_utf8_octet_t)(x / 10 + '0');
1220  x = microseconds % 10;
1221  if (x == 0) break;
1222  *c++ = x + '0';
1223  } while (0);
1224  *c++ = 'S';
1225  }
1226 
1227  /* Return result. */
1228  return afw_utf8_create_copy(s, c - s, p, xctx);
1229 }
1230 
1231 
1232 /* Convert utf8 xml schema dayTimeDuration to internal and set. */
1233 AFW_DEFINE(void)
1235  const afw_utf8_t *utf8, afw_dayTimeDuration_t *internal,
1236  afw_xctx_t *xctx)
1237 {
1238  afw_size_t len, x;
1239  const afw_utf8_octet_t *s;
1240  afw_integer_t i;
1241  afw_boolean_t is_negative;
1242  afw_boolean_t t_encountered;
1243 
1244  s = utf8->s;
1245  len = utf8->len;
1246  memset(internal, 0, sizeof(*internal));
1247 
1248  /* Can start with '-'. */
1249  if (len < 1) goto error;
1250  is_negative = false;
1251  if (*s == '-') {
1252  is_negative = true;
1253  s++;
1254  len--;
1255  }
1256 
1257  /* Next must be 'P'. */
1258  if (*s++ != 'P') goto error;
1259  len--;
1260 
1261  t_encountered = false;
1262  /* Next can be 'T'. */
1263  if (*s == 'T') {
1264  t_encountered = true;
1265  len--;
1266  s++;
1267  };
1268 
1269  /* Next must be a non-negative number. */
1270  x = afw_number_parse_integer(s, len, &i, xctx->p, xctx);
1271  if (i < 0) goto error;
1272  s += x;
1273  len -= x;
1274  if (len < 1) goto error;
1275 
1276  /* Next can be 'D'. */
1277  if (*s == 'D') {
1278  if (t_encountered) goto error;
1279  if (i > AFW_INT32_MAX) goto error;
1280  internal->days = (afw_int32_t)((is_negative) ? -i : i);
1281  s++;
1282  if (--len <= 0) goto finished;
1283  }
1284 
1285  /* 'T' required before time part. This is the time separator */
1286  if (!t_encountered) {
1287  if (*s++ != 'T') goto error;
1288  len--;
1289  if (len < 1) goto error;
1290  x = afw_number_parse_integer(s, len, &i, xctx->p, xctx);
1291  if (i < 0) goto error;
1292  s += x;
1293  len -= x;
1294  if (len < 1) goto error;
1295  };
1296 
1297  /* Next can be 'H'. */
1298  if (*s == 'H') {
1299  if (i > AFW_INT32_MAX) goto error;
1300  internal->hours = (afw_int32_t)((is_negative) ? -i : i);
1301  s++;
1302  if (--len <= 0) goto finished;
1303  x = afw_number_parse_integer(s, len, &i, xctx->p, xctx);
1304  if (i < 0) goto error;
1305  s += x;
1306  len -= x;
1307  if (len < 1) goto error;
1308  }
1309 
1310  /* Next can be 'M'. */
1311  if (*s == 'M') {
1312  if (i > AFW_UINT32_MAX) goto error;
1313  internal->minutes = (afw_int32_t)((is_negative) ? -i : i);
1314  s++;
1315  if (--len <= 0) goto finished;
1316  x = afw_number_parse_integer(s, len, &i, xctx->p, xctx);
1317  if (i < 0) goto error;
1318  s += x;
1319  len -= x;
1320  if (len < 1) goto error;
1321  }
1322 
1323  /* Must be seconds at this point. Will check for 'S' later. */
1324  if (i > AFW_UINT32_MAX) goto error;
1325  internal->seconds = (afw_int32_t)((is_negative) ? -i : i);
1326 
1327  /* Next can be '.' followed by microseconds. */
1328  if (*s == '.') {
1329  do {
1330  s++; len--;
1331  if (len <= 0 || !IMPL_IS_DIGIT(*s)) goto error;
1332  len--;
1333  internal->microseconds = (*s++ - '0') * 100000;
1334  if (len <= 0 || !IMPL_IS_DIGIT(*s)) break;
1335  len--;
1336  internal->microseconds += (*s++ - '0') * 10000;
1337  if (len <= 0 || !IMPL_IS_DIGIT(*s)) break;
1338  len--;
1339  internal->microseconds += (*s++ - '0') * 1000;
1340  if (len <= 0 || !IMPL_IS_DIGIT(*s)) break;
1341  len--;
1342  internal->microseconds += (*s++ - '0') * 100;
1343  if (len <= 0 || !IMPL_IS_DIGIT(*s)) break;
1344  len--;
1345  internal->microseconds += (*s++ - '0') * 10;
1346  if (len <= 0 || !IMPL_IS_DIGIT(*s)) break;
1347  len--;
1348  internal->microseconds += (*s++ - '0');
1349  } while (0);
1350  if (is_negative) {
1351  internal->microseconds = -internal->microseconds;
1352  }
1353  }
1354 
1355  /* At this point, last char must be 'S'. */
1356  if (len != 1 || *s != 'S') goto error;
1357 
1358 finished:
1359  /* Return */
1360  return;
1361 
1362 error:
1363  AFW_THROW_ERROR_Z(general, "dayTimeDuration invalid", xctx);
1364 }
1365 
1366 
1367 /* Convert internal time to utf8 xml schema time in specified pool. */
1368 AFW_DEFINE(const afw_utf8_t *)
1370  const afw_time_t *time, const afw_pool_t *p, afw_xctx_t *xctx)
1371 {
1372  afw_utf8_octet_t to[IMPL_MAX_TIME_LEN];
1373  afw_size_t len;
1374 
1375  len = impl_set_internal_to_utf8_time(&time->time, &to[0], xctx);
1376  len += impl_set_internal_to_utf8_time_zone(&time->time_zone, &to[len],
1377  xctx);
1378 
1379  return afw_utf8_create_copy(&to[0], len, p, xctx);
1380 }
1381 
1382 
1383 /* Convert utf8 xml schema dateTime to internal and set. */
1384 AFW_DEFINE(void)
1386  const afw_utf8_t *utf8, afw_time_t *internal, afw_xctx_t *xctx)
1387 {
1388  afw_size_t len;
1389  const afw_utf8_octet_t *s;
1390 
1391  s = utf8->s;
1392  len = utf8->len;
1393  len = impl_set_utf8_time_to_internal(s, len, &internal->time, xctx);
1394  s += utf8->len - len;
1395  len = impl_set_utf8_time_zone_to_internal(s, len, &internal->time_zone,
1396  xctx);
1397  if (len != 0) {
1398  AFW_THROW_ERROR_Z(general, "Time invalid", xctx);
1399  }
1400 }
1401 
1402 /*
1403  * Convert internal yearMonthDuration to utf8 xml schema yearMonthDuration in
1404  * specified pool.
1405  */
1406 AFW_DEFINE(const afw_utf8_t *)
1408  const afw_yearMonthDuration_t *yearMonthDuration,
1409  const afw_pool_t *p, afw_xctx_t *xctx)
1410 {
1411  afw_utf8_octet_t wa[sizeof("-P4294967295Y65535M") - 1];
1412  afw_utf8_octet_t *s, *c, *end;
1413  afw_integer_t years, months;
1414 
1415  /* Initialize locals. */
1416  c = s = &wa[0];
1417  end = &wa[sizeof(wa)];
1418 
1419  /* If negative duration, start with '-' and use negative of all members. */
1420  if (yearMonthDuration->years < 0 ||
1421  yearMonthDuration->months < 0)
1422  {
1423  years = -yearMonthDuration->years;
1424  months = -yearMonthDuration->months;
1425  *c++ = '-';
1426  }
1427 
1428  /* If positive duration, use members asis. */
1429  else {
1430  years = yearMonthDuration->years;
1431  months = yearMonthDuration->months;
1432  }
1433 
1434  /* Next is always 'P'. */
1435  *c++ = 'P';
1436 
1437  /* If years, put number of years followed by 'Y'. */
1438  if (years != 0) {
1439  c += afw_number_integer_set_u8(years, c, end - c,
1440  xctx);
1441  *c++ = 'Y';
1442  }
1443 
1444  /* If months, put number of months followed by 'M'. */
1445  if (months != 0) {
1446  c += afw_number_integer_set_u8(months, c, end - c,
1447  xctx);
1448  *c++ = 'M';
1449  }
1450 
1451  /* Return result. */
1452  return afw_utf8_create_copy(s, c - s, p, xctx);
1453 }
1454 
1455 
1456 /* Convert utf8 xml schema yearMonthDuration to internal and set. */
1457 AFW_DEFINE(void)
1459  const afw_utf8_t *utf8, afw_yearMonthDuration_t *internal,
1460  afw_xctx_t *xctx)
1461 {
1462  afw_size_t len, x;
1463  const afw_utf8_octet_t *s;
1464  afw_integer_t i;
1465  afw_boolean_t is_negative;
1466 
1467  s = utf8->s;
1468  len = utf8->len;
1469  memset(internal, 0, sizeof(*internal));
1470 
1471  /* Can start with '-'. */
1472  if (len < 1) goto error;
1473  is_negative = false;
1474  if (*s == '-') {
1475  is_negative = true;
1476  s++;
1477  len--;
1478  }
1479 
1480  /* Next must be 'P'. */
1481  if (*s++ != 'P') goto error;
1482  len--;
1483 
1484  /* Next must be a non-negative number. */
1485  x = afw_number_parse_integer(s, len, &i, xctx->p, xctx);
1486  if (i < 0) goto error;
1487  s += x;
1488  len -= x;
1489  if (len < 1) goto error;
1490 
1491  /* Next can be 'Y'. */
1492  if (*s == 'Y') {
1493  if (i > AFW_INT32_MAX) goto error;
1494  internal->years = (afw_int32_t)((is_negative) ? -i : i);
1495  s++;
1496  if (--len <= 0) goto finished;
1497  x = afw_number_parse_integer(s, len, &i, xctx->p, xctx);
1498  if (i < 0) goto error;
1499  s += x;
1500  len -= x;
1501  }
1502 
1503  /* At this point, last char must be 'M'. */
1504  if (len != 1 || *s != 'M' || i > AFW_INT32_MAX) goto error;
1505  internal->months = (afw_int32_t)((is_negative) ? -i : i);
1506 
1507 finished:
1508  /* Return */
1509  return;
1510 
1511 error:
1512  AFW_THROW_ERROR_Z(general, "yearMonthDuration invalid", xctx);
1513 }
1514 
1515 
1516 AFW_DEFINE(int)
1518  afw_xctx_t *xctx)
1519 {
1520  afw_integer_t result;
1521 
1522  if (v1->time_zone.hours != v2->time_zone.hours ||
1523  v1->time_zone.minutes != v2->time_zone.minutes) {
1524  AFW_THROW_ERROR_Z(general,
1525  "Can't compare dates with different time zone values",
1526  xctx);
1527  }
1528  result = v1->date.year - v2->date.year;
1529  if (result != 0) goto finished;
1530  result = v1->date.month - v2->date.month;
1531  if (result != 0) goto finished;
1532  result = v1->date.day - v2->date.day;
1533 
1534 finished:
1535  return (result == 0) ? 0 : (result > 0) ? 1 : -1;
1536 }
1537 
1538 
1539 AFW_DEFINE(int)
1541  afw_xctx_t *xctx)
1542 {
1543  afw_integer_t result;
1544  afw_integer_t v1hour, v2hour, v1minute, v2minute;
1545 
1546  /* if only one value has a time zone then cannot compare */
1547  if ((v1->time_zone.minutes == -1 && v2->time_zone.minutes != -1) ||
1548  (v1->time_zone.minutes != -1 && v2->time_zone.minutes == -1))
1549  {
1550  AFW_THROW_ERROR_Z(general,
1551  "Can't compare dateTimes with only one value time zone",
1552  xctx);
1553  }
1554 
1555 
1556  result = v1->date.year - v2->date.year;
1557  if (result != 0) goto finished;
1558  result = v1->date.month - v2->date.month;
1559  if (result != 0) goto finished;
1560  result = v1->date.day - v2->date.day;
1561  if (result != 0) goto finished;
1562  /* if different time zones, normalize the two times */
1563  if (v1->time_zone.hours != v2->time_zone.hours ||
1564  v1->time_zone.minutes != v2->time_zone.minutes) {
1565  v1hour = v1->time.hour - v1->time_zone.hours;
1566  v2hour = v2->time.hour - v2->time_zone.hours;
1567  v1minute = v1->time.minute - v1->time_zone.minutes;
1568  v2minute = v2->time.minute - v2->time_zone.minutes;
1569  result = v1hour - v2hour;
1570  if (result != 0) goto finished;
1571  result = v1minute - v2minute;
1572  if (result != 0) goto finished;
1573  }
1574  else {
1575  result = (afw_integer_t)v1->time.hour - (afw_integer_t)v2->time.hour;
1576  if (result != 0) goto finished;
1577  result = (afw_integer_t)v1->time.minute - (afw_integer_t)v2->time.minute;
1578  if (result != 0) goto finished;
1579  }
1580  result = (afw_integer_t)v1->time.second - (afw_integer_t)v2->time.second;
1581  if (result != 0) goto finished;
1582  result = (afw_integer_t)v1->time.microsecond - (afw_integer_t)v2->time.microsecond;
1583 
1584 finished:
1585  return (result == 0) ? 0 : (result > 0) ? 1 : -1;
1586 }
1587 
1588 
1589 AFW_DEFINE(int)
1591  afw_xctx_t *xctx)
1592 {
1593  afw_integer_t result;
1594  afw_integer_t v1hour, v2hour, v1minute, v2minute;
1595 
1596  /* if only one value has a time zone then cannot compare */
1597  if ((v1->time_zone.minutes == -1 && v2->time_zone.minutes != -1)||
1598  (v1->time_zone.minutes != -1 && v2->time_zone.minutes == -1))
1599  {
1600  AFW_THROW_ERROR_Z(general,
1601  "Can't compare times with only one value time zone",
1602  xctx);
1603  }
1604 
1605  /* if different time zones, normalize the two times */
1606  if (v1->time_zone.hours != v2->time_zone.hours ||
1607  v1->time_zone.minutes != v2->time_zone.minutes) {
1608  v1hour = v1->time.hour + v1->time_zone.hours;
1609  v2hour = v2->time.hour + v2->time_zone.hours;
1610  v1minute = v1->time.minute + v1->time_zone.minutes;
1611  v2minute = v2->time.minute + v2->time_zone.minutes;
1612  result = v1hour - v2hour;
1613  if (result != 0) goto finished;
1614  result = v1minute - v2minute;
1615  if (result != 0) goto finished;
1616  }
1617  else {
1618  result = (afw_integer_t)v1->time.hour - (afw_integer_t)v2->time.hour;
1619  if (result != 0) goto finished;
1620  result = (afw_integer_t)v1->time.minute - (afw_integer_t)v2->time.minute;
1621  if (result != 0) goto finished;
1622  }
1623 
1624  result = (afw_integer_t)v1->time.second - (afw_integer_t)v2->time.second;
1625  if (result != 0) goto finished;
1626  result = (afw_integer_t)v1->time.microsecond - (afw_integer_t)v2->time.microsecond;
1627 
1628 finished:
1629  return (result == 0) ? 0 : (result > 0) ? 1 : -1;
1630 }
1631 
1632 
1633 AFW_DEFINE_STATIC_INLINE(afw_integer_t)
1634 impl_fQuotient2(afw_integer_t a, unsigned int b)
1635 {
1636  afw_integer_t result;
1637 
1638  if (a < 0) {
1639  result = (a - (afw_integer_t)b) / b;
1640  }
1641  else {
1642  result = a / b;
1643  }
1644 
1645  return result;
1646 }
1647 
1648 
1649 AFW_DEFINE_STATIC_INLINE(afw_integer_t)
1650 impl_modulo2(afw_integer_t a, unsigned int b)
1651 {
1652  return a - impl_fQuotient2(a, b) * b;
1653 }
1654 
1655 
1656 AFW_DEFINE_STATIC_INLINE(afw_integer_t)
1657 impl_fQuotient3(afw_integer_t a, int low, int high)
1658 {
1659  return impl_fQuotient2((a - low), (high - low));
1660 }
1661 
1662 
1663 AFW_DEFINE_STATIC_INLINE(afw_integer_t)
1664 impl_modulo3(afw_integer_t a, int low, int high)
1665 {
1666  return impl_modulo2((a - low), (high - low)) + low;
1667 }
1668 
1669 
1670 AFW_DEFINE(int)
1672 {
1673  afw_integer_t m;
1674 
1675  m = impl_modulo3(month, 1, 13);
1676 
1677  switch (m) {
1678 
1679  case 2:
1680  if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
1681  return 29;
1682  }
1683  return 28;
1684 
1685  case 4:
1686  case 6:
1687  case 9:
1688  case 11:
1689  return 30;
1690 
1691  default:
1692  return 31;
1693  }
1694 }
1695 
1696 
1697 static void
1698 impl_normalize_dayTimeDuration(
1699  const afw_dayTimeDuration_t *from,
1701  afw_xctx_t *xctx)
1702 {
1703  memset(to, 0, sizeof(*to));
1704  afw_integer_t days, minutes, hours;
1705 
1706  to->seconds = from->seconds % 60;
1707 
1708  minutes = from->minutes + (from->seconds / 60);
1709  to->minutes = minutes % 60;
1710 
1711  hours = from->hours + (minutes / 60);
1712  if (hours < AFW_INT32_MIN || hours > AFW_INT32_MAX) {
1713  AFW_THROW_ERROR_Z(general,
1714  "dayTimeDuration limit exceeded", xctx);
1715  }
1716  to->hours = (afw_int32_t)hours;
1717 
1718  days = from->days + (hours / 24);
1719  if (days < AFW_INT32_MIN || days > AFW_INT32_MAX) {
1720  AFW_THROW_ERROR_Z(general,
1721  "dayTimeDuration limit exceeded", xctx);
1722  }
1723  to->days = (afw_int32_t)days;
1724 
1725 }
1726 
1727 
1728 static void
1729 impl_normalize_yearMonthDuration(
1730  const afw_yearMonthDuration_t *from,
1732  afw_xctx_t *xctx)
1733 {
1734  afw_integer_t years;
1735 
1736  memset(to, 0, sizeof(*to));
1737 
1738  to->months = (afw_int32_t)impl_modulo3(from->months, 1, 13);
1739 
1740  years = from->years + impl_fQuotient3(from->months, 1, 13);
1741  if (years < AFW_INT32_MIN || years > AFW_INT32_MAX) {
1742  AFW_THROW_ERROR_Z(general,
1743  "yearMonthDuration limit exceeded", xctx);
1744  }
1745  to->years = (afw_int32_t)years;
1746 }
1747 
1748 
1749 /* Compare two dateTime values. */
1750 AFW_DEFINE(int)
1752  const afw_dayTimeDuration_t *v1,
1753  const afw_dayTimeDuration_t *v2, afw_xctx_t *xctx)
1754 {
1755  afw_dayTimeDuration_t n1, n2;
1756 
1757  impl_normalize_dayTimeDuration(v1, &n1, xctx);
1758  impl_normalize_dayTimeDuration(v2, &n2, xctx);
1759 
1760  /* Return results. */
1761  if (n1.days != n2.days) return (n1.days > n2.days) ? 1 : -1;
1762  if (n1.hours != n2.hours) return (n1.hours > n2.hours) ? 1 : -1;
1763  if (n1.minutes != n2.minutes) return (n1.minutes > n2.minutes) ? 1 : -1;
1764  if (n1.seconds != n2.seconds) return (n1.seconds > n2.seconds) ? 1 : -1;
1765  if (n1.microseconds != n2.microseconds)
1766  return (n1.microseconds > n2.microseconds) ? 1 : -1;
1767  return 0;
1768 }
1769 
1770 
1771 /* Compare two yearMonthDuration values. */
1772 AFW_DEFINE(int)
1774  const afw_yearMonthDuration_t *v1,
1775  const afw_yearMonthDuration_t *v2, afw_xctx_t *xctx)
1776 {
1777  afw_yearMonthDuration_t n1, n2;
1778 
1779  impl_normalize_yearMonthDuration(v1, &n1, xctx);
1780  impl_normalize_yearMonthDuration(v2, &n2, xctx);
1781 
1782  /* Return results. */
1783  if (n1.years != n2.years) return (n1.years > n2.years) ? 1 : -1;
1784  if (n1.months != n2.months) return (n1.months > n2.months) ? 1 : -1;
1785  return 0;
1786 }
1787 
1788 
1789 /* Add dayTimeDuration to date. */
1790 AFW_DEFINE(void)
1792  afw_date_t *date,
1793  const afw_yearMonthDuration_t *yearMonthDuration,
1794  afw_xctx_t *xctx)
1795 {
1796  afw_integer_t year, month;
1797  int days_in_month;
1798 
1799  year = date->date.year + yearMonthDuration->years;
1800  month = date->date.month + yearMonthDuration->months;
1801 
1802  year += impl_fQuotient3(month, 1, 13);
1803  month = impl_modulo3(month, 1, 13);
1804 
1805  if (year < AFW_INT32_MIN || year > AFW_INT32_MAX) {
1806  AFW_THROW_ERROR_Z(general,
1807  "year limit exceeded", xctx);
1808  }
1809 
1810  date->date.year = (afw_int32_t)year;
1811  date->date.month = (afw_int8_t)month;
1812  days_in_month = afw_date_maximum_days_in_month(year, month);
1813  if (date->date.day > days_in_month) {
1814  date->date.day = (afw_int8_t)days_in_month;
1815  }
1816 }
1817 
1818 
1819 /* Subtract yearMonthDuration from date. */
1820 AFW_DEFINE(void)
1822  afw_date_t *date,
1823  const afw_yearMonthDuration_t *yearMonthDuration,
1824  afw_xctx_t *xctx)
1825 {
1826  afw_integer_t year, month;
1827  int days_in_month;
1828 
1829  year = date->date.year - yearMonthDuration->years;
1830  month = date->date.month - yearMonthDuration->months;
1831 
1832  year += impl_fQuotient3(month, 1, 13);
1833  month = impl_modulo3(month, 1, 13);
1834 
1835  if (year < AFW_INT32_MIN || year > AFW_INT32_MAX) {
1836  AFW_THROW_ERROR_Z(general,
1837  "year limit exceeded", xctx);
1838  }
1839 
1840  date->date.year = (afw_int32_t)year;
1841  date->date.month = (afw_int8_t)month;
1842  days_in_month = afw_date_maximum_days_in_month(year, month);
1843  if (date->date.day > days_in_month) {
1844  date->date.day = (afw_int8_t)days_in_month;
1845  }
1846 }
1847 
1848 
1849 /* Add dayTimeDuration to dateTime. */
1850 AFW_DEFINE(void)
1852  afw_dateTime_t *dateTime,
1853  const afw_dayTimeDuration_t *dayTimeDuration,
1854  afw_xctx_t *xctx)
1855 {
1856  afw_integer_t year, month, day, temp, carry;
1857  int dim;
1858 
1859  year = dateTime->date.year;
1860  month = dateTime->date.month;
1861 
1862  temp = dateTime->time.microsecond + dayTimeDuration->microseconds;
1863  dateTime->time.microsecond = (afw_uint32_t)impl_modulo2(temp, 1000000);
1864  carry = impl_fQuotient2(temp, 1000000);
1865 
1866  temp = dateTime->time.second + dayTimeDuration->seconds + carry;
1867  dateTime->time.second = (afw_uint8_t)impl_modulo2(temp, 60);
1868  carry = impl_fQuotient2(temp, 60);
1869 
1870  temp = dateTime->time.minute + dayTimeDuration->minutes + carry;
1871  dateTime->time.minute = (afw_uint8_t)impl_modulo2(temp, 60);
1872  carry = impl_fQuotient2(temp, 60);
1873 
1874  temp = dateTime->time.hour + dayTimeDuration->hours + carry;
1875  dateTime->time.hour = (afw_uint8_t)impl_modulo2(temp, 24);
1876  carry = impl_fQuotient2(temp, 24);
1877 
1878  dim = afw_date_maximum_days_in_month(year, month);
1879  day = dateTime->date.day;
1880  if (day > dim) {
1881  day = dim;
1882  }
1883  else if (dateTime->date.day < 1) {
1884  day = 1;
1885  }
1886  day += dayTimeDuration->days + carry;
1887 
1888  for (;;) {
1889  if (day < 1) {
1890  day += afw_date_maximum_days_in_month(year, month - 1);
1891  carry = -1;
1892  }
1893  else {
1894  dim = afw_date_maximum_days_in_month(year, month);
1895  if (day <= dim) break;
1896  day -= dim;
1897  carry = 1;
1898  }
1899  temp = month + carry;
1900  month = impl_modulo3(temp, 1, 13);
1901  year += impl_fQuotient3(temp, 1, 13);
1902  }
1903 
1904  dateTime->date.day = (afw_uint8_t)day;
1905  dateTime->date.month = (afw_uint8_t)month;
1906  if (year > AFW_INT32_MAX || year < AFW_INT32_MIN) {
1907  AFW_THROW_ERROR_Z(general, "Year limit exceeded", xctx);
1908  }
1909  dateTime->date.year = (afw_int32_t)year;
1910 }
1911 
1912 
1913 /* Subtract dayTimeDuration from dateTime. */
1914 AFW_DEFINE(void)
1916  afw_dateTime_t *dateTime,
1917  const afw_dayTimeDuration_t *dayTimeDuration,
1918  afw_xctx_t *xctx)
1919 {
1920  afw_integer_t year, month, day, temp, carry;
1921  int dim;
1922 
1923  year = dateTime->date.year;
1924  month = dateTime->date.month;
1925 
1926  temp = dateTime->time.microsecond - dayTimeDuration->microseconds;
1927  dateTime->time.microsecond = (afw_uint32_t)impl_modulo2(temp, 1000000);
1928  carry = impl_fQuotient2(temp, 1000000);
1929 
1930  temp = dateTime->time.second - dayTimeDuration->seconds + carry;
1931  dateTime->time.second = (afw_uint8_t)impl_modulo2(temp, 60);
1932  carry = impl_fQuotient2(temp, 60);
1933 
1934  temp = dateTime->time.minute - dayTimeDuration->minutes + carry;
1935  dateTime->time.minute = (afw_uint8_t)impl_modulo2(temp, 60);
1936  carry = impl_fQuotient2(temp, 60);
1937 
1938  temp = dateTime->time.hour - dayTimeDuration->hours + carry;
1939  dateTime->time.hour = (afw_uint8_t)impl_modulo2(temp, 24);
1940  carry = impl_fQuotient2(temp, 24);
1941 
1942  dim = afw_date_maximum_days_in_month(year, month);
1943  day = dateTime->date.day;
1944  if (day > dim) {
1945  day = dim;
1946  }
1947  else if (dateTime->date.day < 1) {
1948  day = 1;
1949  }
1950  day = day - dayTimeDuration->days + carry;
1951 
1952  for (;;) {
1953  if (day < 1) {
1954  day += afw_date_maximum_days_in_month(year, month - 1);
1955  carry = -1;
1956  }
1957  else {
1958  dim = afw_date_maximum_days_in_month(year, month);
1959  if (day <= dim) break;
1960  day -= dim;
1961  carry = 1;
1962  }
1963  temp = month + carry;
1964  month = impl_modulo3(temp, 1, 13);
1965  year += impl_fQuotient3(temp, 1, 13);
1966  }
1967 
1968  dateTime->date.day = (afw_uint8_t)day;
1969  dateTime->date.month = (afw_uint8_t)month;
1970  if (year > AFW_INT32_MAX || year < AFW_INT32_MIN) {
1971  AFW_THROW_ERROR_Z(general, "Year limit exceeded", xctx);
1972  }
1973  dateTime->date.year = (afw_int32_t)year;
1974 }
1975 
1976 
1977 /* Add yearMonthDuration to dateTime. */
1978 AFW_DEFINE(void)
1980  afw_dateTime_t *dateTime,
1981  const afw_yearMonthDuration_t *yearMonthDuration,
1982  afw_xctx_t *xctx)
1983 {
1984  afw_integer_t year, month;
1985  int days_in_month;
1986 
1987  year = dateTime->date.year + yearMonthDuration->years;
1988  month = dateTime->date.month + yearMonthDuration->months;
1989 
1990  year += impl_fQuotient3(month, 1, 13);
1991  month = impl_modulo3(month, 1, 13);
1992 
1993  if (year < AFW_INT32_MIN || year > AFW_INT32_MAX) {
1994  AFW_THROW_ERROR_Z(general,
1995  "year limit exceeded", xctx);
1996  }
1997 
1998  dateTime->date.year = (afw_int32_t)year;
1999  dateTime->date.month = (afw_int8_t)month;
2000  days_in_month = afw_date_maximum_days_in_month(year, month);
2001  if (dateTime->date.day > days_in_month) {
2002  dateTime->date.day = (afw_int8_t)days_in_month;
2003  }
2004 }
2005 
2006 
2007 /* Subtract yearMonthDuration from dateTime. */
2008 AFW_DEFINE(void)
2010  afw_dateTime_t *dateTime,
2011  const afw_yearMonthDuration_t *yearMonthDuration,
2012  afw_xctx_t *xctx)
2013 {
2014  afw_integer_t year, month;
2015  int days_in_month;
2016 
2017  year = dateTime->date.year - yearMonthDuration->years;
2018  month = dateTime->date.month - yearMonthDuration->months;
2019 
2020  year += impl_fQuotient3(month, 1, 13);
2021  month = impl_modulo3(month, 1, 13);
2022 
2023  if (year < AFW_INT32_MIN || year > AFW_INT32_MAX) {
2024  AFW_THROW_ERROR_Z(general,
2025  "year limit exceeded", xctx);
2026  }
2027 
2028  dateTime->date.year = (afw_int32_t)year;
2029  dateTime->date.month = (afw_int8_t)month;
2030  days_in_month = afw_date_maximum_days_in_month(year, month);
2031  if (dateTime->date.day > days_in_month) {
2032  dateTime->date.day = (afw_int8_t)days_in_month;
2033  }
2034 }
2035 
2036 
2037 /* Convert internal dateTime to generalized time (see X.208) */
2038 AFW_DEFINE(const afw_utf8_t *)
2040  const afw_dateTime_t *dateTime,
2041  const afw_pool_t *p, afw_xctx_t *xctx)
2042 {
2043  afw_utf8_octet_t to[IMPL_MAX_DATE_TIME_LEN];
2044  afw_size_t len;
2045 
2046  len = impl_set_internal_to_utf8_date(&dateTime->date, &to[0], xctx);
2047  if (len != 4) {
2048  AFW_THROW_ERROR_Z(general,
2049  "afw_dateType_internal_to_generalized_time() "
2050  "can not convert to > 4 digit years",
2051  xctx);
2052  }
2053  len += impl_set_internal_to_utf8_time(&dateTime->time, &to[len], xctx);
2054  len += impl_set_internal_to_utf8_time_zone(&dateTime->time_zone, &to[len],
2055  xctx);
2056 
2057  return afw_utf8_create_copy(&to[0], len, p, xctx);
2058 }
2059 
2060 
2061 /* Convert generalized time (see X.208) to internal and set. */
2062 AFW_DEFINE(void)
2064  const afw_utf8_t *generalized_time, afw_dateTime_t *internal,
2065  afw_xctx_t *xctx)
2066 {
2067  afw_utf8_octet_t wa[IMPL_MAX_DATE_TIME_LEN];
2068  const afw_utf8_octet_t *i;
2069  afw_utf8_t utf8;
2070  afw_utf8_octet_t *o;
2071  afw_size_t len;
2072 
2073  len = generalized_time->len;
2074  i = generalized_time->s;
2075  o = &wa[0];
2076  if (len < sizeof("yyyymmddhhmmss") - 1) goto error;
2077  utf8.s = o;
2078 
2079  *o++ = *i++;
2080  *o++ = *i++;
2081  *o++ = *i++;
2082  *o++ = *i++;
2083  *o++ = '-';
2084  *o++ = *i++;
2085  *o++ = *i++;
2086  *o++ = '-';
2087  *o++ = *i++;
2088  *o++ = *i++;
2089  *o++ = 'T';
2090  *o++ = *i++;
2091  *o++ = *i++;
2092  *o++ = ':';
2093  *o++ = *i++;
2094  *o++ = *i++;
2095  *o++ = ':';
2096  *o++ = *i++;
2097  *o++ = *i++;
2098 
2099  utf8.len = o - &wa[0];
2100  len -= sizeof("yyyymmddhhmmss") - 1;
2101  if (len > 0) {
2102  if (utf8.len + len > IMPL_MAX_DATE_TIME_LEN) goto error;
2103  memcpy(o, i, len);
2104  utf8.len += len;
2105  }
2106 
2107  afw_dateTime_utf8_set_internal(&utf8, internal, xctx);
2108 
2109  return;
2110 
2111 error:
2112  AFW_THROW_ERROR_Z(general, "Invalid generalized time", xctx);
2113 }
AFW_DEFINE(const afw_object_t *)
#define AFW_DECLARE(type)
Declare a public afw function.
Adaptive Framework Core Internal.
void impl_set_date_no_time_zone(afw_date_no_time_zone_t *date, int year, int month, int day, afw_xctx_t *xctx)
Definition: afw_time.c:80
uint8_t afw_uint8_t
8-bit unsigned integer.
Definition: afw_common.h:175
apr_int32_t afw_int32_t
32-bit signed integer.
Definition: afw_common.h:163
_Bool afw_boolean_t
Definition: afw_common.h:373
int8_t afw_int8_t
8-bit signed integer.
Definition: afw_common.h:157
#define AFW_INT32_MIN
Min int32.
Definition: afw_common.h:166
#define AFW_INT32_MAX
Max int32.
Definition: afw_common.h:169
#define AFW_STRINGIFY(x)
Evaluate x and quote the results.
Definition: afw_common.h:144
apr_uint32_t afw_uint32_t
32-bit unsigned integer.
Definition: afw_common.h:184
char afw_utf8_octet_t
8 bits of utf-8 codepoint.
Definition: afw_common.h:236
apr_size_t afw_size_t
size_t.
Definition: afw_common.h:151
#define AFW_UINT32_MAX
Max uint32.
Definition: afw_common.h:187
apr_int64_t afw_integer_t
typedef for big signed int.
Definition: afw_common.h:321
#define AFW_THROW_ERROR_RV_Z(code, rv_source_id, rv, message_z, xctx)
Macro used to set error and rv in xctx and throw it.
Definition: afw_error.h:301
#define AFW_THROW_ERROR_Z(code, message_z, xctx)
Macro used to set error and 0 rv in xctx and throw it.
Definition: afw_error.h:283
#define afw_number_parse_integer(cursor, len, i, p, xctx)
Parse an integer using specified pool for work area.
Definition: afw_number.h:118
afw_number_integer_set_u8(afw_integer_t i, afw_utf8_octet_t *s, afw_size_t len, afw_xctx_t *xctx)
Convert an integer to u8 in supplied buffer.
Definition: afw_number.c:187
#define afw_pool_calloc(instance, size, xctx)
Call method calloc of interface afw_pool.
#define afw_pool_calloc_type(instance, type, xctx)
Macro to allocate cleared memory to hold type in pool.
Definition: afw_pool.h:167
afw_time_now_local(const afw_pool_t *p, afw_xctx_t *xctx)
Get now local time as time only in specified pool.
Definition: afw_time.c:652
afw_date_create_from_parts(int year, int month, int day, int tz_hours_offset, int tz_minutes_offset, const afw_pool_t *p, afw_xctx_t *xctx)
Create afw_date_t from parts in specific pool.
Definition: afw_time.c:219
afw_date_subtract_yearMonthDuration(afw_date_t *date, const afw_yearMonthDuration_t *yearMonthDuration, afw_xctx_t *xctx)
Subtract yearMonthDuration from date.
Definition: afw_time.c:1821
afw_dayTimeDuration_internal_to_utf8(const afw_dayTimeDuration_t *dayTimeDuration, const afw_pool_t *p, afw_xctx_t *xctx)
Convert internal dayTimeDuration to utf8 xml schema dayTimeDuration in specified pool.
Definition: afw_time.c:1126
afw_dateTime_set_from_parts(afw_dateTime_t *dateTime, int year, int month, int day, int hour, int minute, int second, int microsecond, int tz_hours_offset, int tz_minutes_offset, afw_xctx_t *xctx)
Set afw_dateTime_t from parts.
Definition: afw_time.c:244
afw_date_add_yearMonthDuration(afw_date_t *date, const afw_yearMonthDuration_t *yearMonthDuration, afw_xctx_t *xctx)
Add yearMonthDuration to date.
Definition: afw_time.c:1791
afw_dayTimeDuration_create_from_parts(afw_boolean_t is_positive, afw_int32_t days, afw_int32_t hours, afw_int32_t minutes, afw_int32_t seconds, afw_int32_t microseconds, const afw_pool_t *p, afw_xctx_t *xctx)
Create afw_dayTimeDuration_t from parts in specific pool.
Definition: afw_time.c:404
afw_yearMonthDuration_compare(const afw_yearMonthDuration_t *v1, const afw_yearMonthDuration_t *v2, afw_xctx_t *xctx)
compare two yearMonthDuration values.
Definition: afw_time.c:1773
afw_time_set_now(afw_time_t *time_local, afw_time_t *time_utc, afw_xctx_t *xctx)
Set local and/or utc time to now.
Definition: afw_time.c:558
afw_date_utf8_set_internal(const afw_utf8_t *utf8, afw_date_t *internal, afw_xctx_t *xctx)
Convert utf8 xml schema date to internal and set.
Definition: afw_time.c:1061
afw_dayTimeDuration_compare(const afw_dayTimeDuration_t *v1, const afw_dayTimeDuration_t *v2, afw_xctx_t *xctx)
compare two dateTime values.
Definition: afw_time.c:1751
afw_yearMonthDuration_create_from_parts(afw_boolean_t is_positive, afw_int32_t years, afw_int32_t months, const afw_pool_t *p, afw_xctx_t *xctx)
Create afw_yearMonthDuration_t from parts in specific pool.
Definition: afw_time.c:505
afw_dataType_generalized_time_set_internal(const afw_utf8_t *generalized_time, afw_dateTime_t *internal, afw_xctx_t *xctx)
Convert generalized time (see X.208) to internal and set.
Definition: afw_time.c:2063
afw_date_internal_to_utf8(const afw_date_t *date, const afw_pool_t *p, afw_xctx_t *xctx)
Convert internal date to utf8 xml schema date in specified pool.
Definition: afw_time.c:1045
afw_dateTime_now_local(const afw_pool_t *p, afw_xctx_t *xctx)
Get now local time as dateTime in specified pool.
Definition: afw_time.c:639
afw_dayTimeDuration_set_from_parts(afw_dayTimeDuration_t *dayTimeDuration, afw_boolean_t is_positive, int days, int hours, int minutes, int seconds, int microseconds, afw_xctx_t *xctx)
Set afw_dayTimeDuration_t from parts.
Definition: afw_time.c:340
afw_date_set_from_parts(afw_date_t *date, int year, int month, int day, int tz_hours_offset, int tz_minutes_offset, afw_xctx_t *xctx)
Set afw_date_t from parts.
Definition: afw_time.c:197
afw_dateTime_internal_to_utf8(const afw_dateTime_t *dateTime, const afw_pool_t *p, afw_xctx_t *xctx)
Convert internal dateTime to utf8 xml schema dateTime in specified pool.
Definition: afw_time.c:1081
afw_time_to_microseconds_utc(const afw_time_t *time, afw_xctx_t *xctx)
Convert time normalize to utc to microseconds.
Definition: afw_time.c:665
afw_time_now_utc(const afw_pool_t *p, afw_xctx_t *xctx)
Get now time as time only in specified pool.
Definition: afw_time.c:606
const afw_dateTime_t * afw_dateTime_create_from_apr_time(apr_time_t apr_time, const afw_pool_t *p, afw_xctx_t *xctx)
Create afw_dateTime_t from apr time.
Definition: afw_time.c:324
afw_time_utf8_set_internal(const afw_utf8_t *utf8, afw_time_t *internal, afw_xctx_t *xctx)
Convert utf8 xml schema dateTime to internal and set.
Definition: afw_time.c:1385
afw_yearMonthDuration_internal_to_utf8(const afw_yearMonthDuration_t *yearMonthDuration, const afw_pool_t *p, afw_xctx_t *xctx)
Convert internal yearMonthDuration to utf8 xml schema yearMonthDuration in specified pool.
Definition: afw_time.c:1407
afw_time_internal_to_utf8(const afw_time_t *time, const afw_pool_t *p, afw_xctx_t *xctx)
Convert internal time to utf8 xml schema time in specified pool.
Definition: afw_time.c:1369
afw_dateTime_subtract_yearMonthDuration(afw_dateTime_t *dateTime, const afw_yearMonthDuration_t *yearMonthDuration, afw_xctx_t *xctx)
Subtract yearMonthDuration from dateTime.
Definition: afw_time.c:2009
afw_time_create_from_parts(int hour, int minute, int second, int microsecond, int tz_hours_offset, int tz_minutes_offset, const afw_pool_t *p, afw_xctx_t *xctx)
Create afw_time_t from parts in specific pool.
Definition: afw_time.c:448
afw_yearMonthDuration_set_from_parts(afw_yearMonthDuration_t *yearMonthDuration, afw_boolean_t is_positive, int years, int months, afw_xctx_t *xctx)
Set afw_yearMonthDuration_t from parts.
Definition: afw_time.c:471
afw_time_set_from_parts(afw_time_t *time, int hour, int minute, int second, int microsecond, int tz_hours_offset, int tz_minutes_offset, afw_xctx_t *xctx)
Set afw_time_t from parts.
Definition: afw_time.c:425
afw_date_compare(const afw_date_t *v1, const afw_date_t *v2, afw_xctx_t *xctx)
compare two date values.
Definition: afw_time.c:1517
void afw_dateTime_set_from_apr_time(afw_dateTime_t *dateTime, apr_time_t apr_time, afw_xctx_t *xctx)
Set afw_dateTime_t from apr_time.
Definition: afw_time.c:304
afw_dateTime_subtract_dayTimeDuration(afw_dateTime_t *dateTime, const afw_dayTimeDuration_t *dayTimeDuration, afw_xctx_t *xctx)
Subtract dayTimeDuration from dateTime.
Definition: afw_time.c:1915
afw_dateTime_add_yearMonthDuration(afw_dateTime_t *dateTime, const afw_yearMonthDuration_t *yearMonthDuration, afw_xctx_t *xctx)
Add yearMonthDuration to dateTime.
Definition: afw_time.c:1979
afw_date_maximum_days_in_month(afw_integer_t year, afw_integer_t month)
Determine maximum days in a month.
Definition: afw_time.c:1671
afw_dateTime_compare(const afw_dateTime_t *v1, const afw_dateTime_t *v2, afw_xctx_t *xctx)
compare two dateTime values.
Definition: afw_time.c:1540
afw_dateTime_create_from_parts(int year, int month, int day, int hour, int minute, int second, int microsecond, int tz_hours_offset, int tz_minutes_offset, const afw_pool_t *p, afw_xctx_t *xctx)
Create afw_dateTime_t from parts in specific pool.
Definition: afw_time.c:274
afw_time_compare(const afw_time_t *v1, const afw_time_t *v2, afw_xctx_t *xctx)
compare two time values.
Definition: afw_time.c:1590
afw_dateTime_set_now(afw_dateTime_t *dateTime_local, afw_dateTime_t *dateTime_utc, afw_xctx_t *xctx)
Set local and/or utc dateTime to now.
Definition: afw_time.c:523
afw_dateTime_utf8_set_internal(const afw_utf8_t *utf8, afw_dateTime_t *internal, afw_xctx_t *xctx)
Convert utf8 xml schema dateTime to internal and set.
Definition: afw_time.c:1099
afw_dayTimeDuration_utf8_set_internal(const afw_utf8_t *utf8, afw_dayTimeDuration_t *internal, afw_xctx_t *xctx)
Convert utf8 xml schema dayTimeDuration to internal and set.
Definition: afw_time.c:1234
afw_dateType_internal_to_generalized_time(const afw_dateTime_t *dateTime, const afw_pool_t *p, afw_xctx_t *xctx)
Convert internal dateTime to generalized time (see X.208) in specified pool.
Definition: afw_time.c:2039
afw_dateTime_add_dayTimeDuration(afw_dateTime_t *dateTime, const afw_dayTimeDuration_t *dayTimeDuration, afw_xctx_t *xctx)
Add dayTimeDuration to dateTime.
Definition: afw_time.c:1851
afw_dateTime_now_utc(const afw_pool_t *p, afw_xctx_t *xctx)
Get now time as dateTime in specified pool.
Definition: afw_time.c:593
afw_yearMonthDuration_utf8_set_internal(const afw_utf8_t *utf8, afw_yearMonthDuration_t *internal, afw_xctx_t *xctx)
Convert utf8 xml schema yearMonthDuration to internal and set.
Definition: afw_time.c:1458
#define afw_utf8_create_copy(s, len, p, xctx)
Make a utf-8 sting from chars in pool specified.
Definition: afw_utf8.h:369
date with no time zone.
Definition: afw_common.h:1695
date with time zone.
Definition: afw_common.h:1712
date, time, and time zone.
Definition: afw_common.h:1760
afw_time_no_time_zone_t time
Definition: afw_common.h:1766
afw_date_no_time_zone_t date
Definition: afw_common.h:1763
afw_time_zone_t time_zone
Definition: afw_common.h:1769
dayTime duration
Definition: afw_common.h:1657
Interface afw_pool public struct.
time with no time zone.
Definition: afw_common.h:1726
afw_uint32_t microsecond
Definition: afw_common.h:1738
time with time zone.
Definition: afw_common.h:1746
afw_time_no_time_zone_t time
Definition: afw_common.h:1749
afw_time_zone_t time_zone
Definition: afw_common.h:1752
afw_int8_t minutes
Definition: afw_common.h:1688
afw_int8_t hours
Definition: afw_common.h:1682
NFC normalized UTF-8 string.
Definition: afw_common.h:545
Interface afw_xctx public struct.
yearMonth duration
Definition: afw_common.h:1646