1 /* Copyright (C) 2021 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
30 #include "data_pckts.h"
31 #include "StringBuilder.h"
32 #include "Experiment.h"
35 // ========================================================================
36 // Subclass: FilterNumeric
39 FilterNumeric::FilterNumeric (Experiment *_exp, const char *_cmd,
43 cmd = dbe_strdup (_cmd);
44 name = dbe_strdup (_name);
49 first = (uint64_t) - 1;
50 last = (uint64_t) - 1;
55 FilterNumeric::~FilterNumeric ()
64 // sets min and max for this filter; should be called when the range is
65 // known -- that comes after the first PathTree build, in the current
68 FilterNumeric::set_range (uint64_t findex, uint64_t lindex, uint64_t total)
70 if (first == findex && last == lindex)
89 FilterNumeric::update_range ()
93 if (streq (cmd, NTXT ("sample")))
94 set_range (1, (uint64_t) exp->nsamples (), exp->nsamples ());
95 else if (streq (cmd, NTXT ("thread")))
96 set_range (exp->min_thread, exp->max_thread, exp->thread_cnt);
97 else if (streq (cmd, NTXT ("LWP")))
98 set_range (exp->min_lwp, exp->max_lwp, exp->lwp_cnt);
99 else if (streq (cmd, NTXT ("cpu")))
101 if (exp->min_cpu != (uint64_t) - 1)
102 set_range (exp->min_cpu, exp->max_cpu, exp->cpu_cnt);
106 // get_advanced_filter -- returns a string matching the current setting
108 FilterNumeric::get_advanced_filter ()
112 if (items->size () == 0)
113 return dbe_strdup (NTXT ("0"));
116 if (items->size () > 1)
118 for (int i = 0; i < items->size (); i++)
120 RangePair *rp = items->fetch (i);
122 sb.append (NTXT (" || "));
124 sb.append (prop_name);
125 if (rp->first == rp->last)
127 sb.append (NTXT ("=="));
128 sb.append ((long long) rp->first);
132 sb.append (NTXT (">="));
133 sb.append ((long long) rp->first);
134 sb.append (NTXT (" && "));
135 sb.append (prop_name);
136 sb.append (NTXT ("<="));
137 sb.append ((long long) rp->last);
141 if (items->size () > 1)
143 return sb.toString ();
147 // get_pattern -- returns a string matching the current setting
150 FilterNumeric::get_pattern ()
158 if (last == (uint64_t) - 1 && last == first)
159 // neither set; data not available
160 sb.append (GTXT ("(data not recorded)"));
162 sb.append (GTXT ("all"));
164 else if (items->size () == 0)
165 sb.append (GTXT ("none"));
168 for (int i = 0; i < items->size (); i++)
170 RangePair *rp = items->fetch (i);
173 sb.append ((long long) rp->first);
174 if (rp->first != rp->last)
177 sb.append ((long long) rp->last);
181 pattern = sb.toString ();
186 FilterNumeric::get_status ()
191 return dbe_strdup (status);
194 // set_pattern -- set the filter to a new pattern
195 // set error true/false if there was or was not an error parsing string
196 // Returns true/false if the filter changed, implying a rebuild of data
198 FilterNumeric::set_pattern (char *str, bool *error)
201 // save the old filter
202 Vector<RangePair *> *olditems = items;
204 if (strcmp (str, NTXT ("all")) == 0)
205 // if all, leave items NULL
207 else if (strcmp (str, NTXT ("none")) == 0)
208 // if none, leave items as a zero-length vector
209 items = new Vector<RangePair *>(0);
216 for (bool done = false; done == false;)
218 // tokenize the string
219 // Does it start with a "-" ?
221 val = first; // yes, set val to first, and see what follows
224 // it must start with a number
225 val = get_next_number (s, &nexts, error);
230 // look at the next character
235 *error = include_range (val, val);
241 if (*nexts == ',' || *nexts == '\0')
245 val2 = get_next_number (s, &nexts, error);
258 *error = include_range (val, val2);
276 *error = include_range (val, val);
285 // if there was a parser error leave old setting
298 if (first != (uint64_t) - 1 && last != (uint64_t) - 1)
300 for (long i = VecSize (items) - 1; i >= 0; i--)
302 RangePair *rp = items->get (i);
303 if ((rp->first > last) || (rp->last < first))
309 if (rp->first < first)
314 if (VecSize (items) == 1)
316 RangePair *rp = items->get (0);
317 if ((rp->first == first) && (rp->last == last))
319 // All, leave items NULL
327 // no error, delete the old setting
328 if (olditems != NULL)
330 olditems->destroy ();
335 // regenerate the pattern
340 char *oldpattern = pattern;
341 pattern = NULL; // to force a recompute with new values
342 (void) get_pattern ();
343 changed = strcmp (pattern, oldpattern) != 0;
349 //================================================================
352 // set_status -- regenerate the status line, describing the current setting
354 FilterNumeric::update_status ()
356 // regenerate the status line
361 if (last == (uint64_t) - 1 && last == first)
362 // neither set; data not available
363 status = dbe_sprintf (GTXT ("(data not recorded)"));
364 else if (first == (uint64_t) - 1 || last == (uint64_t) - 1)
366 status = dbe_sprintf (GTXT ("(all)"));
368 // range was set, compute percentage
369 status = dbe_sprintf (GTXT ("total %lld, range: %lld-%lld"),
370 (long long) nitems, (long long) first,
378 Vec_loop (RangePair *, items, index, rp)
380 nselected += rp->last - rp->first + 1;
382 if (last == (uint64_t) - 1)
384 status = dbe_sprintf (GTXT ("(%lld items selected)"),
385 (long long) nselected);
388 status = dbe_sprintf (GTXT ("total %lld, range: %lld-%lld"),
389 (long long) nitems, (long long) first,
394 // Add a range to the filter; called from set_pattern for each index,
397 FilterNumeric::include_range (uint64_t findex, uint64_t lindex)
406 items = new Vector<RangePair *>(0);
408 Vec_loop (RangePair *, items, index, rp)
410 if (findex < rp->first)
412 // Case where the new pair starts before the old
413 if (lindex + 1 < rp->first)
415 // this pair comes cleanly in front of the current item
416 RangePair *rp2 = new RangePair ();
419 items->insert (index, rp2);
423 // This new one extends the previous from the front
426 if (lindex <= rp->last)
428 // but does not extend the back
432 // extend this one out
435 // does it go into the next range?
436 if (index == items->size () - 1)
438 // this is the last range, so it does not
442 RangePair *next = items->fetch (index + 1);
443 if (lindex + 1 < next->first)
445 // no extension, we're done
449 // it does extend the next one
450 next->first = rp->first;
452 // remove the current one, promoting next
453 items->remove (index);
456 else if (findex > rp->last + 1)
457 // the new one is completely beyond the current
461 // the new one may start at or after the current, but it
462 // extends it out; set the current
463 // this pair overlaps the current item
464 // rp-> first is OK -- it's equal or less than findex
471 // fall through -- append to list
472 rp = new RangePair ();
481 // Scan the filter to see if the number given is filtered in or out
482 // return true if number is in, false if it's out
484 FilterNumeric::is_selected (uint64_t number)
490 if (items->size () == 0)
493 Vec_loop (RangePair *, items, index, rp)
495 if (number >= rp->first && number <= rp->last)
502 // Called from parser to extract a number from the current string position
503 // Sets fail true if there was an error, false otherwise
504 // returns the number as parsed
506 FilterNumeric::get_next_number (char *s, char **e, bool *fail)
510 uint64_t val = strtoll (s, e, 10);