1 /*
2  * Copyright (C) 2011 The Android Open Source Project
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  *      http://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 package com.android.loganalysis.parser;
17 
18 import com.android.loganalysis.item.ProcrankItem;
19 import com.android.loganalysis.util.ArrayUtil;
20 
21 import java.util.List;
22 import java.util.regex.Matcher;
23 import java.util.regex.Pattern;
24 
25 /**
26  * A {@link IParser} to handle the output of {@code procrank}.  Memory values returned are in units
27  * of kilobytes.
28  */
29 public class ProcrankParser implements IParser {
30 
31     /** Match a valid line, such as:
32      * " 1313   78128K   77996K   48603K   45812K  com.google.android.apps.maps" */
33     private static final Pattern SHORT_LINE_PAT = Pattern.compile(
34             "\\s*(\\d+)\\s+" + /* PID [1] */
35             "(\\d+)K\\s+(\\d+)K\\s+(\\d+)K\\s+(\\d+)K\\s+" + /* Vss Rss Pss Uss [2-5] */
36             "(\\S+)" /* process name [6] */);
37     private static final Pattern LONG_LINE_PAT = Pattern.compile(
38             "\\s*(\\d+)\\s+" + /* PID [1] */
39             "(\\d+)K\\s+(\\d+)K\\s+(\\d+)K\\s+(\\d+)K\\s+" + /* Vss Rss Pss Uss [2-5] */
40             "(\\d+)K\\s+(\\d+)K\\s+(\\d+)K\\s+(\\d+)K\\s+" + /* Swap PSwap USwap ZSwap [6-9] */
41             "(\\S+)" /* process name [10] */);
42 
43     /** Match the end of the Procrank table, determined by three or more sets of "------". */
44     private static final Pattern END_PAT = Pattern.compile("^(\\s+-{6}){3,}$");
45 
46     /**
47      * {@inheritDoc}
48      */
49     @Override
parse(List<String> lines)50     public ProcrankItem parse(List<String> lines) {
51         final String text = ArrayUtil.join("\n", lines).replaceAll("\\s+$", "");
52         if ("".equals(text.trim())) {
53             return null;
54         }
55 
56         ProcrankItem item = new ProcrankItem();
57         item.setText(text);
58 
59         for (String line : lines) {
60             // If we have reached the end.
61             Matcher endMatcher = END_PAT.matcher(line);
62             if (endMatcher.matches()) {
63                 return item;
64             }
65 
66             Matcher m = SHORT_LINE_PAT.matcher(line);
67             if (m.matches()) {
68                 item.addProcrankLine(Integer.parseInt(m.group(1)), m.group(6),
69                         Integer.parseInt(m.group(2)), Integer.parseInt(m.group(3)),
70                         Integer.parseInt(m.group(4)), Integer.parseInt(m.group(5)));
71                 continue;
72             }
73 
74             m = LONG_LINE_PAT.matcher(line);
75             if (m.matches()) {
76                 item.addProcrankLine(Integer.parseInt(m.group(1)), m.group(10),
77                         Integer.parseInt(m.group(2)), Integer.parseInt(m.group(3)),
78                         Integer.parseInt(m.group(4)), Integer.parseInt(m.group(5)));
79             }
80         }
81 
82         return item;
83     }
84 }
85 
86