| 132 | } |
| 133 | |
| 134 | FormatTokenizationResult IsoSqlFormatTokenizer::ProcessNextToken( |
| 135 | const char** current_pos) { |
| 136 | DCHECK(current_pos != nullptr && *current_pos != nullptr); |
| 137 | const char* str_begin = dt_ctx_->fmt; |
| 138 | const char* str_end = dt_ctx_->fmt + dt_ctx_->fmt_len; |
| 139 | DCHECK(str_begin <= *current_pos && *current_pos < str_end); |
| 140 | if (IsStartOfTextToken(*current_pos)) { |
| 141 | fm_modifier_active_ = false; |
| 142 | return ProcessTextToken(current_pos, str_begin, str_end); |
| 143 | } |
| 144 | unsigned curr_token_size = |
| 145 | min(MAX_TOKEN_SIZE, static_cast<unsigned>(str_end - *current_pos)); |
| 146 | string token_to_probe(*current_pos, curr_token_size); |
| 147 | boost::to_upper(token_to_probe); |
| 148 | while (curr_token_size > 0) { |
| 149 | token_to_probe.resize(curr_token_size); |
| 150 | const auto token = VALID_TOKENS.find(token_to_probe); |
| 151 | if (token != VALID_TOKENS.end()) { |
| 152 | if (token->second.type == FX_MODIFIER) return MISPLACED_FX_MODIFIER_ERROR; |
| 153 | if (token->second.type == FM_MODIFIER) { |
| 154 | fm_modifier_active_ = true; |
| 155 | *current_pos += curr_token_size; |
| 156 | return SUCCESS; |
| 157 | } |
| 158 | if (cast_mode_ == PARSE && IsUsedToken(token_to_probe)) return DUPLICATE_FORMAT; |
| 159 | if (!accept_time_toks_ && token->second.time_token) return DATE_WITH_TIME_ERROR; |
| 160 | int max_len = GetMaxTokenLength(token->first); |
| 161 | DateTimeFormatToken format_token(DateTimeFormatToken( |
| 162 | token->second.type, *current_pos - str_begin, max_len, *current_pos)); |
| 163 | dt_ctx_->fmt_out_len += max_len; |
| 164 | if (token->second.type == YEAR || token->second.type == ROUND_YEAR |
| 165 | || token->second.type == ISO8601_WEEK_NUMBERING_YEAR) { |
| 166 | format_token.divisor = std::pow(10, max_len); |
| 167 | } else if (token->second.type == FRACTION) { |
| 168 | format_token.divisor = std::pow(10, FRACTIONAL_MAX_LEN - max_len); |
| 169 | } |
| 170 | if (fm_modifier_active_) { |
| 171 | fm_modifier_active_ = false; |
| 172 | format_token.fm_modifier = true; |
| 173 | } |
| 174 | dt_ctx_->toks.push_back(format_token); |
| 175 | dt_ctx_->has_date_toks |= token->second.date_token; |
| 176 | dt_ctx_->has_time_toks |= token->second.time_token; |
| 177 | used_tokens_.insert(token_to_probe); |
| 178 | *current_pos += curr_token_size; |
| 179 | return SUCCESS; |
| 180 | } |
| 181 | --curr_token_size; |
| 182 | } |
| 183 | return GENERAL_ERROR; |
| 184 | } |
| 185 | |
| 186 | int IsoSqlFormatTokenizer::GetMaxTokenLength(const string& token) const { |
| 187 | const auto length_it = SPECIAL_LENGTHS.find(token); |