summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/attotime.cpp
blob: c62e803e2c9b582b74d80e48758fa945a2688cde (plain) (blame)
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));
}