1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of the
* License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "stdafx.h"
#include "sql_normalizer.h"
std::string Sql_normalizer::remove_inter_token_spaces(const std::string &text)
{
class InterTokenSpaceFinder
{
public:
InterTokenSpaceFinder(const std::string &text) : quoted(false), escaped(false), n(0), text(text) {}
std::pair<std::string::size_type, std::string::size_type> find_next_space_free_substr()
{
std::pair<std::string::size_type, std::string::size_type> res= std::make_pair(n/*offset*/, 0/*count*/);
std::pair<std::string::size_type, std::string::size_type> space_pos= find_next_intertoken_space();
if (std::string::npos == space_pos.first)
res.second= std::string::npos;
else
res.second= space_pos.first - res.first;
return res;
}
std::pair<std::string::size_type, std::string::size_type> find_next_intertoken_space()
{
std::pair<std::string::size_type, std::string::size_type> res= std::make_pair(std::string::npos/*offset*/, 0/*count*/);
for (std::string::size_type count= text.size(); n < count; ++n)
{
if (quoted)
{
if ('\\' == text[n])
{
escaped= !escaped;
continue;
}
check_quote_symbol(cur_quote_sym);
}
else
{
if (std::isspace(text[n]))
{
res.first= n;
for (++n; (n < count) && std::isspace(text[n]); ++n) ;
res.second= n - res.first;
break;
}
check_quote_symbol('\'') || check_quote_symbol('"') || check_quote_symbol('`');
}
escaped= false;
}
return res;
}
private:
std::string::size_type n;
char cur_quote_sym;
bool quoted;
bool escaped;
const std::string &text;
bool check_quote_symbol(char quote_sym)
{
if (quote_sym == text[n])
{
if (!escaped)
{
if (quoted)
{
if (quote_sym == cur_quote_sym)
quoted= false;
}
else
{
cur_quote_sym= quote_sym;
quoted= true;
}
}
return true;
}
return false;
}
};
InterTokenSpaceFinder space_finder(text);
std::string res;
res.reserve(text.size());
while (true)
{
std::pair<std::string::size_type, std::string::size_type> substr_pos= space_finder.find_next_space_free_substr();
res.append(text, substr_pos.first, substr_pos.second);
if (std::string::npos == substr_pos.second)
break;
}
return res;
}
|