| /** |
| * @file symbol_sort.cpp |
| * Sorting symbols |
| * |
| * @remark Copyright 2002, 2003 OProfile authors |
| * @remark Read the file COPYING |
| * |
| * @author Philippe Elie |
| * @author John Levon |
| */ |
| |
| #include "symbol_sort.h" |
| #include "symbol_functors.h" |
| |
| #include "name_storage.h" |
| #include "op_exception.h" |
| |
| #include <algorithm> |
| #include <sstream> |
| |
| using namespace std; |
| |
| namespace { |
| |
| bool long_filenames; |
| |
| int image_compare(image_name_id l, image_name_id r) |
| { |
| if (long_filenames) |
| return image_names.name(l).compare(image_names.name(r)); |
| return image_names.basename(l).compare(image_names.basename(r)); |
| } |
| |
| |
| int debug_compare(debug_name_id l, debug_name_id r) |
| { |
| if (long_filenames) |
| return debug_names.name(l).compare(debug_names.name(r)); |
| return debug_names.basename(l).compare(debug_names.basename(r)); |
| } |
| |
| |
| int compare_by(sort_options::sort_order order, |
| symbol_entry const & lhs, symbol_entry const & rhs) |
| { |
| switch (order) { |
| case sort_options::sample: |
| if (lhs.sample.counts[0] < rhs.sample.counts[0]) |
| return 1; |
| if (lhs.sample.counts[0] > rhs.sample.counts[0]) |
| return -1; |
| return 0; |
| |
| case sort_options::symbol: |
| return symbol_names.demangle(lhs.name).compare( |
| symbol_names.demangle(rhs.name)); |
| |
| case sort_options::image: |
| return image_compare(lhs.image_name, rhs.image_name); |
| |
| case sort_options::app_name: |
| return image_compare(lhs.app_name, rhs.app_name); |
| |
| case sort_options::vma: |
| if (lhs.sample.vma < rhs.sample.vma) |
| return -1; |
| if (lhs.sample.vma > rhs.sample.vma) |
| return 1; |
| return 0; |
| |
| case sort_options::debug: { |
| file_location const & f1 = lhs.sample.file_loc; |
| file_location const & f2 = rhs.sample.file_loc; |
| int ret = debug_compare(f1.filename, f2.filename); |
| if (ret == 0) |
| ret = f1.linenr - f2.linenr; |
| return ret; |
| } |
| |
| default: { |
| // static_cast<> to shut up g++ 2.91.66 which warn |
| // about ambiguity between <<(int) and <<(long int) |
| ostringstream os; |
| os << "compare_by(): unknown sort option: " |
| << static_cast<int>(order) << endl; |
| throw op_fatal_error(os.str()); |
| } |
| } |
| |
| return 0; |
| } |
| |
| |
| struct symbol_compare { |
| symbol_compare(vector<sort_options::sort_order> const & order, |
| bool reverse) |
| : compare_order(order), reverse_sort(reverse) {} |
| |
| bool operator()(symbol_entry const * lhs, |
| symbol_entry const * rhs) const { |
| return operator()(*lhs, *rhs); |
| } |
| |
| bool operator()(symbol_entry const & lhs, |
| symbol_entry const & rhs) const; |
| |
| protected: |
| vector<sort_options::sort_order> const & compare_order; |
| bool reverse_sort; |
| }; |
| |
| |
| bool symbol_compare::operator()(symbol_entry const & lhs, |
| symbol_entry const & rhs) const |
| { |
| for (size_t i = 0; i < compare_order.size(); ++i) { |
| int ret = compare_by(compare_order[i], lhs, rhs); |
| |
| if (reverse_sort) |
| ret = -ret; |
| if (ret != 0) |
| return ret < 0; |
| } |
| return false; |
| } |
| |
| |
| } // anonymous namespace |
| |
| |
| void sort_options:: |
| sort(symbol_collection & syms, bool reverse_sort, bool lf) const |
| { |
| long_filenames = lf; |
| |
| vector<sort_order> sort_option(options); |
| for (sort_order cur = first; cur != last; cur = sort_order(cur + 1)) { |
| if (find(sort_option.begin(), sort_option.end(), cur) == |
| sort_option.end()) |
| sort_option.push_back(cur); |
| } |
| |
| stable_sort(syms.begin(), syms.end(), |
| symbol_compare(sort_option, reverse_sort)); |
| } |
| |
| |
| void sort_options:: |
| sort(diff_collection & syms, bool reverse_sort, bool lf) const |
| { |
| long_filenames = lf; |
| |
| vector<sort_order> sort_option(options); |
| for (sort_order cur = first; cur != last; cur = sort_order(cur + 1)) { |
| if (find(sort_option.begin(), sort_option.end(), cur) == |
| sort_option.end()) |
| sort_option.push_back(cur); |
| } |
| |
| stable_sort(syms.begin(), syms.end(), |
| symbol_compare(sort_option, reverse_sort)); |
| } |
| |
| |
| void sort_options::add_sort_option(string const & name) |
| { |
| if (name == "vma") { |
| options.push_back(vma); |
| } else if (name == "sample") { |
| options.push_back(sample); |
| } else if (name == "symbol") { |
| options.push_back(symbol); |
| } else if (name == "debug") { |
| options.push_back(debug); |
| } else if (name == "image") { |
| options.push_back(image); |
| } else if (name == "app-name") { |
| options.push_back(app_name); |
| } else { |
| ostringstream os; |
| os << "unknown sort option: " << name << endl; |
| throw op_fatal_error(os.str()); |
| } |
| } |
| |
| |
| void sort_options::add_sort_option(sort_options::sort_order order) |
| { |
| options.push_back(order); |
| } |