]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/base/TextException.cc
Source Format Enforcement (#532)
[thirdparty/squid.git] / src / base / TextException.cc
index 0fbd319949c5076f8a46384ea3e5ee4d98339c8d..d6d84164e8acb27f9cbc358963317b68a9b3ba93 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1996-2014 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
@@ -8,88 +8,72 @@
 
 #include "squid.h"
 #include "base/TextException.h"
-#include "Debug.h"
-#include "util.h"
+#include "sbuf/SBuf.h"
 
-TextException::TextException()
-{
-    message=NULL;
-    theFileName=NULL;
-    theLineNo=0;
-    theId=0;
-}
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
 
-TextException::TextException(const TextException& right) :
-    message((right.message?xstrdup(right.message):NULL)), theFileName(right.theFileName), theLineNo(right.theLineNo), theId(right.theId)
-{
-}
+/// a standard CoW string; avoids noise and circular dependencies of SBuf
+typedef std::runtime_error WhatString;
 
-TextException::TextException(const char *aMsg, const char *aFileName, int aLineNo, unsigned int anId):
-    message(aMsg?xstrdup(aMsg):NULL), theFileName(aFileName), theLineNo(aLineNo), theId(anId)
+/// a collection of strings indexed by pointers to their creator objects
+typedef std::unordered_multimap<const void*, WhatString> WhatStrings;
+
+/// requested what() strings of alive TextException objects
+static WhatStrings *WhatStrings_ = nullptr;
+
+TextException::TextException(SBuf message, const SourceLocation &location):
+    TextException(message.c_str(), location)
 {}
 
 TextException::~TextException() throw()
 {
-    if (message) xfree(message);
+    if (WhatStrings_)
+        WhatStrings_->erase(this); // there only if what() has been called
 }
 
-TextException& TextException::operator=(const TextException &right)
+std::ostream &
+TextException::print(std::ostream &os) const
 {
-    if (this==&right) return *this;
-    if (message) xfree(message);
-    message=(right.message?xstrdup(right.message):NULL);
-    theFileName=right.theFileName;
-    theLineNo=right.theLineNo;
-    theId=right.theId;
-    return *this;
+    os << std::runtime_error::what() <<
+       Debug::Extra << "exception location: " << where;
+    // TODO: ...error_detail: " << (ERR_DETAIL_EXCEPTION_START+id());
+    return os;
 }
 
-const char *TextException::what() const throw()
+const char *
+TextException::what() const throw()
 {
-    /// \todo add file:lineno
-    return message ? message : "TextException without a message";
-}
+    std::ostringstream os;
+    print(os);
+    const WhatString result(os.str());
 
-unsigned int TextException::FileNameHash(const char *fname)
-{
-    const char *s = NULL;
-    unsigned int n = 0;
-    unsigned int j = 0;
-    unsigned int i = 0;
-    s = strrchr(fname, '/');
-
-    if (s)
-        ++s;
-    else
-        s = fname;
+    // extend result.c_str() lifetime to this object lifetime
+    if (!WhatStrings_)
+        WhatStrings_ = new WhatStrings;
+    // *this could change, but we must preserve old results for they may be used
+    WhatStrings_->emplace(std::make_pair(this, result));
 
-    while (*s) {
-        ++j;
-        n ^= 271 * (unsigned) *s;
-        ++s;
-    }
-    i = n ^ (j * 271);
-    /*18bits of a 32 bit integer used  for filename hash (max hash=262143),
-      and 14 bits for storing line number (16k max).
-      If you change this policy remember to update the FileNameHash function
-      in the scripts/calc-must-ids.pl script
-    */
-    return i % 262143;
+    return result.what();
 }
 
-void Throw(const char *message, const char *fileName, int lineNo, unsigned int id)
+std::ostream &
+CurrentException(std::ostream &os)
 {
-
-    // or should we let the exception recepient print the exception instead?
-
-    if (fileName) {
-        debugs(0, 3, fileName << ':' << lineNo << ": exception" <<
-               (message ? ": " : ".") << (message ? message : ""));
+    if (std::current_exception()) {
+        try {
+            throw; // re-throw to recognize the exception type
+        }
+        catch (const std::exception &ex) {
+            os << ex.what();
+        }
+        catch (...) {
+            os << "[unknown exception type]";
+        }
     } else {
-        debugs(0, 3, "exception" <<
-               (message ? ": " : ".") << (message ? message : ""));
+        os << "[no active exception]";
     }
-
-    throw TextException(message, fileName, lineNo, id);
+    return os;
 }