Пытаясь понять, как анализировать строку подключения ODBC, содержащую специальные символы ([]{}(),;?), я хотел бы знать, является ли то, чего я пытаюсь достичь, допустимым требованием или нет. SQLDriverConnect гласит:
Значение DSN или строки подключения, заключенное в фигурные скобки ({}), содержащее любой из символов []{}(),;?*=!@ передается драйверу без изменений.
Для меня это означает, что разрешены специальные символы ([]{}(),;?), включая curly braces и semicolon между ними (по крайней мере, в значениях).
Итак, можно ли ожидать, что ключ PWD (например) будет выглядеть так PWD = {a{b}};c};?
И следует ли анализировать его значение до a{b}};c?
И если да, то можно ли вообще легко выполнить такое требование? Вдохновленный этим решением мой код:
#include <iostream>
#include <istream>
#include <string>
#include <vector>
enum class CSVState {
UnquotedField,
QuotedField
};
std::vector<std::string> readCSVRow(const std::string &row) {
CSVState state = CSVState::UnquotedField;
std::vector<std::string> fields {""};
size_t i = 0; // index of the current field
int depth = 0;
for (int ii = 0; ii < row.size(); ++ii) {
auto& c = row[ii];
switch (state) {
case CSVState::UnquotedField:
switch (c) {
case ';': // end of field
fields.push_back(""); i++;
break;
case '{': state = CSVState::QuotedField;
depth++;
break;
default: fields[i].push_back(c);
break;
}
break;
case CSVState::QuotedField:
switch (c) {
case '{': //state = CSVState::QuotedQuote;
depth++;
fields[i].push_back(c);
break;
case '}':
depth--;
if (depth == 0) {
state = CSVState::UnquotedField;
} else {
fields[i].push_back(c);
}
break;
default: fields[i].push_back(c);
break;
}
break;
}
}
std::cout << "fields: " << fields.size() << std::endl;
return fields;
}
/// Read CSV file, Excel dialect. Accept "quoted fields ""with quotes"""
std::vector<std::vector<std::string>> readCSV(std::istream &in) {
std::vector<std::vector<std::string>> table;
std::string row;
std::getline(in, row);
if (in.bad() || in.fail()) {
std::cout << "bad\n";
return {};
}
auto fields = readCSVRow(row);
table.push_back(fields);
for(auto& f : fields) {
std::cout << "'" << f << "' ";
}
std::cout << std::endl;
}
return table;
}
int main() {
auto res = readCSV(std::cin);
}
Для ввода {a{b}};c}; он будет выдавать 'a{b}' 'c}' '', хотя я думаю, что его следует изменить, чтобы он выдавал a{b}};c}.
Любые подсказки, как это сделать?
Упомянутый вами абзац относится к атрибутам, а не к строкам. Итак, для строки {a{b}};c}; атрибутами, разделенными точкой с запятой, являются {a{b}}, c} и ''.
Значение DSN или строки подключения, заключенное в фигурные скобки.
Ключевым словом здесь является значение, означающее значение атрибута в строке.
Таким образом, любое значение атрибута может быть заключено в фигурные скобки для передачи как есть, но не вся строка.
Обновлено: если вы хотите анализировать значения в фигурных скобках независимо от того, что они содержат, вы можете просто проверить глубину при встрече с точкой с запятой:
case ';': // end of field
if (depth == 0) {
fields.push_back(""); i++;
} else {
fields[i].push_back(c);
}
break;
Таким образом, {a{b}};c}; будет интерпретироваться как {a{b}};c} и '', потому что используется только точка с запятой, не заключенная в фигурные скобки.
@rahman, кажется, я понимаю, чего ты хочешь. Пожалуйста, смотрите мое редактирование.
Дело в том, что первая точка с запятой должна быть частью значения атрибута. В конце концов, нужно извлечь весь пароль как: a{b}};c