1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License.
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzyn#include <assert.h>
18a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzyn#include <errno.h>
19a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzyn#include <fcntl.h>
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/mman.h>
23a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzyn
24a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzyn#include <log/event_tag_map.h>
25a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzyn#include <log/log.h>
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define OUT_TAG "EventTagMap"
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Single entry.
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct EventTag {
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned int    tagIndex;
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const char*     tagStr;
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} EventTag;
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Map.
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct EventTagMap {
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* memory-mapped source file; we get strings from here */
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    void*           mapAddr;
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    size_t          mapLen;
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* array of event tags, sorted numerically by tag index */
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    EventTag*       tagArray;
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int             numTags;
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* fwd */
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int processFile(EventTagMap* map);
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int countMapLines(const EventTagMap* map);
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int parseMapLines(EventTagMap* map);
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int scanTagLine(char** pData, EventTag* tag, int lineNum);
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int sortTags(EventTagMap* map);
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Open the map file and allocate a structure to manage it.
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * We create a private mapping because we want to terminate the log tag
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * strings with '\0'.
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectEventTagMap* android_openEventTagMap(const char* fileName)
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    EventTagMap* newTagMap;
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    off_t end;
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd = -1;
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    newTagMap = calloc(1, sizeof(EventTagMap));
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (newTagMap == NULL)
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return NULL;
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd = open(fileName, O_RDONLY);
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (fd < 0) {
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "%s: unable to open map '%s': %s\n",
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            OUT_TAG, fileName, strerror(errno));
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        goto fail;
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    end = lseek(fd, 0L, SEEK_END);
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    (void) lseek(fd, 0L, SEEK_SET);
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (end < 0) {
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "%s: unable to seek map '%s'\n", OUT_TAG, fileName);
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        goto fail;
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    newTagMap->mapAddr = mmap(NULL, end, PROT_READ | PROT_WRITE, MAP_PRIVATE,
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                fd, 0);
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (newTagMap->mapAddr == MAP_FAILED) {
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "%s: mmap(%s) failed: %s\n",
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            OUT_TAG, fileName, strerror(errno));
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        goto fail;
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    newTagMap->mapLen = end;
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (processFile(newTagMap) != 0)
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        goto fail;
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return newTagMap;
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfail:
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    android_closeEventTagMap(newTagMap);
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (fd >= 0)
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        close(fd);
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return NULL;
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Close the map.
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid android_closeEventTagMap(EventTagMap* map)
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (map == NULL)
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    munmap(map->mapAddr, map->mapLen);
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(map);
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Look up an entry in the map.
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * The entries are sorted by tag number, so we can do a binary search.
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectconst char* android_lookupEventTag(const EventTagMap* map, int tag)
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int hi, lo, mid;
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    lo = 0;
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    hi = map->numTags-1;
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (lo <= hi) {
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int cmp;
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mid = (lo+hi)/2;
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        cmp = map->tagArray[mid].tagIndex - tag;
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (cmp < 0) {
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* tag is bigger */
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            lo = mid + 1;
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (cmp > 0) {
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* tag is smaller */
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            hi = mid - 1;
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* found */
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return map->tagArray[mid].tagStr;
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return NULL;
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Determine whether "c" is a whitespace char.
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic inline int isCharWhitespace(char c)
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return (c == ' ' || c == '\n' || c == '\r' || c == '\t');
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Determine whether "c" is a valid tag char.
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic inline int isCharValidTag(char c)
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return ((c >= 'A' && c <= 'Z') ||
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            (c >= 'a' && c <= 'z') ||
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            (c >= '0' && c <= '9') ||
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            (c == '_'));
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Determine whether "c" is a valid decimal digit.
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic inline int isCharDigit(char c)
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return (c >= '0' && c <= '9');
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Crunch through the file, parsing the contents and creating a tag index.
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int processFile(EventTagMap* map)
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* get a tag count */
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    map->numTags = countMapLines(map);
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (map->numTags < 0)
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //printf("+++ found %d tags\n", map->numTags);
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* allocate storage for the tag index array */
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    map->tagArray = calloc(1, sizeof(EventTag) * map->numTags);
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (map->tagArray == NULL)
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* parse the file, null-terminating tag strings */
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (parseMapLines(map) != 0) {
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "%s: file parse failed\n", OUT_TAG);
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* sort the tags and check for duplicates */
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (sortTags(map) != 0)
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Run through all lines in the file, determining whether they're blank,
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * comments, or possibly have a tag entry.
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * This is a very "loose" scan.  We don't try to detect syntax errors here.
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * The later pass is more careful, but the number of tags found there must
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * match the number of tags found here.
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Returns the number of potential tag entries found.
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int countMapLines(const EventTagMap* map)
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int numTags, unknown;
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const char* cp;
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const char* endp;
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    cp = (const char*) map->mapAddr;
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    endp = cp + map->mapLen;
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    numTags = 0;
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unknown = 1;
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (cp < endp) {
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (*cp == '\n') {
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            unknown = 1;
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (unknown) {
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (isCharDigit(*cp)) {
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                /* looks like a tag to me */
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                numTags++;
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                unknown = 0;
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else if (isCharWhitespace(*cp)) {
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                /* might be leading whitespace before tag num, keep going */
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                /* assume comment; second pass can complain in detail */
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                unknown = 0;
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* we've made up our mind; just scan to end of line */
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        cp++;
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return numTags;
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Parse the tags out of the file.
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int parseMapLines(EventTagMap* map)
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int tagNum, lineStart, lineNum;
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char* cp;
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char* endp;
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    cp = (char*) map->mapAddr;
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    endp = cp + map->mapLen;
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* insist on EOL at EOF; simplifies parsing and null-termination */
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (*(endp-1) != '\n') {
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "%s: map file missing EOL on last line\n", OUT_TAG);
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    tagNum = 0;
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    lineStart = 1;
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    lineNum = 1;
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (cp < endp) {
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //printf("{%02x}", *cp); fflush(stdout);
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (*cp == '\n') {
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            lineStart = 1;
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            lineNum++;
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (lineStart) {
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (*cp == '#') {
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                /* comment; just scan to end */
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                lineStart = 0;
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else if (isCharDigit(*cp)) {
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                /* looks like a tag; scan it out */
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (tagNum >= map->numTags) {
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    fprintf(stderr,
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        "%s: more tags than expected (%d)\n", OUT_TAG, tagNum);
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    return -1;
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (scanTagLine(&cp, &map->tagArray[tagNum], lineNum) != 0)
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    return -1;
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                tagNum++;
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                lineNum++;      // we eat the '\n'
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                /* leave lineStart==1 */
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else if (isCharWhitespace(*cp)) {
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                /* looks like leading whitespace; keep scanning */
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                fprintf(stderr,
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    "%s: unexpected chars (0x%02x) in tag number on line %d\n",
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    OUT_TAG, *cp, lineNum);
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return -1;
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* this is a blank or comment line */
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        cp++;
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (tagNum != map->numTags) {
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "%s: parsed %d tags, expected %d\n",
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            OUT_TAG, tagNum, map->numTags);
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Scan one tag line.
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * "*pData" should be pointing to the first digit in the tag number.  On
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * successful return, it will be pointing to the last character in the
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * tag line (i.e. the character before the start of the next line).
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Returns 0 on success, nonzero on failure.
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int scanTagLine(char** pData, EventTag* tag, int lineNum)
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char* cp = *pData;
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char* startp;
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char* endp;
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned long val;
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    startp = cp;
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (isCharDigit(*++cp))
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ;
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    *cp = '\0';
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    val = strtoul(startp, &endp, 10);
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    assert(endp == cp);
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (endp != cp)
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "ARRRRGH\n");
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    tag->tagIndex = val;
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (*++cp != '\n' && isCharWhitespace(*cp))
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ;
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (*cp == '\n') {
354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,
355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "%s: missing tag string on line %d\n", OUT_TAG, lineNum);
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    tag->tagStr = cp;
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (isCharValidTag(*++cp))
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ;
363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (*cp == '\n') {
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* null terminate and return */
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *cp = '\0';
367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (isCharWhitespace(*cp)) {
368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* CRLF or trailin spaces; zap this char, then scan for the '\n' */
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *cp = '\0';
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* just ignore the rest of the line till \n
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        TODO: read the tag description that follows the tag name
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        */
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        while (*++cp != '\n') {
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
377dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,
378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "%s: invalid tag chars on line %d\n", OUT_TAG, lineNum);
379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    *pData = cp;
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //printf("+++ Line %d: got %d '%s'\n", lineNum, tag->tagIndex, tag->tagStr);
385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Compare two EventTags.
390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int compareEventTags(const void* v1, const void* v2)
392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const EventTag* tag1 = (const EventTag*) v1;
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const EventTag* tag2 = (const EventTag*) v2;
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return tag1->tagIndex - tag2->tagIndex;
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Sort the EventTag array so we can do fast lookups by tag index.  After
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * the sort we do a quick check for duplicate tag indices.
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Returns 0 on success.
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int sortTags(EventTagMap* map)
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i;
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    qsort(map->tagArray, map->numTags, sizeof(EventTag), compareEventTags);
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 1; i < map->numTags; i++) {
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (map->tagArray[i].tagIndex == map->tagArray[i-1].tagIndex) {
413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr, "%s: duplicate tag entries (%d:%s and %d:%s)\n",
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                OUT_TAG,
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                map->tagArray[i].tagIndex, map->tagArray[i].tagStr,
416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                map->tagArray[i-1].tagIndex, map->tagArray[i-1].tagStr);
417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
423