diff --git a/simgear/io/HTTPRepository.cxx b/simgear/io/HTTPRepository.cxx index 41be821a..bfa426a6 100644 --- a/simgear/io/HTTPRepository.cxx +++ b/simgear/io/HTTPRepository.cxx @@ -182,17 +182,11 @@ class HTTPDirectory ChildInfo(Type ty, const std::string & nameData, const std::string & hashData) : type(ty), name(nameData), - hash(hashData), - sizeInBytes(0) + hash(hashData) { } - ChildInfo(const ChildInfo& other) : - type(other.type), - name(other.name), - hash(other.hash), - sizeInBytes(other.sizeInBytes) - { } + ChildInfo(const ChildInfo& other) = default; void setSize(const std::string & sizeData) { @@ -206,7 +200,8 @@ class HTTPDirectory Type type; std::string name, hash; - size_t sizeInBytes; + size_t sizeInBytes = 0; + SGPath path; // absolute path on disk }; typedef std::vector ChildInfoList; @@ -273,44 +268,45 @@ public: return; } - string_list indexNames = indexChildren(); - const_string_list_iterator nameIt = indexNames.begin(); - for (; nameIt != indexNames.end(); ++nameIt) { - SGPath p(absolutePath()); - p.append(*nameIt); - if (p.exists()) { - continue; // only copy if the file is missing entirely - } + char* buf = nullptr; + size_t bufSize = 0; - ChildInfoList::iterator c = findIndexChild(*nameIt); - if (c->type == ChildInfo::DirectoryType) { - continue; // only care about files - } + for (const auto& child : children) { + if (child.type != ChildInfo::FileType) + continue; - SGPath cp = _repository->installedCopyPath; - cp.append(relativePath()); - cp.append(*nameIt); - if (!cp.exists()) { - continue; - } + if (child.path.exists()) + continue; - SGBinaryFile src(cp); - SGBinaryFile dst(p); - src.open(SG_IO_IN); - dst.open(SG_IO_OUT); + SGPath cp = _repository->installedCopyPath; + cp.append(relativePath()); + cp.append(child.name); + if (!cp.exists()) { + continue; + } - char* buf = (char*) malloc(cp.sizeInBytes()); - if (!buf) { - continue; - } + SGBinaryFile src(cp); + SGBinaryFile dst(child.path); + src.open(SG_IO_IN); + dst.open(SG_IO_OUT); - src.read(buf, cp.sizeInBytes()); - dst.write(buf, cp.sizeInBytes()); - src.close(); - dst.close(); + if (bufSize < cp.sizeInBytes()) { + bufSize = cp.sizeInBytes(); + free(buf); + buf = (char*) malloc(bufSize); + if (!buf) { + continue; + } + } - free(buf); - } + src.read(buf, cp.sizeInBytes()); + dst.write(buf, cp.sizeInBytes()); + src.close(); + dst.close(); + + } + + free(buf); } void updateChildrenBasedOnHash() @@ -319,19 +315,20 @@ public: copyInstalledChildren(); - string_list indexNames = indexChildren(), - toBeUpdated, orphans; + string_list toBeUpdated, orphans, + indexNames = indexChildren(); simgear::Dir d(absolutePath()); PathList fsChildren = d.children(0); - for (const auto& child : fsChildren) { const auto& fileName = child.file(); if ((fileName == ".dirindex") || (fileName == ".hashes")) { continue; } - ChildInfo info(child.isDir() ? ChildInfo::DirectoryType : ChildInfo::FileType, fileName, ""); + ChildInfo info(child.isDir() ? ChildInfo::DirectoryType : ChildInfo::FileType, + fileName, ""); + info.path = child; std::string hash = hashForChild(info); ChildInfoList::iterator c = findIndexChild(fileName); @@ -428,19 +425,16 @@ public: void didUpdateFile(const std::string& file, const std::string& hash, size_t sz) { // check hash matches what we expected - ChildInfoList::iterator it = findIndexChild(file); + auto it = findIndexChild(file); if (it == children.end()) { SG_LOG(SG_TERRASYNC, SG_WARN, "updated file but not found in dir:" << _relativePath << " " << file); } else { - SGPath fpath(absolutePath()); - fpath.append(file); - if (it->hash != hash) { // we don't erase the file on a hash mismatch, becuase if we're syncing during the // middle of a server-side update, the downloaded file may actually become valid. _repository->failedToUpdateChild(_relativePath, HTTPRepository::REPO_ERROR_CHECKSUM); } else { - _repository->updatedFileContents(fpath, hash); + _repository->updatedFileContents(it->path, hash); _repository->totalDownloaded += sz; } // of hash matches } // of found in child list @@ -539,8 +533,8 @@ private: continue; } - children.push_back(ChildInfo(typeData == "f" ? ChildInfo::FileType : ChildInfo::DirectoryType, tokens[1], tokens[2])); - + children.emplace_back(ChildInfo(typeData == "f" ? ChildInfo::FileType : ChildInfo::DirectoryType, tokens[1], tokens[2])); + children.back().path = absolutePath() / tokens[1]; if (tokens.size() > 3) { children.back().setSize(tokens[3]); } @@ -572,8 +566,7 @@ private: std::string hashForChild(const ChildInfo& child) const { - SGPath p(absolutePath()); - p.append(child.name); + SGPath p(child.path); if (child.type == ChildInfo::DirectoryType) { p.append(".dirindex"); } @@ -1056,9 +1049,6 @@ HTTPRepository::failure() const entry.lengthBytes = strtol(sizeData.c_str(), NULL, 10); hashes.push_back(entry); } - - SG_LOG(SG_TERRASYNC, SG_INFO, "restored hashes:" << hashes.size()); - } class DirectoryWithPath diff --git a/simgear/io/sg_binobj.cxx b/simgear/io/sg_binobj.cxx index 3fe3591f..82f1b458 100644 --- a/simgear/io/sg_binobj.cxx +++ b/simgear/io/sg_binobj.cxx @@ -160,7 +160,7 @@ public: } } - float readInt() + int32_t readInt() { unsigned int* p = reinterpret_cast(ptr + offset); if ( sgIsBigEndian() ) { diff --git a/simgear/misc/path_test.cxx b/simgear/misc/path_test.cxx index 19e82a27..dac7c0d2 100644 --- a/simgear/misc/path_test.cxx +++ b/simgear/misc/path_test.cxx @@ -160,7 +160,7 @@ void test_path_dir() SG_VERIFY(sub2.isFile()); SG_CHECK_EQUAL(sub2.sizeInBytes(), 250); - SGPath sub3 = p / "subß" / "file𝕽"; + SGPath sub3 = p / "subß" / u8"file𝕽"; sub3.create_dir(0755); { @@ -174,7 +174,7 @@ void test_path_dir() sub3.set_cached(false); SG_VERIFY(sub3.exists()); SG_CHECK_EQUAL(sub3.sizeInBytes(), 100); - SG_CHECK_EQUAL(sub3.file(), "file𝕽"); + SG_CHECK_EQUAL(sub3.file(), u8"file𝕽"); simgear::Dir subD(p / "subA"); simgear::PathList dirChildren = subD.children(simgear::Dir::TYPE_DIR | simgear::Dir::NO_DOT_OR_DOTDOT); @@ -188,7 +188,7 @@ void test_path_dir() simgear::Dir subS(sub3.dirPath()); fileChildren = subS.children(simgear::Dir::TYPE_FILE | simgear::Dir::NO_DOT_OR_DOTDOT); SG_CHECK_EQUAL(fileChildren.size(), 1); - SG_CHECK_EQUAL(fileChildren[0], subS.path() / "file𝕽"); + SG_CHECK_EQUAL(fileChildren[0], subS.path() / u8"file𝕽"); } diff --git a/simgear/misc/strutils.cxx b/simgear/misc/strutils.cxx index b15a73e7..88bf2d21 100644 --- a/simgear/misc/strutils.cxx +++ b/simgear/misc/strutils.cxx @@ -1136,44 +1136,49 @@ bool matchPropPathToTemplate(const std::string& path, const std::string& templat bool parseStringAsLatLonValue(const std::string& s, double& degrees) { - string ss = simplify(s); - auto spacePos = ss.find_first_of(" *"); - - if (spacePos == std::string::npos) { - degrees = std::stod(ss); - } else { - degrees = std::stod(ss.substr(0, spacePos)); + try { + string ss = simplify(s); + auto spacePos = ss.find_first_of(" *"); - double minutes = 0.0, seconds = 0.0; - - // check for minutes marker - auto quotePos = ss.find('\''); - if (quotePos == std::string::npos) { - const auto minutesStr = ss.substr(spacePos+1); - if (!minutesStr.empty()) { - minutes = std::stod(minutesStr); + if (spacePos == std::string::npos) { + degrees = std::stod(ss); + } else { + degrees = std::stod(ss.substr(0, spacePos)); + + double minutes = 0.0, seconds = 0.0; + + // check for minutes marker + auto quotePos = ss.find('\''); + if (quotePos == std::string::npos) { + const auto minutesStr = ss.substr(spacePos+1); + if (!minutesStr.empty()) { + minutes = std::stod(minutesStr); + } + } else { + minutes = std::stod(ss.substr(spacePos+1, quotePos - spacePos)); + const auto secondsStr = ss.substr(quotePos+1); + if (!secondsStr.empty()) { + seconds = std::stod(secondsStr); + } + } + + if ((seconds < 0.0) || (minutes < 0.0)) { + // don't allow sign information in minutes or seconds + return false; + } + + double offset = (minutes / 60.0) + (seconds / 3600.0); + degrees += (degrees >= 0.0) ? offset : -offset; } - } else { - minutes = std::stod(ss.substr(spacePos+1, quotePos - spacePos)); - const auto secondsStr = ss.substr(quotePos+1); - if (!secondsStr.empty()) { - seconds = std::stod(secondsStr); + + // since we simplified, any trailing N/S/E/W must be the last char + const char lastChar = ::toupper(ss.back()); + if ((lastChar == 'W') || (lastChar == 'S')) { + degrees = -degrees; } - } - - if ((seconds < 0.0) || (minutes < 0.0)) { - // don't allow sign information in minutes or seconds - return false; - } - - double offset = (minutes / 60.0) + (seconds / 3600.0); - degrees += (degrees >= 0.0) ? offset : -offset; - } - - // since we simplified, any trailing N/S/E/W must be the last char - const char lastChar = ::toupper(ss.back()); - if ((lastChar == 'W') || (lastChar == 'S')) { - degrees = -degrees; + } catch (std::exception&) { + // std::stdo can throw + return false; } return true; diff --git a/simgear/misc/strutils_test.cxx b/simgear/misc/strutils_test.cxx index 35ac5b79..d9559ad3 100644 --- a/simgear/misc/strutils_test.cxx +++ b/simgear/misc/strutils_test.cxx @@ -676,6 +676,13 @@ void test_parseGeod() SG_VERIFY(strutils::parseStringAsGeod("\t40 30'50\"S, 12 34'56\"W ", &a, true)); SG_CHECK_EQUAL_EP(a.getLongitudeDeg(), -12.58222222); SG_CHECK_EQUAL_EP(a.getLatitudeDeg(), -40.5138888); + + + // malformed inputs + + SG_VERIFY(strutils::parseStringAsGeod("12.345,", &a, true) == false); + double d; + SG_VERIFY(strutils::parseStringAsLatLonValue("", d) == false); } void test_formatGeod() diff --git a/simgear/structure/event_mgr.cxx b/simgear/structure/event_mgr.cxx index 12e56d5d..435b18f8 100644 --- a/simgear/structure/event_mgr.cxx +++ b/simgear/structure/event_mgr.cxx @@ -119,6 +119,14 @@ void SGEventMgr::removeTask(const std::string& name) } } +void SGEventMgr::dump() +{ + SG_LOG(SG_GENERAL, SG_INFO, "EventMgr: sim-time queue:"); + _simQueue.dump(); + SG_LOG(SG_GENERAL, SG_INFO, "EventMgr: real-time queue:"); + _rtQueue.dump(); +} + //////////////////////////////////////////////////////////////////////// // SGTimerQueue // This is the priority queue implementation: @@ -270,3 +278,11 @@ SGTimer* SGTimerQueue::findByName(const std::string& name) const return NULL; } + +void SGTimerQueue::dump() +{ + for (int i=0; i < _numEntries; ++i) { + const auto t = _table[i].timer; + SG_LOG(SG_GENERAL, SG_INFO, "\ttimer:" << t->name << ", interval=" << t->interval); + } +} diff --git a/simgear/structure/event_mgr.hxx b/simgear/structure/event_mgr.hxx index 41dc7b86..eaaec7f0 100644 --- a/simgear/structure/event_mgr.hxx +++ b/simgear/structure/event_mgr.hxx @@ -38,6 +38,8 @@ public: double nextTime() { return -_table[0].pri; } SGTimer* findByName(const std::string& name) const; + + void dump(); private: // The "priority" is stored as a negative time. This allows the // implementation to treat the "top" of the heap as the largest @@ -119,6 +121,8 @@ public: void removeTask(const std::string& name); + + void dump(); private: friend class SGTimer; diff --git a/version b/version index ddab0701..5c8cec8e 100644 --- a/version +++ b/version @@ -1 +1 @@ -2018.3.0 +2018.4.0