Merged epicsInt64-library-support branch
This commit is contained in:
@@ -15,6 +15,24 @@ EPICS Base 3.15.0.x releases are not intended for use in production systems.</p>
|
||||
<h2 align="center">Changes between 3.15.0.1 and 3.15.0.2</h2>
|
||||
<!-- Insert new items immediately below here ... -->
|
||||
|
||||
<h3>Support routines for 64-bit integers</h3>
|
||||
|
||||
<p>The libCom library now provides support for 64-bit integer types on all
|
||||
supported architectures. The epicsTypes.h header file defines epicsInt64 and
|
||||
epicsUInt64 type definitions for both C and C++ code. The epicsStdlib.h header
|
||||
also declares the following for parsing strings into the relevent sized integer
|
||||
variables: Functions epicsParseLLong(), epicsParseULLong() with related macros
|
||||
epicsScanLLong() and epicsScanULLong(), and the functions epicsParseInt64()
|
||||
and epicsParseUInt64(). Use the first two functions and the macros for long long
|
||||
and unsigned long long integer types, and the last two functions for the
|
||||
epicsInt64 and epicsUInt64 types. Note that the latter can map to the types long
|
||||
and unsigned long on some 64-bit architectures such as linux-x86_64, not to the
|
||||
two long long types.</p>
|
||||
|
||||
<p>This version does not provide the ability to define 64-bit record fields, the
|
||||
use of the 64-bit types in the IOC database will come in a later release of
|
||||
EPICS Base.</p>
|
||||
|
||||
<h3>Full support for loadable support modules</h3>
|
||||
|
||||
<p>Apparently later versions of Base 3.14 permitted support modules to be loaded
|
||||
|
||||
@@ -85,6 +85,68 @@ epicsParseULong(const char *str, unsigned long *to, int base, char **units)
|
||||
return 0;
|
||||
}
|
||||
|
||||
epicsShareFunc int
|
||||
epicsParseLLong(const char *str, long long *to, int base, char **units)
|
||||
{
|
||||
int c;
|
||||
char *endp;
|
||||
long long value;
|
||||
|
||||
while ((c = *str) && isspace(c))
|
||||
++str;
|
||||
|
||||
errno = 0;
|
||||
value = strtoll(str, &endp, base);
|
||||
|
||||
if (endp == str)
|
||||
return S_stdlib_noConversion;
|
||||
if (errno == EINVAL) /* Not universally supported */
|
||||
return S_stdlib_badBase;
|
||||
if (errno == ERANGE)
|
||||
return S_stdlib_overflow;
|
||||
|
||||
while ((c = *endp) && isspace(c))
|
||||
++endp;
|
||||
if (c && !units)
|
||||
return S_stdlib_extraneous;
|
||||
|
||||
*to = value;
|
||||
if (units)
|
||||
*units = endp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
epicsShareFunc int
|
||||
epicsParseULLong(const char *str, unsigned long long *to, int base, char **units)
|
||||
{
|
||||
int c;
|
||||
char *endp;
|
||||
unsigned long long value;
|
||||
|
||||
while ((c = *str) && isspace(c))
|
||||
++str;
|
||||
|
||||
errno = 0;
|
||||
value = strtoull(str, &endp, base);
|
||||
|
||||
if (endp == str)
|
||||
return S_stdlib_noConversion;
|
||||
if (errno == EINVAL) /* Not universally supported */
|
||||
return S_stdlib_badBase;
|
||||
if (errno == ERANGE)
|
||||
return S_stdlib_overflow;
|
||||
|
||||
while ((c = *endp) && isspace(c))
|
||||
++endp;
|
||||
if (c && !units)
|
||||
return S_stdlib_extraneous;
|
||||
|
||||
*to = value;
|
||||
if (units)
|
||||
*units = endp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
epicsShareFunc int
|
||||
epicsParseDouble(const char *str, double *to, char **units)
|
||||
{
|
||||
@@ -190,7 +252,7 @@ epicsParseInt32(const char *str, epicsInt32 *to, int base, char **units)
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
#if (LONG_MAX > 0x7fffffff)
|
||||
#if (LONG_MAX > 0x7fffffffLL)
|
||||
if (value < -0x80000000L || value > 0x7fffffffL)
|
||||
return S_stdlib_overflow;
|
||||
#endif
|
||||
@@ -208,7 +270,7 @@ epicsParseUInt32(const char *str, epicsUInt32 *to, int base, char **units)
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
#if (ULONG_MAX > 0xffffffff)
|
||||
#if (ULONG_MAX > 0xffffffffULL)
|
||||
if (value > 0xffffffffUL && value <= ~0xffffffffUL)
|
||||
return S_stdlib_overflow;
|
||||
#endif
|
||||
@@ -217,6 +279,43 @@ epicsParseUInt32(const char *str, epicsUInt32 *to, int base, char **units)
|
||||
return 0;
|
||||
}
|
||||
|
||||
epicsShareFunc int
|
||||
epicsParseInt64(const char *str, epicsInt64 *to, int base, char **units)
|
||||
{
|
||||
#if (LONG_MAX == 0x7fffffffffffffffLL)
|
||||
long value;
|
||||
int status = epicsParseLong(str, &value, base, units);
|
||||
#else
|
||||
long long value;
|
||||
int status = epicsParseLLong(str, &value, base, units);
|
||||
#endif
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
*to = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
epicsShareFunc int
|
||||
epicsParseUInt64(const char *str, epicsUInt64 *to, int base, char **units)
|
||||
{
|
||||
#if (ULONG_MAX == 0xffffffffffffffffULL)
|
||||
unsigned long value;
|
||||
int status = epicsParseULong(str, &value, base, units);
|
||||
#else
|
||||
unsigned long long value;
|
||||
int status = epicsParseULLong(str, &value, base, units);
|
||||
#endif
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
*to = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
epicsShareFunc int
|
||||
epicsParseFloat(const char *str, float *to, char **units)
|
||||
{
|
||||
|
||||
@@ -35,6 +35,10 @@ epicsShareFunc int
|
||||
epicsParseLong(const char *str, long *to, int base, char **units);
|
||||
epicsShareFunc int
|
||||
epicsParseULong(const char *str, unsigned long *to, int base, char **units);
|
||||
epicsShareFunc int
|
||||
epicsParseLLong(const char *str, long long *to, int base, char **units);
|
||||
epicsShareFunc int
|
||||
epicsParseULLong(const char *str, unsigned long long *to, int base, char **units);
|
||||
epicsShareFunc int
|
||||
epicsParseDouble(const char *str, double *to, char **units);
|
||||
|
||||
@@ -55,6 +59,11 @@ epicsShareFunc int
|
||||
epicsShareFunc int
|
||||
epicsParseUInt32(const char *str, epicsUInt32 *to, int base, char **units);
|
||||
|
||||
epicsShareFunc int
|
||||
epicsParseInt64(const char *str, epicsInt64 *to, int base, char **units);
|
||||
epicsShareFunc int
|
||||
epicsParseUInt64(const char *str, epicsUInt64 *to, int base, char **units);
|
||||
|
||||
#define epicsParseFloat32(str, to, units) epicsParseFloat(str, to, units)
|
||||
#define epicsParseFloat64(str, to, units) epicsParseDouble(str, to, units)
|
||||
|
||||
@@ -63,6 +72,8 @@ epicsShareFunc int
|
||||
*/
|
||||
#define epicsScanLong(str, to, base) !epicsParseLong(str, to, base, NULL)
|
||||
#define epicsScanULong(str, to, base) !epicsParseULong(str, to, base, NULL)
|
||||
#define epicsScanLLong(str, to, base) !epicsParseLLong(str, to, base, NULL)
|
||||
#define epicsScanULLong(str, to, base) !epicsParseULLong(str, to, base, NULL)
|
||||
#define epicsScanFloat(str, to) !epicsParseFloat(str, to, NULL)
|
||||
#define epicsScanDouble(str, to) !epicsParseDouble(str, to, NULL)
|
||||
|
||||
|
||||
@@ -133,6 +133,8 @@ INC_vxWorks += task_params.h
|
||||
Com_SRCS_vxWorks += epicsDynLink.c
|
||||
Com_SRCS_vxWorks += veclist.c
|
||||
Com_SRCS_vxWorks += logMsgToErrlog.cpp
|
||||
Com_SRCS_vxWorks += strtoll.c
|
||||
Com_SRCS_vxWorks += strtoull.c
|
||||
|
||||
#This forces the vxWorks compatibility stuff to be loaded
|
||||
OBJS_vxWorks = vxComLibrary
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Saskatchewan
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
* This header fragment is intended to be included as part of epicsString.h
|
||||
* This header is included as part of epicsString.h and epicsStdlib.h
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -18,6 +17,13 @@ extern "C" {
|
||||
*/
|
||||
epicsShareFunc double epicsStrtod(const char *str, char **endp);
|
||||
|
||||
/*
|
||||
* VxWorks doesn't provide these routines, so for now we do
|
||||
*/
|
||||
|
||||
long long int strtoll(const char *nptr, char **endptr, int base);
|
||||
unsigned long long int strtoull(const char *nptr, char **endptr, int base);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
139
src/libCom/osi/os/vxWorks/strtoll.c
Normal file
139
src/libCom/osi/os/vxWorks/strtoll.c
Normal file
@@ -0,0 +1,139 @@
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef LLONG_MAX
|
||||
#define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL
|
||||
#define LLONG_MIN (-0x7FFFFFFFFFFFFFFFLL - 1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Convert a string to a long long integer.
|
||||
*
|
||||
* Assumes that the upper and lower case
|
||||
* alphabets and digits are each contiguous.
|
||||
*/
|
||||
long long
|
||||
strtoll(const char * __restrict nptr, char ** __restrict endptr, int base)
|
||||
{
|
||||
const char *s;
|
||||
unsigned long long acc;
|
||||
char c;
|
||||
unsigned long long cutoff;
|
||||
int neg, any, cutlim;
|
||||
|
||||
/*
|
||||
* Skip white space and pick up leading +/- sign if any.
|
||||
* If base is 0, allow 0x for hex and 0 for octal, else
|
||||
* assume decimal; if base is already 16, allow 0x.
|
||||
*/
|
||||
s = nptr;
|
||||
do {
|
||||
c = *s++;
|
||||
} while (isspace((unsigned char)c));
|
||||
if (c == '-') {
|
||||
neg = 1;
|
||||
c = *s++;
|
||||
} else {
|
||||
neg = 0;
|
||||
if (c == '+')
|
||||
c = *s++;
|
||||
}
|
||||
if ((base == 0 || base == 16) &&
|
||||
c == '0' && (*s == 'x' || *s == 'X') &&
|
||||
((s[1] >= '0' && s[1] <= '9') ||
|
||||
(s[1] >= 'A' && s[1] <= 'F') ||
|
||||
(s[1] >= 'a' && s[1] <= 'f'))) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == '0' ? 8 : 10;
|
||||
acc = any = 0;
|
||||
if (base < 2 || base > 36)
|
||||
goto noconv;
|
||||
|
||||
/*
|
||||
* Compute the cutoff value between legal numbers and illegal
|
||||
* numbers. That is the largest legal value, divided by the
|
||||
* base. An input number that is greater than this value, if
|
||||
* followed by a legal input character, is too big. One that
|
||||
* is equal to this value may be valid or not; the limit
|
||||
* between valid and invalid numbers is then based on the last
|
||||
* digit. For instance, if the range for quads is
|
||||
* [-9223372036854775808..9223372036854775807] and the input base
|
||||
* is 10, cutoff will be set to 922337203685477580 and cutlim to
|
||||
* either 7 (neg==0) or 8 (neg==1), meaning that if we have
|
||||
* accumulated a value > 922337203685477580, or equal but the
|
||||
* next digit is > 7 (or 8), the number is too big, and we will
|
||||
* return a range error.
|
||||
*
|
||||
* Set 'any' if any `digits' consumed; make it negative to indicate
|
||||
* overflow.
|
||||
*/
|
||||
cutoff = neg ? (unsigned long long)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX
|
||||
: LLONG_MAX;
|
||||
cutlim = cutoff % base;
|
||||
cutoff /= base;
|
||||
for ( ; ; c = *s++) {
|
||||
if (c >= '0' && c <= '9')
|
||||
c -= '0';
|
||||
else if (c >= 'A' && c <= 'Z')
|
||||
c -= 'A' - 10;
|
||||
else if (c >= 'a' && c <= 'z')
|
||||
c -= 'a' - 10;
|
||||
else
|
||||
break;
|
||||
if (c >= base)
|
||||
break;
|
||||
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
|
||||
any = -1;
|
||||
else {
|
||||
any = 1;
|
||||
acc *= base;
|
||||
acc += c;
|
||||
}
|
||||
}
|
||||
if (any < 0) {
|
||||
acc = neg ? LLONG_MIN : LLONG_MAX;
|
||||
errno = ERANGE;
|
||||
} else if (!any) {
|
||||
noconv:
|
||||
errno = EINVAL;
|
||||
} else if (neg)
|
||||
acc = -acc;
|
||||
if (endptr != NULL)
|
||||
*endptr = (char *)(any ? s - 1 : nptr);
|
||||
return (acc);
|
||||
}
|
||||
116
src/libCom/osi/os/vxWorks/strtoull.c
Normal file
116
src/libCom/osi/os/vxWorks/strtoull.c
Normal file
@@ -0,0 +1,116 @@
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef ULLONG_MAX
|
||||
#define ULLONG_MAX 0xFFFFFFFFFFFFFFFFULL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Convert a string to an unsigned long long integer.
|
||||
*
|
||||
* Assumes that the upper and lower case
|
||||
* alphabets and digits are each contiguous.
|
||||
*/
|
||||
unsigned long long
|
||||
strtoull(const char * __restrict nptr, char ** __restrict endptr, int base)
|
||||
{
|
||||
const char *s;
|
||||
unsigned long long acc;
|
||||
char c;
|
||||
unsigned long long cutoff;
|
||||
int neg, any, cutlim;
|
||||
|
||||
/*
|
||||
* See strtoq for comments as to the logic used.
|
||||
*/
|
||||
s = nptr;
|
||||
do {
|
||||
c = *s++;
|
||||
} while (isspace((unsigned char)c));
|
||||
if (c == '-') {
|
||||
neg = 1;
|
||||
c = *s++;
|
||||
} else {
|
||||
neg = 0;
|
||||
if (c == '+')
|
||||
c = *s++;
|
||||
}
|
||||
if ((base == 0 || base == 16) &&
|
||||
c == '0' && (*s == 'x' || *s == 'X') &&
|
||||
((s[1] >= '0' && s[1] <= '9') ||
|
||||
(s[1] >= 'A' && s[1] <= 'F') ||
|
||||
(s[1] >= 'a' && s[1] <= 'f'))) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == '0' ? 8 : 10;
|
||||
acc = any = 0;
|
||||
if (base < 2 || base > 36)
|
||||
goto noconv;
|
||||
|
||||
cutoff = ULLONG_MAX / base;
|
||||
cutlim = ULLONG_MAX % base;
|
||||
for ( ; ; c = *s++) {
|
||||
if (c >= '0' && c <= '9')
|
||||
c -= '0';
|
||||
else if (c >= 'A' && c <= 'Z')
|
||||
c -= 'A' - 10;
|
||||
else if (c >= 'a' && c <= 'z')
|
||||
c -= 'a' - 10;
|
||||
else
|
||||
break;
|
||||
if (c >= base)
|
||||
break;
|
||||
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
|
||||
any = -1;
|
||||
else {
|
||||
any = 1;
|
||||
acc *= base;
|
||||
acc += c;
|
||||
}
|
||||
}
|
||||
if (any < 0) {
|
||||
acc = ULLONG_MAX;
|
||||
errno = ERANGE;
|
||||
} else if (!any) {
|
||||
noconv:
|
||||
errno = EINVAL;
|
||||
} else if (neg)
|
||||
acc = -acc;
|
||||
if (endptr != NULL)
|
||||
*endptr = (char *)(any ? s - 1 : nptr);
|
||||
return (acc);
|
||||
}
|
||||
@@ -58,6 +58,8 @@ MAIN(epicsStdlibTest)
|
||||
{
|
||||
unsigned long u;
|
||||
long l;
|
||||
unsigned long long ull;
|
||||
long long ll;
|
||||
double d;
|
||||
float f;
|
||||
char *endp;
|
||||
@@ -67,13 +69,19 @@ MAIN(epicsStdlibTest)
|
||||
epicsUInt16 u16;
|
||||
epicsInt32 i32;
|
||||
epicsUInt32 u32;
|
||||
epicsInt64 i64;
|
||||
epicsUInt64 u64;
|
||||
|
||||
testPlan(153);
|
||||
testPlan(199);
|
||||
|
||||
testOk(epicsParseLong("", &l, 0, NULL) == S_stdlib_noConversion,
|
||||
"Long '' => noConversion");
|
||||
testOk(epicsParseULong("", &u, 0, NULL) == S_stdlib_noConversion,
|
||||
"ULong '' => noConversion");
|
||||
testOk(epicsParseLLong("", &ll, 0, NULL) == S_stdlib_noConversion,
|
||||
"LLong '' => noConversion");
|
||||
testOk(epicsParseULLong("", &ull, 0, NULL) == S_stdlib_noConversion,
|
||||
"ULLong '' => noConversion");
|
||||
testOk(epicsParseFloat("", &f, NULL) == S_stdlib_noConversion,
|
||||
"Float '' => noConversion");
|
||||
testOk(epicsParseDouble("", &d, NULL) == S_stdlib_noConversion,
|
||||
@@ -83,6 +91,10 @@ MAIN(epicsStdlibTest)
|
||||
"Long '\\t 1\\n' => noConversion");
|
||||
testOk(epicsParseULong("\t \n", &u, 0, NULL) == S_stdlib_noConversion,
|
||||
"ULong '\\t 1\\n' => noConversion");
|
||||
testOk(epicsParseLLong("\t \n", &ll, 0, NULL) == S_stdlib_noConversion,
|
||||
"LLong '\\t 1\\n' => noConversion");
|
||||
testOk(epicsParseULLong("\t \n", &ull, 0, NULL) == S_stdlib_noConversion,
|
||||
"ULLong '\\t 1\\n' => noConversion");
|
||||
testOk(epicsParseFloat("\t \n", &f, NULL) == S_stdlib_noConversion,
|
||||
"Float '\\t 1\\n' => noConversion");
|
||||
testOk(epicsParseDouble("\t \n", &d, NULL) == S_stdlib_noConversion,
|
||||
@@ -92,6 +104,10 @@ MAIN(epicsStdlibTest)
|
||||
"Long '!' => noConversion");
|
||||
testOk(epicsParseULong("!", &u, 0, NULL) == S_stdlib_noConversion,
|
||||
"ULong '!' => noConversion");
|
||||
testOk(epicsParseLLong("!", &ll, 0, NULL) == S_stdlib_noConversion,
|
||||
"LLong '!' => noConversion");
|
||||
testOk(epicsParseULLong("!", &ull, 0, NULL) == S_stdlib_noConversion,
|
||||
"ULLong '!' => noConversion");
|
||||
testOk(epicsParseFloat("!", &f, NULL) == S_stdlib_noConversion,
|
||||
"Float '!' => noConversion");
|
||||
testOk(epicsParseDouble("!", &d, NULL) == S_stdlib_noConversion,
|
||||
@@ -99,16 +115,22 @@ MAIN(epicsStdlibTest)
|
||||
|
||||
testOk(epicsScanLong("0", &l, 0) && l == 0, "Long '0'");
|
||||
testOk(epicsScanULong("0", &u, 0) && u == 0, "ULong '0'");
|
||||
testOk(epicsScanLLong("0", &ll, 0) && ll == 0, "LLong '0'");
|
||||
testOk(epicsScanULLong("0", &ull, 0) && ull == 0, "ULLong '0'");
|
||||
testOk(epicsScanFloat("0", &f) && f == 0, "Float '0'");
|
||||
testOk(epicsScanDouble("0", &d) && d == 0, "Double '0'");
|
||||
|
||||
testOk(epicsScanLong("\t 1\n", &l, 0) && l == 1, "Long '\\t 1\\n'");
|
||||
testOk(epicsScanULong("\t 1\n", &u, 0) && u == 1, "ULong '\\t 1\\n'");
|
||||
testOk(epicsScanLLong("\t 1\n", &ll, 0) && ll == 1, "LLong '\\t 1\\n'");
|
||||
testOk(epicsScanULLong("\t 1\n", &ull, 0) && ull == 1, "ULLong '\\t 1\\n'");
|
||||
testOk(epicsScanFloat("\t 1\n", &f) && f == 1, "Float '\\t 1\\n'");
|
||||
testOk(epicsScanDouble("\t 1\n", &d) && d == 1, "Double '\\t 1\\n'");
|
||||
|
||||
testOk(epicsScanLong("-1", &l, 0) && l == -1, "Long '-1'");
|
||||
testOk(epicsScanULong("-1", &u, 0) && u + 1 == 0, "ULong '-1'");
|
||||
testOk(epicsScanLLong("-1", &ll, 0) && ll == -1, "LLong '-1'");
|
||||
testOk(epicsScanULLong("-1", &ull, 0) && ull + 1 == 0, "ULLong '-1'");
|
||||
testOk(epicsScanFloat("-1", &f) && f == -1, "Float '-1'");
|
||||
testOk(epicsScanDouble("-1", &d) && d == -1, "Double '-1'");
|
||||
|
||||
@@ -116,6 +138,10 @@ MAIN(epicsStdlibTest)
|
||||
"Long '2!' => extraneous");
|
||||
testOk(epicsParseULong("2!", &u, 0, NULL) == S_stdlib_extraneous,
|
||||
"ULong '2!' => extraneous");
|
||||
testOk(epicsParseLLong("2!", &ll, 0, NULL) == S_stdlib_extraneous,
|
||||
"LLong '2!' => extraneous");
|
||||
testOk(epicsParseULLong("2!", &ull, 0, NULL) == S_stdlib_extraneous,
|
||||
"ULLong '2!' => extraneous");
|
||||
testOk(epicsParseFloat("2!", &f, NULL) == S_stdlib_extraneous,
|
||||
"Float '2!' => extraneous");
|
||||
testOk(epicsParseDouble("2!", &d, NULL) == S_stdlib_extraneous,
|
||||
@@ -125,6 +151,10 @@ MAIN(epicsStdlibTest)
|
||||
"Long '3 \\n\\t!' => extraneous");
|
||||
testOk(epicsParseULong("3 \n\t!", &u, 0, NULL) == S_stdlib_extraneous,
|
||||
"ULong '3 \\n\\t!' => extraneous");
|
||||
testOk(epicsParseLLong("3 \n\t!", &ll, 0, NULL) == S_stdlib_extraneous,
|
||||
"LLong '3 \\n\\t!' => extraneous");
|
||||
testOk(epicsParseULLong("3 \n\t!", &ull, 0, NULL) == S_stdlib_extraneous,
|
||||
"ULLong '3 \\n\\t!' => extraneous");
|
||||
testOk(epicsParseFloat("3 \n\t!", &f, NULL) == S_stdlib_extraneous,
|
||||
"Float '3 \\n\\t!' => extraneous");
|
||||
testOk(epicsParseDouble("3 \n\t!", &d, NULL) == S_stdlib_extraneous,
|
||||
@@ -134,6 +164,10 @@ MAIN(epicsStdlibTest)
|
||||
"Long '2!' => units='!'");
|
||||
testOk(!epicsParseULong("2!", &u, 0, &endp) && *endp == '!',
|
||||
"ULong '2!' => units='!'");
|
||||
testOk(!epicsParseLLong("2!", &ll, 0, &endp) && *endp == '!',
|
||||
"LLong '2!' => units='!'");
|
||||
testOk(!epicsParseULLong("2!", &ull, 0, &endp) && *endp == '!',
|
||||
"ULLong '2!' => units='!'");
|
||||
testOk(!epicsParseFloat("2!", &f, &endp) && *endp == '!',
|
||||
"Float '2!' => units='!'");
|
||||
testOk(!epicsParseDouble("2!", &d, &endp) && *endp == '!',
|
||||
@@ -143,6 +177,10 @@ MAIN(epicsStdlibTest)
|
||||
"Long '3 \\n\\t!' => units='!'");
|
||||
testOk(!epicsParseULong("3 \n\t!", &u, 0, &endp) && *endp == '!',
|
||||
"ULong '3 \\n\\t!' => units='!'");
|
||||
testOk(!epicsParseLLong("3 \n\t!", &ll, 0, &endp) && *endp == '!',
|
||||
"LLong '3 \\n\\t!' => units='!'");
|
||||
testOk(!epicsParseULLong("3 \n\t!", &ull, 0, &endp) && *endp == '!',
|
||||
"ULLong '3 \\n\\t!' => units='!'");
|
||||
testOk(!epicsParseFloat("3 \n\t!", &f, &endp) && *endp == '!',
|
||||
"Float '3 \\n\\t!' => units='!'");
|
||||
testOk(!epicsParseDouble("3 \n\t!", &d, &endp) && *endp == '!',
|
||||
@@ -150,31 +188,43 @@ MAIN(epicsStdlibTest)
|
||||
|
||||
testOk(epicsScanLong("0x0", &l, 0) && l == 0, "Long '0x0'");
|
||||
testOk(epicsScanULong("0x0", &u, 0) && u == 0, "ULong '0x0'");
|
||||
testOk(epicsScanLLong("0x0", &ll, 0) && ll == 0, "LLong '0x0'");
|
||||
testOk(epicsScanULLong("0x0", &ull, 0) && ull == 0, "ULLong '0x0'");
|
||||
testOk(epicsScanFloat("0x0", &f) && f == 0, "Float '0x0'");
|
||||
testOk(epicsScanDouble("0x0", &d) && d == 0, "Double '0x0'");
|
||||
|
||||
testOk(epicsScanLong("0x1", &l, 0) && l == 1, "Long '0x1'");
|
||||
testOk(epicsScanULong("0x1", &u, 0) && u == 1, "ULong '0x1'");
|
||||
testOk(epicsScanLLong("0x1", &ll, 0) && ll == 1, "LLong '0x1'");
|
||||
testOk(epicsScanULLong("0x1", &ull, 0) && ull == 1, "ULLong '0x1'");
|
||||
testOk(epicsScanFloat("0x1", &f) && f == 1, "Float '0x1'");
|
||||
testOk(epicsScanDouble("0x1", &d) && d == 1, "Double '0x1'");
|
||||
|
||||
testOk(epicsScanLong("+0x1", &l, 0) && l == 1, "Long '+0x1'");
|
||||
testOk(epicsScanULong("+0x1", &u, 0) && u == 1, "ULong '+0x1'");
|
||||
testOk(epicsScanLLong("+0x1", &ll, 0) && ll == 1, "LLong '+0x1'");
|
||||
testOk(epicsScanULLong("+0x1", &ull, 0) && ull == 1, "ULLong '+0x1'");
|
||||
testOk(epicsScanFloat("+0x1", &f) && f == 1, "Float '+0x1'");
|
||||
testOk(epicsScanDouble("+0x1", &d) && d == 1, "Double '+0x1'");
|
||||
|
||||
testOk(epicsScanLong("-0x1", &l, 0) && l == -1, "Long '-0x1'");
|
||||
testOk(epicsScanULong("-0x1", &u, 0) && u == -1, "ULong '-0x1'");
|
||||
testOk(epicsScanLLong("-0x1", &ll, 0) && ll == -1, "LLong '-0x1'");
|
||||
testOk(epicsScanULLong("-0x1", &ull, 0) && ull == -1, "ULLong '-0x1'");
|
||||
testOk(epicsScanFloat("-0x1", &f) && f == -1, "Float '-0x1'");
|
||||
testOk(epicsScanDouble("-0x1", &d) && d == -1, "Double '-0x1'");
|
||||
|
||||
testOk(epicsScanLong("0xf", &l, 0) && l == 15, "Long '0xf'");
|
||||
testOk(epicsScanULong("0xf", &u, 0) && u == 15, "ULong '0xf'");
|
||||
testOk(epicsScanLLong("0xf", &ll, 0) && ll == 15, "LLong '0xf'");
|
||||
testOk(epicsScanULLong("0xf", &ull, 0) && ull == 15, "ULLong '0xf'");
|
||||
testOk(epicsScanFloat("0xf", &f) && f == 15, "Float '0xf'");
|
||||
testOk(epicsScanDouble("0xf", &d) && d == 15, "Double '0xf'");
|
||||
|
||||
testOk(epicsScanLong("0XF", &l, 0) && l == 15, "Long '0XF'");
|
||||
testOk(epicsScanULong("0XF", &u, 0) && u == 15, "ULong '0XF'");
|
||||
testOk(epicsScanLLong("0XF", &ll, 0) && ll == 15, "LLong '0XF'");
|
||||
testOk(epicsScanULLong("0XF", &ull, 0) && ull == 15, "ULLong '0XF'");
|
||||
testOk(epicsScanFloat("0XF", &f) && f == 15, "Float '0XF'");
|
||||
testOk(epicsScanDouble("0XF", &d) && d == 15, "Double '0XF'");
|
||||
|
||||
@@ -182,6 +232,11 @@ MAIN(epicsStdlibTest)
|
||||
"Long '0x0' in base 10 => extraneous");
|
||||
testOk(epicsParseULong("0x0", &u, 10, NULL) == S_stdlib_extraneous,
|
||||
"ULong '0x0' in base 10 => extraneous");
|
||||
testOk(epicsParseLLong("0x0", &ll, 10, NULL) == S_stdlib_extraneous,
|
||||
"LLong '0x0' in base 10 => extraneous");
|
||||
testOk(epicsParseULLong("0x0", &ull, 10, NULL) == S_stdlib_extraneous,
|
||||
"ULLong '0x0' in base 10 => extraneous");
|
||||
|
||||
testOk(epicsScanLong("0x10", &l, 0) && l == 0x10,
|
||||
"Long '0x10' in base 0");
|
||||
testOk(epicsScanULong("0x10", &u, 0) && u == 0x10,
|
||||
@@ -199,6 +254,10 @@ MAIN(epicsStdlibTest)
|
||||
"Long '0x7fffffff'");
|
||||
testOk(epicsScanULong("0xffffffff", &u, 0) && u == 0xffffffff,
|
||||
"ULong '0xffffffff'");
|
||||
testOk(epicsScanLLong("0x7fffffffffffffff", &ll, 0) &&
|
||||
ll == 0x7fffffffffffffff, "LLong '0x7fffffffffffffff'");
|
||||
testOk(epicsScanULLong("0xffffffffffffffff", &ull, 0) &&
|
||||
ull == 0xffffffffffffffff, "ULLong '0xffffffffffffffff'");
|
||||
testOk(epicsScanFloat("0xffffff", &f) && f == 0xffffff,
|
||||
"Float '0xffffff'");
|
||||
testOk(epicsScanDouble("0xffffffff", &d) && d == 0xffffffff,
|
||||
@@ -208,6 +267,10 @@ MAIN(epicsStdlibTest)
|
||||
"Long '-0x7fffffff'");
|
||||
testOk(epicsScanULong("-0x7fffffff", &u, 0) && u == -0x7fffffff,
|
||||
"ULong '-0x7fffffff'");
|
||||
testOk(epicsScanLLong("-0x7fffffffffffffff", &ll, 0)
|
||||
&& ll == -0x7fffffffffffffff, "LLong '-0x7fffffffffffffff'");
|
||||
testOk(epicsScanULLong("-0x7fffffffffffffff", &ull, 0) &&
|
||||
ull == -0x7fffffffffffffff, "ULLong '-0x7fffffffffffffff'");
|
||||
testOk(epicsScanFloat("-0xffffff", &f) && f == -0xffffff,
|
||||
"Float '-0xffffff'");
|
||||
testOk(epicsScanDouble("-0x7fffffff", &d) && d == -0x7fffffff,
|
||||
@@ -264,6 +327,23 @@ MAIN(epicsStdlibTest)
|
||||
testOk(epicsParseUInt32("-0x100000000", &u32, 0, NULL) == S_stdlib_overflow,
|
||||
"UInt32 '-0x100000000' => overflow");
|
||||
|
||||
testOk(!epicsParseInt64("0x7fffffffffffffff", &i64, 0, NULL) &&
|
||||
i64 == 0x7fffffffffffffff, "Int64 '0x7fffffffffffffff'");
|
||||
testOk(!epicsParseInt64("-0x8000000000000000", &i64, 0, NULL) &&
|
||||
i64 == -0x8000000000000000L, "Int64 '-0x8000000000000000'");
|
||||
testOk(!epicsParseUInt64("0xffffffffffffffff", &u64, 0, NULL) &&
|
||||
u64 == 0xffffffffffffffff, "UInt64 '0xffffffffffffffff'");
|
||||
testOk(!epicsParseUInt64("-1", &u64, 0, NULL) && u64 == 0xffffffffffffffffU,
|
||||
"UInt64 '-1'");
|
||||
testOk(epicsParseInt64("0x8000000000000000", &i64, 0, NULL) == S_stdlib_overflow,
|
||||
"Int64 '0x8000000000000000' => overflow");
|
||||
testOk(epicsParseInt64("-0x8000000000000001", &i64, 0, NULL) == S_stdlib_overflow,
|
||||
"Int64 '-0x8000000000000001' => overflow");
|
||||
testOk(epicsParseUInt64("0x10000000000000000", &u64, 0, NULL) == S_stdlib_overflow,
|
||||
"UInt64 '0x10000000000000000' => overflow");
|
||||
testOk(epicsParseUInt64("-0x10000000000000000", &u64, 0, NULL) == S_stdlib_overflow,
|
||||
"UInt64 '-0x10000000000000000' => overflow");
|
||||
|
||||
testOk(epicsScanFloat(".1", &f) && fabs(f - 0.1) < 1e-7,
|
||||
"Float '.1'");
|
||||
testOk(epicsScanDouble(".1", &d) && fabs(d - 0.1) < 1e-15,
|
||||
|
||||
Reference in New Issue
Block a user