//-----------------------------------------------------------------------------
// 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_to_nsecs
//
// purpose	Convert a time period expressed in a string with suffixes and
//		decimal fractions to int_fast64_t nanoseconds.
//
// arguments	1 (const char *) time string
//
// returns	(int_fast64_t) >= 0 : resultant time in nanoseconds
//		(int_fast64_t)  < 0 : error
//
// format	[#[.#]w|W][#[.#]d|D][#[.#]h|H][#[.#]m|M][#[.#][s|S]]
//-----------------------------------------------------------------------------
int_fast64_t
str_to_nsecs (
    const char *	arg_time_str
    )
__PROTO_END__
{
    int_fast64_t		accum		;
    int_fast64_t		frac		;
    int_fast64_t		whole		;

    const char *		ptr		;

    int				ch		;
    int				dot		;
    int				mult		;
    int				suffix		;


    //----------------------------------
    // Scan argument and do conversions.
    //----------------------------------
    dot = 0;
    accum = 0;
    frac = 0;
    whole = 0;
    mult = 1000000000;

    ptr = arg_time_str;
    while ( ( ch = * ptr ) ) {
	suffix = 0;

	switch ( ch ) {

	case '0':	case '1':	case '2':	case '3':	case '4':
	case '5':	case '6':	case '7':	case '8':	case '9':
	    ch -= '0';
	    if ( dot ) {
		if ( dot <= 9 ) {
		    mult /= 10;
		    frac += ch * mult;
		    ++ dot;
		}
	    }
	    else {
		if ( whole > INT_FAST64_MAX / 10 ) goto return_error;
		whole *= 10;
		if ( whole > INT_FAST64_MAX - ch ) goto return_error;
		whole += ch;
	    }
	    break;

	case '.':
	    dot = 1;
	    break;

	case 's':
	case 'S':
	    suffix = 1;
	    break;

	case 'm':
	case 'M':
	    suffix = 60;
	    break;

	case 'h':
	case 'H':
	    suffix = 3600;
	    break;

	case 'd':
	case 'D':
	    suffix = 86400;
	    break;

	case 'w':
	case 'W':
	    suffix = 604800;
	    break;

	default:
	    goto return_error;
	}

	if ( suffix ) {
	    if ( whole > INT_FAST64_MAX / 1000000000 ) goto return_error;
	    whole *= 1000000000;
	    if ( whole > INT_FAST64_MAX - frac ) goto return_error;
	    whole += frac;
	    if ( whole > INT_FAST64_MAX / suffix ) goto return_error;
	    whole *= suffix;
	    if ( accum > INT_FAST64_MAX - whole ) goto return_error;
	    accum += whole;
	    mult = 1000000000;
	    frac = 0;
	    whole = 0;
	    dot = 0;
	}

	++ ptr;
    }

    if ( whole > INT_FAST64_MAX / 1000000000 ) goto return_error;
    whole *= 1000000000;
    if ( whole > INT_FAST64_MAX - frac ) goto return_error;
    whole += frac;
    if ( whole > INT_FAST64_MAX - whole ) goto return_error;
    accum += whole;

    return accum;

 return_error:
    return (int_fast64_t) ( - ( ptr - arg_time_str ) );
}

