Coverage Report

Created: 2026-02-26 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ntp-dev/libntp/vint64ops.c
Line
Count
Source
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 "ntp_malloc.h"
19
#include "vint64ops.h"
20
21
/* -------------------------------------------------------------------------*/
22
23
vint64
24
strtouv64(
25
  char *  begp,
26
  char ** endp,
27
  int base
28
  )
29
0
{
30
0
  vint64  res;
31
0
  u_char  digit;
32
0
  int sig, num;
33
0
  u_char *src;
34
  
35
0
  num = sig = 0;
36
0
  src = (u_char *)begp;
37
0
  while (isspace(*src))
38
0
    src++;
39
40
0
  if (*src == '-') {
41
0
    src++;
42
0
    sig = 1;
43
0
  } else  if (*src == '+') {
44
0
    src++;
45
0
  }
46
47
0
  if (base == 0) {
48
0
    base = 10;
49
0
    if (*src == '0') {
50
0
      base = 8;
51
0
      if (toupper(*++src) == 'X') {
52
0
        src++;
53
0
        base = 16;
54
0
      }
55
0
    }
56
0
  } else if (base == 16) { /* remove optional leading '0x' or '0X' */
57
0
    if (src[0] == '0' && toupper(src[1]) == 'X')
58
0
      src += 2;
59
0
  } else if (base <= 2 || base > 36) {
60
0
    memset(&res, 0xFF, sizeof(res));
61
0
    errno = ERANGE;
62
0
    return res;
63
0
  }
64
  
65
0
  ZERO(res);
66
0
  while (*src) {
67
0
    if (isdigit(*src))
68
0
      digit = *src - '0';
69
0
    else if (isupper(*src))
70
0
      digit = *src - 'A' + 10;
71
0
    else if (islower(*src))
72
0
      digit = *src - 'a' + 10;
73
0
    else
74
0
      break;
75
0
    if (digit >= base)
76
0
      break;
77
0
    num = 1;
78
0
#if defined(HAVE_INT64)
79
0
    res.Q_s = res.Q_s * base + digit;
80
#else
81
    /* res *= base, using 16x16->32 bit
82
     * multiplication. Slow but portable.
83
     */ 
84
    {
85
      uint32_t accu;
86
      accu       = (uint32_t)res.W_s.ll * base;
87
      res.W_s.ll = (uint16_t)accu;
88
      accu       = (accu >> 16)
89
                 + (uint32_t)res.W_s.lh * base;
90
      res.W_s.lh = (uint16_t)accu;
91
      /* the upper bits can be done in one step: */
92
      res.D_s.hi = res.D_s.hi * base + (accu >> 16);
93
    }
94
    M_ADD(res.D_s.hi, res.D_s.lo, 0, digit);
95
#endif
96
0
    src++;
97
0
  }
98
0
  if (!num)
99
0
    errno = EINVAL;
100
0
  if (endp)
101
0
    *endp = (char *)src;
102
0
  if (sig)
103
0
    M_NEG(res.D_s.hi, res.D_s.lo);
104
0
  return res;
105
0
}
106
107
/* -------------------------------------------------------------------------*/
108
109
int
110
icmpv64(
111
  const vint64 * lhs,
112
  const vint64 * rhs
113
  )
114
0
{
115
0
  int res;
116
117
0
#if defined(HAVE_INT64)
118
0
  res = (lhs->q_s > rhs->q_s)
119
0
      - (lhs->q_s < rhs->q_s);
120
#else 
121
  res = (lhs->d_s.hi > rhs->d_s.hi)
122
      - (lhs->d_s.hi < rhs->d_s.hi);
123
  if ( ! res )
124
    res = (lhs->D_s.lo > rhs->D_s.lo)
125
        - (lhs->D_s.lo < rhs->D_s.lo);
126
#endif
127
128
0
  return res;
129
0
}
130
131
/* -------------------------------------------------------------------------*/
132
133
int
134
ucmpv64(
135
  const vint64 * lhs,
136
  const vint64 * rhs
137
  )
