Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / chrono / io / duration_units.hpp
1 //  (C) Copyright Howard Hinnant
2 //  (C) Copyright 2011 Vicente J. Botet Escriba
3 //  Use, modification and distribution are subject to the Boost Software License,
4 //  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 //  http://www.boost.org/LICENSE_1_0.txt).
6 //
7
8 #ifndef BOOST_CHRONO_IO_DURATION_UNITS_HPP
9 #define BOOST_CHRONO_IO_DURATION_UNITS_HPP
10
11 #include <boost/chrono/config.hpp>
12 #include <boost/ratio/ratio_io.hpp>
13 #include <boost/chrono/duration.hpp>
14 #include <boost/chrono/io/duration_style.hpp>
15 #include <boost/chrono/io/ios_base_state.hpp>
16 #include <boost/assert.hpp>
17 #include <string>
18 #include <ios>
19 #include <locale>
20 #include <algorithm>
21
22 namespace boost
23 {
24   namespace chrono
25   {
26     class rt_ratio
27     {
28     public:
29       template <typename Period>
30       rt_ratio(Period const&) :
31         num(Period::type::num), den(Period::type::den)
32       {
33       }
34
35       rt_ratio(intmax_t n = 0, intmax_t d = 0) :
36         num(n), den(d)
37       {
38       }
39
40       intmax_t num;
41       intmax_t den;
42     };
43
44     /**
45      * @c duration_units facet gives useful information about the duration units,
46      * as the number of plural forms, the plural form associated to a duration,
47      * the text associated to a plural form and a duration's period,
48      */
49     template <typename CharT = char>
50     class duration_units: public std::locale::facet
51     {
52     public:
53       /**
54        * Type of character the facet is instantiated on.
55        */
56       typedef CharT char_type;
57       /**
58        * Type of character string passed to member functions.
59        */
60       typedef std::basic_string<CharT> string_type;
61
62       /**
63        * Unique identifier for this type of facet.
64        */
65       static std::locale::id id;
66
67       /**
68        * Construct a @c duration_units facet.
69        * @param refs
70        * @Effects Construct a @c duration_units facet.
71        * If the @c refs argument is @c 0 then destruction of the object is
72        * delegated to the @c locale, or locales, containing it. This allows
73        * the user to ignore lifetime management issues. On the other had,
74        * if @c refs is @c 1 then the object must be explicitly deleted;
75        * the @c locale will not do so. In this case, the object can be
76        * maintained across the lifetime of multiple locales.
77        */
78       explicit duration_units(size_t refs = 0) :
79         std::locale::facet(refs)
80       {
81       }
82
83       /**
84        * @return pointer to the start of valid [N/D] units.
85        */
86       virtual const string_type* get_n_d_valid_units_start() const =0;
87       /**
88        * @effect calls the do_...
89        * @return pointer to the end of valid [N/D] units.
90        */
91       virtual const string_type* get_n_d_valid_units_end() const=0;
92
93       /**
94        * @return pointer to the start of valid units, symbol or prefix with its different plural forms.
95        */
96       virtual const string_type* get_valid_units_start() const=0;
97       /**
98        * @return pointer to the end of valid units.
99        */
100       virtual const string_type* get_valid_units_end() const=0;
101
102       /**
103        * @param k the found pointer to the [N/D] unit.
104        * @return true if @c k matches a valid unit.
105        */
106       virtual bool match_n_d_valid_unit(const string_type* k) const = 0;
107       /**
108        * @param k the found pointer to the unit.
109        * @Effects @c rt is set to the valid Period when the @c k matches a valid unit.
110        * @return true if @c k matches a valid unit.
111        */
112       virtual bool match_valid_unit(const string_type* k, rt_ratio& rt) const = 0;
113
114       /**
115        * @effect calls the do_...
116        * @return the pattern to be used by default.
117        */
118       virtual string_type get_pattern() const=0;
119
120       /**
121        * @effect calls the do_...
122        * @return the unit associated to this duration.
123        */
124       template <typename Rep, typename Period>
125       string_type get_unit(duration_style style, duration<Rep, Period> const& d) const
126       {
127         return do_get_unit(style, rt_ratio(Period()), static_cast<intmax_t>(d.count()));
128       }
129       /**
130        * @effect calls the do_...
131        * @return the [N/D] suffix unit associated to this duration.
132        */
133       template <typename Rep, typename Period>
134       string_type get_n_d_unit(duration_style style, duration<Rep, Period> const& d) const
135       {
136         return do_get_n_d_unit(style, rt_ratio(Period()), static_cast<intmax_t>(d.count()));
137       }
138
139       /**
140        * @effect calls the do_...
141        * @return true if the unit associated to the given Period is named, false otherwise.
142        */
143       template <typename Period>
144       bool is_named_unit() const
145       {
146         return do_is_named_unit(rt_ratio(Period()));
147       }
148
149
150     protected:
151
152       /**
153        * @Effects Destroys the facet
154        */
155       virtual ~duration_units()
156       {
157       }
158       /**
159        * @return the [N/D] suffix unit associated to this duration.
160        */
161       virtual string_type do_get_n_d_unit(duration_style style, rt_ratio rt, intmax_t v) const = 0;
162       /**
163        * @return the unit associated to this duration.
164        */
165       virtual string_type do_get_unit(duration_style style,rt_ratio rt, intmax_t v) const = 0;
166       /**
167        * @return true if the unit associated to the given Period is named, false otherwise.
168        */
169       virtual bool do_is_named_unit(rt_ratio rt) const =0;
170
171     };
172
173     template <typename CharT>
174     std::locale::id duration_units<CharT>::id;
175
176     namespace detail
177     {
178       template<typename CharT>
179       struct duration_units_default_holder
180       {
181         typedef std::basic_string<CharT> string_type;
182         static string_type* n_d_valid_units_;
183         static string_type* valid_units_;
184         static bool initialized_;
185       };
186       template <typename CharT>
187       typename duration_units_default_holder<CharT>::string_type* duration_units_default_holder<CharT>::n_d_valid_units_=0;
188       template <typename CharT>
189       typename duration_units_default_holder<CharT>::string_type* duration_units_default_holder<CharT>::valid_units_=0;
190       template<typename CharT>
191       bool duration_units_default_holder<CharT>::initialized_ = false;
192     }
193
194     /**
195      * This class is used to define the strings for the default English
196      */
197     template <typename CharT = char>
198     class duration_units_default: public duration_units<CharT>
199     {
200     protected:
201       static const std::size_t pfs_ = 2;
202
203     public:
204       /**
205        * Type of character the facet is instantiated on.
206        */
207       typedef CharT char_type;
208       /**
209        * Type of character string passed to member functions.
210        */
211       typedef std::basic_string<CharT> string_type;
212
213       /**
214        * Construct a @c duration_units_default facet.
215        * @param refs
216        * @Effects Construct a @c duration_units_default facet.
217        * If the @c refs argument is @c 0 then destruction of the object is
218        * delegated to the @c locale, or locales, containing it. This allows
219        * the user to ignore lifetime management issues. On the other had,
220        * if @c refs is @c 1 then the object must be explicitly deleted;
221        * the @c locale will not do so. In this case, the object can be
222        * maintained across the lifetime of multiple locales.
223        */
224       explicit duration_units_default(size_t refs = 0) :
225         duration_units<CharT> (refs)
226       {
227       }
228
229       /**
230        * Destroys the facet.
231        */
232       ~duration_units_default()
233       {
234       }
235
236     public:
237
238       /**
239        * @param k the found pointer to the [N/D] unit.
240        * @return true if @c k matches a valid unit.
241        */
242       bool match_n_d_valid_unit(const string_type* k) const
243       {
244         std::size_t index = (k - get_n_d_valid_units_start()) / (pfs_ + 1);
245         switch (index)
246         {
247         case 0:
248           break;
249         default:
250           return false;
251         }
252         return true;
253       }
254       /**
255        * @param k the found pointer to the unit.
256        * @Effects @c rt is set to the valid Period when the @c k matches a valid unit.
257        * @return true if @c k matches a valid unit.
258        */
259       bool match_valid_unit(const string_type* k, rt_ratio& rt) const
260       {
261         std::size_t index = (k - get_valid_units_start()) / (pfs_ + 1);
262         switch (index)
263         {
264         case 0:
265           rt = rt_ratio(atto());
266           break;
267         case 1:
268           rt = rt_ratio(femto());
269           break;
270         case 2:
271           rt = rt_ratio(pico());
272           break;
273         case 3:
274           rt = rt_ratio(nano());
275           break;
276         case 4:
277           rt = rt_ratio(micro());
278           break;
279         case 5:
280           rt = rt_ratio(milli());
281           break;
282         case 6:
283           rt = rt_ratio(centi());
284           break;
285         case 7:
286           rt = rt_ratio(deci());
287           break;
288         case 8:
289           rt = rt_ratio(deca());
290           break;
291         case 9:
292           rt = rt_ratio(hecto());
293           break;
294         case 10:
295           rt = rt_ratio(kilo());
296           break;
297         case 11:
298           rt = rt_ratio(mega());
299           break;
300         case 12:
301           rt = rt_ratio(giga());
302           break;
303         case 13:
304           rt = rt_ratio(tera());
305           break;
306         case 14:
307           rt = rt_ratio(peta());
308           break;
309         case 15:
310           rt = rt_ratio(exa());
311           break;
312         case 16:
313           rt = rt_ratio(ratio<1> ());
314           break;
315         case 17:
316           rt = rt_ratio(ratio<60> ());
317           break;
318         case 18:
319           rt = rt_ratio(ratio<3600> ());
320           break;
321         default:
322           return false;
323         }
324         return true;
325       }
326
327       /**
328        * @return pointer to the start of valid [N/D] units.
329        */
330       virtual const string_type* get_n_d_valid_units_start()const
331       {
332         return  detail::duration_units_default_holder<CharT>::n_d_valid_units_;
333       }
334       /**
335        * @return pointer to the end of valid [N/D] units.
336        */
337       virtual const string_type* get_n_d_valid_units_end()const
338       {
339         return detail::duration_units_default_holder<CharT>::n_d_valid_units_ + (pfs_ + 1);
340       }
341
342       /**
343        * @return pointer to the start of valid units.
344        */
345       virtual const string_type* get_valid_units_start() const
346       {
347         return detail::duration_units_default_holder<CharT>::valid_units_;
348       }
349       /**
350        * @return pointer to the end of valid units.
351        */
352       virtual const string_type* get_valid_units_end() const
353       {
354         return detail::duration_units_default_holder<CharT>::valid_units_ + 19 * (pfs_ + 1);
355       }
356
357       string_type get_pattern() const
358       {
359         static const CharT t[] =
360         { '%', 'v', ' ', '%', 'u' };
361         static const string_type pattern(t, t + sizeof (t) / sizeof (t[0]));
362
363         return pattern;
364       }
365
366     protected:
367       /**
368        *
369        * This facet names the units associated to the following periods:
370        * atto,femto,pico,nano,micro,milli,centi,deci,ratio<1>,deca,hecto,kilo,mega,giga,tera,peta,exa,ratio<60> and ratio<3600>.
371        * @return true if the unit associated to the given Period is named, false otherwise.
372        */
373       bool do_is_named_unit(rt_ratio rt) const
374       {
375         if (rt.num==1) {
376           switch (rt.den)
377           {
378           case BOOST_RATIO_INTMAX_C(1):
379           case BOOST_RATIO_INTMAX_C(10):
380           case BOOST_RATIO_INTMAX_C(100):
381           case BOOST_RATIO_INTMAX_C(1000):
382           case BOOST_RATIO_INTMAX_C(1000000):
383           case BOOST_RATIO_INTMAX_C(1000000000):
384           case BOOST_RATIO_INTMAX_C(1000000000000):
385           case BOOST_RATIO_INTMAX_C(1000000000000000):
386           case BOOST_RATIO_INTMAX_C(1000000000000000000):
387             return true;
388           default:
389             return false;
390           }
391         } else if (rt.den==1) {
392           switch (rt.num)
393           {
394           case BOOST_RATIO_INTMAX_C(10):
395           case BOOST_RATIO_INTMAX_C(60):
396           case BOOST_RATIO_INTMAX_C(100):
397           case BOOST_RATIO_INTMAX_C(1000):
398           case BOOST_RATIO_INTMAX_C(3600):
399           case BOOST_RATIO_INTMAX_C(1000000):
400           case BOOST_RATIO_INTMAX_C(1000000000):
401           case BOOST_RATIO_INTMAX_C(1000000000000):
402           case BOOST_RATIO_INTMAX_C(1000000000000000):
403           case BOOST_RATIO_INTMAX_C(1000000000000000000):
404             return true;
405           default:
406             return false;
407           }
408         }
409         return false;
410
411       }
412
413       /**
414        * In English the suffix used after [N/D] is the one associated to the period ratio<1>.
415        * @return the [N/D] suffix unit associated to this duration.
416        */
417       string_type do_get_n_d_unit(duration_style style, rt_ratio, intmax_t v) const
418       {
419         return do_get_unit(style, ratio<1>(), do_get_plural_form(v));
420       }
421
422       /**
423        * @return the unit associated to this duration if it is named, "" otherwise.
424        */
425       string_type do_get_unit(duration_style style, rt_ratio rt, intmax_t v) const
426       {
427         if (rt.num==1) {
428           switch (rt.den)
429           {
430           case BOOST_RATIO_INTMAX_C(1):
431             return do_get_unit(style, ratio<1>(), do_get_plural_form(v));
432           case BOOST_RATIO_INTMAX_C(10):
433             return do_get_unit(style, deci(), do_get_plural_form(v));
434           case BOOST_RATIO_INTMAX_C(100):
435             return do_get_unit(style, centi(), do_get_plural_form(v));
436           case BOOST_RATIO_INTMAX_C(1000):
437             return do_get_unit(style, milli(), do_get_plural_form(v));
438           case BOOST_RATIO_INTMAX_C(1000000):
439             return do_get_unit(style, micro(), do_get_plural_form(v));
440           case BOOST_RATIO_INTMAX_C(1000000000):
441             return do_get_unit(style, nano(), do_get_plural_form(v));
442           case BOOST_RATIO_INTMAX_C(1000000000000):
443             return do_get_unit(style, pico(), do_get_plural_form(v));
444           case BOOST_RATIO_INTMAX_C(1000000000000000):
445             return do_get_unit(style, femto(), do_get_plural_form(v));
446           case BOOST_RATIO_INTMAX_C(1000000000000000000):
447             return do_get_unit(style, atto(), do_get_plural_form(v));
448           default:
449             ;
450           }
451         } else if (rt.den==1) {
452           switch (rt.num)
453           {
454           case BOOST_RATIO_INTMAX_C(10):
455              return do_get_unit(style, deca(), do_get_plural_form(v));
456           case BOOST_RATIO_INTMAX_C(60):
457             return do_get_unit(style, ratio<60>(), do_get_plural_form(v));
458           case BOOST_RATIO_INTMAX_C(100):
459              return do_get_unit(style, hecto(), do_get_plural_form(v));
460            case BOOST_RATIO_INTMAX_C(1000):
461              return do_get_unit(style, kilo(), do_get_plural_form(v));
462            case BOOST_RATIO_INTMAX_C(3600):
463              return do_get_unit(style, ratio<3600>(), do_get_plural_form(v));
464            case BOOST_RATIO_INTMAX_C(1000000):
465              return do_get_unit(style, mega(), do_get_plural_form(v));
466            case BOOST_RATIO_INTMAX_C(1000000000):
467              return do_get_unit(style, giga(), do_get_plural_form(v));
468            case BOOST_RATIO_INTMAX_C(1000000000000):
469              return do_get_unit(style, tera(), do_get_plural_form(v));
470            case BOOST_RATIO_INTMAX_C(1000000000000000):
471              return do_get_unit(style, peta(), do_get_plural_form(v));
472            case BOOST_RATIO_INTMAX_C(1000000000000000000):
473              return do_get_unit(style, exa(), do_get_plural_form(v));
474            default:
475              ;
476            }
477         }
478         BOOST_ASSERT(false&&"ratio parameter can not be translated");
479         //throw "exception";
480         return string_type();
481       }
482
483     protected:
484       /**
485        * @return the number of associated plural forms this facet manages.
486        */
487       virtual std::size_t do_get_plural_forms() const
488       {
489         return static_get_plural_forms();
490       }
491       static std::size_t static_get_plural_forms()
492       {
493         return pfs_;
494       }
495       /**
496        * Gets the associated plural form.
497        * @param value the duration representation
498        * @return the plural form associated to the @c value parameter. In English there are 2 plural forms
499        * 0 singular (-1 or 1)
500        * 1 plural for all others
501        */
502       virtual std::size_t do_get_plural_form(int_least64_t value) const
503       {
504         return static_get_plural_form(value);
505       }
506       static std::size_t static_get_plural_form(int_least64_t value)
507       {
508         return (value == -1 || value == 1) ? 0 : 1;
509       }
510
511       /**
512        * @param style the duration style.
513        * @param period the period associated to the duration seconds.
514        * @param pf the requested plural form.
515        * @return if style is symbol returns "s", otherwise if pf is 0 return "second", if pf is 1 "seconds"
516        */
517       virtual string_type do_get_unit(duration_style style, ratio<1> u, std::size_t pf) const
518       {
519         return static_get_unit(style,u,pf);
520       }
521       static string_type static_get_unit(duration_style style, ratio<1> , std::size_t pf)
522       {
523         static const CharT t[] =
524         { 's' };
525         static const string_type symbol(t, t + sizeof (t) / sizeof (t[0]));
526         static const CharT u[] =
527         { 's', 'e', 'c', 'o', 'n', 'd' };
528         static const string_type singular(u, u + sizeof (u) / sizeof (u[0]));
529         static const CharT v[] =
530         { 's', 'e', 'c', 'o', 'n', 'd', 's' };
531         static const string_type plural(v, v + sizeof (v) / sizeof (v[0]));
532
533         if (style == duration_style::symbol)
534         {
535           return symbol;
536         }
537         if (pf == 0)
538         {
539           return singular;
540         }
541         if (pf == 1)
542         {
543           return plural;
544         }
545         BOOST_ASSERT(false&&"style/pf parameters not valid");
546         //throw "exception";
547         return string_type();
548       }
549
550       /**
551        * @param style the duration style.
552        * @param period the period associated to the duration minutes.
553        * @param pf the requested plural form.
554        * @return if style is symbol returns "min", otherwise if pf is 0 return "minute", if pf is 1 "minutes"
555        */
556       virtual string_type do_get_unit(duration_style style, ratio<60> u, std::size_t pf) const
557       {
558         return static_get_unit(style,u,pf);
559       }
560       static string_type static_get_unit(duration_style style, ratio<60> , std::size_t pf)
561       {
562         static const CharT t[] =
563         { 'm', 'i', 'n' };
564         static const string_type symbol(t, t + sizeof (t) / sizeof (t[0]));
565
566         static const CharT u[] =
567         { 'm', 'i', 'n', 'u', 't', 'e' };
568         static const string_type singular(u, u + sizeof (u) / sizeof (u[0]));
569         static const CharT v[] =
570         { 'm', 'i', 'n', 'u', 't', 'e', 's' };
571         static const string_type plural(v, v + sizeof (v) / sizeof (v[0]));
572
573         if (style == duration_style::symbol) return symbol;
574         if (pf == 0) return singular;
575         if (pf == 1) return plural;
576         BOOST_ASSERT(false&&"style/pf parameters not valid");
577         //throw "exception";
578         return string_type();
579
580       }
581
582       /**
583        * @param style the duration style.
584        * @param period the period associated to the duration hours.
585        * @param pf the requested plural form.
586        * @return if style is symbol returns "h", otherwise if pf is 0 return "hour", if pf is 1 "hours"
587        */
588       virtual string_type do_get_unit(duration_style style, ratio<3600> u, std::size_t pf) const
589       {
590         return static_get_unit(style,u,pf);
591       }
592       static string_type static_get_unit(duration_style style, ratio<3600> , std::size_t pf)
593       {
594         static const CharT t[] =
595         { 'h' };
596         static const string_type symbol(t, t + sizeof (t) / sizeof (t[0]));
597         static const CharT u[] =
598         { 'h', 'o', 'u', 'r' };
599         static const string_type singular(u, u + sizeof (u) / sizeof (u[0]));
600         static const CharT v[] =
601         { 'h', 'o', 'u', 'r', 's' };
602         static const string_type plural(v, v + sizeof (v) / sizeof (v[0]));
603
604         if (style == duration_style::symbol) return symbol;
605         if (pf == 0) return singular;
606         if (pf == 1) return plural;
607         BOOST_ASSERT(false&&"style/pf parameters not valid");
608         //throw "exception";
609         return string_type();
610
611       }
612       /**
613        * @param style the duration style.
614        * @param u the period tag atto.
615        * @param pf the requested plural form.
616        * @return the concatenation of the prefix associated to @c period + the one associated to seconds.
617        */
618       virtual string_type do_get_unit(duration_style style, atto u, std::size_t pf) const
619       {
620         return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf);
621       }
622       static string_type static_get_unit(duration_style style, atto u, std::size_t pf)
623       {
624         return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf);
625       }
626       /**
627        * @param style the duration style.
628        * @param u the period tag femto.
629        * @param pf the requested plural form.
630        * @return the concatenation of the prefix associated to period @c u + the one associated to seconds.
631        */
632       virtual string_type do_get_unit(duration_style style, femto u, std::size_t pf) const
633       {
634         return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf);
635       }
636       static string_type static_get_unit(duration_style style, femto u, std::size_t pf)
637       {
638         return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf);
639       }
640       /**
641        * @param style the duration style.
642        * @param u the period tag femto.
643        * @param pf the requested plural form.
644        * @return the concatenation of the prefix associated to period @c u + the one associated to seconds.
645        */
646       virtual string_type do_get_unit(duration_style style, pico u, std::size_t pf) const
647       {
648         return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf);
649       }
650       static string_type static_get_unit(duration_style style, pico u, std::size_t pf)
651       {
652         return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf);
653       }
654       virtual string_type do_get_unit(duration_style style, nano u, std::size_t pf) const
655       {
656         return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf);
657       }
658       static string_type static_get_unit(duration_style style, nano u, std::size_t pf)
659       {
660         return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf);
661       }
662       virtual string_type do_get_unit(duration_style style, micro u, std::size_t pf) const
663       {
664         return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf);
665       }
666       static string_type static_get_unit(duration_style style, micro u, std::size_t pf)
667       {
668         return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf);
669       }
670       virtual string_type do_get_unit(duration_style style, milli u, std::size_t pf) const
671       {
672         return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf);
673       }
674       static string_type static_get_unit(duration_style style, milli u, std::size_t pf)
675       {
676         return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf);
677       }
678       virtual string_type do_get_unit(duration_style style, centi u, std::size_t pf) const
679       {
680         return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf);
681       }
682       static string_type static_get_unit(duration_style style, centi u, std::size_t pf)
683       {
684         return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf);
685       }
686       virtual string_type do_get_unit(duration_style style, deci u, std::size_t pf) const
687       {
688         return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf);
689       }
690       static string_type static_get_unit(duration_style style, deci u, std::size_t pf)
691       {
692         return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf);
693       }
694       virtual string_type do_get_unit(duration_style style, deca u, std::size_t pf) const
695       {
696         return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf);
697       }
698       static string_type static_get_unit(duration_style style, deca u, std::size_t pf)
699       {
700         return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf);
701       }
702       virtual string_type do_get_unit(duration_style style, hecto u, std::size_t pf) const
703       {
704         return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf);
705       }
706       static string_type static_get_unit(duration_style style, hecto u, std::size_t pf)
707       {
708         return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf);
709       }
710       virtual string_type do_get_unit(duration_style style, kilo u, std::size_t pf) const
711       {
712         return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf);
713       }
714       static string_type static_get_unit(duration_style style, kilo u, std::size_t pf)
715       {
716         return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf);
717       }
718       virtual string_type do_get_unit(duration_style style, mega u, std::size_t pf) const
719       {
720         return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf);
721       }
722       static string_type static_get_unit(duration_style style, mega u, std::size_t pf)
723       {
724         return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf);
725       }
726       virtual string_type do_get_unit(duration_style style, giga u, std::size_t pf) const
727       {
728         return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf);
729       }
730       static string_type static_get_unit(duration_style style, giga u, std::size_t pf)
731       {
732         return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf);
733       }
734       virtual string_type do_get_unit(duration_style style, tera u, std::size_t pf) const
735       {
736         return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf);
737       }
738       static string_type static_get_unit(duration_style style, tera u, std::size_t pf)
739       {
740         return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf);
741       }
742       virtual string_type do_get_unit(duration_style style, peta u, std::size_t pf) const
743       {
744         return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf);
745       }
746       static string_type static_get_unit(duration_style style, peta u, std::size_t pf)
747       {
748         return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf);
749       }
750       virtual string_type do_get_unit(duration_style style, exa u, std::size_t pf) const
751       {
752         return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf);
753       }
754       static string_type static_get_unit(duration_style style, exa u, std::size_t pf)
755       {
756         return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf);
757       }
758
759     protected:
760
761       /**
762        * @param style the duration style.
763        * @param u the period tag atto.
764        * @return depending on the value of @c style return the ratio_string symbol or prefix.
765        */
766       virtual string_type do_get_ratio_prefix(duration_style style, atto u) const
767       {
768         return static_get_ratio_prefix(style, u);
769       }
770       static string_type static_get_ratio_prefix(duration_style style, atto)
771       {
772         if (style == duration_style::symbol) return ratio_string<atto, CharT>::symbol();
773         return ratio_string<atto, CharT>::prefix();
774       }
775       virtual string_type do_get_ratio_prefix(duration_style style, femto u) const
776       {
777         return static_get_ratio_prefix(style, u);
778       }
779       static string_type static_get_ratio_prefix(duration_style style, femto)
780       {
781         if (style == duration_style::symbol) return ratio_string<femto, CharT>::symbol();
782         return ratio_string<femto, CharT>::prefix();
783       }
784       virtual string_type do_get_ratio_prefix(duration_style style, pico u) const
785       {
786         return static_get_ratio_prefix(style, u);
787       }
788       static string_type static_get_ratio_prefix(duration_style style, pico)
789       {
790         if (style == duration_style::symbol) return ratio_string<pico, CharT>::symbol();
791         return ratio_string<pico, CharT>::prefix();
792       }
793       virtual string_type do_get_ratio_prefix(duration_style style, nano u) const
794       {
795         return static_get_ratio_prefix(style, u);
796       }
797       static string_type static_get_ratio_prefix(duration_style style, nano)
798       {
799         if (style == duration_style::symbol) return ratio_string<nano, CharT>::symbol();
800         return ratio_string<nano, CharT>::prefix();
801       }
802       virtual string_type do_get_ratio_prefix(duration_style style, micro u) const
803       {
804         return static_get_ratio_prefix(style, u);
805       }
806       static string_type static_get_ratio_prefix(duration_style style, micro)
807       {
808         if (style == duration_style::symbol) return ratio_string<micro, CharT>::symbol();
809         return ratio_string<micro, CharT>::prefix();
810       }
811       virtual string_type do_get_ratio_prefix(duration_style style, milli u) const
812       {
813         return static_get_ratio_prefix(style, u);
814       }
815       static string_type static_get_ratio_prefix(duration_style style, milli)
816       {
817         if (style == duration_style::symbol) return ratio_string<milli, CharT>::symbol();
818         return ratio_string<milli, CharT>::prefix();
819       }
820       virtual string_type do_get_ratio_prefix(duration_style style, centi u) const
821       {
822         return static_get_ratio_prefix(style, u);
823       }
824       static string_type static_get_ratio_prefix(duration_style style, centi)
825       {
826         if (style == duration_style::symbol) return ratio_string<centi, CharT>::symbol();
827         return ratio_string<centi, CharT>::prefix();
828       }
829       virtual string_type do_get_ratio_prefix(duration_style style, deci u) const
830       {
831         return static_get_ratio_prefix(style, u);
832       }
833       static string_type static_get_ratio_prefix(duration_style style, deci)
834       {
835         if (style == duration_style::symbol) return ratio_string<deci, CharT>::symbol();
836         return ratio_string<deci, CharT>::prefix();
837       }
838       virtual string_type do_get_ratio_prefix(duration_style style, deca u) const
839       {
840         return static_get_ratio_prefix(style, u);
841       }
842       static string_type static_get_ratio_prefix(duration_style style, deca)
843       {
844         if (style == duration_style::symbol) return ratio_string<deca, CharT>::symbol();
845         return ratio_string<deca, CharT>::prefix();
846       }
847       virtual string_type do_get_ratio_prefix(duration_style style, hecto u) const
848       {
849         return static_get_ratio_prefix(style, u);
850       }
851       static string_type static_get_ratio_prefix(duration_style style, hecto)
852       {
853         if (style == duration_style::symbol) return ratio_string<hecto, CharT>::symbol();
854         return ratio_string<hecto, CharT>::prefix();
855       }
856       virtual string_type do_get_ratio_prefix(duration_style style, kilo u) const
857       {
858         return static_get_ratio_prefix(style, u);
859       }
860       static string_type static_get_ratio_prefix(duration_style style, kilo)
861       {
862         if (style == duration_style::symbol) return ratio_string<kilo, CharT>::symbol();
863         return ratio_string<kilo, CharT>::prefix();
864       }
865       virtual string_type do_get_ratio_prefix(duration_style style, mega u) const
866       {
867         return static_get_ratio_prefix(style, u);
868       }
869       static string_type static_get_ratio_prefix(duration_style style, mega)
870       {
871         if (style == duration_style::symbol) return ratio_string<mega, CharT>::symbol();
872         return ratio_string<mega, CharT>::prefix();
873       }
874       virtual string_type do_get_ratio_prefix(duration_style style, giga u) const
875       {
876         return static_get_ratio_prefix(style, u);
877       }
878       static string_type static_get_ratio_prefix(duration_style style, giga)
879       {
880         if (style == duration_style::symbol) return ratio_string<giga, CharT>::symbol();
881         return ratio_string<giga, CharT>::prefix();
882       }
883       virtual string_type do_get_ratio_prefix(duration_style style, tera u) const
884       {
885         return static_get_ratio_prefix(style, u);
886       }
887       static string_type static_get_ratio_prefix(duration_style style, tera)
888       {
889         if (style == duration_style::symbol) return ratio_string<tera, CharT>::symbol();
890         return ratio_string<tera, CharT>::prefix();
891       }
892       virtual string_type do_get_ratio_prefix(duration_style style, peta u) const
893       {
894         return static_get_ratio_prefix(style, u);
895       }
896       static string_type static_get_ratio_prefix(duration_style style, peta)
897       {
898         if (style == duration_style::symbol) return ratio_string<peta, CharT>::symbol();
899         return ratio_string<peta, CharT>::prefix();
900       }
901       virtual string_type do_get_ratio_prefix(duration_style style, exa u) const
902       {
903         return static_get_ratio_prefix(style, u);
904       }
905       static string_type static_get_ratio_prefix(duration_style style, exa)
906       {
907         if (style == duration_style::symbol) return ratio_string<exa, CharT>::symbol();
908         return ratio_string<exa, CharT>::prefix();
909       }
910
911     protected:
912       template <typename Period>
913       string_type* fill_units(string_type* it, Period) const
914       {
915         std::size_t pfs = do_get_plural_forms();
916         for (std::size_t pf = 0; pf < pfs; ++pf)
917         {
918           *it++ = do_get_unit(duration_style::prefix, Period(), pf);
919         }
920         *it++ = do_get_unit(duration_style::symbol, Period(), 0);
921         return it;
922       }
923     public:
924       template <typename Period>
925       static string_type* static_fill_units(string_type* it, Period)
926       {
927         std::size_t pfs = static_get_plural_forms();
928         for (std::size_t pf = 0; pf < pfs; ++pf)
929         {
930           *it++ = static_get_unit(duration_style::prefix, Period(), pf);
931         }
932         *it++ = static_get_unit(duration_style::symbol, Period(), 0);
933         return it;
934       }
935       static string_type* static_init_valid_units(string_type* it)
936       {
937         it = static_fill_units(it, atto());
938         it = static_fill_units(it, femto());
939         it = static_fill_units(it, pico());
940         it = static_fill_units(it, nano());
941         it = static_fill_units(it, micro());
942         it = static_fill_units(it, milli());
943         it = static_fill_units(it, centi());
944         it = static_fill_units(it, deci());
945         it = static_fill_units(it, deca());
946         it = static_fill_units(it, hecto());
947         it = static_fill_units(it, kilo());
948         it = static_fill_units(it, mega());
949         it = static_fill_units(it, giga());
950         it = static_fill_units(it, tera());
951         it = static_fill_units(it, peta());
952         it = static_fill_units(it, exa());
953         it = static_fill_units(it, ratio<1> ());
954         it = static_fill_units(it, ratio<60> ());
955         it = static_fill_units(it, ratio<3600> ());
956         return it;
957       }
958     };
959
960     namespace detail
961     {
962
963       template<typename CharT>
964       struct duration_units_default_initializer_t
965       {
966         duration_units_default_initializer_t()
967           {
968               if (!duration_units_default_holder<CharT>::initialized_)
969               {
970                 typedef typename duration_units_default_holder<CharT>::string_type string_type;
971                 duration_units_default_holder<CharT>::n_d_valid_units_ = new string_type[3];
972                 duration_units_default_holder<CharT>::valid_units_ = new string_type[19 * 3];
973
974                 string_type* it = duration_units_default_holder<CharT>::n_d_valid_units_;
975                 it = duration_units_default<CharT>::static_fill_units(it, ratio<1> ());
976                 it = duration_units_default<CharT>::static_init_valid_units(duration_units_default_holder<CharT>::valid_units_);
977
978                 duration_units_default_holder<CharT>::initialized_ = true;
979               }
980           }
981         ~duration_units_default_initializer_t()
982           {
983             if (duration_units_default_holder<CharT>::initialized_)
984             {
985               delete[] duration_units_default_holder<CharT>::n_d_valid_units_;
986               duration_units_default_holder<CharT>::n_d_valid_units_ = 0;
987               delete[] duration_units_default_holder<CharT>::valid_units_;
988               duration_units_default_holder<CharT>::valid_units_ = 0;
989               duration_units_default_holder<CharT>::initialized_ = false;
990             }
991         }
992       };
993       namespace /**/
994       {
995         duration_units_default_initializer_t<char> duration_units_default_initializer;
996         duration_units_default_initializer_t<wchar_t> wduration_units_default_initializer;
997       } // namespace
998     }
999   } // chrono
1000
1001 } // boost
1002
1003 #endif  // header