1 // time_format_holder.hpp
2 
3 // Boost Logging library
4 //
5 // Author: John Torjo, www.torjo.com
6 //
7 // Copyright (C) 2007 John Torjo (see www.torjo.com for email)
8 //
9 // Distributed under the Boost Software License, Version 1.0.
10 //    (See accompanying file LICENSE_1_0.txt or copy at
11 //          http://www.boost.org/LICENSE_1_0.txt)
12 //
13 // See http://www.boost.org for updates, documentation, and revision history.
14 // See http://www.torjo.com/log2/ for more details
15 
16 
17 #ifndef JT28092007_time_format_holder_HPP_DEFINED
18 #define JT28092007_time_format_holder_HPP_DEFINED
19 
20 #include <hpx/util/assert.hpp>
21 #include <hpx/util/logging/detail/fwd.hpp>
22 
23 #include <algorithm>
24 #include <cstdio>
25 #include <cstddef>
26 #include <sstream>
27 #include <string>
28 #include <vector>
29 
30 namespace hpx { namespace util { namespace logging { namespace detail {
31 
32 /**
33     This only holds the time format, and allows writing a certain time
34 */
35 struct time_format_holder {
36 private:
37     struct index_info {
38         typedef std::size_t uint;
39 
index_infohpx::util::logging::detail::time_format_holder::index_info40         index_info(uint src_idx_, int *format_idx_, int advance_size_ = 2,
41                    int size_ = 2)
42             : src_idx(src_idx_), format_idx(format_idx_),
43               advance_size(advance_size_), size(size_) {}
44         uint src_idx;
45         int * format_idx;
46         int advance_size;
47         int size;
48 
by_indexhpx::util::logging::detail::time_format_holder::index_info49         static bool by_index(const index_info & first, const index_info & second) {
50             return first.src_idx < second.src_idx;
51         }
52     };
53 
54 public:
operator ==hpx::util::logging::detail::time_format_holder55     bool operator==(const time_format_holder & other) const {
56         return m_format == other.m_format;
57     }
58 
59 
60     /**
61         constructs a time format holder object
62     */
time_format_holderhpx::util::logging::detail::time_format_holder63     time_format_holder(const std::string & format) : m_day(-1),
64         m_month(-1), m_yy(-1), m_yyyy(-1), m_hour(-1), m_min(-1),
65         m_sec(-1),m_millisec(-1),m_microsec(-1),m_nanosec(-1) {
66         set_format(format);
67     }
68 
set_formathpx::util::logging::detail::time_format_holder69     void set_format(const std::string & format) {
70         // format too big
71         HPX_ASSERT( format.size() < 64);
72         m_format.clear();
73 
74         m_day = -1; m_month = -1; m_yy = -1; m_yyyy = -1; m_hour = -1;
75         m_min = -1; m_sec = -1;m_millisec = -1;m_microsec = -1;m_nanosec = -1;
76 
77         typedef std::size_t uint;
78         uint day_idx    = format.find("$dd");
79         uint month_idx  = format.find("$MM");
80         uint yy_idx     = format.find("$yy");
81         uint yyyy_idx   = format.find("$yyyy");
82         uint hour_idx   = format.find("$hh");
83         uint min_idx    = format.find("$mm");
84         uint sec_idx    = format.find("$ss");
85         uint millisec_idx    = format.find("$mili");
86         uint microsec_idx    = format.find("$micro");
87         uint nanosec_idx    = format.find("$nano");
88 
89         typedef std::vector<index_info> array;
90         array indexes;
91         if ( day_idx != std::string::npos)
92             indexes.push_back( index_info(day_idx, &m_day) );
93         if ( month_idx != std::string::npos)
94             indexes.push_back( index_info(month_idx, &m_month) );
95 
96         if ( yy_idx != std::string::npos || yyyy_idx != std::string::npos) {
97             if ( yyyy_idx  != std::string::npos)
98                 indexes.push_back( index_info(yyyy_idx, &m_yyyy, 4) ); //-V112
99             else
100                 indexes.push_back( index_info(yy_idx, &m_yy) );
101         }
102 
103         if ( hour_idx != std::string::npos)
104             indexes.push_back( index_info(hour_idx, &m_hour ) );
105         if ( min_idx != std::string::npos)
106             indexes.push_back( index_info(min_idx, &m_min) );
107         if ( sec_idx != std::string::npos)
108             indexes.push_back( index_info(sec_idx, &m_sec) );
109         if ( millisec_idx != std::string::npos)
110             indexes.push_back( index_info(millisec_idx, &m_millisec, 4, 3) );
111             //-V112 //-V525
112         if ( microsec_idx != std::string::npos)
113             indexes.push_back( index_info(microsec_idx, &m_microsec, 5, 6) );
114         if ( nanosec_idx != std::string::npos)
115             indexes.push_back( index_info(nanosec_idx, &m_nanosec, 4, 9) ); //-V112
116 
117         std::sort( indexes.begin(), indexes.end(), index_info::by_index);
118 
119         // create the format string, that we can actually pass to sprintf
120         uint prev_idx = 0;
121         int idx = 0;
122         for ( array::iterator begin = indexes.begin(), end = indexes.end();
123         begin != end; ++begin) {
124             m_format += format.substr( prev_idx, begin->src_idx - prev_idx);
125             *begin->format_idx = idx;
126             std::ostringstream cur_sprintf_format;
127             cur_sprintf_format << "%0" << begin->size << "d";
128             m_format += cur_sprintf_format.str();
129             prev_idx = static_cast<hpx::util::logging::detail
130                 ::time_format_holder::index_info::uint>(begin->src_idx +
131                     static_cast<hpx::util::logging::detail::time_format_holder
132                     ::index_info::uint>(begin->advance_size) + 1ul);
133             ++idx;
134         }
135 
136         m_format += format.substr(prev_idx);
137     }
138 
write_timehpx::util::logging::detail::time_format_holder139     void write_time(char buffer[], int day, int month,
140         int year, int hour, int min, int sec, int millisec, int microsec,
141         int nanosec) const {
142         int vals[11];
143         vals[m_day + 1]      = day;
144         vals[m_month + 1]    = month;
145         vals[m_yy + 1]       = year % 100;
146         vals[m_yyyy + 1]     = year;
147         vals[m_hour + 1]     = hour;
148         vals[m_min + 1]      = min;
149         vals[m_sec + 1]      = sec;
150         vals[m_millisec + 1]        = millisec;
151         vals[m_microsec + 1]        = microsec;
152         vals[m_nanosec + 1]         = nanosec;
153 
154         // ignore value at index 0
155         // - it's there so that I don't have to test for an index being -1
156         sprintf( buffer, m_format.c_str(), vals[1], vals[2], vals[3],
157             vals[4], vals[5], vals[6], vals[7], vals[8], vals[9], vals[10] );
158     }
159 
write_timehpx::util::logging::detail::time_format_holder160     void write_time(char buffer[], int day, int month, int year,
161         int hour, int min, int sec) const {
162         int vals[8];
163         vals[m_day + 1]      = day;
164         vals[m_month + 1]    = month;
165         vals[m_yy + 1]       = year % 100;
166         vals[m_yyyy + 1]     = year;
167         vals[m_hour + 1]     = hour;
168         vals[m_min + 1]      = min;
169         vals[m_sec + 1]      = sec;
170 
171         // ignore value at index 0
172         // - it's there so that I don't have to test for an index being -1
173         sprintf( buffer, m_format.c_str(), vals[1], vals[2], vals[3],
174             vals[4], vals[5], vals[6], vals[7] );
175     }
176 
177 private:
178     // the indexes of each escape sequence within the format string
179     int m_day, m_month, m_yy, m_yyyy, m_hour, m_min, m_sec, m_millisec,
180         m_microsec, m_nanosec;
181     std::string m_format;
182 };
183 
184 }}}}
185 
186 #endif
187