--- /dev/null 2019-12-03 13:48:48.000000000 -0500 +++ new/src/jdk.incubator.jpackage/windows/native/libjpackage/ErrorHandling.cpp 2019-12-03 13:48:45.922078300 -0500 @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include + +#include "ErrorHandling.h" +#include "Log.h" + + +namespace { + +tstring getFilename(const SourceCodePos& pos) { + const std::string buf(pos.file); + const std::string::size_type idx = buf.find_last_of("\\/"); + if (idx == std::string::npos) { + return tstrings::fromUtf8(buf); + } + return tstrings::fromUtf8(buf.substr(idx + 1)); +} + +void reportError(const SourceCodePos& pos, const tstring& msg) { + Logger::defaultLogger().log(Logger::LOG_ERROR, getFilename(pos).c_str(), + pos.lno, tstrings::fromUtf8(pos.func).c_str(), msg); +} + +} // namespace + +void reportError(const SourceCodePos& pos, const std::exception& e) { + reportError(pos, (tstrings::any() << "Exception with message \'" + << e.what() << "\' caught").tstr()); +} + + +void reportUnknownError(const SourceCodePos& pos) { + reportError(pos, _T("Unknown exception caught")); +} + + +std::string makeMessage(const std::exception& e, const SourceCodePos& pos) { + std::ostringstream printer; + printer << getFilename(pos) << "(" << pos.lno << ") at " + << pos.func << "(): " + << e.what(); + return printer.str(); +} + + +namespace { + +bool isNotSpace(int chr) { + return isspace(chr) == 0; +} + + +enum TrimMode { + TrimLeading = 0x10, + TrimTrailing = 0x20, + TrimBoth = TrimLeading | TrimTrailing +}; + +// Returns position of the last printed character in the given string. +// Returns std::string::npos if nothing was printed. +size_t printWithoutWhitespaces(std::ostream& out, const std::string& str, + TrimMode mode) { + std::string::const_reverse_iterator it = str.rbegin(); + std::string::const_reverse_iterator end = str.rend(); + + if (mode & TrimLeading) { + // skip leading whitespace + std::string::const_iterator entry = std::find_if(str.begin(), + str.end(), isNotSpace); + end = std::string::const_reverse_iterator(entry); + } + + if (mode & TrimTrailing) { + // skip trailing whitespace + it = std::find_if(it, end, isNotSpace); + } + + if (it == end) { + return std::string::npos; + } + + const size_t pos = str.rend() - end; + const size_t len = end - it; + out.write(str.c_str() + pos, len); + return pos + len - 1; +} + +} // namespace + +std::string joinErrorMessages(const std::string& a, const std::string& b) { + const std::string endPhraseChars(";.,:!?"); + const std::string space(" "); + const std::string dotAndSpace(". "); + + std::ostringstream printer; + printer.exceptions(std::ios::failbit | std::ios::badbit); + + size_t idx = printWithoutWhitespaces(printer, a, TrimTrailing); + size_t extra = 0; + if (idx < a.size() && endPhraseChars.find(a[idx]) == std::string::npos) { + printer << dotAndSpace; + extra = dotAndSpace.size(); + } else if (idx != std::string::npos) { + printer << space; + extra = space.size(); + } + + idx = printWithoutWhitespaces(printer, b, TrimBoth); + + const std::string str = printer.str(); + + if (std::string::npos == idx && extra) { + // Nothing printed from the 'b' message. Backout delimiter string. + return str.substr(0, str.size() - extra); + } + return str; +}