Dev: improve robustness of CTags.cmake
[marnav.git] / src / marnav / nmea / time.cpp
blobc779b79ec5068a1f823a274a2b45c3744e1529ac
1 #include <marnav/nmea/time.hpp>
2 #include <stdexcept>
4 namespace marnav
6 namespace nmea
9 /// @cond DEV
10 namespace
12 template <class T> static T parse_time(const std::string & str)
14 try {
15 std::size_t pos = 0;
16 double t = std::stod(str, &pos);
17 if (pos != str.size())
18 throw std::invalid_argument{"invalid format for 'double'"};
20 const uint32_t h = static_cast<uint32_t>(t / 10000) % 100;
21 const uint32_t m = static_cast<uint32_t>(t / 100) % 100;
22 const uint32_t s = static_cast<uint32_t>(t) % 100;
23 const uint32_t ms = static_cast<uint32_t>(t * 1000) % 1000;
24 return T{h, m, s, ms};
25 } catch (std::invalid_argument &) {
26 throw std::invalid_argument{"invalid format, 'HHMMSS[.mmm]' expected"};
30 /// @endcond
32 void trait_time::check(uint32_t h, uint32_t m, uint32_t s, uint32_t ms)
34 if (h > 23)
35 throw std::invalid_argument{"invalid hour in nmea::time"};
36 if (m > 59)
37 throw std::invalid_argument{"invalid minute in nmea::time"};
38 if (s > 59)
39 throw std::invalid_argument{"invalid second in nmea::time"};
40 if (ms > 999)
41 throw std::invalid_argument{"invalid milliseconds in nmea::time"};
44 void trait_duration::check(uint32_t h, uint32_t m, uint32_t s, uint32_t ms)
46 if (h > 99)
47 throw std::invalid_argument{"invalid hour in nmea::duration"};
48 if (m > 59)
49 throw std::invalid_argument{"invalid minute in nmea::duration"};
50 if (s > 59)
51 throw std::invalid_argument{"invalid second in nmea::duration"};
52 if (ms > 999)
53 throw std::invalid_argument{"invalid milliseconds in nmea::duration"};
56 /// Parses the time information within the specified string (start and end of string).
57 /// If the string is empty, the result will be initialized to zero.
58 /// The time to be parsed must be in the form: "HHMMSS.mmm" (milliseconds are optional).
59 /// - HH : zero leading hour of the day (00..23)
60 /// - MM : zero leading minute of the hour (00..59)
61 /// - SS : zero leading second of the minute (00..59)
62 /// - mmm : milliseconds (000..999)
63 ///
64 /// @param[in] str The string to parse.
65 /// @return The parsed time.
66 /// @exception std::invalid_argument Thrown if the string is malformed.
67 time time::parse(const std::string & str)
69 return parse_time<time>(str);
72 /// Returns a string representation in the form 'hhmmss', or ir the specified time has
73 /// milliseconds other than 0, is provides the form 'hhmmss.sss`.
74 std::string to_string(const time & t)
76 char buf[32];
77 if (t.milliseconds()) {
78 snprintf(buf, sizeof(buf), "%02u%02u%02u.%03u", t.hour(), t.minutes(), t.seconds(),
79 t.milliseconds());
80 } else {
81 snprintf(buf, sizeof(buf), "%02u%02u%02u", t.hour(), t.minutes(), t.seconds());
83 return buf;
86 /// Returns the data as formatted string.
87 ///
88 /// @param[in] t The data to format.
89 /// @param[in] width Number of digits for sub-seconds. Since sub-seconds
90 /// are represented as milliseconds in nmea::time, this value can be between 1 and 3.
91 /// If the value is \c 0, the function \c to_string will be used. Values greater
92 /// than 3 are equivalent to 3.
93 std::string format(const nmea::time & t, unsigned int width)
95 if (width == 0)
96 return to_string(t);
97 if (width > 3)
98 width = 3;
100 char fmt[32];
101 snprintf(fmt, sizeof(fmt), "%%02u%%02u%%02u.%%0%uu", width);
102 uint32_t div = 1;
103 for (unsigned int i = 0; i < width; ++i)
104 div *= 10;
105 char buf[64];
106 snprintf(buf, sizeof(buf), fmt, t.hour(), t.minutes(), t.seconds(), t.milliseconds() / div);
107 return buf;
110 /// Parses the duration information within the specified string (start and end of string).
111 /// If the string is empty, the result will be initialized to zero.
112 /// The duration to be parsed must be in the form: "HHMMSS.mmm" (milliseconds are optional).
113 /// - HH : zero leading hour of the day (00..99)
114 /// - MM : zero leading minute of the hour (00..59)
115 /// - SS : zero leading second of the minute (00..59)
116 /// - mmm : milliseconds (000..999)
118 /// @param[in] str The string to parse.
119 /// @return The parsed duration
120 /// @exception std::invalid_argument Thrown if the string is malformed.
121 duration duration::parse(const std::string & str)
123 return parse_time<duration>(str);
126 /// Returns a string representation in the form 'hhmmss', does not render fractions of seconds.
127 std::string to_string(const duration & d)
129 char buf[7];
130 snprintf(buf, sizeof(buf), "%02u%02u%02u", d.hour(), d.minutes(), d.seconds());
131 return buf;