1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************
attotime.cpp
Support functions for working with attotime data.
***************************************************************************/
#include "emucore.h"
#include "eminline.h"
#include "attotime.h"
const attotime attotime::zero(0);
const attotime attotime::never(0x7fffffffffffffffll, 0xfffffffd);
//-------------------------------------------------
// generate_string - flexibly generate a string
// of arbitrary precision
//-------------------------------------------------
char const *attotime::generate_string(char *buffer, int precision, bool dividers) const noexcept
{
// special case: never
if (is_never())
sprintf(buffer, "%-*s", precision, "(never)");
// start with seconds
char *dest = buffer + sprintf(buffer, "%d", seconds());
if (precision > 0)
{
*dest++ = '.';
// handle the fraction
static s64 const s_divisors[] =
{
(subseconds::PER_SECOND - 1) / 10ll + 1,
(subseconds::PER_SECOND - 1) / 100ll + 1,
(subseconds::PER_SECOND - 1) / 1000ll + 1,
(subseconds::PER_SECOND - 1) / 10000ll + 1,
(subseconds::PER_SECOND - 1) / 100000ll + 1,
(subseconds::PER_SECOND - 1) / 1000000ll + 1,
(subseconds::PER_SECOND - 1) / 10000000ll + 1,
(subseconds::PER_SECOND - 1) / 100000000ll + 1,
(subseconds::PER_SECOND - 1) / 1000000000ll + 1,
(subseconds::PER_SECOND - 1) / 10000000000ll + 1,
(subseconds::PER_SECOND - 1) / 100000000000ll + 1,
(subseconds::PER_SECOND - 1) / 1000000000000ll + 1,
(subseconds::PER_SECOND - 1) / 10000000000000ll + 1,
(subseconds::PER_SECOND - 1) / 100000000000000ll + 1,
(subseconds::PER_SECOND - 1) / 1000000000000000ll + 1,
(subseconds::PER_SECOND - 1) / 10000000000000000ll + 1,
(subseconds::PER_SECOND - 1) / 100000000000000000ll + 1,
(subseconds::PER_SECOND - 1) / 1000000000000000000ll + 1
};
s64 rem = frac().raw();
precision = std::min<int>(precision, std::size(s_divisors));
for (int index = 0; index < precision; index++)
{
if (dividers && index != 0 && index % 3 == 0)
*dest++ = '\'';
s64 digit = rem / s_divisors[index];
rem -= digit * s_divisors[index];
*dest++ = '0' + std::clamp<int>(digit, 0, 9);
}
*dest = 0;
}
return buffer;
}
//-------------------------------------------------
// as_string - return a temporary printable
// string describing an attotime
//-------------------------------------------------
const char *attotime::as_string(int precision, bool dividers) const noexcept
{
static char s_buffers[8][MAX_STRING_LEN];
static int s_nextbuf;
return generate_string(&s_buffers[s_nextbuf++ % 8][0], precision, dividers);
}
//-------------------------------------------------
// to_string - return a human-readable string
// describing an attotime for use in logs
//-------------------------------------------------
std::string attotime::to_string(int precision, bool dividers) const
{
char buffer[MAX_STRING_LEN];
return std::string(generate_string(&buffer[0], precision, dividers));
}
|