diff options
Diffstat (limited to 'mbglib/common/mbgutil.c')
-rwxr-xr-x | mbglib/common/mbgutil.c | 462 |
1 files changed, 286 insertions, 176 deletions
diff --git a/mbglib/common/mbgutil.c b/mbglib/common/mbgutil.c index edc41b4..d3cb946 100755 --- a/mbglib/common/mbgutil.c +++ b/mbglib/common/mbgutil.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgutil.c 1.6 2012/10/15 13:12:17 martin REL_M $ + * $Id: mbgutil.c 1.6.1.18 2016/07/22 09:57:11 martin TEST $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,6 +10,30 @@ * * ----------------------------------------------------------------------- * $Log: mbgutil.c $ + * Revision 1.6.1.18 2016/07/22 09:57:11 martin + * Quieted some compiler warninges. + * Revision 1.6.1.17 2016/07/15 14:09:48 martin + * Use functions from new module timeutil. + * Revision 1.6.1.16 2016/04/26 09:23:36 martin + * Revision 1.6.1.15 2016/03/16 11:46:34Z martin + * *** empty log message *** + * Revision 1.6.1.14 2015/12/01 11:36:25 martin + * *** empty log message *** + * Revision 1.6.1.13 2015/11/24 15:44:55 martin + * Revision 1.6.1.12 2015/11/20 16:30:41Z martin + * Revision 1.6.1.11 2015/11/02 10:12:28Z martin + * *** empty log message *** + * Revision 1.6.1.10 2015/10/30 11:36:54 martin + * Revision 1.6.1.9 2015/09/08 10:37:02Z martin + * Revision 1.6.1.8 2015/08/27 16:17:27Z martin + * Use safe string functions from str_util.c. + * Revision 1.6.1.7 2014/05/27 11:32:47 martin + * Revision 1.6.1.6 2014/05/27 11:26:24 martin + * Revision 1.6.1.5 2014/03/13 16:04:12 martin + * Revision 1.6.1.4 2014/03/13 15:45:36 martin + * Revision 1.6.1.3 2014/03/13 14:31:52Z martin + * Revision 1.6.1.2 2013/10/23 10:40:53Z martin + * Revision 1.6.1.1 2013/10/22 10:05:55 martin * Revision 1.6 2012/10/15 13:12:17 martin * Fixed build under DOS. * Fixed format/type mismatch when printing UTC offset. @@ -35,12 +59,17 @@ #include <mbgutil.h> #undef _MBGUTIL +#include <cfg_hlp.h> +#include <mbgerror.h> #include <pcpsutil.h> -#include <pcpslstr.h> +#include <charcode.h> #include <pcpsdev.h> +#include <str_util.h> +#include <qsdefs.h> #include <stdio.h> #include <time.h> +#include <limits.h> // required at least for Linux: #include <stdarg.h> @@ -60,32 +89,32 @@ static int mbg_date_time_dist = 2; static int mbg_pos_dist = 2; static uint16_t mbg_year_lim = 1980; +static const char str_inv_cnv[] = "(invalid conversion)"; + +// The size_t type can eventually be larger than an int type. +// However, some snprintf-like functions expect a size_t value +// to specify the buffer size, but just return an int value. +// So we take care that at least the return value is limited +// to MAXINT. #if defined( MBG_TGT_WIN32 ) - #define mbg_vsnprintf _vsnprintf + #define _int_from_size_t( _n ) \ + ( ( (_n) > INT_MAX ) ? INT_MAX : (int) (_n) ) #else - #define mbg_vsnprintf vsnprintf -#endif - - -#if defined( MBG_TGT_DOS ) - -static /*HDR*/ -int vsnprintf( char *s, int max_len, const char *fmt, va_list arg_list ) -{ - return vsprintf( s, fmt, arg_list ); - -} // vsnprintf - + #define _int_from_size_t( _n ) (_n) #endif /*HDR*/ +/** + * @brief Get the DLL/shared library's version code + * + * @return The version code at which the library was built + */ _MBG_API_ATTR int _MBG_API mbgutil_get_version( void ) { - return MBGUTIL_VERSION; } // mbgutil_get_version @@ -93,54 +122,58 @@ _MBG_API_ATTR int _MBG_API mbgutil_get_version( void ) /*HDR*/ +/** + * @brief Check the DLL/shared library's compatibility + * + * @param header_version Version code defined in the header file when the application is built + * + * @return ::MBG_SUCCESS if compatible, else ::MBG_ERR_LIB_NOT_COMPATIBLE + */ _MBG_API_ATTR int _MBG_API mbgutil_check_version( int header_version ) { if ( header_version >= MBGUTIL_COMPAT_VERSION ) - return PCPS_SUCCESS; + return MBG_SUCCESS; - return -1; + return MBG_ERR_LIB_NOT_COMPATIBLE; } // mbgutil_check_version -// We have our own version of snprintf() since under Windows -// _snprintf(), returns -1 and does not write a terminating 0 -// if the output exceeds the buffer size. -// -// This function terminates the output string properly. However, -// the maximum return value is (max_len - 1), so the function -// can not be used to determine the buffer size that would be -// required for an untruncated string. - /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_snprintf( char *s, size_t max_len, const char * fmt, ... ) +/** + * @brief A portable, safe implementation of snprintf() + * + * For a detailed description see ::vsnprintf_safe + * + * @param s pointer to the output buffer + * @param max_len size of the output buffer + * @param fmt format string according to subsequent parameters + * @param ... variable argument list according to the format string + * + * @return the number of characters written to the output buffer, except the terminating 0 + * + * @see ::vsnprintf_safe + * @see ::snprintf_safe + */ +_MBG_API_ATTR int __attribute__( ( format( printf, 3, 4 ) ) ) +_MBG_API mbg_snprintf( char *s, size_t max_len, const char * fmt, ... ) { - int n; - + size_t n; va_list ap; - va_start( ap, fmt ); - - n = mbg_vsnprintf( s, max_len, fmt, ap ); - - va_end( ap ); - + // TODO: size_t can be larger than int, so what happens if + // a very long string is written to the buffer and the number + // of bytes written exceeds MAXINT, in which case the number + // can't be returned? - #if defined( MBG_TGT_WIN32 ) - - // Terminate the output string properly under Windows. - // For other targets assume the POSIX version is available. - if ( n < 0 || n >= (int) max_len ) - { - n = max_len - 1; - s[n] = 0; - } + va_start( ap, fmt ); - #endif + n = vsnprintf_safe( s, max_len, fmt, ap ); + va_end( ap ); - return n; + return _int_from_size_t( n ); } // mbg_snprintf @@ -149,14 +182,26 @@ _MBG_API_ATTR int _MBG_API mbg_snprintf( char *s, size_t max_len, const char * f /*HDR*/ _MBG_API_ATTR int _MBG_API mbg_strncpy( char *s, size_t max_len, const char *src ) { - //##++ This could be coded more efficiently - return mbg_snprintf( s, max_len, "%s", src ); + size_t n = sn_cpy_str_safe( s, max_len, src ); + return _int_from_size_t( n ); } // mbg_strncpy /*HDR*/ +/** + * @brief Write a character multiple times to a string buffer + * + * Append a terminating 0 to the buffer. + * + * @param s pointer to the output buffer + * @param max_len size of the output buffer + * @param c the character to write to the output buffer + * @param n the number of characters to write to the output buffer + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ _MBG_API_ATTR int _MBG_API mbg_strchar( char *s, size_t max_len, char c, size_t n ) { size_t i; @@ -168,48 +213,54 @@ _MBG_API_ATTR int _MBG_API mbg_strchar( char *s, size_t max_len, char c, size_t if ( i >= max_len ) break; + if ( i >= ( INT_MAX - 1 ) ) + break; + s[i] = c; } s[i] = 0; - return i; + return (int) i; } // mbg_strchar /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_date_short( char *s, int max_len, +_MBG_API_ATTR int _MBG_API mbg_str_date_short( char *s, int max_len, int mday, int month ) { - return mbg_snprintf( s, max_len, "%02u.%02u.", mday, month ); - + size_t n = snprintf_safe( s, max_len, "%02u.%02u.", mday, month ); + return _int_from_size_t( n ); + } // mbg_str_date_short /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_date( char *s, int max_len, +_MBG_API_ATTR int _MBG_API mbg_str_date( char *s, int max_len, int mday, int month, int year ) { - int n = mbg_str_date_short( s, max_len, mday, month ); - n += mbg_snprintf( s + n, max_len - n, "%04u", - ( year < 256 ) ? - pcps_exp_year( (uint8_t) year, mbg_year_lim ) : - year - ); - return n; + size_t n = mbg_str_date_short( s, max_len, mday, month ); + + n += snprintf_safe( &s[n], max_len - n, "%04u", + ( year < 256 ) ? + pcps_exp_year( (uint8_t) year, mbg_year_lim ) : + year ); + + return _int_from_size_t( n ); } // mbg_str_date /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_time_short( char *s, int max_len, +_MBG_API_ATTR int _MBG_API mbg_str_time_short( char *s, int max_len, int hour, int min ) { - return mbg_snprintf( s, max_len, "%2u:%02u", hour, min ); + size_t n = snprintf_safe( s, max_len, "%2u:%02u", hour, min ); + return _int_from_size_t( n ); } // mbg_str_time_short @@ -219,11 +270,11 @@ _MBG_API_ATTR int _MBG_API mbg_str_time_short( char *s, int max_len, _MBG_API_ATTR int _MBG_API mbg_str_time( char *s, int max_len, int hour, int min, int sec ) { - int n = mbg_str_time_short( s, max_len, hour, min ); + size_t n = mbg_str_time_short( s, max_len, hour, min ); - n += mbg_snprintf( s + n, max_len - n, ":%02u", sec ); + n += snprintf_safe( &s[n], max_len - n, ":%02u", sec ); - return n; + return _int_from_size_t( n ); } // mbg_str_time @@ -233,11 +284,11 @@ _MBG_API_ATTR int _MBG_API mbg_str_time( char *s, int max_len, _MBG_API_ATTR int _MBG_API mbg_str_time_long( char *s, int max_len, int hour, int min, int sec, int sec100 ) { - int n = mbg_str_time( s, max_len, hour, min, sec ); + size_t n = mbg_str_time( s, max_len, hour, min, sec ); - n += mbg_snprintf( s + n, max_len - n, ".%02u", sec100 ); + n += snprintf_safe( &s[n], max_len - n, ".%02u", sec100 ); - return n; + return _int_from_size_t( n ); } // mbg_str_time_long @@ -247,31 +298,33 @@ _MBG_API_ATTR int _MBG_API mbg_str_time_long( char *s, int max_len, _MBG_API_ATTR int _MBG_API mbg_str_tm_gps_date_time( char *s, int max_len, const TM_GPS *pt ) { - int n = mbg_str_date( s, max_len, pt->mday, pt->month, pt->year ); - n += mbg_strchar( s + n, max_len - n, ' ', mbg_date_time_dist ); - n += mbg_str_time( s + n, max_len - n, pt->hour, pt->min, pt->sec ); + size_t n = mbg_str_date( s, max_len, pt->mday, pt->month, pt->year ); + n += mbg_strchar( &s[n], max_len - n, ' ', mbg_date_time_dist ); + n += mbg_str_time( &s[n], max_len - _int_from_size_t( n ), pt->hour, pt->min, pt->sec ); - return n; + return _int_from_size_t( n ); } // mbg_str_tm_gps_date_time /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_date_short( char *s, int max_len, +_MBG_API_ATTR int _MBG_API mbg_str_pcps_date_short( char *s, int max_len, const PCPS_TIME *pt ) { - return mbg_str_date_short( s, max_len, pt->mday, pt->month ); + size_t n = mbg_str_date_short( s, max_len, pt->mday, pt->month ); + return _int_from_size_t( n ); } // mbg_str_pcps_date_short /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_date( char *s, int max_len, +_MBG_API_ATTR int _MBG_API mbg_str_pcps_date( char *s, int max_len, const PCPS_TIME *pt ) { - return mbg_str_date( s, max_len, pt->mday, pt->month, pt->year ); + size_t n = mbg_str_date( s, max_len, pt->mday, pt->month, pt->year ); + return _int_from_size_t( n ); } // mbg_str_pcps_date @@ -281,7 +334,8 @@ _MBG_API_ATTR int _MBG_API mbg_str_pcps_date( char *s, int max_len, _MBG_API_ATTR int _MBG_API mbg_str_pcps_time_short( char *s, int max_len, const PCPS_TIME *pt ) { - return mbg_str_time_short( s, max_len, pt->hour, pt->min ); + size_t n = mbg_str_time_short( s, max_len, pt->hour, pt->min ); + return _int_from_size_t( n ); } // mbg_str_pcps_time_short @@ -291,7 +345,8 @@ _MBG_API_ATTR int _MBG_API mbg_str_pcps_time_short( char *s, int max_len, _MBG_API_ATTR int _MBG_API mbg_str_pcps_time( char *s, int max_len, const PCPS_TIME *pt ) { - return mbg_str_time( s, max_len, pt->hour, pt->min, pt->sec ); + size_t n = mbg_str_time( s, max_len, pt->hour, pt->min, pt->sec ); + return _int_from_size_t( n ); } // mbg_str_pcps_time @@ -301,60 +356,77 @@ _MBG_API_ATTR int _MBG_API mbg_str_pcps_time( char *s, int max_len, _MBG_API_ATTR int _MBG_API mbg_str_pcps_time_long( char *s, int max_len, const PCPS_TIME *pt ) { - return mbg_str_time_long( s, max_len, pt->hour, pt->min, pt->sec, pt->sec100 ); + size_t n = mbg_str_time_long( s, max_len, pt->hour, pt->min, pt->sec, pt->sec100 ); + return _int_from_size_t( n ); } // mbg_str_pcps_time_long /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_date_time( char *s, int max_len, - const PCPS_TIME *pt, +_MBG_API_ATTR int _MBG_API mbg_str_pcps_date_time( char *s, int max_len, + const PCPS_TIME *pt, const char *tz_str ) { - int n = mbg_str_pcps_date( s, max_len, pt ); - n += mbg_strchar( s + n, max_len - n, ' ', mbg_date_time_dist ); - n += mbg_str_pcps_time( s + n, max_len - n, pt ); + size_t n = mbg_str_pcps_date( s, max_len, pt ); + n += mbg_strchar( &s[n], max_len - n, ' ', mbg_date_time_dist ); + n += mbg_str_pcps_time( &s[n], max_len - _int_from_size_t( n ), pt ); + + return _int_from_size_t( n ); - return n; - } // mbg_str_pcps_date_time /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date( char *s, int max_len, +_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date( char *s, int max_len, uint32_t sec ) { - time_t t = sec; - struct tm tm = *gmtime( &t ); - return mbg_str_date( s, max_len, tm.tm_mday, tm.tm_mon + 1, tm.tm_year ); + struct tm tm = { 0 }; + time_t t = cvt_to_time_t( sec ); + int rc = mbg_gmtime( &tm, &t ); + + return mbg_rc_is_success( rc ) ? + mbg_str_date( s, max_len, tm.tm_mday, tm.tm_mon + 1, tm.tm_year ) : + sn_cpy_str_safe( s, max_len, str_inv_cnv ); } // mbg_str_pcps_hr_date /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time( char *s, int max_len, +_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time( char *s, int max_len, uint32_t sec ) { - time_t t = sec; - struct tm tm = *gmtime( &t ); - return mbg_str_time( s, max_len, tm.tm_hour, tm.tm_min, tm.tm_sec ); + struct tm tm = { 0 }; + time_t t = cvt_to_time_t( sec ); + int rc = mbg_gmtime( &tm, &t ); + + return mbg_rc_is_success( rc ) ? + mbg_str_time( s, max_len, tm.tm_hour, tm.tm_min, tm.tm_sec ) : + sn_cpy_str_safe( s, max_len, str_inv_cnv ); } // mbg_str_pcps_hr_time /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date_time_utc( char *s, int max_len, +_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date_time_utc( char *s, int max_len, const PCPS_HR_TIME *pt ) { - time_t t = pt->tstamp.sec; - struct tm tm = *gmtime( &t ); - int n = mbg_str_date( s, max_len, tm.tm_mday , tm.tm_mon + 1, tm.tm_year ); - n += mbg_strchar( s + n, max_len - n, ' ', mbg_date_time_dist ); - n += mbg_str_time( s + n, max_len - n, tm.tm_hour, tm.tm_min, tm.tm_sec ); + struct tm tm = { 0 }; + int n = 0; + time_t t = cvt_to_time_t( pt->tstamp.sec ); + int rc = mbg_gmtime( &tm, &t ); + + if ( mbg_rc_is_success( rc ) ) + { + n = mbg_str_date( s, max_len, tm.tm_mday , tm.tm_mon + 1, tm.tm_year ); + n += mbg_strchar( &s[n], max_len - n, ' ', mbg_date_time_dist ); + n += mbg_str_time( &s[n], max_len - n, tm.tm_hour, tm.tm_min, tm.tm_sec ); + } + else + n = sn_cpy_str_safe( s, max_len, str_inv_cnv ); return n; @@ -363,14 +435,23 @@ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date_time_utc( char *s, int max_len, /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date_time_loc( char *s, int max_len, +_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date_time_loc( char *s, int max_len, const PCPS_HR_TIME *pt ) { - time_t t = pt->tstamp.sec + pt->utc_offs; - struct tm tm = *gmtime( &t ); - int n = mbg_str_date( s, max_len, tm.tm_mday , tm.tm_mon + 1, tm.tm_year ); - n += mbg_strchar( s + n, max_len - n, ' ', mbg_date_time_dist ); - n += mbg_str_time( s + n, max_len - n, tm.tm_hour, tm.tm_min, tm.tm_sec ); + struct tm tm = { 0 }; + int n = 0; + long l = (long) pt->tstamp.sec + pt->utc_offs; + time_t t = cvt_to_time_t( l ); + int rc = mbg_gmtime( &tm, &t ); + + if ( mbg_rc_is_success( rc ) ) + { + n = mbg_str_date( s, max_len, tm.tm_mday , tm.tm_mon + 1, tm.tm_year ); + n += mbg_strchar( &s[n], max_len - n, ' ', mbg_date_time_dist ); + n += mbg_str_time( &s[n], max_len - n, tm.tm_hour, tm.tm_min, tm.tm_sec ); + } + else + n = sn_cpy_str_safe( s, max_len, str_inv_cnv ); return n; @@ -379,40 +460,41 @@ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date_time_loc( char *s, int max_len, /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_frac( char *s, int max_len, +_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_frac( char *s, int max_len, uint32_t frac ) { - return mbg_snprintf( s, max_len, PCPS_HRT_FRAC_SCALE_FMT, - frac_sec_from_bin( frac, PCPS_HRT_FRAC_SCALE ) ); + size_t n = snprintf_safe( s, max_len, PCPS_HRT_FRAC_SCALE_FMT, + (ulong) frac_sec_from_bin( frac, PCPS_HRT_FRAC_SCALE ) ); + return _int_from_size_t( n ); } // mbg_str_pcps_hr_time_frac /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_offs( char *s, int max_len, +_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_offs( char *s, int max_len, const PCPS_HR_TIME *pt, const char *info ) { - int n = mbg_snprintf( s, max_len, "%s", info ); + size_t n = snprintf_safe( s, max_len, "%s", info ); if ( pt->utc_offs ) { ldiv_t ldt = ldiv( labs( pt->utc_offs ) / 60, 60 ); - n += mbg_snprintf( s + n, max_len - n, "%c%02lu:%02luh", - ( pt->utc_offs < 0 ) ? '-' : '+', - ldt.quot, ldt.rem ); + n += snprintf_safe( &s[n], max_len - n, "%c%02lu:%02luh", + ( pt->utc_offs < 0 ) ? '-' : '+', + ldt.quot, ldt.rem ); } - return n; + return _int_from_size_t( n ); } // mbg_str_pcps_hr_time_offs /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_utc( char *s, int max_len, +_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_utc( char *s, int max_len, const PCPS_HR_TIME *pt ) { int n = mbg_str_pcps_hr_date_time_utc( s, max_len, pt ); @@ -420,7 +502,7 @@ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_utc( char *s, int max_len, if ( n < ( max_len - 1 ) ) { s[n++] = '.'; - n += mbg_str_pcps_hr_time_frac( s + n, max_len - n, pt->tstamp.frac ); + n += mbg_str_pcps_hr_time_frac( &s[n], max_len - n, pt->tstamp.frac ); } return n; @@ -430,7 +512,7 @@ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_utc( char *s, int max_len, /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_loc( char *s, int max_len, +_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_loc( char *s, int max_len, const PCPS_HR_TIME *pt ) { int n = mbg_str_pcps_hr_date_time_loc( s, max_len, pt ); @@ -438,7 +520,7 @@ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_loc( char *s, int max_len, if ( n < ( max_len - 1 ) ) { s[n++] = '.'; - n += mbg_str_pcps_hr_time_frac( s + n, max_len - n, pt->tstamp.frac ); + n += mbg_str_pcps_hr_time_frac( &s[n], max_len - n, pt->tstamp.frac ); } if ( n < ( max_len - 1 ) ) @@ -452,7 +534,7 @@ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_loc( char *s, int max_len, cp = "GPS"; s[n++] = ' '; - n += mbg_str_pcps_hr_time_offs( s + n, max_len - n, pt, cp ); + n += mbg_str_pcps_hr_time_offs( &s[n], max_len - n, pt, cp ); } return n; @@ -462,53 +544,51 @@ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_loc( char *s, int max_len, /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_tstamp_raw( char *s, int max_len, +_MBG_API_ATTR int _MBG_API mbg_str_pcps_tstamp_raw( char *s, int max_len, const PCPS_TIME_STAMP *pt ) { - return mbg_snprintf( s, max_len, "%08lX.%08lX", pt->sec, pt->frac ); + size_t n = snprintf_safe( s, max_len, "%08lX.%08lX", (ulong) pt->sec, (ulong) pt->frac ); + return _int_from_size_t( n ); } // mbg_str_pcps_tstamp_raw /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_raw( char *s, int max_len, +_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_raw( char *s, int max_len, const PCPS_HR_TIME *pt ) { - int n = mbg_str_pcps_tstamp_raw( s, max_len, &pt->tstamp ); - n += mbg_str_pcps_hr_time_offs( s + n, max_len - n, pt, ", Loc: " ); - n += mbg_snprintf( s + n, max_len - n, ", st: 0x%04X", pt->status ); + size_t n = mbg_str_pcps_tstamp_raw( s, max_len, &pt->tstamp ); + n += mbg_str_pcps_hr_time_offs( &s[n], max_len - _int_from_size_t( n ), pt, ", Loc: " ); + n += snprintf_safe( &s[n], max_len - n, ", st: 0x%04X", pt->status ); + + return _int_from_size_t( n ); - return n; - } // mbg_str_pcps_hr_time_raw /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_ucap( char *s, int max_len, +_MBG_API_ATTR int _MBG_API mbg_str_ucap( char *s, int max_len, const PCPS_HR_TIME *pt ) { - int n = mbg_snprintf( s, max_len, "CAP%u: ", pt->signal ); - n += mbg_str_pcps_hr_tstamp_loc( s + n, max_len - n, pt ); + size_t n = snprintf_safe( s, max_len, "CAP%u: ", pt->signal ); + n += mbg_str_pcps_hr_tstamp_loc( &s[n], max_len - _int_from_size_t( n ), pt ); + + return _int_from_size_t( n ); - return n; - } // mbg_str_ucap /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pos_dms( char *s, int max_len, +_MBG_API_ATTR int _MBG_API mbg_str_pos_dms( char *s, int max_len, const DMS *pdms, int prec ) { - return mbg_snprintf( s, max_len, "%c %i" DEG "%02i'%02.*f\"", - pdms->prefix, - pdms->deg, - pdms->min, - prec, - pdms->sec - ); + size_t n = snprintf_safe( s, max_len, "%c %i" DEG "%02i'%02.*f\"", + pdms->prefix, pdms->deg, pdms->min, + prec, pdms->sec ); + return _int_from_size_t( n ); } // mbg_str_pos_dms @@ -517,14 +597,15 @@ _MBG_API_ATTR int _MBG_API mbg_str_pos_dms( char *s, int max_len, /*HDR*/ _MBG_API_ATTR int _MBG_API mbg_str_pos_alt( char *s, int max_len, double alt ) { - return mbg_snprintf( s, max_len, "%.0fm", alt ); + size_t n = snprintf_safe( s, max_len, "%.0fm", alt ); + return _int_from_size_t( n ); } // mbg_str_pos_alt /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pos( char *s, int max_len, +_MBG_API_ATTR int _MBG_API mbg_str_pos( char *s, int max_len, const POS *ppos, int prec ) { int n; @@ -532,15 +613,15 @@ _MBG_API_ATTR int _MBG_API mbg_str_pos( char *s, int max_len, if ( ppos->lla[LON] || ppos->lla[LAT] || ppos->lla[ALT] ) { n = mbg_str_pos_dms( s, max_len, &ppos->latitude, prec ); - n += mbg_strchar( s + n, max_len - n, ',', 1 ); - n += mbg_strchar( s + n, max_len - n, ' ', mbg_pos_dist ); - n += mbg_str_pos_dms( s + n, max_len - n, &ppos->longitude, prec ); - n += mbg_strchar( s + n, max_len - n, ',', 1 ); - n += mbg_strchar( s + n, max_len - n, ' ', mbg_pos_dist ); - n += mbg_str_pos_alt( s + n, max_len - n, ppos->lla[ALT] ); + n += mbg_strchar( &s[n], max_len - n, ',', 1 ); + n += mbg_strchar( &s[n], max_len - n, ' ', mbg_pos_dist ); + n += mbg_str_pos_dms( &s[n], max_len - n, &ppos->longitude, prec ); + n += mbg_strchar( &s[n], max_len - n, ',', 1 ); + n += mbg_strchar( &s[n], max_len - n, ' ', mbg_pos_dist ); + n += mbg_str_pos_alt( &s[n], max_len - n, ppos->lla[ALT] ); } else - n = mbg_strncpy( s, max_len, "N/A" ); + n = mbg_strncpy( s, max_len, str_not_avail ); return n; @@ -549,53 +630,82 @@ _MBG_API_ATTR int _MBG_API mbg_str_pos( char *s, int max_len, /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_dev_name( char *s, int max_len, const char *short_name, +_MBG_API_ATTR int _MBG_API mbg_str_dev_name( char *s, int max_len, const char *short_name, uint16_t fw_rev_num, PCI_ASIC_VERSION asic_version_num ) { - #define HW_NAME_SZ PCPS_CLOCK_NAME_SZ+PCPS_SN_SIZE+1 + #define HW_NAME_SZ ( PCPS_CLOCK_NAME_SZ + PCPS_SN_SIZE + 1 ) - char model_code[HW_NAME_SZ]; - PCPS_SN_STR sernum; + char model_code[HW_NAME_SZ] = { 0 }; + PCPS_SN_STR sernum = { 0 }; unsigned int i = 0; - int n = 0; + size_t n = 0; + size_t l = strlen( short_name ); - memset( model_code, 0, sizeof( model_code ) ); - memset( sernum, 0, sizeof( sernum ) ); - - if ( strlen( short_name ) > 0 ) + if ( l > 0 ) { - if ( strstr( short_name, "COM") ) - return mbg_snprintf(s, max_len,"%s", short_name); + // For serial port string specifies we just copy + // the short_name. + if ( device_id_is_serial( short_name ) ) + { + n = sn_cpy_str_safe( s, max_len, short_name ); + goto out; + } + + // If the short_name has more than HW_NAME_SZ characters + // then we have to reduce the maximum length. + // For bus level device, the short_name usually consists of + // the model name, followed by an underscore '_', followed + // by the serial number, e.g. "PZF180PEX_046411000030". + if ( HW_NAME_SZ < l ) + l = HW_NAME_SZ; - for ( i = 0; ( i < HW_NAME_SZ ) && ( i < strlen( short_name ) ); i++ ) + for ( i = 0; i < l; i++ ) { if ( short_name[i] == '_' ) { i++; break; } + model_code[i] = short_name[i]; } - strncpy( sernum, &short_name[i], PCPS_SN_SIZE-1 ); - if ( sernum[12] == ' ' ) - sernum[12] = '\0'; + strncpy_safe( sernum, &short_name[i], sizeof( sernum ) ); + + //### TODO + // Legal serial numbers have MBG_GRP_SERNUM_LEN characters, which is + // less than the maximum length of a PCPS_SN_STR type string. + // Do we really have to check and truncate the PCPS_SN_STR sernum? + if ( sernum[MBG_GRP_SERNUM_LEN] == ' ' ) + sernum[MBG_GRP_SERNUM_LEN] = '\0'; } - n = mbg_snprintf( s, max_len, "%s, S/N %s", model_code, sernum ); + n = snprintf_safe( s, max_len, "%s, S/N %s", model_code, sernum ); - if ( fw_rev_num > 0 ) - n += mbg_snprintf( &s[n], max_len," (FW v%X.%02X", fw_rev_num>>8, fw_rev_num & 0x00FF ); + if ( fw_rev_num || asic_version_num ) + n += sn_cpy_str_safe( &s[n], max_len - n, " (" ); - if ( asic_version_num > 0 ) + if ( fw_rev_num ) { - mbg_snprintf( &s[n], max_len," / ASIC v%d.%02d)", _convert_asic_version_number( asic_version_num ) >> 8, - ( _convert_asic_version_number( asic_version_num ) ) & 0xFF ); + n += snprintf_safe( &s[n], max_len - n, "FW v%X.%02X", + fw_rev_num >> 8, fw_rev_num & 0xFF ); + // Append a separator if ASIC version will follow. + if ( asic_version_num ) + n += sn_cpy_str_safe( &s[n], max_len - n, " / " ); } - else - mbg_snprintf( &s[n], max_len,")" ); - return strlen(s); + if ( asic_version_num ) + { + n += snprintf_safe( &s[n], max_len - n, "ASIC v%d.%02d", + _convert_asic_version_number( asic_version_num ) >> 8, + _convert_asic_version_number( asic_version_num ) & 0xFF ); + } + + if ( fw_rev_num || asic_version_num ) + n += sn_cpy_str_safe( &s[n], max_len - n, ")" ); + +out: + return _int_from_size_t( n ); } // mbg_str_dev_name |