move assignment operators for folly::Synchronized
[folly.git] / folly / Format.cpp
1 /*
2  * Copyright 2013 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "folly/Format.h"
18
19 namespace folly {
20 namespace detail {
21
22 extern const FormatArg::Align formatAlignTable[];
23 extern const FormatArg::Sign formatSignTable[];
24
25 }  // namespace detail
26
27 using namespace folly::detail;
28
29 void FormatArg::initSlow() {
30   auto b = fullArgString.begin();
31   auto end = fullArgString.end();
32
33   // Parse key
34   auto p = static_cast<const char*>(memchr(b, ':', end - b));
35   if (!p) {
36     key_ = StringPiece(b, end);
37     return;
38   }
39   key_ = StringPiece(b, p);
40
41   if (*p == ':') {
42     // parse format spec
43     if (++p == end) return;
44
45     // fill/align, or just align
46     Align a;
47     if (p + 1 != end &&
48         (a = formatAlignTable[static_cast<unsigned char>(p[1])]) !=
49         Align::INVALID) {
50       fill = *p;
51       align = a;
52       p += 2;
53       if (p == end) return;
54     } else if ((a = formatAlignTable[static_cast<unsigned char>(*p)]) !=
55                Align::INVALID) {
56       align = a;
57       if (++p == end) return;
58     }
59
60     Sign s;
61     unsigned char uSign = static_cast<unsigned char>(*p);
62     if ((s = formatSignTable[uSign]) != Sign::INVALID) {
63       sign = s;
64       if (++p == end) return;
65     }
66
67     if (*p == '#') {
68       basePrefix = true;
69       if (++p == end) return;
70     }
71
72     if (*p == '0') {
73       enforce(align == Align::DEFAULT, "alignment specified twice");
74       fill = '0';
75       align = Align::PAD_AFTER_SIGN;
76       if (++p == end) return;
77     }
78
79     if (*p >= '0' && *p <= '9') {
80       auto b = p;
81       do {
82         ++p;
83       } while (p != end && *p >= '0' && *p <= '9');
84       width = to<int>(StringPiece(b, p));
85
86       if (p == end) return;
87     }
88
89     if (*p == ',') {
90       thousandsSeparator = true;
91       if (++p == end) return;
92     }
93
94     if (*p == '.') {
95       auto b = ++p;
96       while (p != end && *p >= '0' && *p <= '9') {
97         ++p;
98       }
99       precision = to<int>(StringPiece(b, p));
100
101       if (p == end) return;
102     }
103
104     presentation = *p;
105     if (++p == end) return;
106   }
107
108   error("extra characters in format string");
109 }
110
111 void FormatArg::validate(Type type) const {
112   enforce(keyEmpty(), "index not allowed");
113   switch (type) {
114   case Type::INTEGER:
115     enforce(precision == kDefaultPrecision,
116             "precision not allowed on integers");
117     break;
118   case Type::FLOAT:
119     enforce(!basePrefix,
120             "base prefix ('#') specifier only allowed on integers");
121     enforce(!thousandsSeparator,
122             "thousands separator (',') only allowed on integers");
123     break;
124   case Type::OTHER:
125     enforce(align != Align::PAD_AFTER_SIGN,
126             "'='alignment only allowed on numbers");
127     enforce(sign == Sign::DEFAULT,
128             "sign specifier only allowed on numbers");
129     enforce(!basePrefix,
130             "base prefix ('#') specifier only allowed on integers");
131     enforce(!thousandsSeparator,
132             "thousands separator (',') only allowed on integers");
133     break;
134   }
135 }
136
137 }  // namespace folly