1 /*
<lambda>null2 * Copyright 2018 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package trebuchet.importers.ftrace.events
18
19 import trebuchet.importers.ftrace.FtraceImporterState
20 import trebuchet.importers.ftrace.FtraceLine
21 import trebuchet.io.DataSlice
22 import trebuchet.model.InvalidId
23 import trebuchet.util.BufferReader
24 import trebuchet.util.MatchResult
25 import trebuchet.util.StringCache
26 import java.util.regex.Matcher
27 import java.util.regex.Pattern
28
29 const val FtraceLineRE = """^ *(.{1,16})-(\d+) +(?:\( *(\d+)?-*\) )?\[(\d+)] (?:[dX.][^\s]+)? *([\d.]*): *([^:]*): *(.*) *$"""
30
31 interface FtraceEventDetails {
32 fun import(event: FtraceEvent, state: FtraceImporterState)
33 }
34
35 val NoDetails = object : FtraceEventDetails {
importnull36 override fun import(event: FtraceEvent, state: FtraceImporterState) {}
37 }
38
39 typealias EventDetailsParser = (state: EventParserState, slice: DataSlice) -> FtraceEventDetails?
40
41 class SharedEventParserState {
42 private val patterns = mutableListOf<Pattern>()
43 private val detailHandlers = hashMapOf<String, EventDetailsParser>()
44 private var frozen = false
45
46 init {
<lambda>null47 EventRegistry.forEach { it(this) }
48 }
49
addPatternnull50 fun addPattern(newPattern: String) = addPattern(Pattern.compile(newPattern))
51
52 fun addPattern(newPattern: Pattern): Int {
53 if (frozen) throw IllegalStateException("State is frozen")
54 val index = patterns.size
55 patterns.add(newPattern)
56 return index
57 }
58
createParsernull59 fun createParser(): EventParserState {
60 frozen = true
61 return EventParserState(patterns, detailHandlers)
62 }
63
onParseDetailsnull64 fun onParseDetails(funcName: String, parser: EventDetailsParser) {
65 if (frozen) throw IllegalStateException("State is frozen")
66 detailHandlers[funcName] = parser
67 }
68
onParseDetailsWithMatchnull69 inline fun onParseDetailsWithMatch(funcName: String, regex: String,
70 crossinline result: MatchResult.() -> FtraceEventDetails?) {
71 val patternMatcher = addPattern(regex)
72 onParseDetails(funcName) { state, details ->
73 state.ifMatches(patternMatcher, details) {
74 return@onParseDetails this.result()
75 }
76 null
77 }
78 }
79
onParseDetailsWithMatchnull80 inline fun onParseDetailsWithMatch(funcNames: Array<String>, regex: String,
81 crossinline result: MatchResult.() -> FtraceEventDetails?) {
82 val patternMatcher = addPattern(regex)
83 funcNames.forEach { funcName ->
84 onParseDetails(funcName) { state, details ->
85 state.ifMatches(patternMatcher, details) {
86 return@onParseDetails this.result()
87 }
88 null
89 }
90 }
91 }
92 }
93
94 val GlobalSharedParserState = SharedEventParserState()
95
createEventParsernull96 fun createEventParser() = GlobalSharedParserState.createParser()
97
98 class EventParserState constructor(patterns: List<Pattern>,
99 private val detailHandlers: Map<String, EventDetailsParser>) {
100 val matchers = Array<Matcher>(patterns.size) { patterns[it].matcher("") }
101 val stringCache = StringCache()
102 val reader = BufferReader()
103
104 inline fun ifMatches(matcher: Int, slice: DataSlice, result: MatchResult.() -> Unit): Boolean {
105 reader.reset(slice, stringCache)
106 return reader.tryMatch(matchers[matcher], result)
107 }
108
109 fun detailsForText(funcName: CharSequence, detailsSlice: DataSlice): FtraceEventDetails {
110 return detailHandlers[funcName]?.invoke(this, detailsSlice) ?: NoDetails
111 }
112
113 inline fun <T> readDetails(detailsSlice: DataSlice, init: BufferReader.() -> T): T {
114 return reader.read(detailsSlice, stringCache, init)
115 }
116 }