// "http://foo.bar.com/a/b/c.txt?a=b&c=d#lol" => "txt" // "http://foo.bar.com/index.html" => "html" // "http://foo.bar.com/a/b/" => "" std::string getUrlExtension(const std::string& url) { std::string url2 = toLowerCase(trim(url)); int questionMark = stringIndexOf(url2, "?"); if (questionMark >= 0) { url2 = url2.substr(0, questionMark); } int hash = stringIndexOf(url2, "#"); if (hash >= 0) { url2 = url2.substr(0, hash); } int slash = stringLastIndexOf(url2, "/"); if (slash >= 0) { url2 = url2.substr(slash + 1); } int dot = stringLastIndexOf(url2, "."); if (dot >= 0) { url2 = url2.substr(dot + 1); } return url2; }
std::string iurlstream::getUrlFilename(std::string url) const { std::string filename = url; // strip query string, anchor from URL int questionmark = stringIndexOf(url, "?"); if (questionmark >= 0) { filename = filename.substr(0, questionmark); } int hash = stringIndexOf(url, "#"); if (hash >= 0) { filename = filename.substr(0, hash); } filename = getTail(filename); if (filename.empty()) { filename = "index.tmp"; // for / urls like http://google.com/ } return filename; }
// line = "ZNK6VectorIiE3getEi at vector.h:587" // <FUNCTION> at <LINESTR> void injectAddr2lineInfo(entry& ent, const std::string& line) { ent.line = 0; int atIndex = stringIndexOf(line, " at "); if (atIndex >= 0) { if (ent.function.empty()) { ent.function = line.substr(0, atIndex); } ent.lineStr = line.substr(atIndex + 4); int colonIndex = stringIndexOf(ent.lineStr, ":"); if (colonIndex >= 0) { ent.file = ent.lineStr.substr(0, colonIndex); std::string rest = ent.lineStr.substr(colonIndex + 1); if (stringIsInteger(rest)) { ent.line = stringToInteger(rest); } } } else { if (ent.function.empty()) { ent.function = line; } } // demangle function name if necessary if (startsWith(ent.function, "Z")) { ent.function = "_" + ent.function; } if (startsWith(ent.function, "_Z")) { int status; char* demangled = abi::__cxa_demangle(ent.function.c_str(), NULL, 0, &status); if (status == 0 && demangled) { ent.function = demangled; } } }
void printStackTrace(std::ostream& out) { // constructing the following object jumps into fancy code in call_stack_gcc/windows.cpp // to rebuild the stack trace; implementation differs for each operating system stacktrace::call_stack trace; std::vector<stacktrace::entry> entries = trace.stack; // get longest line string length to line up stack traces void* fakeStackPtr = stacktrace::getFakeCallStackPointer(); int entriesToShowCount = 0; int funcNameLength = 0; int lineStrLength = 0; for (size_t i = 0; i < entries.size(); ++i) { // remove references to std:: namespace stringReplaceInPlace(entries[i].function, "std::", ""); // a few substitutions related to predefined types for simplicity stringReplaceInPlace(entries[i].function, "basic_ostream", "ostream"); stringReplaceInPlace(entries[i].function, "basic_istream", "istream"); stringReplaceInPlace(entries[i].function, "basic_ofstream", "ofstream"); stringReplaceInPlace(entries[i].function, "basic_ifstream", "ifstream"); stringReplaceInPlace(entries[i].function, "basic_string", "string"); // remove template arguments // TODO: does not work well for nested templates int lessThan = stringIndexOf(entries[i].function, "<"); while (lessThan >= 0) { // see if there is a matching > for this < int greaterThan = lessThan + 1; int count = 1; while (greaterThan < (int) entries[i].function.length()) { if (entries[i].function[greaterThan] == '<') { count++; } else if (entries[i].function[greaterThan] == '>') { count--; if (count == 0) { break; } } greaterThan++; } if (count == 0 && lessThan >= 0 && greaterThan > lessThan) { entries[i].function.erase(lessThan, greaterThan - lessThan + 1); } else { // look for the next < in the string, if any, to see if it has a matching > lessThan = stringIndexOf(entries[i].function, "<", lessThan + 1); } } if (!STACK_TRACE_SHOULD_FILTER || !shouldFilterOutFromStackTrace(entries[i].function)) { lineStrLength = std::max(lineStrLength, (int) entries[i].lineStr.length()); funcNameLength = std::max(funcNameLength, (int) entries[i].function.length()); entriesToShowCount++; } } if (entries.empty() || entriesToShowCount == 0) { out << " *** No useful stack trace available." << std::endl; out << " ***" << std::endl; return; } if (lineStrLength > 0) { out << " *** Stack trace (line numbers are approximate):" << std::endl; if (STACK_TRACE_SHOW_TOP_BOTTOM_BARS) { out << " *** " << std::setw(lineStrLength) << std::left << "file:line" << " " << "function" << std::endl; out << " *** " << std::string(lineStrLength + 2 + funcNameLength, '=') << std::endl; } } else { out << " *** Stack trace:" << std::endl; } for (size_t i = 0; i < entries.size(); ++i) { stacktrace::entry entry = entries[i]; entry.file = getTail(entry.file); // skip certain entries for clarity if (STACK_TRACE_SHOULD_FILTER && shouldFilterOutFromStackTrace(entry.function)) { continue; } // show Main() as main() to hide hidden case-change by Stanford C++ lib internals if (startsWith(entry.function, "Main(")) { entry.function.replace(0, 5, "main("); } std::string lineStr = ""; if (!entry.lineStr.empty()) { lineStr = entry.lineStr; if (lineStr == "?? ??:0") { lineStr = "(unknown)"; } } else if (entry.line > 0) { lineStr = "line " + integerToString(entry.line); } // JL debugging // cout << "entry #" << i << endl; // cout << "lineStrLength: " << lineStrLength << endl; // cout << "lineStr: " << lineStr << endl; // cout << "entry.function: " << entry.function << endl; // JL end debugging out << " *** " << std::left << std::setw(lineStrLength) << lineStr << " " << entry.function << std::endl; // don't show entries beneath the student's main() function, for simplicity if (entry.function == "main()") { break; } } if (entries.size() == 1 && entries[0].address == fakeStackPtr) { out << " *** (partial stack due to crash)" << std::endl; } if (STACK_TRACE_SHOW_TOP_BOTTOM_BARS && lineStrLength > 0) { out << " *** " << std::string(lineStrLength + 2 + funcNameLength, '=') << std::endl; } out << " ***" << std::endl; out << " *** NOTE:" << std::endl; out << " *** Any line numbers listed above are approximate." << std::endl; out << " *** To learn more about why the program crashed, we" << std::endl; out << " *** suggest running your program under the debugger." << std::endl; out << " ***" << std::endl; }
void printStackTrace(std::ostream& out) { // constructing the following object jumps into fancy code in call_stack_gcc/windows.cpp // to rebuild the stack trace; implementation differs for each operating system stacktrace::call_stack trace; std::vector<stacktrace::entry> entries = trace.stack; // get longest line string length to line up stack traces void* fakeStackPtr = stacktrace::getFakeCallStackPointer(); int entriesToShowCount = 0; int funcNameLength = 0; int lineStrLength = 0; for (size_t i = 0; i < entries.size(); ++i) { // remove references to std:: namespace stringReplaceInPlace(entries[i].function, "std::", ""); // remove template arguments while (stringContains(entries[i].function, "<") && stringContains(entries[i].function, ">")) { int lessThan = stringIndexOf(entries[i].function, "<"); int greaterThan = stringIndexOf(entries[i].function, ">", lessThan); if (lessThan >= 0 && greaterThan > lessThan) { entries[i].function.erase(lessThan, greaterThan - lessThan + 1); } } if (!STACK_TRACE_SHOULD_FILTER || !shouldFilterOutFromStackTrace(entries[i].function)) { lineStrLength = std::max(lineStrLength, (int) entries[i].lineStr.length()); funcNameLength = std::max(funcNameLength, (int) entries[i].function.length()); entriesToShowCount++; } } if (entries.empty() || entriesToShowCount == 0) { return; // couldn't get a stack trace, or had no useful data :-( } if (lineStrLength > 0) { out << " *** Stack trace (line numbers are approximate):" << std::endl; if (STACK_TRACE_SHOW_TOP_BOTTOM_BARS) { out << " *** " << std::setw(lineStrLength) << std::left << "file:line" << " " << "function" << std::endl; out << " *** " << std::string(lineStrLength + 2 + funcNameLength, '=') << std::endl; } } else { out << " *** Stack trace:" << std::endl; } for (size_t i = 0; i < entries.size(); ++i) { stacktrace::entry entry = entries[i]; entry.file = getTail(entry.file); // skip certain entries for clarity if (STACK_TRACE_SHOULD_FILTER && shouldFilterOutFromStackTrace(entry.function)) { continue; } // show Main() as main() to hide hidden case-change by Stanford C++ lib internals if (startsWith(entry.function, "Main(")) { entry.function.replace(0, 5, "main("); } std::string lineStr = ""; if (!entry.lineStr.empty()) { lineStr = entry.lineStr; } else if (entry.line > 0) { lineStr = "line " + integerToString(entry.line); } out << " *** " << std::left << std::setw(lineStrLength) << lineStr << " " << entry.function << std::endl; // don't show entries beneath the student's main() function, for simplicity if (entry.function == "main()") { break; } } if (entries.size() == 1 && entries[0].address == fakeStackPtr) { out << " *** (partial stack due to crash)" << std::endl; } if (STACK_TRACE_SHOW_TOP_BOTTOM_BARS && lineStrLength > 0) { out << " *** " << std::string(lineStrLength + 2 + funcNameLength, '=') << std::endl; } // out << " ***" << std::endl; // out << " *** NOTE:" << std::endl; // out << " *** Any line numbers listed above are approximate." << std::endl; // out << " *** To learn more about why the program crashed, we" << std::endl; // out << " *** suggest running your program under the debugger." << std::endl; out << " ***" << std::endl; }