Copyright 2014 Google Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Implements methods to remove frames from profiles.

package profile

import (
	
	
	
)

var (
	reservedNames = []string{"(anonymous namespace)", "operator()"}
	bracketRx     = func() *regexp.Regexp {
		var  []string
		for ,  := range append(reservedNames, "(") {
			 = append(, regexp.QuoteMeta())
		}
		return regexp.MustCompile(strings.Join(, "|"))
	}()
)
simplifyFunc does some primitive simplification of function names.
Account for leading '.' on the PPC ELF v1 ABI.
Account for unsimplified names -- try to remove the argument list by trimming starting from the first '(', but skipping reserved names that have '('.
	for ,  := range bracketRx.FindAllStringSubmatchIndex(, -1) {
		 := false
		for ,  := range reservedNames {
			if [[0]:[1]] ==  {
				 = true
				break
			}
		}
		if ! {
			 = [:[0]]
			break
		}
	}
	return 
}
Prune removes all nodes beneath a node matching dropRx, and not matching keepRx. If the root node of a Sample matches, the sample will have an empty stack.
func ( *Profile) (,  *regexp.Regexp) {
	 := make(map[uint64]bool)
	 := make(map[uint64]bool)

	for ,  := range .Location {
		var  int
		for  = len(.Line) - 1;  >= 0; -- {
			if  := .Line[].Function;  != nil && .Name != "" {
				 := simplifyFunc(.Name)
				if .MatchString() {
					if  == nil || !.MatchString() {
						break
					}
				}
			}
		}

Found matching entry to prune.
			[.ID] = true
Remove the matching location.
Matched the top entry: prune the whole location.
				[.ID] = true
			} else {
				.Line = .Line[+1:]
			}
		}
	}
Prune locs from each Sample
Scan from the root to the leaves to find the prune location. Do not prune frames before the first user frame, to avoid pruning everything.
		 := false
		for  := len(.Location) - 1;  >= 0; -- {
			 := .Location[].ID
			if ![] && ![] {
				 = true
				continue
			}
			if ! {
				continue
			}
			if [] {
				.Location = .Location[+1:]
				break
			}
			if [] {
				.Location = .Location[:]
				break
			}
		}
	}
}
RemoveUninteresting prunes and elides profiles using built-in tables of uninteresting function names.
func ( *Profile) () error {
	var ,  *regexp.Regexp
	var  error

	if .DropFrames != "" {
		if ,  = regexp.Compile("^(" + .DropFrames + ")$");  != nil {
			return fmt.Errorf("failed to compile regexp %s: %v", .DropFrames, )
		}
		if .KeepFrames != "" {
			if ,  = regexp.Compile("^(" + .KeepFrames + ")$");  != nil {
				return fmt.Errorf("failed to compile regexp %s: %v", .KeepFrames, )
			}
		}
		.Prune(, )
	}
	return nil
}
PruneFrom removes all nodes beneath the lowest node matching dropRx, not including itself. Please see the example below to understand this method as well as the difference from Prune method. A sample contains Location of [A,B,C,B,D] where D is the top frame and there's no inline. PruneFrom(A) returns [A,B,C,B,D] because there's no node beneath A. Prune(A, nil) returns [B,C,B,D] by removing A itself. PruneFrom(B) returns [B,C,B,D] by removing all nodes beneath the first B when scanning from the bottom. Prune(B, nil) returns [D] because a matching node is found by scanning from the root.
func ( *Profile) ( *regexp.Regexp) {
	 := make(map[uint64]bool)

	for ,  := range .Location {
		for  := 0;  < len(.Line); ++ {
			if  := .Line[].Function;  != nil && .Name != "" {
				 := simplifyFunc(.Name)
Found matching entry to prune.
					[.ID] = true
					.Line = .Line[:]
					break
				}
			}
		}
	}
Prune locs from each Sample
Scan from the bottom leaf to the root to find the prune location.
		for ,  := range .Location {
			if [.ID] {
				.Location = .Location[:]
				break
			}
		}
	}