| 1944 | } |
| 1945 | |
| 1946 | void parse_single_table(std::string::iterator& it, |
| 1947 | const std::string::iterator& end, |
| 1948 | table*& curr_table) |
| 1949 | { |
| 1950 | if (it == end || *it == ']') |
| 1951 | throw_parse_exception("Table name cannot be empty"); |
| 1952 | |
| 1953 | std::string full_table_name; |
| 1954 | bool inserted = false; |
| 1955 | |
| 1956 | auto key_end = [](char c) { return c == ']'; }; |
| 1957 | |
| 1958 | auto key_part_handler = [&](const std::string& part) { |
| 1959 | if (part.empty()) |
| 1960 | throw_parse_exception("Empty component of table name"); |
| 1961 | |
| 1962 | if (!full_table_name.empty()) |
| 1963 | full_table_name += '.'; |
| 1964 | full_table_name += part; |
| 1965 | |
| 1966 | if (curr_table->contains(part)) |
| 1967 | { |
| 1968 | #if !defined(__PGI) |
| 1969 | auto b = curr_table->get(part); |
| 1970 | #else |
| 1971 | // Workaround for PGI compiler |
| 1972 | std::shared_ptr<base> b = curr_table->get(part); |
| 1973 | #endif |
| 1974 | if (b->is_table()) |
| 1975 | curr_table = static_cast<table*>(b.get()); |
| 1976 | else if (b->is_table_array()) |
| 1977 | curr_table = std::static_pointer_cast<table_array>(b) |
| 1978 | ->get() |
| 1979 | .back() |
| 1980 | .get(); |
| 1981 | else |
| 1982 | throw_parse_exception("Key " + full_table_name |
| 1983 | + "already exists as a value"); |
| 1984 | } |
| 1985 | else |
| 1986 | { |
| 1987 | inserted = true; |
| 1988 | curr_table->insert(part, make_table()); |
| 1989 | curr_table = static_cast<table*>(curr_table->get(part).get()); |
| 1990 | } |
| 1991 | }; |
| 1992 | |
| 1993 | key_part_handler(parse_key(it, end, key_end, key_part_handler)); |
| 1994 | |
| 1995 | if (it == end) |
| 1996 | throw_parse_exception( |
| 1997 | "Unterminated table declaration; did you forget a ']'?"); |
| 1998 | |
| 1999 | if (*it != ']') |
| 2000 | { |
| 2001 | std::string errmsg{"Unexpected character in table definition: "}; |
| 2002 | errmsg += '"'; |
| 2003 | errmsg += *it; |
no test coverage detected