summaryrefslogtreecommitdiff
path: root/utils.cc
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2008-08-05 13:17:04 -0400
committerJohn Wiegley <johnw@newartisans.com>2008-08-05 18:05:49 -0400
commitf6f4a46cf5b14f9a2170cd6475958efbf320caec (patch)
tree05bc1defcdebc201de3dd10477483d906a842821 /utils.cc
parentb7970b29855563e4c67f85af8b31233eda80c22a (diff)
downloadfork-ledger-f6f4a46cf5b14f9a2170cd6475958efbf320caec.tar.gz
fork-ledger-f6f4a46cf5b14f9a2170cd6475958efbf320caec.tar.bz2
fork-ledger-f6f4a46cf5b14f9a2170cd6475958efbf320caec.zip
Moved around most of the files so that source code is in src/, documentation
is in doc/, etc.
Diffstat (limited to 'utils.cc')
-rw-r--r--utils.cc716
1 files changed, 0 insertions, 716 deletions
diff --git a/utils.cc b/utils.cc
deleted file mode 100644
index 5ac5cef0..00000000
--- a/utils.cc
+++ /dev/null
@@ -1,716 +0,0 @@
-/*
- * Copyright (c) 2003-2008, John Wiegley. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of New Artisans LLC nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "utils.h"
-
-/**********************************************************************
- *
- * Assertions
- */
-
-#if defined(ASSERTS_ON)
-
-namespace ledger {
-
-DECLARE_EXCEPTION(assertion_failed, std::logic_error);
-
-void debug_assert(const string& reason,
- const string& func,
- const string& file,
- unsigned long line)
-{
- std::ostringstream buf;
- buf << "Assertion failed in \"" << file << "\", line " << line
- << ": " << func << ": " << reason;
- throw assertion_failed(buf.str());
-}
-
-} // namespace ledger
-
-#endif
-
-/**********************************************************************
- *
- * Verification (basically, very slow asserts)
- */
-
-#if defined(VERIFY_ON)
-
-namespace ledger {
-
-bool verify_enabled = false;
-
-typedef std::pair<std::string, std::size_t> allocation_pair;
-typedef std::map<void *, allocation_pair> live_memory_map;
-typedef std::multimap<void *, allocation_pair> live_objects_map;
-
-typedef std::pair<unsigned int, std::size_t> count_size_pair;
-typedef std::map<std::string, count_size_pair> object_count_map;
-
-static live_memory_map * live_memory = NULL;
-static object_count_map * live_memory_count = NULL;
-static object_count_map * total_memory_count = NULL;
-
-static bool memory_tracing_active = false;
-
-static live_objects_map * live_objects = NULL;
-static object_count_map * live_object_count = NULL;
-static object_count_map * total_object_count = NULL;
-static object_count_map * total_ctor_count = NULL;
-
-void initialize_memory_tracing()
-{
- memory_tracing_active = false;
-
- live_memory = new live_memory_map;
- live_memory_count = new object_count_map;
- total_memory_count = new object_count_map;
-
- live_objects = new live_objects_map;
- live_object_count = new object_count_map;
- total_object_count = new object_count_map;
- total_ctor_count = new object_count_map;
-
- memory_tracing_active = true;
-}
-
-void shutdown_memory_tracing()
-{
- memory_tracing_active = false;
-
- if (live_objects) {
- IF_DEBUG("memory.counts")
- report_memory(std::cerr, true);
- else IF_DEBUG("memory.counts.live")
- report_memory(std::cerr);
- else if (live_objects->size() > 0)
- report_memory(std::cerr);
- }
-
- checked_delete(live_memory); live_memory = NULL;
- checked_delete(live_memory_count); live_memory_count = NULL;
- checked_delete(total_memory_count); total_memory_count = NULL;
-
- checked_delete(live_objects); live_objects = NULL;
- checked_delete(live_object_count); live_object_count = NULL;
- checked_delete(total_object_count); total_object_count = NULL;
- checked_delete(total_ctor_count); total_ctor_count = NULL;
-}
-
-inline void add_to_count_map(object_count_map& the_map,
- const char * name, std::size_t size)
-{
- object_count_map::iterator k = the_map.find(name);
- if (k != the_map.end()) {
- (*k).second.first++;
- (*k).second.second += size;
- } else {
- std::pair<object_count_map::iterator, bool> result =
- the_map.insert(object_count_map::value_type(name, count_size_pair(1, size)));
- VERIFY(result.second);
- }
-}
-
-std::size_t current_memory_size()
-{
- std::size_t memory_size = 0;
-
- foreach (const object_count_map::value_type& pair, *live_memory_count)
- memory_size += pair.second.second;
-
- return memory_size;
-}
-
-static void trace_new_func(void * ptr, const char * which, std::size_t size)
-{
- memory_tracing_active = false;
-
- if (! live_memory) return;
-
- live_memory->insert
- (live_memory_map::value_type(ptr, allocation_pair(which, size)));
-
- add_to_count_map(*live_memory_count, which, size);
- add_to_count_map(*total_memory_count, which, size);
- add_to_count_map(*total_memory_count, "__ALL__", size);
-
- memory_tracing_active = true;
-}
-
-static void trace_delete_func(void * ptr, const char * which)
-{
- memory_tracing_active = false;
-
- if (! live_memory) return;
-
- // Ignore deletions of memory not tracked, since it's possible that
- // a user (like boost) allocated a block of memory before memory
- // tracking began, and then deleted it before memory tracking ended.
- // If it really is a double-delete, the malloc library on OS/X will
- // notify me.
-
- live_memory_map::iterator i = live_memory->find(ptr);
- if (i == live_memory->end())
- return;
-
- std::size_t size = (*i).second.second;
- VERIFY((*i).second.first == which);
-
- live_memory->erase(i);
-
- object_count_map::iterator j = live_memory_count->find(which);
- VERIFY(j != live_memory_count->end());
-
- (*j).second.second -= size;
- if (--(*j).second.first == 0)
- live_memory_count->erase(j);
-
- memory_tracing_active = true;
-}
-
-} // namespace ledger
-
-void * operator new(std::size_t size) throw (std::bad_alloc) {
- void * ptr = std::malloc(size);
- if (DO_VERIFY() && ledger::memory_tracing_active)
- ledger::trace_new_func(ptr, "new", size);
- return ptr;
-}
-void * operator new(std::size_t size, const std::nothrow_t&) throw() {
- void * ptr = std::malloc(size);
- if (DO_VERIFY() && ledger::memory_tracing_active)
- ledger::trace_new_func(ptr, "new", size);
- return ptr;
-}
-void * operator new[](std::size_t size) throw (std::bad_alloc) {
- void * ptr = std::malloc(size);
- if (DO_VERIFY() && ledger::memory_tracing_active)
- ledger::trace_new_func(ptr, "new[]", size);
- return ptr;
-}
-void * operator new[](std::size_t size, const std::nothrow_t&) throw() {
- void * ptr = std::malloc(size);
- if (DO_VERIFY() && ledger::memory_tracing_active)
- ledger::trace_new_func(ptr, "new[]", size);
- return ptr;
-}
-void operator delete(void * ptr) throw() {
- if (DO_VERIFY() && ledger::memory_tracing_active)
- ledger::trace_delete_func(ptr, "new");
- std::free(ptr);
-}
-void operator delete(void * ptr, const std::nothrow_t&) throw() {
- if (DO_VERIFY() && ledger::memory_tracing_active)
- ledger::trace_delete_func(ptr, "new");
- std::free(ptr);
-}
-void operator delete[](void * ptr) throw() {
- if (DO_VERIFY() && ledger::memory_tracing_active)
- ledger::trace_delete_func(ptr, "new[]");
- std::free(ptr);
-}
-void operator delete[](void * ptr, const std::nothrow_t&) throw() {
- if (DO_VERIFY() && ledger::memory_tracing_active)
- ledger::trace_delete_func(ptr, "new[]");
- std::free(ptr);
-}
-
-namespace ledger {
-
-inline void report_count_map(std::ostream& out, object_count_map& the_map)
-{
- foreach (object_count_map::value_type& pair, the_map)
- out << " " << std::right << std::setw(12) << pair.second.first
- << " " << std::right << std::setw(7) << pair.second.second
- << " " << std::left << pair.first
- << std::endl;
-}
-
-std::size_t current_objects_size()
-{
- std::size_t objects_size = 0;
-
- foreach (const object_count_map::value_type& pair, *live_object_count)
- objects_size += pair.second.second;
-
- return objects_size;
-}
-
-void trace_ctor_func(void * ptr, const char * cls_name, const char * args,
- std::size_t cls_size)
-{
- memory_tracing_active = false;
-
- if (! live_objects) return;
-
- static char name[1024];
- std::strcpy(name, cls_name);
- std::strcat(name, "(");
- std::strcat(name, args);
- std::strcat(name, ")");
-
- DEBUG("memory.debug", "TRACE_CTOR " << ptr << " " << name);
-
- live_objects->insert
- (live_objects_map::value_type(ptr, allocation_pair(cls_name, cls_size)));
-
- add_to_count_map(*live_object_count, cls_name, cls_size);
- add_to_count_map(*total_object_count, cls_name, cls_size);
- add_to_count_map(*total_object_count, "__ALL__", cls_size);
- add_to_count_map(*total_ctor_count, name, cls_size);
-
- memory_tracing_active = true;
-}
-
-void trace_dtor_func(void * ptr, const char * cls_name, std::size_t cls_size)
-{
- memory_tracing_active = false;
-
- if (! live_objects) return;
-
- DEBUG("memory.debug", "TRACE_DTOR " << ptr << " " << cls_name);
-
- live_objects_map::iterator i = live_objects->find(ptr);
- if (i == live_objects->end()) {
- std::cerr << "Attempting to delete " << ptr << " a non-living " << cls_name
- << std::endl;
- assert(false);
- }
-
- int ptr_count = live_objects->count(ptr);
- for (int x = 0; x < ptr_count; x++, i++) {
- if ((*i).second.first == cls_name) {
- live_objects->erase(i);
- break;
- }
- }
-
- object_count_map::iterator k = live_object_count->find(cls_name);
- VERIFY(k != live_object_count->end());
-
- (*k).second.second -= cls_size;
- if (--(*k).second.first == 0)
- live_object_count->erase(k);
-
- memory_tracing_active = true;
-}
-
-void report_memory(std::ostream& out, bool report_all)
-{
- if (! live_memory) return;
-
- if (live_memory_count->size() > 0) {
- out << "NOTE: There may be memory held by Boost "
- << "and libstdc++ after ledger::shutdown()" << std::endl;
- out << "Live memory count:" << std::endl;
- report_count_map(out, *live_memory_count);
- }
-
- if (live_memory->size() > 0) {
- out << "Live memory:" << std::endl;
-
- foreach (const live_memory_map::value_type& pair, *live_memory)
- out << " " << std::right << std::setw(12) << pair.first
- << " " << std::right << std::setw(7) << pair.second.second
- << " " << std::left << pair.second.first
- << std::endl;
- }
-
- if (report_all && total_memory_count->size() > 0) {
- out << "Total memory counts:" << std::endl;
- report_count_map(out, *total_memory_count);
- }
-
- if (live_object_count->size() > 0) {
- out << "Live object count:" << std::endl;
- report_count_map(out, *live_object_count);
- }
-
- if (live_objects->size() > 0) {
- out << "Live objects:" << std::endl;
-
- foreach (const live_objects_map::value_type& pair, *live_objects)
- out << " " << std::right << std::setw(12) << pair.first
- << " " << std::right << std::setw(7) << pair.second.second
- << " " << std::left << pair.second.first
- << std::endl;
- }
-
- if (report_all) {
- if (total_object_count->size() > 0) {
- out << "Total object counts:" << std::endl;
- report_count_map(out, *total_object_count);
- }
-
- if (total_ctor_count->size() > 0) {
- out << "Total constructor counts:" << std::endl;
- report_count_map(out, *total_ctor_count);
- }
- }
-}
-
-
-string::string() : std::string() {
- TRACE_CTOR(string, "");
-}
-string::string(const string& str) : std::string(str) {
- TRACE_CTOR(string, "copy");
-}
-string::string(const std::string& str) : std::string(str) {
- TRACE_CTOR(string, "const std::string&");
-}
-string::string(const int len, char x) : std::string(len, x) {
- TRACE_CTOR(string, "const int, char");
-}
-string::string(const char * str) : std::string(str) {
- TRACE_CTOR(string, "const char *");
-}
-string::string(const char * str, const char * end) : std::string(str, end) {
- TRACE_CTOR(string, "const char *, const char *");
-}
-string::string(const string& str, int x) : std::string(str, x) {
- TRACE_CTOR(string, "const string&, int");
-}
-string::string(const string& str, int x, int y) : std::string(str, x, y) {
- TRACE_CTOR(string, "const string&, int, int");
-}
-string::string(const char * str, int x) : std::string(str, x) {
- TRACE_CTOR(string, "const char *, int");
-}
-string::string(const char * str, int x, int y) : std::string(str, x, y) {
- TRACE_CTOR(string, "const char *, int, int");
-}
-string::~string() throw() {
- TRACE_DTOR(string);
-}
-
-} // namespace ledger
-
-#endif // VERIFY_ON
-
-ledger::string empty_string("");
-
-/**********************************************************************
- *
- * Logging
- */
-
-#if defined(LOGGING_ON)
-
-namespace ledger {
-
-log_level_t _log_level = LOG_WARN;
-std::ostream * _log_stream = &std::cerr;
-std::ostringstream _log_buffer;
-
-#if defined(TRACING_ON)
-unsigned int _trace_level;
-#endif
-
-#ifdef BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK
-#define CURRENT_TIME() boost::posix_time::microsec_clock::universal_time()
-#else
-#define CURRENT_TIME() boost::posix_time::second_clock::universal_time()
-#endif
-
-static inline void stream_memory_size(std::ostream& out, std::size_t size)
-{
- if (size < 1024)
- out << size << 'b';
- else if (size < (1024 * 1024))
- out << (double(size) / 1024.0) << 'K';
- else if (size < (1024 * 1024 * 1024))
- out << (double(size) / (1024.0 * 1024.0)) << 'M';
- else
- out << (double(size) / (1024.0 * 1024.0 * 1024.0)) << 'G';
-}
-
-static bool logger_has_run = false;
-static ptime logger_start;
-
-bool logger_func(log_level_t level)
-{
- unsigned long appender = 0;
-
- if (! logger_has_run) {
- logger_has_run = true;
- logger_start = CURRENT_TIME();
-
- IF_VERIFY()
- *_log_stream << " TIME OBJSZ MEMSZ" << std::endl;
-
- appender = (logger_start - current_time).total_milliseconds();
- }
-
- *_log_stream << std::right << std::setw(5)
- << (CURRENT_TIME() - logger_start).total_milliseconds();
-
- IF_VERIFY() {
- *_log_stream << std::right << std::setw(6) << std::setprecision(3);
- stream_memory_size(*_log_stream, current_objects_size());
- *_log_stream << std::right << std::setw(6) << std::setprecision(3);
- stream_memory_size(*_log_stream, current_memory_size());
- }
-
- *_log_stream << " " << std::left << std::setw(7);
-
- switch (level) {
- case LOG_CRIT: *_log_stream << "[CRIT]"; break;
- case LOG_FATAL: *_log_stream << "[FATAL]"; break;
- case LOG_ASSERT: *_log_stream << "[ASSRT]"; break;
- case LOG_ERROR: *_log_stream << "[ERROR]"; break;
- case LOG_VERIFY: *_log_stream << "[VERFY]"; break;
- case LOG_WARN: *_log_stream << "[WARN]"; break;
- case LOG_INFO: *_log_stream << "[INFO]"; break;
- case LOG_EXCEPT: *_log_stream << "[EXCPT]"; break;
- case LOG_DEBUG: *_log_stream << "[DEBUG]"; break;
- case LOG_TRACE: *_log_stream << "[TRACE]"; break;
-
- case LOG_OFF:
- case LOG_ALL:
- assert(false);
- break;
- }
-
- *_log_stream << ' ' << _log_buffer.str();
-
- if (appender)
- *_log_stream << " (" << appender << "ms startup)";
-
- *_log_stream << std::endl;
-
- _log_buffer.str("");
-
- return true;
-}
-
-} // namespace ledger
-
-#if defined(DEBUG_ON)
-
-namespace ledger {
-
-optional<std::string> _log_category;
-
-} // namespace ledger
-
-#endif // DEBUG_ON
-#endif // LOGGING_ON
-
-/**********************************************************************
- *
- * Timers (allows log entries to specify cumulative time spent)
- */
-
-#if defined(LOGGING_ON) && defined(TIMERS_ON)
-
-namespace ledger {
-
-struct timer_t
-{
- log_level_t level;
- ptime begin;
- time_duration spent;
- std::string description;
- bool active;
-
- timer_t(log_level_t _level, std::string _description)
- : level(_level), begin(CURRENT_TIME()),
- spent(time_duration(0, 0, 0, 0)),
- description(_description), active(true) {}
-};
-
-typedef std::map<std::string, timer_t> timer_map;
-
-static timer_map timers;
-
-void start_timer(const char * name, log_level_t lvl)
-{
-#if defined(VERIFY_ON)
- memory_tracing_active = false;
-#endif
-
- timer_map::iterator i = timers.find(name);
- if (i == timers.end()) {
- timers.insert(timer_map::value_type(name, timer_t(lvl, _log_buffer.str())));
- } else {
- assert((*i).second.description == _log_buffer.str());
- (*i).second.begin = CURRENT_TIME();
- (*i).second.active = true;
- }
- _log_buffer.str("");
-
-#if defined(VERIFY_ON)
- memory_tracing_active = true;
-#endif
-}
-
-void stop_timer(const char * name)
-{
-#if defined(VERIFY_ON)
- memory_tracing_active = false;
-#endif
-
- timer_map::iterator i = timers.find(name);
- assert(i != timers.end());
-
- (*i).second.spent += CURRENT_TIME() - (*i).second.begin;
- (*i).second.active = false;
-
-#if defined(VERIFY_ON)
- memory_tracing_active = true;
-#endif
-}
-
-void finish_timer(const char * name)
-{
-#if defined(VERIFY_ON)
- memory_tracing_active = false;
-#endif
-
- timer_map::iterator i = timers.find(name);
- if (i == timers.end())
- return;
-
- time_duration spent = (*i).second.spent;
- if ((*i).second.active) {
- spent = CURRENT_TIME() - (*i).second.begin;
- (*i).second.active = false;
- }
-
- _log_buffer << (*i).second.description << ' ';
-
- bool need_paren =
- (*i).second.description[(*i).second.description.size() - 1] != ':';
-
- if (need_paren)
- _log_buffer << '(';
-
- _log_buffer << spent.total_milliseconds() << "ms";
-
- if (need_paren)
- _log_buffer << ')';
-
- logger_func((*i).second.level);
-
- timers.erase(i);
-
-#if defined(VERIFY_ON)
- memory_tracing_active = true;
-#endif
-}
-
-} // namespace ledger
-
-#endif // LOGGING_ON && TIMERS_ON
-
-/**********************************************************************
- *
- * Exception handling
- */
-
-namespace ledger {
-
-std::ostringstream _desc_buffer;
-std::ostringstream _ctxt_buffer;
-
-} // namespace ledger
-
-/**********************************************************************
- *
- * General utility functions
- */
-
-namespace ledger {
-
-path expand_path(const path& pathname)
-{
- if (pathname.empty())
- return pathname;
-
-#if 0
- // jww (2007-04-30): I need to port this code to use
- // boost::filesystem::path
- const char * pfx = NULL;
- string::size_type pos = pathname.find_first_of('/');
-
- if (pathname.length() == 1 || pos == 1) {
- pfx = std::getenv("HOME");
-#ifdef HAVE_GETPWUID
- if (! pfx) {
- // Punt. We're trying to expand ~/, but HOME isn't set
- struct passwd * pw = getpwuid(getuid());
- if (pw)
- pfx = pw->pw_dir;
- }
-#endif
- }
-#ifdef HAVE_GETPWNAM
- else {
- string user(pathname, 1, pos == string::npos ?
- string::npos : pos - 1);
- struct passwd * pw = getpwnam(user.c_str());
- if (pw)
- pfx = pw->pw_dir;
- }
-#endif
-
- // if we failed to find an expansion, return the path unchanged.
-
- if (! pfx)
- return pathname;
-
- string result(pfx);
-
- if (pos == string::npos)
- return result;
-
- if (result.length() == 0 || result[result.length() - 1] != '/')
- result += '/';
-
- result += pathname.substr(pos + 1);
-
- return result;
-#else
- return pathname;
-#endif
-}
-
-path resolve_path(const path& pathname)
-{
- path temp = pathname;
- if (temp.string()[0] == '~')
- temp = expand_path(temp);
- temp.normalize();
- return temp;
-}
-
-} // namespace ledger