From 56f90e5b925aa8340b7b8dc0cf38015567140e39 Mon Sep 17 00:00:00 2001 From: vng Date: Fri, 11 Oct 2013 19:57:25 +0300 Subject: [PATCH] Remove throwing SourceOutOfBoundsException due to runtime overhead (checked in iOS profiler). --- coding/coding.pro | 1 - coding/parse_xml.hpp | 70 +++++++++++++++++---------- coding/reader.hpp | 22 ++------- coding/source.hpp | 19 -------- generator/xml_element.cpp | 10 ++-- map/feature_vec_model.cpp | 2 +- platform/chunks_download_strategy.cpp | 2 +- 7 files changed, 57 insertions(+), 69 deletions(-) delete mode 100644 coding/source.hpp diff --git a/coding/coding.pro b/coding/coding.pro index b87816960c..7852a26118 100644 --- a/coding/coding.pro +++ b/coding/coding.pro @@ -53,7 +53,6 @@ HEADERS += \ reader.hpp \ diff.hpp \ diff_patch_common.hpp \ - source.hpp \ lodepng.hpp \ lodepng_io.hpp \ lodepng_io_private.hpp \ diff --git a/coding/parse_xml.hpp b/coding/parse_xml.hpp index b5ca32b904..9896155bc2 100644 --- a/coding/parse_xml.hpp +++ b/coding/parse_xml.hpp @@ -1,39 +1,59 @@ #pragma once #include "internal/xmlparser.h" -#include "source.hpp" #include "../base/assert.hpp" -static const size_t KMaxXMLFileBufferSize = 16384; - -template -bool ParseXML(SourceT & source, XMLDispatcherT & dispatcher, bool useCharData = false) +template +uint64_t ParseXMLSequence(SequenceT & source, XMLDispatcherT & dispatcher, bool useCharData = false) { // Create the parser XmlParser parser(dispatcher, useCharData); if (!parser.Create()) - return false; + return 0; - try - { - while (true) - { - char * buffer = static_cast(parser.GetBuffer(KMaxXMLFileBufferSize)); - CHECK(buffer, ()); - source.Read(buffer, KMaxXMLFileBufferSize); - if (!parser.ParseBuffer(KMaxXMLFileBufferSize, false)) - return false; - } - } - catch (SourceOutOfBoundsException & e) - { - size_t const toRead = e.BytesRead(); - // 0 - means Reader overflow (see ReaderSource::Read) - if (toRead == 0 || !parser.ParseBuffer(toRead, true)) - return false; - } + int const BUFFER_SIZE = 16 * 1024; - return true; + uint64_t res = 0; + int readed; + do + { + char * buffer = static_cast(parser.GetBuffer(BUFFER_SIZE)); + ASSERT(buffer, ()); + + readed = source.Read(buffer, BUFFER_SIZE); + if (readed == 0 || !parser.ParseBuffer(readed, false)) + return res; + + res += readed; + } while (readed == BUFFER_SIZE); + + return res; +} + +namespace +{ + +template class SequenceAdapter +{ + SourceT & m_source; +public: + SequenceAdapter(SourceT & source) : m_source(source) {} + uint64_t Read(void * p, uint64_t size) + { + uint64_t const correctSize = min(size, m_source.Size()); + m_source.Read(p, correctSize); + return correctSize; + } +}; + +} + +template +bool ParseXML(SourceT & source, XMLDispatcherT & dispatcher, bool useCharData = false) +{ + uint64_t const size = source.Size(); + SequenceAdapter adapter(source); + return (ParseXMLSequence(adapter, dispatcher, useCharData) == size); } diff --git a/coding/reader.hpp b/coding/reader.hpp index 6e2a106034..25dd91218b 100644 --- a/coding/reader.hpp +++ b/coding/reader.hpp @@ -1,6 +1,5 @@ #pragma once #include "endianness.hpp" -#include "source.hpp" #include "../base/assert.hpp" #include "../base/logging.hpp" @@ -180,23 +179,10 @@ public: void Read(void * p, size_t size) { - uint64_t const readerSize = m_reader.Size(); - if (m_pos + size > readerSize) - { - size_t remainingSize = 0; - if (readerSize >= m_pos) - { - remainingSize = static_cast(readerSize - m_pos); - m_reader.Read(m_pos, p, remainingSize); - m_pos = readerSize; - } - MYTHROW1(SourceOutOfBoundsException, remainingSize, ()); - } - else - { - m_reader.Read(m_pos, p, size); - m_pos += size; - } + ASSERT(m_pos + size <= m_reader.Size(), (m_pos, size, m_reader.Size())); + + m_reader.Read(m_pos, p, size); + m_pos += size; } void Skip(uint64_t size) diff --git a/coding/source.hpp b/coding/source.hpp deleted file mode 100644 index 1a4c7274c9..0000000000 --- a/coding/source.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "../base/base.hpp" -#include "../base/exception.hpp" - - -class SourceOutOfBoundsException : public RootException -{ -public: - SourceOutOfBoundsException(size_t bytesRead, char const * what, string const & msg) - : RootException(what, msg), m_BytesRead(bytesRead) - { - } - - size_t BytesRead() const { return m_BytesRead; } - -private: - size_t const m_BytesRead; -}; diff --git a/generator/xml_element.cpp b/generator/xml_element.cpp index 294dbaf552..df1ace1957 100644 --- a/generator/xml_element.cpp +++ b/generator/xml_element.cpp @@ -2,9 +2,11 @@ #include "../coding/parse_xml.hpp" #include "../coding/reader.hpp" -#include "../std/cstdio.hpp" +#include "../std/cstdio.hpp" #include "../std/algorithm.hpp" +#include "../std/limits.hpp" + bool BaseOSMParser::is_our_tag(string const & name) { @@ -62,7 +64,7 @@ void BaseOSMParser::Pop(string const &) struct StdinReader { - size_t Read(char * buffer, size_t bufferSize) + uint64_t Read(char * buffer, uint64_t bufferSize) { return fread(buffer, sizeof(char), bufferSize, stdin); } @@ -72,11 +74,11 @@ struct StdinReader void ParseXMLFromStdIn(BaseOSMParser & parser) { StdinReader reader; - ParseXML(reader, parser); + (void)ParseXMLSequence(reader, parser); } void ParseXMLFromFile(FileReader const & reader, BaseOSMParser & parser) { ReaderSource src(reader); - ParseXML(src, parser); + CHECK(ParseXML(src, parser), ()); } diff --git a/map/feature_vec_model.cpp b/map/feature_vec_model.cpp index 958394e8b1..bc5287c9a1 100644 --- a/map/feature_vec_model.cpp +++ b/map/feature_vec_model.cpp @@ -17,7 +17,7 @@ namespace model { // While reading any files (classificator or mwm), there are 2 types of possible exceptions: -// Reader::Exception; FileAbsentException; SourceOutOfBoundsException. +// Reader::Exception, FileAbsentException. // Let's process RootException everywhere, to supress such errors. void FeaturesFetcher::InitClassificator() diff --git a/platform/chunks_download_strategy.cpp b/platform/chunks_download_strategy.cpp index 14670b649f..57e4a7353e 100644 --- a/platform/chunks_download_strategy.cpp +++ b/platform/chunks_download_strategy.cpp @@ -121,7 +121,7 @@ int64_t ChunksDownloadStrategy::LoadOrInitChunks( string const & fName, } catch (RootException const & e) { - // Usually - file not exists. May be SourceOutOfBoundsException. + // Usually - file not exists or Reader::Exception. LOG(LDEBUG, (e.Msg())); }