138
0
{
139
0
  int res;
140
  
141
0
#if defined(HAVE_INT64)
142
0
  res = (lhs->Q_s > rhs->Q_s)
143
0
      - (lhs->Q_s < rhs->Q_s);
144
#else 
145
  res = (lhs->D_s.hi > rhs->D_s.hi)
146
      - (lhs->D_s.hi < rhs->D_s.hi);
147
  if ( ! res )
148
    res = (lhs->D_s.lo > rhs->D_s.lo)
149
        - (lhs->D_s.lo < rhs->D_s.lo);
150
#endif
151
0
  return res;
152
0
}
153
154
/* -------------------------------------------------------------------------*/
155
156
vint64
157
addv64(
158
  const vint64 *lhs,
159
  const vint64 *rhs
160
  )
161
0
{
162
0
  vint64 res;
163
164
0
#if defined(HAVE_INT64)
165
0
  res.Q_s = lhs->Q_s + rhs->Q_s;
166
#else
167
  res = *lhs;
168
  M_ADD(res.D_s.hi, res.D_s.lo, rhs->D_s.hi, rhs->D_s.lo);
169
#endif
170
0
  return res;
171
0
}
172
173
/* -------------------------------------------------------------------------*/
174
175
vint64
176
subv64(
177
  const vint64 *lhs,
178
  const vint64 *rhs
179
  )
180
0
{
181
0
  vint64 res;
182
183
0
#if defined(HAVE_INT64)
184
0
  res.Q_s = lhs->Q_s - rhs->Q_s;
185
#else
186
  res = *lhs;
187
  M_SUB(res.D_s.hi, res.D_s.lo, rhs->D_s.hi, rhs->D_s.lo);
188
#endif
189
0
  return res;
190
0
}
191
192
/* -------------------------------------------------------------------------*/
193
194
vint64
195
addv64i32(
196
  const vint64 * lhs,
197
  int32_t        rhs
198
  )
199
0
{
200
0
  vint64 res;
201
202
0
  res = *lhs;
203
0
#if defined(HAVE_INT64)
204
0
  res.q_s += rhs;
205
#else
206
  M_ADD(res.D_s.hi, res.D_s.lo,  -(rhs < 0), rhs);
207
#endif
208
0
  return res;
209
0
}
210
211
/* -------------------------------------------------------------------------*/
212
213
vint64
214
subv64i32(
215
  const vint64 * lhs,
216
  int32_t        rhs
217
  )
218
0
{
219
0
  vint64 res;
220
221
0
  res = *lhs;
222
0
#if defined(HAVE_INT64)
223
0
  res.q_s -= rhs;
224
#else
225
  M_SUB(res.D_s.hi, res.D_s.lo,  -(rhs < 0), rhs);
226
#endif
227
0
  return res;
228
0
}
229
230
/* -------------------------------------------------------------------------*/
231
232
vint64
233
addv64u32(
234
  const vint64 * lhs,
235
  uint32_t       rhs
236
  )
237
0
{
238
0
  vint64 res;
239
240
0
  res = *lhs;
241
0
#if defined(HAVE_INT64)
242
0
  res.Q_s += rhs;
243
#else
244
  M_ADD(res.D_s.hi, res.D_s.lo, 0, rhs);
245
#endif
246
0
  return res;
247
0
}
248
249
/* -------------------------------------------------------------------------*/
250
251
vint64
252
subv64u32(
253
  const vint64 * lhs,
254
  uint32_t       rhs
255
  )
256
0
{
257
0
  vint64 res;
258
259
0
  res = *lhs;
260
0
#if defined(HAVE_INT64)
261
0
  res.Q_s -= rhs;
262
#else
263
  M_SUB(res.D_s.hi, res.D_s.lo, 0, rhs);
264
#endif
265
0
  return res;
266
0
}