Bring C code up to coding standards

Reformatting and comment improvement only. No code changes.
This commit is contained in:
Laurence Withers 2010-01-08 19:22:36 +00:00
parent 9f3fbd4116
commit 420df40a5b
9 changed files with 298 additions and 172 deletions

View File

@ -1,7 +1,7 @@
/* libiso8601/src/libiso8601/000_TopHeader.h /* libiso8601/src/libiso8601/000_TopHeader.h
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */

View File

@ -1,7 +1,7 @@
/* libiso8601/src/libiso8601/000_TopSource.c /* libiso8601/src/libiso8601/000_TopSource.c
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */

View File

@ -1,25 +1,28 @@
/* libiso8601/src/libiso8601/100_calc.c /* libiso8601/src/libiso8601/100_calc.c
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
/* CALCULATION ROUTINES /* CALCULATION ROUTINES ********************************************************
*
* This file contains calculation routines used internally in the library. Our date format is the This file contains calculation routines used internally in the library. Our
* number of days elapsed since 0000-001 (so that date would be 0, -0001-365 would be -1, etc.). date format is the number of days elapsed since 0000-001 (so that date would be
* Time is represented as the number of seconds elapsed since midnight at the start of the day. It 0, -0001-365 would be -1, etc.). Time is represented as the number of seconds
* is a value between 0 and 86399 (or 86400 for leap seconds). elapsed since midnight at the start of the day. It is a value between 0 and
*/ 86399 (or 86400 for leap seconds).
*******************************************************************************/
#define DAYS_IN_400_YEARS (146097) #define DAYS_IN_400_YEARS (146097)
int iso8601_isleap(int year) int
iso8601_isleap(int year)
{ {
if(year % 4) return 0; if(year % 4) return 0;
if(year % 100) return 1; if(year % 100) return 1;
@ -31,14 +34,15 @@ int iso8601_isleap(int year)
/* struct monthcount, _days_in_month_common[], _days_in_month_leap[] /* struct monthcount, _days_in_month_common[], _days_in_month_leap[]
* *
* Tables of the number of days in each month, and the number of days elapsed since the start of * Tables of the number of days in each month, and the number of days elapsed
* the year for each month. * since the start of the year for each month.
*/ */
struct monthcount { struct monthcount {
int elapsed, days; int elapsed, days;
}; };
static const struct monthcount _days_in_month_common[] = { static const struct monthcount
_days_in_month_common[] = {
{ 0, 31 }, { 0, 31 },
{ 31, 28 }, { 31, 28 },
{ 59, 31 }, { 59, 31 },
@ -53,7 +57,8 @@ static const struct monthcount _days_in_month_common[] = {
{ 334, 31 } { 334, 31 }
}; };
static const struct monthcount _days_in_month_leap[] = { static const struct monthcount
_days_in_month_leap[] = {
{ 0, 31 }, { 0, 31 },
{ 31, 29 }, { 31, 29 },
{ 60, 31 }, { 60, 31 },
@ -70,7 +75,8 @@ static const struct monthcount _days_in_month_leap[] = {
static int _days_in_month(int year, int month) static int
_days_in_month(int year, int month)
{ {
const struct monthcount* mc; const struct monthcount* mc;
@ -85,42 +91,45 @@ static int _days_in_month(int year, int month)
static void _to_year(int* year, int* days_left, const struct iso8601_date* date) static void
_to_year(int* year, int* days_left, const struct iso8601_date* date)
{ {
div_t qr; div_t qr;
int ndays = date->day; int ndays = date->day;
// Each 400 years have 97 leap days, giving 365*400+97 = DAYS_IN_400_YEARS days in 400 years /* Each 400 years have 97 leap days, giving 365*400+97 = DAYS_IN_400_YEARS
days in 400 years */
qr = div(ndays, DAYS_IN_400_YEARS); qr = div(ndays, DAYS_IN_400_YEARS);
*year = qr.quot * 400; *year = qr.quot * 400;
ndays = qr.rem; ndays = qr.rem;
// ensure that we always end up with between 0 and 146096 days remaining /* ensure that we always end up with between 0 and 146096 days remaining */
if(ndays < 0) { if(ndays < 0) {
ndays += DAYS_IN_400_YEARS; ndays += DAYS_IN_400_YEARS;
*year -= 400; *year -= 400;
} }
// we insert `fake' leap days for years 101, 201, 301 /* we insert `fake' leap days for years 101, 201, 301 */
if(ndays >= 36890) ++ndays; if(ndays >= 36890) ++ndays;
if(ndays >= 73415) ++ndays; if(ndays >= 73415) ++ndays;
if(ndays >= 109940) ++ndays; if(ndays >= 109940) ++ndays;
// each remaining 100 year block has 24 leap days, giving 365*100+24 = 36524 days /* each remaining 100 year block has 24 leap days, giving 365*100+24 = 36524
days */
qr = div(ndays, 36525); qr = div(ndays, 36525);
*year += qr.quot * 100; *year += qr.quot * 100;
ndays = qr.rem; ndays = qr.rem;
// each 4-year block has 1 leap day, giving 365*4 + 1 = 1461 days /* each 4-year block has 1 leap day, giving 365*4 + 1 = 1461 days */
qr = div(ndays, 1461); qr = div(ndays, 1461);
*year += qr.quot * 4; *year += qr.quot * 4;
ndays = qr.rem; ndays = qr.rem;
// the first year of a 4-year block has 1 leap day, 366 days /* the first year of a 4-year block has 1 leap day, 366 days */
if(ndays >= 366) { if(ndays >= 366) {
--ndays; // pretend to have dealt with leap day --ndays; /* pretend to have dealt with leap day */
// 365 days per remaining year /* 365 days per remaining year */
qr = div(ndays, 365); qr = div(ndays, 365);
*year += qr.quot; *year += qr.quot;
ndays = qr.rem; ndays = qr.rem;
@ -131,15 +140,16 @@ static void _to_year(int* year, int* days_left, const struct iso8601_date* date)
void iso8601_to_cal(int* year, int* month, int* day, const struct iso8601_date* date) void
iso8601_to_cal(int* year, int* month, int* day, const struct iso8601_date* date)
{ {
const struct monthcount* mc; const struct monthcount* mc;
int ndays; int ndays;
// perform year calulation /* perform year calulation */
_to_year(year, &ndays, date); _to_year(year, &ndays, date);
// now we simply have number of days elapsed since day 001 in `year'. /* now we simply have number of days elapsed since day 001 in `year'. */
mc = iso8601_isleap(*year) ? _days_in_month_leap : _days_in_month_common; mc = iso8601_isleap(*year) ? _days_in_month_leap : _days_in_month_common;
*month = 1; *month = 1;
while(ndays >= mc->days) { while(ndays >= mc->days) {
@ -152,35 +162,38 @@ void iso8601_to_cal(int* year, int* month, int* day, const struct iso8601_date*
void iso8601_to_ord(int* year, int* oday, const struct iso8601_date* date) void
iso8601_to_ord(int* year, int* oday, const struct iso8601_date* date)
{ {
int ndays; int ndays;
// perform year calcutation /* perform year calcutation */
_to_year(year, &ndays, date); _to_year(year, &ndays, date);
// now we simply have number of days elapsed since day 001 in `year'. /* now we simply have number of days elapsed since day 001 in `year'. */
*oday = ndays + 1; *oday = ndays + 1;
} }
static int _weekday_of_year(int year) static int
_weekday_of_year(int year)
{ {
int w = 6; int w = 6;
/* Algorithm notes: /* Algorithm notes:
* - 0 = sun, 1 = mon, ..., 6 = sat * 0 = sun, 1 = mon, ..., 6 = sat
* - 0000-001 is a Saturday, day 6 * 0000-001 is a Saturday, day 6
* - every year we pass gives us one additional day (364 is divisible by 7) * every year we pass gives us one additional day (364 is divisible by 7)
* - but of course every leap year we pass gives us a further day * but of course every leap year we pass gives us a further day
* - so for every 400 years, we add 497 (400 common years, 97 leap years); 497 % 7 = 0 * so for every 400 years, we add 497 (400 common years, 97 leap years);
* 497 % 7 = 0
*/ */
year %= 400; year %= 400;
if(year < 0) year += 400; // end up with between 0-399 years left if(year < 0) year += 400; /* end up with between 0-399 years left */
w += year; // excluding leap years, we increase by 1 day a year w += year; /* excluding leap years, we increase by 1 day a year */
w += (year + 3) / 4; // there is one leap year for every four years w += (year + 3) / 4; /* there is one leap year for every four years */
w -= (year - 1) / 100; // but one less for every century over 0 w -= (year - 1) / 100; /* but one less for every century over 0 */
w %= 7; w %= 7;
return w; return w;
@ -188,42 +201,47 @@ static int _weekday_of_year(int year)
void iso8601_to_week(int* year, int* week, int* wday, const struct iso8601_date* date) void
iso8601_to_week(int* year, int* week, int* wday,
const struct iso8601_date* date)
{ {
int ndays, w, has53 = 0; int ndays, w, has53 = 0;
div_t d; div_t d;
// perform year and weekday calculation /* perform year and weekday calculation */
_to_year(year, &ndays, date); _to_year(year, &ndays, date);
w = _weekday_of_year(*year); w = _weekday_of_year(*year);
// find out what day jan 1 was; from there, we can find the ISO week and year number /* find out what day jan 1 was; from there, we can find the ISO week and
year number */
switch(w) { switch(w) {
case 4: // W01 starts XXXY-12-28 case 4: /* W01 starts XXXY-12-28 */
w += 7; w += 7;
has53 = 1; // years starting Thursday have 53 weeks has53 = 1; /* years starting Thursday have 53 weeks */
break; break;
case 5: // W01 starts XXXZ-01-03 case 5: /* W01 starts XXXZ-01-03 */
case 6: // W01 starts XXXZ-01-02 case 6: /* W01 starts XXXZ-01-02 */
break; break;
case 0: // W01 starts XXXZ-01-01 case 0: /* W01 starts XXXZ-01-01 */
case 1: // W01 starts XXXY-12-31 case 1: /* W01 starts XXXY-12-31 */
case 2: // W01 starts XXXY-12-30 case 2: /* W01 starts XXXY-12-30 */
w += 7; // for week calculation w += 7; /* for week calculation */
break; break;
case 3: // W01 starts XXXY-12-29 case 3: /* W01 starts XXXY-12-29 */
w += 7; w += 7;
if(iso8601_isleap(*year)) has53 = 1; // leap years starting Wednesday have 53 weeks if(iso8601_isleap(*year)) has53 = 1; /* leap years starting Wednesday
have 53 weeks */
} }
// now we simply add the number of days elapsed since the start of the year, and % 7 /* now we simply add the number of days elapsed since the start of the
year, and % 7 */
w += ndays; w += ndays;
d = div(w, 7); // w can never be 0 d = div(w, 7); /* w can never be 0 */
// do Sunday correction /* do Sunday correction */
if(!d.rem) { if(!d.rem) {
d.rem = 7; d.rem = 7;
--d.quot; --d.quot;
@ -256,54 +274,57 @@ void iso8601_to_week(int* year, int* week, int* wday, const struct iso8601_date*
int _from_year(struct iso8601_date* date, int year) static int
_from_year(struct iso8601_date* date, int year)
{ {
div_t qr; div_t qr;
// check for range errors /* check for range errors */
if(year < -5879609 || year > 5879609) { if(year < -5879609 || year > 5879609) {
errno = ERANGE; errno = ERANGE;
return -1; return -1;
} }
// Each 400 years have 97 leap days, giving 365*400+97 = DAYS_IN_400_YEARS days in 400 years /* Each 400 years have 97 leap days, giving 365*400+97 = DAYS_IN_400_YEARS
days in 400 years */
qr = div(year, 400); qr = div(year, 400);
date->day = qr.quot * DAYS_IN_400_YEARS; date->day = qr.quot * DAYS_IN_400_YEARS;
year = qr.rem; year = qr.rem;
// ensure we have between 0 and 399 years /* ensure we have between 0 and 399 years */
if(year < 0) { if(year < 0) {
date->day -= DAYS_IN_400_YEARS; date->day -= DAYS_IN_400_YEARS;
year += 400; year += 400;
} }
// excluding leap days, there are 365 days per year /* excluding leap days, there are 365 days per year */
date->day += 365 * year; date->day += 365 * year;
date->day += (year + 3) / 4; // there is one leap year for every four years date->day += (year + 3) / 4; /* one leap year for every four years */
date->day -= (year - 1) / 100; // but one less for every century over 0 date->day -= (year - 1) / 100; /* but one less for every century over 0 */
return 0; return 0;
} }
int iso8601_from_cal(struct iso8601_date* date, int year, int month, int day) int
iso8601_from_cal(struct iso8601_date* date, int year, int month, int day)
{ {
const struct monthcount* mc; const struct monthcount* mc;
// check for domain errors /* check for domain errors */
mc = iso8601_isleap(year) ? _days_in_month_leap : _days_in_month_common; mc = iso8601_isleap(year) ? _days_in_month_leap : _days_in_month_common;
if(month < 1 || month > 12 || day < 1 || day > mc[month - 1].days) { if(month < 1 || month > 12 || day < 1 || day > mc[month - 1].days) {
errno = EDOM; errno = EDOM;
return -1; return -1;
} }
// perform year calculation /* perform year calculation */
if(_from_year(date, year)) return -1; if(_from_year(date, year)) return -1;
// now get number of days elapsed up to start of month /* now get number of days elapsed up to start of month */
date->day += mc[month - 1].elapsed; date->day += mc[month - 1].elapsed;
// and add number of days elapsed sinced start of month /* and add number of days elapsed sinced start of month */
date->day += day - 1; date->day += day - 1;
return 0; return 0;
@ -311,18 +332,19 @@ int iso8601_from_cal(struct iso8601_date* date, int year, int month, int day)
int iso8601_from_ord(struct iso8601_date* date, int year, int oday) int
iso8601_from_ord(struct iso8601_date* date, int year, int oday)
{ {
// check for domain errors /* check for domain errors */
if(oday < 1 || oday > (iso8601_isleap(year) ? 366 : 365)) { if(oday < 1 || oday > (iso8601_isleap(year) ? 366 : 365)) {
errno = EDOM; errno = EDOM;
return -1; return -1;
} }
// perform year calculation /* perform year calculation */
if(_from_year(date, year)) return -1; if(_from_year(date, year)) return -1;
// now simply add number of days elapsed this year /* now simply add number of days elapsed this year */
date->day += oday - 1; date->day += oday - 1;
return 0; return 0;
@ -330,18 +352,19 @@ int iso8601_from_ord(struct iso8601_date* date, int year, int oday)
int iso8601_from_week(struct iso8601_date* date, int isoyear, int week, int wday) int
iso8601_from_week(struct iso8601_date* date, int isoyear, int week, int wday)
{ {
int day1off, maxwk; int day1off, maxwk;
// compute year part /* compute year part */
_from_year(date, isoyear); _from_year(date, isoyear);
// 400-year cycle; ensure we're between 0-400 years /* 400-year cycle; ensure we're between 0-400 years */
isoyear %= 400; isoyear %= 400;
if(isoyear < 0) isoyear += 400; if(isoyear < 0) isoyear += 400;
// domain check /* domain check */
maxwk = (((isoyear % 7) == 52) || ((isoyear % 28) == 24)) ? 53 : 52; maxwk = (((isoyear % 7) == 52) || ((isoyear % 28) == 24)) ? 53 : 52;
if(wday < 1 || wday > 7 || week < 1 || week > maxwk) { if(wday < 1 || wday > 7 || week < 1 || week > maxwk) {
errno = EDOM; errno = EDOM;
@ -349,18 +372,20 @@ int iso8601_from_week(struct iso8601_date* date, int isoyear, int week, int wday
} }
/* Algorithm notes: /* Algorithm notes:
* We now compute the offset between the start day of the ISO year and the start day of the * We now compute the offset between the start day of the ISO year and
* real year. Year 0000 starts on a Saturday, meaning the ISO year 0000 starts on 0000-003 * the start day of the real year. Year 0000 starts on a Saturday, meaning
* (offset of +2 days). Each year reduces the offset by one day, and each leap year reduces it * the ISO year 0000 starts on 0000-003 (offset of +2 days). Each year
* by a further day; the offset wraps from -3 to +3. * reduces the offset by one day, and each leap year reduces it by a
* further day; the offset wraps from -3 to +3.
*/ */
day1off = 2 - isoyear; // reduce offset by 1 for each year day1off = 2 - isoyear; /* reduce offset by 1 for each year */
day1off += (isoyear - 1) / 100; // cancel out 1 leap year for each century past the first day1off += (isoyear - 1) / 100; /* cancel out 1 leap year for each century
day1off -= (isoyear + 3) / 4; // 1 leap year every 4 years past the first */
day1off -= (isoyear + 3) / 4; /* 1 leap year every 4 years */
day1off %= 7; day1off %= 7;
if(day1off < -3) day1off += 7; if(day1off < -3) day1off += 7;
// now simply add in the day offset and days/weeks elapsed /* now simply add in the day offset and days/weeks elapsed */
date->day += day1off + (week - 1) * 7 + wday - 1; date->day += day1off + (week - 1) * 7 + wday - 1;
return 0; return 0;
@ -368,11 +393,13 @@ int iso8601_from_week(struct iso8601_date* date, int isoyear, int week, int wday
void iso8601_to_clocktime(int* hour, int* min, int* sec, const struct iso8601_date* date) void
iso8601_to_clocktime(int* hour, int* min, int* sec,
const struct iso8601_date* date)
{ {
div_t qr; div_t qr;
// special case: leap second /* special case: leap second */
if(date->sec == 86400) { if(date->sec == 86400) {
*hour = 23; *hour = 23;
*min = 59; *min = 59;
@ -380,7 +407,7 @@ void iso8601_to_clocktime(int* hour, int* min, int* sec, const struct iso8601_da
return; return;
} }
// normal case /* normal case */
qr = div(date->sec, 3600); qr = div(date->sec, 3600);
*hour = qr.quot; *hour = qr.quot;
qr = div(qr.rem, 60); qr = div(qr.rem, 60);
@ -390,21 +417,22 @@ void iso8601_to_clocktime(int* hour, int* min, int* sec, const struct iso8601_da
int iso8601_from_clocktime(struct iso8601_date* date, int hour, int min, int sec) int
iso8601_from_clocktime(struct iso8601_date* date, int hour, int min, int sec)
{ {
// special case: leap second /* special case: leap second */
if(hour == 23 && min == 59 && sec == 60) { if(hour == 23 && min == 59 && sec == 60) {
date->sec = 86400; date->sec = 86400;
return 0; return 0;
} }
// domain check /* domain check */
if(hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || sec > 59) { if(hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || sec > 59) {
errno = EDOM; errno = EDOM;
return -1; return -1;
} }
// normal calculation /* normal calculation */
date->sec = hour * 3600 + min * 60 + sec; date->sec = hour * 3600 + min * 60 + sec;
return 0; return 0;
} }

View File

@ -1,13 +1,20 @@
/* libiso8601/src/libiso8601/100_leap.c /* libiso8601/src/libiso8601/100_leap.c
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
static int leap_second_days_table[] = { /* leap_second_days_table[]
* This is a sorted array of days (in libiso8601 format) on which a positive
* leap second occurred. This table is built in to the library, but may be
* overridden at runtime by changing what leap_second_days points to. There
* should be no other references to this table, therefore.
*/
static int
leap_second_days_table[] = {
720439, /* 1972-06-30 */ 720439, /* 1972-06-30 */
720623, /* 1972-12-31 */ 720623, /* 1972-12-31 */
720988, /* 1973-12-31 */ 720988, /* 1973-12-31 */
@ -36,21 +43,41 @@ static int leap_second_days_table[] = {
static int* leap_second_days = leap_second_days_table; /* leap_second_days[], leap_second_days_num
static int leap_second_days_num = sizeof(leap_second_days_table) / sizeof(int); * Pointer to an array (and number of elements in the array) representing the
* table of positive leap seconds. The array is sorted and contains libiso8601
* day numbers of days with positive leap seconds.
*/
static int*
leap_second_days = leap_second_days_table;
static int
leap_second_days_num = sizeof(leap_second_days_table) / sizeof(int);
int iso8601_seconds_leap(const struct iso8601_date* date) /* iso8601_seconds_leap()
* Returns the number of seconds that elapse on a given date, which requires us
* to search the table of leap seconds to see if we need to return a special
* case.
*/
int
iso8601_seconds_leap(const struct iso8601_date* date)
{ {
int i; int i;
for(i = 0; i < leap_second_days_num; ++i) if(leap_second_days[i] == date->day) return 86401; for(i = 0; i < leap_second_days_num; ++i) {
if(leap_second_days[i] == date->day) return 86401;
}
return 86400; return 86400;
} }
static int _leap_elapsed_day(int sday, int eday) /* _leap_elapsed_day()
* Returns the number of leap seconds that have elapsed between sday (start
* day) and eday (end day), both in libiso8601 format.
*/
static int
_leap_elapsed_day(int sday, int eday)
{ {
int spos, epos; int spos, epos;
@ -66,16 +93,31 @@ static int _leap_elapsed_day(int sday, int eday)
int iso8601_leap_elapsed(const struct iso8601_date* start, const struct iso8601_date* end) /* iso8601_leap_elapsed()
* Wrapper around _leap_elapsed_day().
*/
int
iso8601_leap_elapsed(const struct iso8601_date* start,
const struct iso8601_date* end)
{ {
return _leap_elapsed_day(start->day, end->day); return _leap_elapsed_day(start->day, end->day);
} }
/* leap_table_free_old
* If set, then when we update the leap table, we should free the old array.
* Initially clear so that we don't free our static built-in table.
*/
static int leap_table_free_old = 0; static int leap_table_free_old = 0;
void iso8601_leap_table_set(int* new_table, int new_size)
/* iso8601_leap_table_set()
* Switch to using a new table of leap seconds, possibly freeing the old one.
*/
void
iso8601_leap_table_set(int* new_table, int new_size)
{ {
if(leap_table_free_old) free(leap_second_days); if(leap_table_free_old) free(leap_second_days);
leap_table_free_old = 0; leap_table_free_old = 0;
@ -86,11 +128,22 @@ void iso8601_leap_table_set(int* new_table, int new_size)
static const char* leap_table_signature = "/O9PdPZI"; /* leap_table_signature
* The first 8 bytes of a leap second table must match this string, otherwise
* the file is taken not to be of the correct format.
*/
static const char*
leap_table_signature = "/O9PdPZI";
int iso8601_leap_table_load(const char* fname) /* iso8601_leap_table_load()
* Loads a new table of leap seconds from disk. Ensures the signature of the
* given file matches leap_table_signature, and does some basic sanity
* checking (file in sorted order etc.).
*/
int
iso8601_leap_table_load(const char* fname)
{ {
struct stat st; struct stat st;
int fd, saved_errno, i, new_size, * days = 0; int fd, saved_errno, i, new_size, * days = 0;

View File

@ -1,24 +1,25 @@
/* libiso8601/src/libiso8601/200_parser.c /* libiso8601/src/libiso8601/200_parser.c
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
int iso8601_parse(const char* str, struct iso8601_date* earliest, struct iso8601_date* latest, int
struct iso8601_details* details) iso8601_parse(const char* str, struct iso8601_date* earliest,
struct iso8601_date* latest, struct iso8601_details* details)
{ {
enum { enum {
state_none, state_none,
state_year, // e.g. `2006' or `2006123' state_year, /* e.g. `2006' or `2006123' */
state_date2, // 2nd component of date, e.g. `2006-' or `2006-1' state_date2, /* 2nd component of date, e.g. `2006-' or `2006-1' */
state_day, // e.g. `2006-01-' or `2006-01-01' state_day, /* e.g. `2006-01-' or `2006-01-01' */
state_week_basic, // e.g. `2006W' or `2006W123' state_week_basic, /* e.g. `2006W' or `2006W123' */
state_week_extended, // e.g. `2006-W' or `2006-W31' state_week_extended, /* e.g. `2006-W' or `2006-W31' */
state_week_day, // e.g. `2006-W31-' state_week_day, /* e.g. `2006-W31-' */
state_week_done, // `2006-W31-1' state_week_done, /* `2006-W31-1' */
state_time_basic, state_time_basic,
state_time_hour, state_time_hour,
state_time_min, state_time_min,
@ -34,8 +35,9 @@ int iso8601_parse(const char* str, struct iso8601_date* earliest, struct iso8601
div_t qr; div_t qr;
char ch; char ch;
int num = 0, neg = 0, dig = 0, tz_neg = 0, nsec = -1, nsec_dig = -1, leap_sec_req = 0; int num = 0, neg = 0, dig = 0, tz_neg = 0, nsec = -1, nsec_dig = -1,
int y = 0, m = -1, d = -1, w = -1, wd = -1, hour = -1, min = -1, sec = -1, tz_sec = 0; leap_sec_req = 0, y = 0, m = -1, d = -1, w = -1, wd = -1, hour = -1,
min = -1, sec = -1, tz_sec = 0;
double frac; double frac;
struct iso8601_elapsed elapsed; struct iso8601_elapsed elapsed;
@ -436,7 +438,8 @@ int iso8601_parse(const char* str, struct iso8601_date* earliest, struct iso8601
case '-': case '-':
tz_neg = -1; tz_neg = -1;
case '+': case '+':
state = (state == state_time_nsec_basic) ? state_tz_basic : state_tz_hour; state = (state == state_time_nsec_basic) ?
state_tz_basic : state_tz_hour;
break; break;
} }
break; break;
@ -544,7 +547,8 @@ done:
if(m != -1) { if(m != -1) {
if(d == -1) { if(d == -1) {
ERROR_IF(earliest && iso8601_from_cal(earliest, y, m, 1)); ERROR_IF(earliest && iso8601_from_cal(earliest, y, m, 1));
ERROR_IF(latest && iso8601_from_cal(latest, y, m, _days_in_month(y, m))); ERROR_IF(latest && iso8601_from_cal(latest, y, m,
_days_in_month(y, m)));
if(details) details->date_prec = iso8601_prec_month; if(details) details->date_prec = iso8601_prec_month;
} else { } else {
@ -608,7 +612,8 @@ done:
} else if(min != -1) { } else if(min != -1) {
if(nsec_dig == -1) { if(nsec_dig == -1) {
ERROR_IF(earliest && iso8601_from_clocktime(earliest, hour, min, 0)); ERROR_IF(earliest && iso8601_from_clocktime(earliest,
hour, min, 0));
ERROR_IF(latest && iso8601_from_clocktime(latest, hour, min, 59)); ERROR_IF(latest && iso8601_from_clocktime(latest, hour, min, 59));
if(latest) latest->nsec = 999999999; if(latest) latest->nsec = 999999999;
if(details) details->time_prec = iso8601_prec_min; if(details) details->time_prec = iso8601_prec_min;
@ -617,7 +622,8 @@ done:
frac = nsec * 60.0 / 1e9; frac = nsec * 60.0 / 1e9;
sec = (int)frac; sec = (int)frac;
nsec = (frac - sec) * 1e9; nsec = (frac - sec) * 1e9;
ERROR_IF(earliest && iso8601_from_clocktime(earliest, hour, min, sec)); ERROR_IF(earliest && iso8601_from_clocktime(earliest,
hour, min, sec));
if(earliest) earliest->nsec = nsec; if(earliest) earliest->nsec = nsec;
ERROR_IF(latest && iso8601_from_clocktime(latest, hour, min, sec)); ERROR_IF(latest && iso8601_from_clocktime(latest, hour, min, sec));
if(latest) latest->nsec = nsec; if(latest) latest->nsec = nsec;
@ -639,7 +645,8 @@ done:
frac *= 60; frac *= 60;
sec = (int)frac; sec = (int)frac;
nsec = (frac - sec) * 1e9; nsec = (frac - sec) * 1e9;
ERROR_IF(earliest && iso8601_from_clocktime(earliest, hour, min, sec)); ERROR_IF(earliest && iso8601_from_clocktime(earliest,
hour, min, sec));
if(earliest) earliest->nsec = nsec; if(earliest) earliest->nsec = nsec;
ERROR_IF(latest && iso8601_from_clocktime(latest, hour, min, sec)); ERROR_IF(latest && iso8601_from_clocktime(latest, hour, min, sec));
if(latest) latest->nsec = nsec; if(latest) latest->nsec = nsec;
@ -676,7 +683,8 @@ done:
int iso8601_invalid(const struct iso8601_date* date) int
iso8601_invalid(const struct iso8601_date* date)
{ {
return date->nsec < 0 return date->nsec < 0
|| date->nsec >= BILLION || date->nsec >= BILLION

View File

@ -1,13 +1,18 @@
/* libiso8601/src/libiso8601/print.c /* libiso8601/src/libiso8601/200_print.c
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
static const struct iso8601_details _default_details = { /* _default_details
* If the user doesn't pass precision details to iso8601_print(), these are
* used instead.
*/
static const struct iso8601_details
_default_details = {
iso8601_prec_day, iso8601_prec_day,
iso8601_prec_sec, iso8601_prec_sec,
1, 1,
@ -16,7 +21,8 @@ static const struct iso8601_details _default_details = {
char* iso8601_print(char* str, int amt, const struct iso8601_date* date, char*
iso8601_print(char* str, int amt, const struct iso8601_date* date,
const struct iso8601_details* details) const struct iso8601_details* details)
{ {
int y, m, d, ret = 0, extended; int y, m, d, ret = 0, extended;
@ -27,10 +33,10 @@ char* iso8601_print(char* str, int amt, const struct iso8601_date* date,
str_orig = str; str_orig = str;
// use default details if none provided /* use default details if none provided */
if(!details) details = &_default_details; if(!details) details = &_default_details;
// adjust output for timezone /* adjust output for timezone */
dttz = *date; dttz = *date;
if(details->tz_sec) { if(details->tz_sec) {
elapsed.sec = details ? details->tz_sec : 0; elapsed.sec = details ? details->tz_sec : 0;
@ -38,7 +44,7 @@ char* iso8601_print(char* str, int amt, const struct iso8601_date* date,
iso8601_add_elapsed(&dttz, &elapsed); iso8601_add_elapsed(&dttz, &elapsed);
} }
// determine whether or not to force extended output /* determine whether or not to force extended output */
iso8601_to_cal(&y, &m, &d, &dttz); iso8601_to_cal(&y, &m, &d, &dttz);
extended = details->extended || y < 0 || y > 9999; extended = details->extended || y < 0 || y > 9999;
@ -55,27 +61,32 @@ char* iso8601_print(char* str, int amt, const struct iso8601_date* date,
case iso8601_prec_day: case iso8601_prec_day:
if(y < 0) ret = snprintf(str, amt, "%05d-%02d-%02d", y, m, d); if(y < 0) ret = snprintf(str, amt, "%05d-%02d-%02d", y, m, d);
else ret = snprintf(str, amt, extended ? "%04d-%02d-%02d" : "%04d%02d%02d", y, m, d); else ret = snprintf(str, amt, extended ?
"%04d-%02d-%02d" : "%04d%02d%02d", y, m, d);
break; break;
case iso8601_prec_ord: case iso8601_prec_ord:
iso8601_to_ord(&y, &d, &dttz); iso8601_to_ord(&y, &d, &dttz);
if(y < 0) ret = snprintf(str, amt, "%05d-%03d", y, d); if(y < 0) ret = snprintf(str, amt, "%05d-%03d", y, d);
else ret = snprintf(str, amt, extended ? "%04d-%03d" : "%04d%03d", y, d); else ret = snprintf(str, amt, extended ?
"%04d-%03d" : "%04d%03d", y, d);
break; break;
case iso8601_prec_week: case iso8601_prec_week:
iso8601_to_week(&y, &m, &d, &dttz); iso8601_to_week(&y, &m, &d, &dttz);
extended = y < 0 || y > 9999 || details->extended; // ISO year is different /* note: ISO year can differ, so recompute extended flag */
extended = y < 0 || y > 9999 || details->extended;
if(y < 0) snprintf(str, amt, "%05d-W%02d", y, m); if(y < 0) snprintf(str, amt, "%05d-W%02d", y, m);
else snprintf(str, amt, extended ? "%04d-W%02d" : "%04dW%02d", y, m); else snprintf(str, amt, extended ? "%04d-W%02d" : "%04dW%02d", y, m);
return str_orig; return str_orig;
case iso8601_prec_wday: case iso8601_prec_wday:
iso8601_to_week(&y, &m, &d, &dttz); iso8601_to_week(&y, &m, &d, &dttz);
extended = y < 0 || y > 9999 || details->extended; // ISO year is different /* note: ISO year can differ, so recompute extended flag */
extended = y < 0 || y > 9999 || details->extended;
if(y < 0) ret = snprintf(str, amt, "%05d-W%02d-%d", y, m, d); if(y < 0) ret = snprintf(str, amt, "%05d-W%02d-%d", y, m, d);
else ret = snprintf(str, amt, extended ? "%04d-W%02d-%d" : "%04dW%02d%d", y, m, d); else ret = snprintf(str, amt, extended ?
"%04d-W%02d-%d" : "%04dW%02d%d", y, m, d);
break; break;
} }
@ -111,7 +122,8 @@ char* iso8601_print(char* str, int amt, const struct iso8601_date* date,
break; break;
case iso8601_prec_sec: case iso8601_prec_sec:
ret = snprintf(str, amt, extended ? "T%02d:%02d:%02d" : "T%02d%02d%02d", y, m, d); ret = snprintf(str, amt, extended ?
"T%02d:%02d:%02d" : "T%02d%02d%02d", y, m, d);
break; break;
case iso8601_prec_hourfrac: case iso8601_prec_hourfrac:
@ -121,12 +133,14 @@ char* iso8601_print(char* str, int amt, const struct iso8601_date* date,
case iso8601_prec_minfrac: case iso8601_prec_minfrac:
frac = m + (d + date->nsec / 1e9) / 60.0; frac = m + (d + date->nsec / 1e9) / 60.0;
ret = snprintf(str, amt, extended ? "T%02d:%#012.9f" : "T%02d%#012.9f", y, frac); ret = snprintf(str, amt, extended ?
"T%02d:%#012.9f" : "T%02d%#012.9f", y, frac);
break; break;
case iso8601_prec_secfrac: case iso8601_prec_secfrac:
frac = d + date->nsec / 1e9; frac = d + date->nsec / 1e9;
ret = snprintf(str, amt, extended ? "T%02d:%02d:%#012.9f" : "T%02d%02d%#012.9f", y, m, frac); ret = snprintf(str, amt, extended ?
"T%02d:%02d:%#012.9f" : "T%02d%02d%#012.9f", y, m, frac);
break; break;
} }
@ -150,8 +164,10 @@ char* iso8601_print(char* str, int amt, const struct iso8601_date* date,
ret -= m * 60; ret -= m * 60;
d = ret; d = ret;
if(d) snprintf(str, amt, extended ? "%02d:%02d:%02d" : "%02d%02d%02d", y, m, d); if(d) snprintf(str, amt, extended ?
else if(m) snprintf(str, amt, extended ? "%02d:%02d" : "%02d%02d", y, m); "%02d:%02d:%02d" : "%02d%02d%02d", y, m, d);
else if(m) snprintf(str, amt, extended ?
"%02d:%02d" : "%02d%02d", y, m);
else snprintf(str, amt, "%02d", y); else snprintf(str, amt, "%02d", y);
} else { } else {
*str++ = 'Z'; *str++ = 'Z';

View File

@ -1,16 +1,17 @@
/* libiso8601/src/libiso8601/400_c_library.c /* libiso8601/src/libiso8601/400_c_library.c
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
// days between 0000-001 and 1970-001 (the unix epoch) /* days between 0000-001 and 1970-001 (the unix epoch) */
#define EPOCH_GDAY (719528) #define EPOCH_GDAY (719528)
void iso8601_now(struct iso8601_date* date, struct iso8601_details* details) void
iso8601_now(struct iso8601_date* date, struct iso8601_details* details)
{ {
static int use_gettimeofday = 0; static int use_gettimeofday = 0;
struct timespec ts; struct timespec ts;
@ -44,7 +45,8 @@ void iso8601_now(struct iso8601_date* date, struct iso8601_details* details)
int iso8601_set_sysclock(const struct iso8601_date* date) int
iso8601_set_sysclock(const struct iso8601_date* date)
{ {
static int use_settimeofday = 0; static int use_settimeofday = 0;
struct timeval tv; struct timeval tv;
@ -71,7 +73,8 @@ int iso8601_set_sysclock(const struct iso8601_date* date)
void iso8601_from_ts(struct iso8601_date* date, const struct timespec* ts) void
iso8601_from_ts(struct iso8601_date* date, const struct timespec* ts)
{ {
ldiv_t qr; ldiv_t qr;
@ -83,7 +86,8 @@ void iso8601_from_ts(struct iso8601_date* date, const struct timespec* ts)
void iso8601_to_ts(struct timespec* ts, const struct iso8601_date* date) void
iso8601_to_ts(struct timespec* ts, const struct iso8601_date* date)
{ {
ts->tv_sec = 86400L * (date->day - EPOCH_GDAY) + date->sec; ts->tv_sec = 86400L * (date->day - EPOCH_GDAY) + date->sec;
ts->tv_nsec = date->nsec; ts->tv_nsec = date->nsec;
@ -91,7 +95,8 @@ void iso8601_to_ts(struct timespec* ts, const struct iso8601_date* date)
void iso8601_from_tv(struct iso8601_date* date, const struct timeval* tv) void
iso8601_from_tv(struct iso8601_date* date, const struct timeval* tv)
{ {
ldiv_t qr; ldiv_t qr;
@ -103,7 +108,8 @@ void iso8601_from_tv(struct iso8601_date* date, const struct timeval* tv)
void iso8601_to_tv(struct timeval* tv, const struct iso8601_date* date) void
iso8601_to_tv(struct timeval* tv, const struct iso8601_date* date)
{ {
tv->tv_sec = 86400L * (date->day - EPOCH_GDAY) + date->sec; tv->tv_sec = 86400L * (date->day - EPOCH_GDAY) + date->sec;
tv->tv_usec = date->nsec / 1000; tv->tv_usec = date->nsec / 1000;
@ -111,7 +117,8 @@ void iso8601_to_tv(struct timeval* tv, const struct iso8601_date* date)
void iso8601_from_time_t(struct iso8601_date* date, const time_t* t) void
iso8601_from_time_t(struct iso8601_date* date, const time_t* t)
{ {
ldiv_t qr; ldiv_t qr;
@ -123,7 +130,8 @@ void iso8601_from_time_t(struct iso8601_date* date, const time_t* t)
void iso8601_to_time_t(time_t* t, const struct iso8601_date* date) void
iso8601_to_time_t(time_t* t, const struct iso8601_date* date)
{ {
*t = 86400L * (date->day - EPOCH_GDAY) + date->sec; *t = 86400L * (date->day - EPOCH_GDAY) + date->sec;
} }

View File

@ -1,13 +1,14 @@
/* libiso8601/src/libiso8601/400_manip.c /* libiso8601/src/libiso8601/400_manip.c
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
int iso8601_lt(const struct iso8601_date* d1, const struct iso8601_date* d2) int
iso8601_lt(const struct iso8601_date* d1, const struct iso8601_date* d2)
{ {
if(d1->day < d2->day) return 1; if(d1->day < d2->day) return 1;
if(d1->day > d2->day) return 0; if(d1->day > d2->day) return 0;
@ -19,7 +20,8 @@ int iso8601_lt(const struct iso8601_date* d1, const struct iso8601_date* d2)
int iso8601_lte(const struct iso8601_date* d1, const struct iso8601_date* d2) int
iso8601_lte(const struct iso8601_date* d1, const struct iso8601_date* d2)
{ {
if(d1->day < d2->day) return 1; if(d1->day < d2->day) return 1;
if(d1->day > d2->day) return 0; if(d1->day > d2->day) return 0;
@ -31,14 +33,17 @@ int iso8601_lte(const struct iso8601_date* d1, const struct iso8601_date* d2)
int iso8601_eq(const struct iso8601_date* d1, const struct iso8601_date* d2) int
iso8601_eq(const struct iso8601_date* d1, const struct iso8601_date* d2)
{ {
return (d1->day == d2->day) && (d1->sec == d2->sec) && (d1->nsec == d2->nsec); return (d1->day == d2->day) && (d1->sec == d2->sec)
&& (d1->nsec == d2->nsec);
} }
int iso8601_cmp(const struct iso8601_date* d1, const struct iso8601_date* d2) int
iso8601_cmp(const struct iso8601_date* d1, const struct iso8601_date* d2)
{ {
if(d1->day < d2->day) return -1; if(d1->day < d2->day) return -1;
if(d1->day > d2->day) return 1; if(d1->day > d2->day) return 1;
@ -51,12 +56,14 @@ int iso8601_cmp(const struct iso8601_date* d1, const struct iso8601_date* d2)
void iso8601_add_elapsed(struct iso8601_date* date, const struct iso8601_elapsed* per) void
iso8601_add_elapsed(struct iso8601_date* date,
const struct iso8601_elapsed* per)
{ {
div_t qr; div_t qr;
int leapcorrect; int leapcorrect;
/* work out number to advance `day' by */ /* work out number to advance day by */
qr = div(per->sec, 86400); qr = div(per->sec, 86400);
leapcorrect = _leap_elapsed_day(date->day, date->day + qr.quot); leapcorrect = _leap_elapsed_day(date->day, date->day + qr.quot);
date->day += qr.quot; date->day += qr.quot;
@ -81,12 +88,14 @@ void iso8601_add_elapsed(struct iso8601_date* date, const struct iso8601_elapsed
void iso8601_subtract_elapsed(struct iso8601_date* date, const struct iso8601_elapsed* per) void
iso8601_subtract_elapsed(struct iso8601_date* date,
const struct iso8601_elapsed* per)
{ {
div_t qr; div_t qr;
int leapcorrect; int leapcorrect;
/* work out number to advance `day' by */ /* work out number to advance day by */
qr = div(per->sec, 86400); qr = div(per->sec, 86400);
leapcorrect = _leap_elapsed_day(date->day - qr.quot, date->day); leapcorrect = _leap_elapsed_day(date->day - qr.quot, date->day);
date->day -= qr.quot; date->day -= qr.quot;
@ -111,7 +120,9 @@ void iso8601_subtract_elapsed(struct iso8601_date* date, const struct iso8601_el
void iso8601_add_multiple(struct iso8601_date* date, const struct iso8601_elapsed* per, int n) void
iso8601_add_multiple(struct iso8601_date* date,
const struct iso8601_elapsed* per, int n)
{ {
long long nsec; long long nsec;
lldiv_t qr; lldiv_t qr;
@ -128,7 +139,8 @@ void iso8601_add_multiple(struct iso8601_date* date, const struct iso8601_elapse
void iso8601_difference(const struct iso8601_date* d1, const struct iso8601_date* d2, void
iso8601_difference(const struct iso8601_date* d1, const struct iso8601_date* d2,
struct iso8601_elapsed* per, int* sign) struct iso8601_elapsed* per, int* sign)
{ {
const struct iso8601_date* e1, * e2; const struct iso8601_date* e1, * e2;
@ -160,8 +172,9 @@ void iso8601_difference(const struct iso8601_date* d1, const struct iso8601_date
int iso8601_elapsed_div(const struct iso8601_elapsed* num, const struct iso8601_elapsed* denom, int
struct iso8601_elapsed* remain) iso8601_elapsed_div(const struct iso8601_elapsed* num,
const struct iso8601_elapsed* denom, struct iso8601_elapsed* remain)
{ {
unsigned long long pnum, pdenom; unsigned long long pnum, pdenom;
lldiv_t val, v2; lldiv_t val, v2;

View File

@ -1,7 +1,7 @@
/* libiso8601/src/libiso8601/999_BottomHeader.h /* libiso8601/src/libiso8601/999_BottomHeader.h
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */