aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/format/GLAPISpec.java
blob: 57b587cb3057fd4241ed85562328f8297f63eb56 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * 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.
 */

package com.android.ide.eclipse.gltrace.format;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Model a single GL API function call's specification.
 */
public class GLAPISpec {
    private static final String GL_SPECS_FILE = "/entries.in"; //$NON-NLS-1$
    private static final String GLES2_ENTRIES_HEADER_V1 =
            "# com.android.ide.eclipse.gltrace.glentries, v1"; //$NON-NLS-1$
    private static Map<String, GLAPISpec> sApiSpecs;

    private final String mGLFunction;
    private final GLDataTypeSpec mReturnType;
    private final List<GLDataTypeSpec> mArgs;

    private GLAPISpec(String glFunction, GLDataTypeSpec returnType, List<GLDataTypeSpec> args) {
        mGLFunction = glFunction;
        mReturnType = returnType;
        mArgs = args;
    }

    public String getFunction() {
        return mGLFunction;
    }

    public GLDataTypeSpec getReturnValue() {
        return mReturnType;
    }

    public List<GLDataTypeSpec> getArgs() {
        return mArgs;
    }

    public static Map<String, GLAPISpec> getSpecs() {
        if (sApiSpecs == null) {
            sApiSpecs = parseApiSpecs(GLAPISpec.class.getResourceAsStream(GL_SPECS_FILE));
        }

        return sApiSpecs;
    }

    private static Map<String, GLAPISpec> parseApiSpecs(InputStream specFile) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(specFile));
        Map<String, GLAPISpec> specs = new HashMap<String, GLAPISpec>(400);

        try{
            String header = reader.readLine().trim();
            assert header.equals(GLES2_ENTRIES_HEADER_V1);

            String line;
            while ((line = reader.readLine()) != null) {
                // strip away the comments
                int commentPos = line.indexOf('#');
                if (commentPos != -1) {
                    line = line.substring(0, commentPos);
                }
                line = line.trim();

                // parse non empty lines
                if (line.length() > 0) {
                    GLAPISpec spec = parseLine(line);
                    specs.put(spec.getFunction(), spec);
                }
            }

            specFile.close();
        } catch (IOException e) {
            // this is unlikely to happen as the file is present within this .jar file.
            // Even if it does happen, we just return whatever we've read till now. The net
            // impact will be that the function calls will not be parsed fully and will just
            // display the function name.
        }

        return specs;
    }

    /**
     * Parse a GL API Specification entry from "/entries.in". Each line is of the format:
     * {@code returnType, funcName, arg*}. This method is package private for testing.
     */
    static GLAPISpec parseLine(String line) {
        List<String> words = Arrays.asList(line.split(","));

        String retType = words.get(0).trim();
        String func = words.get(1).trim();
        List<String> argDefinitions = words.subList(2, words.size());

        List<GLDataTypeSpec> glArgs = new ArrayList<GLDataTypeSpec>(argDefinitions.size()/2);
        for (String argDefn: argDefinitions) {
            // an argDefn is something like: "const GLvoid* data"
            argDefn = argDefn.trim();
            int lastSeparator = argDefn.lastIndexOf(' ');
            if (lastSeparator == -1) {
                // no space => a void type with no argument name
                glArgs.add(new GLDataTypeSpec(argDefn, null));
            } else {
                // everything upto the last space is the type
                String type = argDefn.substring(0, lastSeparator);

                // and the last word is the variable name
                String name = argDefn.substring(lastSeparator + 1);
                glArgs.add(new GLDataTypeSpec(type, name));
            }
        }

        return new GLAPISpec(func, new GLDataTypeSpec(retType, null), glArgs);
    }
}