diff --git a/src/main.cpp b/src/main.cpp index 7db1718..f3531a9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -124,13 +124,29 @@ int main(int argc, char** argv) { settings.selected_groups()) ); - CATCH_AND_RETURN(triangle_data, wavefront::parse_error, 1, wavefront::parse_face_data(scan_data)); + std::cerr << "Scanned " << scan_data.total_lines << " lines" << std::endl; + std::cerr << "Found " << scan_data.category_map["v"].size() << " vertices" << std::endl; + std::cerr << "Found " << scan_data.category_map["vn"].size() << " normals" << std::endl; + std::cerr << "Found " << scan_data.category_map["vt"].size() << " texture coordinates" << std::endl; + std::cerr << "Found " << scan_data.category_map["f"].size() << " faces" << std::endl; - std::cerr << "Scanned " << scan_data.total_lines << " lines\n"; - std::cerr << "Found " << scan_data.category_map["v"].size() << " vertices\n"; - std::cerr << "Found " << scan_data.category_map["vn"].size() << " normals\n"; - std::cerr << "Found " << scan_data.category_map["vt"].size() << " texture coordinates\n"; - std::cerr << "Found " << scan_data.category_map["f"].size() << " faces\n"; + CATCH_AND_RETURN(face_data, wavefront::parse_error, 1, wavefront::parse_face_data(scan_data)); + std::cerr << "Selected " << face_data.triangle_list.size() << " triangles" << std::endl; + std::cerr << "Selected " << face_data.index_position_set.size() << " vertex positions" << std::endl; + std::cerr << "Selected " << face_data.index_normal_set.size() << " vertex normals" << std::endl; + std::cerr << "Selected " << face_data.index_texcoord_set.size() << " vertex texture coordinates" << std::endl; + + CATCH_AND_RETURN(coordinate_data, wavefront::parse_error, 1, wavefront::parse_coordinate_data(scan_data, face_data)); + + auto number_list = create_number_list(coordinate_data); + + std::cerr << "Generated number list with " << number_list.size() << " values" << std::endl; + + auto coordinate_index_data = create_coordinate_index(coordinate_data, number_list); + + // Form coordinate_list_data : std::vector variant of coordinate_index_data. Internally, it creates std::set initially, stores everything in the set and then convert to vector. + // Then we can form coordinate_line_mapping : std::map pointing for each entry to entry in coordinate_list_data. + // Then using face_data.triangle_list and scan_data.category_map[v/vn/vt], coordinate_line_mapping, we can form vertex_list_data. The vertex here is 1-3 IndexType numbers pointing to coordinate_list_data. return 0; } diff --git a/src/numset.hpp b/src/numset.hpp index 8b13999..8d744ff 100644 --- a/src/numset.hpp +++ b/src/numset.hpp @@ -45,13 +45,13 @@ struct less_with_nan_first_and_nearly_equal { static const auto min_value = std::numeric_limits::min(); static const auto max_value = std::numeric_limits::max(); - if (std::isnan(a)) { + if (std::isnan(a)) [[unlikely]] { return !std::isnan(b); } - if (std::isnan(b)) { + if (std::isnan(b)) [[unlikely]] { return false; } - if (a == b) { + if (a == b) [[unlikely]] { return false; } auto difference = std::abs(a - b); diff --git a/src/parse.cpp b/src/parse.cpp index 3202045..c31e3fd 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -1,7 +1,3 @@ -#include -#include -#include -#include #include #include "parse.hpp" @@ -91,11 +87,11 @@ namespace wavefront { } } - parse_face_data_result parse_face_data(const scan_result &scan_data) { + wavefront_face_data_result_t parse_face_data(const scan_result &scan_data) { using register_vertex_func_t = std::function; using register_index_func_t = std::function &, const std::size_t &)>; - parse_face_data_result result; + wavefront_face_data_result_t result; std::array current_triangle; std::size_t current_triangle_index; std::size_t triangles_added; @@ -106,11 +102,28 @@ namespace wavefront { target.emplace(source); } }; + + const register_vertex_func_t register_vertex_indices = [&](triangle_vertex_indices &vertex) { + if (vertex.position_index > 0) { + result.index_position_set.emplace(vertex.position_index); + } else { + throw parse_error(std::format( + "[{}:{}]: {}", + vertex.face_line_number, + current_triangle_index, + "Position index must be positive integer" + )); + } + if (vertex.normal_index > 0) { + result.index_normal_set.emplace(vertex.normal_index); + } + if (vertex.texcoord_index > 0) { + result.index_texcoord_set.emplace(vertex.texcoord_index); + } + }; const register_vertex_func_t add_vertex_to_triangle = [&](triangle_vertex_indices &vertex) { - register_index[1](result.index_position_set, vertex.position_index); - register_index[!!vertex.normal_index](result.index_normal_set, vertex.normal_index); - register_index[!!vertex.texcoord_index](result.index_texcoord_set, vertex.texcoord_index); + register_vertex_indices(vertex); current_triangle[current_triangle_index++] = vertex; }; @@ -128,6 +141,7 @@ namespace wavefront { add_triangle(); }, [&](triangle_vertex_indices &vertex) { + register_vertex_indices(vertex); current_triangle[1] = current_triangle[2]; current_triangle[2] = vertex; add_triangle(); diff --git a/src/parse.hpp b/src/parse.hpp index 124401f..aa1e25b 100644 --- a/src/parse.hpp +++ b/src/parse.hpp @@ -2,14 +2,22 @@ #define __WAVEFRONT_PARSE_HPP__ #include +#include +#include #include +#include +#include +#include #include #include #include +#include #include #include +#include #include "scan.hpp" +#include "numset.hpp" namespace wavefront { class parse_error : public std::runtime_error { @@ -17,7 +25,7 @@ namespace wavefront { parse_error(const std::string &message) : std::runtime_error(message) {} }; - using vertex_index_t = std::int32_t; + using vertex_index_t = std::int64_t; using file_line_t = typename decltype(std::declval().line_data)::key_type; struct triangle_vertex_indices { @@ -27,12 +35,319 @@ namespace wavefront { vertex_index_t normal_index; }; - struct parse_face_data_result { + struct wavefront_face_data_result_t { std::vector> triangle_list; std::set index_position_set, index_normal_set, index_texcoord_set; }; - parse_face_data_result parse_face_data(const scan_result &scan_data); + template + struct coordinate_data_t { + std::map> position_coordinates; + std::map> normal_coordinates; + std::variant< + std::monostate, + std::map, + std::map>, + std::map> + > texture_coordinates; + }; + + wavefront_face_data_result_t parse_face_data(const scan_result &scan_data); + + template + coordinate_data_t parse_coordinate_data(const scan_result &scan_data, const wavefront_face_data_result_t &face_data) { + using namespace std::string_literals; + coordinate_data_t result; + + const auto &position_data = scan_data.category_map.at("v"s); + for (const auto &position_index : face_data.index_position_set) { + std::array position_coordinates; + const auto &position_line_index = position_data.at(position_index); + const auto &position_line = scan_data.line_data.at(position_line_index); + + decltype(position_line.find_first_of(' ')) number_begin_pos = 2, number_end_pos; + for (std::size_t position_coordinate_index = 0; position_coordinate_index < 3; position_coordinate_index++) { + if (number_begin_pos >= position_line.size()) { + throw parse_error(std::format( + "[{}]: {}", + position_line_index, + std::format("Line \"{}\" must contain at least {} numbers", "v", 3) + )); + } + number_end_pos = std::min(position_line.find_first_of(' ', number_begin_pos), position_line.size()); + auto [number_end, conversion_error] = std::from_chars( + position_line.data() + number_begin_pos, + position_line.data() + number_end_pos, + position_coordinates[position_coordinate_index], + std::chars_format::fixed + ); + if (conversion_error != std::errc() || position_line.data() + number_end_pos != number_end) { + throw parse_error(std::format( + "[{}]: {}", + position_line_index, + std::format("Unable to parse \"{}\" floating point value", "v") + )); + } + number_begin_pos = std::min(position_line.find_first_not_of(' ', number_end_pos), position_line.size()); + } + if (number_begin_pos < position_line.size()) { + if (position_line.find_first_not_of("0123456789.-", number_begin_pos)) { + throw parse_error(std::format( + "[{}]: {}", + position_line_index, + std::format("Additional data in \"{}\" line: expected {} only", "v", " [weight]") + )); + } + } + result.position_coordinates[position_line_index] = position_coordinates; + } + if (face_data.index_normal_set.size() > 0 && scan_data.category_map.contains("vn"s)) { + const auto &normal_data = scan_data.category_map.at("vn"s); + for (const auto &normal_index : face_data.index_normal_set) { + std::array normal_coordinates; + const auto &normal_line_index = normal_data.at(normal_index); + const auto &normal_line = scan_data.line_data.at(normal_line_index); + + decltype(normal_line.find_first_of(' ')) number_begin_pos = 3, number_end_pos; + for (std::size_t normal_coordinate_index = 0; normal_coordinate_index < 3; normal_coordinate_index++) { + if (number_begin_pos >= normal_line.size()) { + throw parse_error(std::format( + "[{}]: {}", + normal_line_index, + std::format("Line \"{}\" must contain exactly {} numbers", "vn", 3) + )); + } + number_end_pos = std::min(normal_line.find_first_of(' ', number_begin_pos), normal_line.size()); + auto [number_end, conversion_error] = std::from_chars( + normal_line.data() + number_begin_pos, + normal_line.data() + number_end_pos, + normal_coordinates[normal_coordinate_index], + std::chars_format::fixed + ); + if (conversion_error != std::errc() || normal_line.data() + number_end_pos != number_end) { + throw parse_error(std::format( + "[{}]: {}", + normal_line_index, + std::format("Unable to parse \"{}\" floating point value", "vn") + )); + } + number_begin_pos = std::min(normal_line.find_first_not_of(' ', number_end_pos), normal_line.size()); + } + if (number_end_pos != normal_line.size()) { + throw parse_error(std::format( + "[{}]: {}", + normal_line_index, + std::format("Additional data in \"{}\" line: expected {} only", "vn", " ") + )); + } + result.normal_coordinates[normal_line_index] = normal_coordinates; + } + } + + if (face_data.index_texcoord_set.size() > 0 && scan_data.category_map.contains("vt"s)) { + using insert_texcoord_data_t = std::function; + + const auto &texcoord_data = scan_data.category_map.at("vt"s); + for (const auto &texcoord_index : face_data.index_texcoord_set) { + std::array texcoord_coordinates; + const auto &texcoord_line_index = texcoord_data.at(texcoord_index); + const auto &texcoord_line = scan_data.line_data.at(texcoord_line_index); + + decltype(texcoord_line.find_first_of(' ')) number_begin_pos = 3, number_end_pos; + std::size_t texcoord_coordinate_index = 0; + while (number_begin_pos < texcoord_line.size()) { + if (texcoord_coordinate_index >= 3) { + throw parse_error(std::format( + "[{}]: {}", + texcoord_line_index, + std::format("Line \"{}\" must contain maximum {} numbers", "vt", 3) + )); + } + number_end_pos = std::min(texcoord_line.find_first_of(' ', number_begin_pos), texcoord_line.size()); + auto [number_end, conversion_error] = std::from_chars( + texcoord_line.data() + number_begin_pos, + texcoord_line.data() + number_end_pos, + texcoord_coordinates[texcoord_coordinate_index++], + std::chars_format::fixed + ); + if (conversion_error != std::errc() || texcoord_line.data() + number_end_pos != number_end) { + throw parse_error(std::format( + "[{}]: {}", + texcoord_line_index, + std::format("Unable to parse \"{}\" floating point value", "vt") + )); + } + number_begin_pos = std::min(texcoord_line.find_first_not_of(' ', number_end_pos), texcoord_line.size()); + } + if (texcoord_coordinate_index == 0) [[unlikely]] { + throw parse_error(std::format( + "[{}]: {}", + texcoord_line_index, + std::format("Unable to parse \"{}\" line: expected minimum one number", "vt") + )); + } + if (result.texture_coordinates.valueless_by_exception() || result.texture_coordinates.index() == 0) [[unlikely]] { + if (texcoord_coordinate_index == 1) { + result.texture_coordinates = std::map{}; + } else if (texcoord_coordinate_index == 2) { + result.texture_coordinates = std::map>{}; + } else if (texcoord_coordinate_index == 3) { + result.texture_coordinates = std::map>{}; + } else { + throw parse_error(std::format( + "[{}]: {}", + texcoord_line_index, + std::format("Line \"{}\" must contain maximum {} numbers", "vt", 3) + )); + } + } + if (texcoord_coordinate_index == 0) [[unlikely]] { + throw parse_error(std::format( + "[{}]: {}", + texcoord_line_index, + std::format("Unable to parse \"{}\" line: expected minimum one number", "vt") + )); + } + try { + if (texcoord_coordinate_index == 1) { + std::get<1>(result.texture_coordinates)[texcoord_line_index] = texcoord_coordinates[0]; + } else if (texcoord_coordinate_index == 2) { + std::get<2>(result.texture_coordinates)[texcoord_line_index] = std::array{texcoord_coordinates[0], texcoord_coordinates[1]}; + } else if (texcoord_coordinate_index == 3) { + std::get<3>(result.texture_coordinates)[texcoord_line_index] = texcoord_coordinates; + } + } catch (std::bad_variant_access&) { + throw parse_error(std::format( + "[{}]: {}", + texcoord_line_index, + std::format("Line \"{}\": {}D texture coordinates expected, got {}D texture coordinates", "vt", result.texture_coordinates.index(), texcoord_coordinate_index) + )); + } + } + } + return result; + } + + template + std::vector create_number_list(const coordinate_data_t &coordinate_data) { + numset_t number_set; + + for (const auto& [line_number, coordinates] : coordinate_data.position_coordinates) { + for (const auto &coordinate : coordinates) { + number_set.emplace(coordinate); + } + } + for (const auto& [line_number, coordinates] : coordinate_data.normal_coordinates) { + for (const auto &coordinate : coordinates) { + number_set.emplace(coordinate); + } + } + + std::visit([&](const auto &texture_coordinate_map) { + if constexpr (std::ranges::range>) { + for (const auto& [line_number, coordinates] : texture_coordinate_map) { + if constexpr (std::ranges::range>) { + for (const auto &coordinate : coordinates) { + number_set.emplace(coordinate); + } + } else { + number_set.emplace(coordinates); + } + } + } + }, coordinate_data.texture_coordinates); + + number_set.emplace(std::numeric_limits::quiet_NaN()); + + std::vector number_list; + number_list.reserve(number_set.size()); + std::copy(number_set.begin(), number_set.end(), std::back_inserter(number_list)); + + return number_list; + } + + template + coordinate_data_t create_coordinate_index(const coordinate_data_t &coordinate_data, const std::vector &float_list) { + coordinate_data_t coordinate_index_data; + + for (const auto& [line_number, coordinates] : coordinate_data.position_coordinates) { + std::array position_coordinate_indices; + for (decltype(coordinates.size()) dim = 0; dim < coordinates.size(); ++dim) { + auto iterator = std::lower_bound(float_list.begin(), float_list.end(), coordinates[dim]); + assert(iterator != float_list.end()); + position_coordinate_indices[dim] = std::distance(float_list.begin(), iterator); + } + coordinate_index_data.position_coordinates[line_number] = position_coordinate_indices; + } + for (const auto& [line_number, coordinates] : coordinate_data.normal_coordinates) { + std::array normal_coordinate_indices; + for (decltype(coordinates.size()) dim = 0; dim < coordinates.size(); ++dim) { + auto iterator = std::lower_bound(float_list.begin(), float_list.end(), coordinates[dim]); + assert(iterator != float_list.end()); + normal_coordinate_indices[dim] = std::distance(float_list.begin(), iterator); + } + coordinate_index_data.normal_coordinates[line_number] = normal_coordinate_indices; + } + if (!coordinate_data.texture_coordinates.valueless_by_exception() && coordinate_data.texture_coordinates.index() > 0) { + std::visit([&](const auto &texture_coordinate_map) { + if constexpr (std::ranges::range>) { + if constexpr (std::ranges::range::mapped_type>) { + coordinate_index_data.texture_coordinates = std::map< + typename std::decay_t::key_type, + std::array< + IndexType, + std::tuple_size_v::mapped_type> + > + >{}; + } else { + coordinate_index_data.texture_coordinates = std::map< + typename std::decay_t::key_type, + IndexType + >{}; + } + for (const auto& [line_number, coordinates] : texture_coordinate_map) { + if constexpr (std::ranges::range>) { + std::array texcoord_coordinate_indices; + for (std::size_t dim = 0; dim < coordinates.size(); ++dim) { + auto iterator = std::lower_bound(float_list.begin(), float_list.end(), coordinates[dim]); + assert(iterator != float_list.end()); + texcoord_coordinate_indices[dim] = std::distance(float_list.begin(), iterator); + } + std::visit([&](auto &target_data) { + if constexpr (std::is_same_v< + std::map< + file_line_t, + std::array< + IndexType, + std::tuple_size_v::mapped_type> + > + >, + typename std::decay_t + >) { + target_data[line_number] = texcoord_coordinate_indices; + } + }, coordinate_index_data.texture_coordinates); + } else { + auto iterator = std::lower_bound(float_list.begin(), float_list.end(), coordinates); + assert(iterator != float_list.end()); + auto coordinate = std::distance(float_list.begin(), iterator); + std::visit([&](auto &target_data) { + if constexpr (std::is_same_v< + std::map, + typename std::decay_t + >) { + target_data[line_number] = coordinate; + } + }, coordinate_index_data.texture_coordinates); + } + } + } + int j = 0; + }, coordinate_data.texture_coordinates); + } + + return coordinate_index_data; + } } #endif // __WAVEFRONT_PARSE_HPP__ \ No newline at end of file diff --git a/src/parser.hpp b/src/parser.hpp deleted file mode 100644 index d8758d4..0000000 --- a/src/parser.hpp +++ /dev/null @@ -1,306 +0,0 @@ -#ifndef _WAVEFRONT_PARSER_FILE_HPP_ -#define _WAVEFRONT_PARSER_FILE_HPP_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "settings.hpp" - -namespace wavefront::parser { - class parse_error : public std::runtime_error { - public: - parse_error(const std::string &message) : std::runtime_error(message) {} - }; - - template - class File { - - public: - File() = default; - - void parse(const Settings &settings); - }; - - namespace { - template - std::array repeat_value(ValueType value) { - std::array result; - result.fill(value); - return result; - } - - inline std::string_view trim(const std::string_view &source) { - static const auto if_space = [](auto source_char){ - return std::isspace(source_char); - }; - auto left = std::find_if_not(source.begin(), source.end(), if_space); - auto right = std::find_if_not(source.rbegin(), source.rend(), if_space).base(); - return std::string_view(left, right - left); - } - } - - template - void File::parse(const Settings &settings) { - using line_processor_func_t = std::function< - void(const std::string_view &type, const std::string_view &content) - >; - using store_vec3_factory_func_t = std::function< - line_processor_func_t(std::vector> &target_vector) - >; - using store_filter_factory_func_t = std::function< - line_processor_func_t(std::optional &target_filter) - >; - using check_filter_func_t = std::function; - - static const auto return_true = []()->bool { return true; }; - - std::size_t current_line_number = 0; - - const auto process_float = [&](FloatType &target_value, const char *data_begin, const char *data_end) { - auto [number_end, conversion_error] = std::from_chars( - data_begin, - data_end, - target_value, - std::chars_format::fixed - ); - if (conversion_error != std::errc() || number_end != data_end) { - std::stringstream error_message; - error_message - << "[" - << current_line_number - << "]" - << ": " - << "Unable to parse the expected float data"; - if (conversion_error != std::errc()) { - auto error_condition = std::make_error_condition(conversion_error); - error_message - << ": " - << error_condition.message(); - } else { - error_message - << ": " - << "Unexpected trailing characters"; - } - throw parse_error(error_message.str()); - } - }; - - std::vector> wavefront_data_position; - std::vector> wavefront_data_normal; - std::vector< - std::variant< - std::monostate, - FloatType, - std::array, - std::array - > - > wavefront_data_texcoord; - std::vector, 3>> wavefront_data_triangle; - - wavefront_data_position.push_back(repeat_value(std::numeric_limits::quiet_NaN())); - wavefront_data_normal.push_back(repeat_value(std::numeric_limits::quiet_NaN())); - wavefront_data_texcoord.push_back(std::monostate{}); - - const store_vec3_factory_func_t create_vec3_store_func = [&](std::vector> &target_vector) { - return line_processor_func_t([&](const std::string_view &type, const std::string_view &content) { - std::array vec3{}; - std::size_t component_count = 0; - decltype(content.size()) content_processed = 0; - - // 4th component (weight) is ignored if present. - while (component_count < 3 && content_processed < content.size()) { - auto chunk_end_pos = content.find_first_of(' ', content_processed); - if (chunk_end_pos == std::string_view::npos) { - chunk_end_pos = content.size(); - } - process_float( - vec3[component_count], - content.data() + content_processed, - content.data() + chunk_end_pos - ); - - ++component_count; - content_processed = chunk_end_pos + 1; - auto next_non_space_pos = content.find_first_not_of(' ', content_processed); - if (next_non_space_pos == std::string_view::npos) { - break; - } - content_processed = next_non_space_pos; - } - - if (component_count < 3) { - std::stringstream error_message; - error_message - << "[" - << current_line_number - << "]" - << ": " - << "Insufficient number of components for " - << '"' - << type - << '"' - << " line"; - throw parse_error(error_message.str()); - } - - target_vector.push_back(vec3); - }); - }; - - const line_processor_func_t store_texcoords = [&](const std::string_view &type, const std::string_view &content) { - using insert_data_func_t = std::function; - - std::array data_vec3{}; - decltype(content.size()) content_processed = 0; - std::size_t component_count = 0; - - const std::array insert_data = { - [](){}, - [&](void) { wavefront_data_texcoord.push_back(data_vec3[0]); }, - [&](void) { wavefront_data_texcoord.push_back(std::array{data_vec3[0], data_vec3[1]}); }, - [&](void) { wavefront_data_texcoord.push_back(data_vec3); } - }; - - while (content_processed < content.size()) { - if (component_count >= 3) { - std::stringstream error_message; - error_message - << "[" - << current_line_number - << "]" - << ": " - << "Too many components for " - << '"' - << type - << '"' - << " line"; - throw parse_error(error_message.str()); - } - - auto chunk_end_pos = content.find_first_of(' ', content_processed); - if (chunk_end_pos == std::string_view::npos) { - chunk_end_pos = content.size(); - } - process_float( - data_vec3[component_count], - content.data() + content_processed, - content.data() + chunk_end_pos - ); - - ++component_count; - content_processed = chunk_end_pos + 1; - auto next_non_space_pos = content.find_first_not_of(' ', content_processed); - if (next_non_space_pos == std::string_view::npos) { - break; - } - content_processed = next_non_space_pos; - } - - if (component_count < 1) { - std::stringstream error_message; - error_message - << "[" - << current_line_number - << "]" - << ": " - << "Insufficient number of components for " - << '"' - << type - << '"' - << " line"; - throw parse_error(error_message.str()); - } - - insert_data[component_count](); - }; - - static const store_filter_factory_func_t create_filter_store = [](std::optional &target_filter) { - return [&](const std::string_view &type, const std::string_view &content) { - auto trimmed_name = trim(content); - if (trimmed_name.empty()) { - target_filter.reset(); - } else { - target_filter = std::string(trimmed_name); - } - }; - }; - - std::optional current_object, current_group; - check_filter_func_t check_object = return_true; - check_filter_func_t check_group = return_true; - if (settings.selected_objects().size() > 0) { - check_object = [&]()->bool { - auto selected = settings.selected_objects(); - auto begin = selected.begin(); - auto end = selected.end(); - return std::find(begin, end, current_object.value_or("")) != end; - }; - } - if (settings.selected_groups().size() > 0) { - check_group = [&]()->bool { - auto selected = settings.selected_groups(); - auto begin = selected.begin(); - auto end = selected.end(); - return std::find(begin, end, current_group.value_or("")) != end; - }; - } - - const std::map line_processor_map{ - { "v", create_vec3_store_func(wavefront_data_position) }, - { "vn", create_vec3_store_func(wavefront_data_normal) }, - { "vt", store_texcoords }, - { "o", create_filter_store(current_object) }, - { "g", create_filter_store(current_group) }, - }; - - const auto max_type_length = [&]() { - std::size_t max_length = 0; - for (const auto &[type, _] : line_processor_map) { - if (type.size() > max_length) { - max_length = type.size(); - } - } - return max_length; - }(); - - std::string line; - - while (std::getline(settings.input(), line)) { - ++current_line_number; - - if (line.empty() || line[0] == '#') { - continue; - } - - auto first_space_pos = line.find_first_of(' '); - - if (first_space_pos == std::string::npos || first_space_pos > max_type_length || first_space_pos + 1 >= line.size()) { - continue; - } - - auto type = std::string_view(line.data(), first_space_pos); - auto content = std::string_view(line.data() + first_space_pos + 1, line.size() - first_space_pos - 1); - - auto processor_func = line_processor_map.find(type); - if (processor_func == line_processor_map.end()) { - continue; - } - - processor_func->second(type, content); - } - } - -} - -#endif // _WAVEFRONT_PARSER_FILE_HPP_ diff --git a/src/scan.cpp b/src/scan.cpp index b862a7d..a5ee70e 100644 --- a/src/scan.cpp +++ b/src/scan.cpp @@ -104,20 +104,9 @@ namespace wavefront { return max_length; }(); - while (!input.eof()) { + std::string line; + while (std::getline(input, line)) { ++result.total_lines; - input.getline(buffer.data(), buffer.size()); - auto line_size = input.gcount(); - - if (input.fail() && line_size == buffer.size()) [[unlikely]] { - throw scan_error(std::format( - "[{}]: {}", - result.total_lines, - "Line too long" - )); - } - - std::string_view line(buffer.data(), line_size); if (line.empty() || line[0] == '#' || trim(line).empty()) [[unlikely]] { continue;