]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gprofng/src/Filter.cc
1 /* Copyright (C) 2021-2024 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);