//-----------------------------------------------------------------------------
// Copyright © 2004 - Philip Howard - All rights reserved
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//-----------------------------------------------------------------------------
// package	libh/time
// homepage	http://libh.slashusr.org/
//-----------------------------------------------------------------------------
// author	Philip Howard
// email	libh at ipal dot org
// homepage	http://phil.ipal.org/
//-----------------------------------------------------------------------------
// This file is best viewed using a fixed spaced font such as Courier
// and in a display at least 120 columns wide.
//-----------------------------------------------------------------------------

#include "time_lib.h"

__PROTO_BEGIN__
//-----------------------------------------------------------------------------
// function	str_cal_to_ymdhmsu
//
// purpose	Convert date and time in a string to calendar elements via
//		separate pointer arguments.
//
// arguments	1 (const char *) date and time string
//		2 (long int *) where to store year
//		3 (int *) where to store month
//		4 (int *) where to store day of month
//		5 (int *) where to store hour of day
//		6 (int *) where to store minute of hour
//		7 (int *) where to store second of minute
//		8 (long *) where to store microsecond of second
//
// returns	(int) == 0 : OK
//		(int)  < 0 : error
//
// format	yyyy/mm/dd_hh:mm:ss.nnnnnn[nnnnnnnnnnnn]
//
// note		Any non-numeric character may be used as separators, but
//		such use should be limited to reasonable punctuation only
//		for future compatibility.
//-----------------------------------------------------------------------------
int
str_cal_to_ymdhmsu (
    const char *	arg_str
    ,
    long int *		arg_year
    ,
    int *		arg_month
    ,
    int *		arg_mday
    ,
    int *		arg_hour
    ,
    int *		arg_min
    ,
    int *		arg_sec
    ,
    long *		arg_usec
    )
__PROTO_END__
{
    if ( ! arg_str ) return -1;

    if ( ! * arg_str ) goto no_year;
    {
	long	year	;
	int	ch	;
	int	neg	;

	neg = 0;
	if ( ( ch = * arg_str ) == '-' ) {
	    neg = 1;
	    ++ arg_str;
	}
	else if ( ( ch = * arg_str ) == '+' ) {
	    ++ arg_str;
	}
	for ( year = 0; ( ch = * arg_str ) >= '0' && ch <= '9'; ++ arg_str ) {
	    year *= 10;
	    year += ch - '0';
	}
	if ( ( ( ch == 'a' || ch == 'A' ) && ( arg_str[1] == 'd' || arg_str[1] == 'D' ) ) ||
	     ( ( ch == 'c' || ch == 'C' ) && ( arg_str[1] == 'e' || arg_str[1] == 'E' ) ) ) {
	    arg_str += 2;
	}
	else if ( ( ch == 'b' || ch == 'B' ) && ( arg_str[1] == 'c' || arg_str[1] == 'C' ) ) {
	    year = 1 - year;
	    arg_str += 2;
	    if ( ( ch = * arg_str ) == 'e' || ch == 'E' ) ++ arg_str;
	}
	else if ( neg ) {
	    year = 0 - year;
	}
	if ( arg_year ) * arg_year = year;
	if ( * arg_str ) ++ arg_str;
    }

    if ( ! * arg_str ) goto no_month;
    {
	int	month	;
	int	ch	;

	for ( month = 0; ( ch = * arg_str ) >= '0' && ch <= '9'; ++ arg_str ) {
	    month *= 10;
	    month += ch - '0';
	}
	if ( arg_month ) * arg_month = month;
	if ( * arg_str ) ++ arg_str;
    }

    if ( ! * arg_str ) goto no_mday;
    {
	int	mday	;
	int	ch	;

	for ( mday = 0; ( ch = * arg_str ) >= '0' && ch <= '9'; ++ arg_str ) {
	    mday *= 10;
	    mday += ch - '0';
	}
	if ( arg_mday ) * arg_mday = mday;
	if ( * arg_str ) ++ arg_str;
    }

    if ( ! * arg_str ) goto no_hour;
    {
	int	hour	;
	int	ch	;

	for ( hour = 0; ( ch = * arg_str ) >= '0' && ch <= '9'; ++ arg_str ) {
	    hour *= 10;
	    hour += ch - '0';
	}
	if ( arg_hour ) * arg_hour = hour;
	if ( * arg_str ) ++ arg_str;
    }

    if ( ! * arg_str ) goto no_min;
    {
	int	minute	;
	int	ch	;

	for ( minute = 0; ( ch = * arg_str ) >= '0' && ch <= '9'; ++ arg_str ) {
	    minute *= 10;
	    minute += ch - '0';
	}
	if ( arg_min ) * arg_min = minute;
	if ( * arg_str ) ++ arg_str;
    }

    if ( ! * arg_str ) goto no_sec;
    {
	int	second	;
	int	ch	;

	for ( second = 0; ( ch = * arg_str ) >= '0' && ch <= '9'; ++ arg_str ) {
	    second *= 10;
	    second += ch - '0';
	}
	if ( arg_sec ) * arg_sec = second;
	if ( * arg_str ) ++ arg_str;
    }

    if ( ! * arg_str ) goto no_usec;
    {
	long		fract	;
	long		scale	;
	int		ch	;

	scale = 1000000L;
	for ( fract = 0; ( ch = * arg_str ) >= '0' && ch <= '9'; ++ arg_str ) {
	    if ( scale > 1 ) {
		fract *= 10;
		fract += ch - '0';
		scale /= 10;
	    }
	}
	fract *= scale;
	if ( arg_usec ) * arg_usec = fract;
    }
    goto done;

 no_year:
    if ( arg_year ) * arg_year = 0;
 no_month:
    if ( arg_month ) * arg_month = 1;
 no_mday:
    if ( arg_mday ) * arg_mday = 1;
 no_hour:
    if ( arg_hour ) * arg_hour = 0;
 no_min:
    if ( arg_min ) * arg_min = 0;
 no_sec:
    if ( arg_sec ) * arg_sec = 0;
 no_usec:
    if ( arg_usec ) * arg_usec = 0;
 done:
    return 0;
}

