| /* | |
| * Copyright (c) 2019, 2024, 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 <algorithm> | |
| #include <string.h> | |
| #include <cerrno> | |
| #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::runtime_error& 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::runtime_error& 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((unsigned char) 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; | |
| } | |
| std::string lastCRTError() { | |
| #ifndef _WIN32 | |
| return strerror(errno); | |
| #else | |
| TCHAR buffer[2048]; | |
| if (0 == _tcserror_s(buffer, errno)) { | |
| return (tstrings::any() << buffer).str(); | |
| } | |
| return ""; | |
| #endif | |
| } |