]> git.tdb.fi Git - libs/core.git/blob - source/fmt.cpp
Rewrite lexical_cast to use internal conversion routines
[libs/core.git] / source / fmt.cpp
1 /* $Id$
2
3 This file is part of libmspstrings
4 Copyright © 2006-2008 Mikko Rasa
5 Distributed under the LGPL
6 */
7
8 #include <msp/core/except.h>
9 #include "fmt.h"
10
11 using namespace std;
12
13 namespace Msp {
14
15 /**
16 Resets the format to the default.  Mainly used by constructors.
17 */
18 Fmt &Fmt::reset()
19 {
20         wd=0;
21         prec=6;
22         spos=false;
23         fillc=' ';
24         base=DEC;
25         sbase=false;
26         fmode=AUTOFLT;
27         spoint=false;
28         align=RIGHT;
29         ucase=false;
30         type=STR;
31
32         return *this;
33 }
34
35 /**
36 Applies the format to the given ostream.  All existing formatting information
37 is overwritten.
38 */
39 void Fmt::apply(ostream &out) const
40 {
41         out.flags(((base==HEX) ? ios_base::hex : (base==OCT) ? ios_base::oct : ios_base::dec)
42                 | ((fmode==SCI) ? ios_base::scientific : (fmode==FIXED) ? ios_base::fixed : ios_base::fmtflags(0))
43                 | (fillc=='0' ? ios_base::internal : (align==LEFT) ? ios_base::left : ios_base::right)
44                 | (sbase ? ios_base::showbase : ios_base::fmtflags(0))
45                 | (spoint ? ios_base::showpoint : ios_base::fmtflags(0))
46                 | (spos ? ios_base::showpos : ios_base::fmtflags(0))
47                 | (ucase ? ios_base::uppercase : ios_base::fmtflags(0)));
48         out.fill(fillc);
49         out.width(wd);
50         out.precision(prec);
51 }
52
53 /**
54 Parses a printf-style conversion specification.  Called from constructors.
55 */
56 void Fmt::parse(const char *f)
57 {
58         if(*f=='%') ++f;
59
60         for(; *f; ++f)
61         {
62                 if(*f=='#')
63                 {
64                         sbase=true;
65                         spoint=true;
66                 }
67                 else if(*f=='0')
68                         fillc='0';
69                 else if(*f=='-')
70                         align=LEFT;
71                 else if(*f=='+')
72                         spos=true;
73                 else
74                         break;
75         }
76
77         wd=0;
78         for(; *f; ++f)
79         {
80                 if(*f>='0' && *f<='9')
81                         wd=wd*10+(*f-'0');
82                 else
83                         break;
84         }
85
86         if(*f=='.')
87         {
88                 ++f;
89                 prec=0;
90                 for(; *f; ++f)
91                 {
92                         if(*f>='0' && *f<='9')
93                                 prec=prec*10+(*f-'0');
94                         else
95                                 break;
96                 }
97         }
98
99         type=NUM;
100         if(*f=='d' || *f=='u')
101                 base=DEC;
102         else if(*f=='x' || *f=='X')
103                 base=HEX;
104         else if(*f=='o')
105                 base=OCT;
106         else if(*f=='b')
107                 base=BIN;
108         else if(*f=='e' || *f=='E')
109                 fmode=SCI;
110         else if(*f=='f' || *f=='F')
111                 fmode=FIXED;
112         else if(*f=='g' || *f=='G')
113                 fmode=AUTOFLT;
114         else if(*f=='p' || *f=='P')
115         {
116                 base=HEX;
117                 sbase=true;
118         }
119         else if(*f=='c')
120                 type=CHAR;
121         else if(*f=='s')
122                 type=STR;
123         else if(*f=='i')
124                 base=AUTOBASE;
125         else
126                 throw InvalidParameterValue("Invalid conversion specifier");
127
128         if(*f=='E' || *f=='F' || *f=='G' || *f=='X' || *f=='P')
129                 ucase=true;
130
131         ++f;
132
133         if(*f)
134                 throw InvalidParameterValue("Extra characters in conversion specification");
135 }
136
137 } // namespace Msp