Home | History | Annotate | Download | only in libpp
      1 /**
      2  * @file symbol_sort.cpp
      3  * Sorting symbols
      4  *
      5  * @remark Copyright 2002, 2003 OProfile authors
      6  * @remark Read the file COPYING
      7  *
      8  * @author Philippe Elie
      9  * @author John Levon
     10  */
     11 
     12 #include "symbol_sort.h"
     13 #include "symbol_functors.h"
     14 
     15 #include "name_storage.h"
     16 #include "op_exception.h"
     17 
     18 #include <algorithm>
     19 #include <sstream>
     20 
     21 using namespace std;
     22 
     23 namespace {
     24 
     25 bool long_filenames;
     26 
     27 int image_compare(image_name_id l, image_name_id r)
     28 {
     29 	if (long_filenames)
     30 		return image_names.name(l).compare(image_names.name(r));
     31 	return image_names.basename(l).compare(image_names.basename(r));
     32 }
     33 
     34 
     35 int debug_compare(debug_name_id l, debug_name_id r)
     36 {
     37 	if (long_filenames)
     38 		return debug_names.name(l).compare(debug_names.name(r));
     39 	return debug_names.basename(l).compare(debug_names.basename(r));
     40 }
     41 
     42 
     43 int compare_by(sort_options::sort_order order,
     44                symbol_entry const & lhs, symbol_entry const & rhs)
     45 {
     46 	switch (order) {
     47 		case sort_options::sample:
     48 			if (lhs.sample.counts[0] < rhs.sample.counts[0])
     49 				return 1;
     50 			if (lhs.sample.counts[0] > rhs.sample.counts[0])
     51 				return -1;
     52 			return 0;
     53 
     54 		case sort_options::symbol:
     55 			return symbol_names.demangle(lhs.name).compare(
     56 				symbol_names.demangle(rhs.name));
     57 
     58 		case sort_options::image:
     59 			return image_compare(lhs.image_name, rhs.image_name);
     60 
     61 		case sort_options::app_name:
     62 			return image_compare(lhs.app_name, rhs.app_name);
     63 
     64 		case sort_options::vma:
     65 			if (lhs.sample.vma < rhs.sample.vma)
     66 				return -1;
     67 			if (lhs.sample.vma > rhs.sample.vma)
     68 				return 1;
     69 			return 0;
     70 
     71 		case sort_options::debug: {
     72 			file_location const & f1 = lhs.sample.file_loc;
     73 			file_location const & f2 = rhs.sample.file_loc;
     74 			int ret = debug_compare(f1.filename, f2.filename);
     75 			if (ret == 0)
     76 				ret = f1.linenr - f2.linenr;
     77 			return ret;
     78 		}
     79 
     80 		default: {
     81 			// static_cast<> to shut up g++ 2.91.66 which warn
     82 			// about ambiguity between <<(int) and <<(long int)
     83 			ostringstream os;
     84 			os << "compare_by(): unknown sort option: "
     85 			   << static_cast<int>(order) << endl;
     86 			throw op_fatal_error(os.str());
     87 		}
     88 	}
     89 
     90 	return 0;
     91 }
     92 
     93 
     94 struct symbol_compare {
     95 	symbol_compare(vector<sort_options::sort_order> const & order,
     96 	               bool reverse)
     97 		: compare_order(order), reverse_sort(reverse) {}
     98 
     99 	bool operator()(symbol_entry const * lhs,
    100 			symbol_entry const * rhs) const {
    101 		return operator()(*lhs, *rhs);
    102 	}
    103 
    104 	bool operator()(symbol_entry const & lhs,
    105 			symbol_entry const & rhs) const;
    106 
    107 protected:
    108 	vector<sort_options::sort_order> const & compare_order;
    109 	bool reverse_sort;
    110 };
    111 
    112 
    113 bool symbol_compare::operator()(symbol_entry const & lhs,
    114 				symbol_entry const & rhs) const
    115 {
    116 	for (size_t i = 0; i < compare_order.size(); ++i) {
    117 		int ret = compare_by(compare_order[i], lhs, rhs);
    118 
    119 		if (reverse_sort)
    120 			ret = -ret;
    121 		if (ret != 0)
    122 			return ret < 0;
    123 	}
    124 	return false;
    125 }
    126 
    127 
    128 } // anonymous namespace
    129 
    130 
    131 void sort_options::
    132 sort(symbol_collection & syms, bool reverse_sort, bool lf) const
    133 {
    134 	long_filenames = lf;
    135 
    136 	vector<sort_order> sort_option(options);
    137 	for (sort_order cur = first; cur != last; cur = sort_order(cur + 1)) {
    138 		if (find(sort_option.begin(), sort_option.end(), cur) ==
    139 		    sort_option.end())
    140 			sort_option.push_back(cur);
    141 	}
    142 
    143 	stable_sort(syms.begin(), syms.end(),
    144 	            symbol_compare(sort_option, reverse_sort));
    145 }
    146 
    147 
    148 void sort_options::
    149 sort(diff_collection & syms, bool reverse_sort, bool lf) const
    150 {
    151 	long_filenames = lf;
    152 
    153 	vector<sort_order> sort_option(options);
    154 	for (sort_order cur = first; cur != last; cur = sort_order(cur + 1)) {
    155 		if (find(sort_option.begin(), sort_option.end(), cur) ==
    156 		    sort_option.end())
    157 			sort_option.push_back(cur);
    158 	}
    159 
    160 	stable_sort(syms.begin(), syms.end(),
    161 	            symbol_compare(sort_option, reverse_sort));
    162 }
    163 
    164 
    165 void sort_options::add_sort_option(string const & name)
    166 {
    167 	if (name == "vma") {
    168 		options.push_back(vma);
    169 	} else if (name == "sample") {
    170 		options.push_back(sample);
    171 	} else if (name == "symbol") {
    172 		options.push_back(symbol);
    173 	} else if (name == "debug") {
    174 		options.push_back(debug);
    175 	} else if (name == "image") {
    176 		options.push_back(image);
    177 	} else if (name == "app-name") {
    178 		options.push_back(app_name);
    179 	} else {
    180 		ostringstream os;
    181 		os << "unknown sort option: " << name << endl;
    182 		throw op_fatal_error(os.str());
    183 	}
    184 }
    185 
    186 
    187 void sort_options::add_sort_option(sort_options::sort_order order)
    188 {
    189 	options.push_back(order);
    190 }
    191