Coverage Report

Created: 2023-05-19 06:16

/src/ntp-dev/libntp/vint64ops.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * vint64ops.c - operations on 'vint64' values
3
 *
4
 * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project.
5
 * The contents of 'html/copyright.html' apply.
6
 * ----------------------------------------------------------------------
7
 * This is an attempt to get the vint64 calculations stuff centralised.
8
 */
9
10
#include <config.h>
11
#include <stdlib.h>
12
#include <ctype.h>
13
#include <string.h>
14
#include <errno.h>
15
16
#include "ntp_types.h"
17
#include "ntp_fp.h"
18
#include "vint64ops.h"
19
20
/* ---------------------------------------------------------------------
21
 * GCC is rather sticky with its 'const' attribute. We have to do it more
22
 * explicit than with a cast if we want to get rid of a CONST qualifier.
23
 * Greetings from the PASCAL world, where casting was only possible via
24
 * untagged unions...
25
 */
26
static inline void*
27
noconst(
28
  const void* ptr
29
  )
30
0
{
31
0
  union {
32
0
    const void * cp;
33
0
    void *       vp;
34
0
  } tmp;
35
0
  tmp.cp = ptr;
36
0
  return tmp.vp;
37
0
}
38
39
/* -------------------------------------------------------------------------*/
40
41
vint64
42
strtouv64(
43
  const char * begp,
44
  char **      endp,
45
  int          base
46
  )
47
0
{
48
0
  vint64  res;
49
0
  u_char  digit;
50
0
  int     sig, num;
51
0
  const u_char *src;
52
  
53
0
  num = sig = 0;
54
0
  src = (const u_char*)begp;
55
0
  while (isspace(*src))
56
0
    src++;
57
58
0
  if (*src == '-') {
59
0
    src++;
60
0
    sig = 1;
61
0
  } else  if (*src == '+') {
62
0
    src++;
63
0
  }
64
65
0
  if (base == 0) {
66
0
    base = 10;
67
0
    if (*src == '0') {
68
0
      base = 8;
69
0
      if (toupper(*++src) == 'X') {
70
0
        src++;
71
0
        base = 16;
72
0
      }
73
0
    }
74
0
  } else if (base == 16) { /* remove optional leading '0x' or '0X' */
75
0
    if (src[0] == '0' && toupper(src[1]) == 'X')
76
0
      src += 2;
77
0
  } else if (base <= 2 || base > 36) {
78
0
    memset(&res, 0xFF, sizeof(res));
79
0
    errno = ERANGE;
80
0
    return res;
81
0
  }
82
  
83
0
  memset(&res, 0, sizeof(res));
84
0
  while (*src) {
85
0
    if (isdigit(*src))
86
0
      digit = *src - '0';
87
0
    else if (isupper(*src))
88
0
      digit = *src - 'A' + 10;
89
0
    else if (islower(*src))
90
0
      digit = *src - 'a' + 10;
91
0
    else
92
0
      break;
93
0
    if (digit >= base)
94
0
      break;
95
0
    num = 1;
96
0
#if defined(HAVE_INT64)
97
0
    res.Q_s = res.Q_s * base + digit;
98
#else
99
    /* res *= base, using 16x16->32 bit
100
     * multiplication. Slow but portable.
101
     */ 
102
    {
103
      uint32_t accu;
104
      accu       = (uint32_t)res.W_s.ll * base;
105
      res.W_s.ll = (uint16_t)accu;
106
      accu       = (accu >> 16)
107
                 + (uint32_t)res.W_s.lh * base;
108
      res.W_s.lh = (uint16_t)accu;
109
      /* the upper bits can be done in one step: */
110
      res.D_s.hi = res.D_s.hi * base + (accu >> 16);
111
    }
112
    M_ADD(res.D_s.hi, res.D_s.lo, 0, digit);
113
#endif
114
0
    src++;
115
0
  }
116
0
  if (!num)
117
0
    errno = EINVAL;
118
0
  if (endp)
119
0
    *endp = (char*)noconst(src);
120
0
  if (sig)
121
0
    M_NEG(res.D_s.hi, res.D_s.lo);
122
0
  return res;
123
0
}
124
125
/* -------------------------------------------------------------------------*/
126
127
int
128
icmpv64(
129
  const vint64 * lhs,
130
  const vint64 * rhs
131
  )
132
0
{
133
0
  int res;
134
135
0
#if defined(HAVE_INT64)
136
0
  res = (lhs->q_s > rhs->q_s)
137
0
      - (lhs->q_s < rhs->q_s);
138
#else 
139
  res = (lhs->d_s.hi > rhs->d_s.hi)
140
      - (lhs->d_s.hi < rhs->d_s.hi);
141
  if ( ! res )
142
    res = (lhs->D_s.lo > rhs->D_s.lo)
143
        - (lhs->D_s.lo < rhs->D_s.lo);
144
#endif
145
146
0
  return res;
147
0
}
148
149
/* -------------------------------------------------------------------------*/
150
151
int
152
ucmpv64(
153
  const vint64 * lhs,
154
  const vint64 * rhs
155
  )
156
0
{
157
0
  int res;
158
  
159
0
#if defined(HAVE_INT64)
160
0
  res = (lhs->Q_s > rhs->Q_s)
161
0
      - (lhs->Q_s < rhs->Q_s);
162
#else 
163
  res = (lhs->D_s.hi > rhs->D_s.hi)
164
      - (lhs->D_s.hi < rhs->D_s.hi);
165
  if ( ! res )
166
    res = (lhs->D_s.lo > rhs->D_s.lo)
167
        - (lhs->D_s.lo < rhs->D_s.lo);
168
#endif
169
0
  return res;
170
0
}
171
172
/* -------------------------------------------------------------------------*/
173
174
vint64
175
addv64(
176
  const vint64 *lhs,
177
  const vint64 *rhs
178
  )
179
0
{
180
0
  vint64 res;
181
182
0
#if defined(HAVE_INT64)
183
0
  res.Q_s = lhs->Q_s + rhs->Q_s;
184
#else
185
  res = *lhs;
186
  M_ADD(res.D_s.hi, res.D_s.lo, rhs->D_s.hi, rhs->D_s.lo);
187
#endif
188
0
  return res;
189
0
}
190
191
/* -------------------------------------------------------------------------*/
192
193
vint64
194
subv64(
195
  const vint64 *lhs,
196
  const vint64 *rhs
197
  )
198
0
{
199
0
  vint64 res;
200
201
0
#if defined(HAVE_INT64)
202
0
  res.Q_s = lhs->Q_s - rhs->Q_s;
203
#else
204
  res = *lhs;
205
  M_SUB(res.D_s.hi, res.D_s.lo, rhs->D_s.hi, rhs->D_s.lo);
206
#endif
207
0
  return res;
208
0
}
209
210
/* -------------------------------------------------------------------------*/
211
212
vint64
213
addv64i32(
214
  const vint64 * lhs,
215
  int32_t        rhs
216
  )
217
0
{
218
0
  vint64 res;
219
220
0
  res = *lhs;
221
0
#if defined(HAVE_INT64)
222
0
  res.q_s += rhs;
223
#else
224
  M_ADD(res.D_s.hi, res.D_s.lo,  -(rhs < 0), rhs);
225
#endif
226
0
  return res;
227
0
}
228
229
/* -------------------------------------------------------------------------*/
230
231
vint64
232
subv64i32(
233
  const vint64 * lhs,
234
  int32_t        rhs
235
  )
236
0
{
237
0
  vint64 res;
238
239
0
  res = *lhs;
240
0
#if defined(HAVE_INT64)
241
0
  res.q_s -= rhs;
242
#else
243
  M_SUB(res.D_s.hi, res.D_s.lo,  -(rhs < 0), rhs);
244
#endif
245
0
  return res;
246
0
}
247
248
/* -------------------------------------------------------------------------*/
249
250
vint64
251
addv64u32(
252
  const vint64 * lhs,
253
  uint32_t       rhs
254
  )
255
0
{
256
0
  vint64 res;
257
258
0
  res = *lhs;
259
0
#if defined(HAVE_INT64)
260
0
  res.Q_s += rhs;
261
#else
262
  M_ADD(res.D_s.hi, res.D_s.lo, 0, rhs);
263
#endif
264
0
  return res;
265
0
}
266
267
/* -------------------------------------------------------------------------*/
268
269
vint64
270
subv64u32(
271
  const vint64 * lhs,
272
  uint32_t       rhs
273
  )
274
0
{
275
0
  vint64 res;
276
277
0
  res = *lhs;
278
0
#if defined(HAVE_INT64)
279
0
  res.Q_s -= rhs;
280
#else
281
  M_SUB(res.D_s.hi, res.D_s.lo, 0, rhs);
282
#endif
283
0
  return res;
284
0
}