⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 event_tag_map.c

📁 Android 一些工具
💻 C
字号:
/* * Copyright (C) 2007 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. */#include "cutils/event_tag_map.h"#include "cutils/log.h"#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <sys/mman.h>#include <errno.h>#include <assert.h>#define OUT_TAG "EventTagMap"/* * Single entry. */typedef struct EventTag {    unsigned int    tagIndex;    const char*     tagStr;} EventTag;/* * Map. */struct EventTagMap {    /* memory-mapped source file; we get strings from here */    void*           mapAddr;    size_t          mapLen;    /* array of event tags, sorted numerically by tag index */    EventTag*       tagArray;    int             numTags;};/* fwd */static int processFile(EventTagMap* map);static int countMapLines(const EventTagMap* map);static int parseMapLines(EventTagMap* map);static int scanTagLine(char** pData, EventTag* tag, int lineNum);static int sortTags(EventTagMap* map);static void dumpTags(const EventTagMap* map);/* * Open the map file and allocate a structure to manage it. * * We create a private mapping because we want to terminate the log tag * strings with '\0'. */EventTagMap* android_openEventTagMap(const char* fileName){    EventTagMap* newTagMap;    off_t end;    int fd = -1;    newTagMap = calloc(1, sizeof(EventTagMap));    if (newTagMap == NULL)        return NULL;    fd = open(fileName, O_RDONLY);    if (fd < 0) {        fprintf(stderr, "%s: unable to open map '%s': %s\n",            OUT_TAG, fileName, strerror(errno));        goto fail;    }    end = lseek(fd, 0L, SEEK_END);    (void) lseek(fd, 0L, SEEK_SET);    if (end < 0) {        fprintf(stderr, "%s: unable to seek map '%s'\n", OUT_TAG, fileName);        goto fail;    }    newTagMap->mapAddr = mmap(NULL, end, PROT_READ | PROT_WRITE, MAP_PRIVATE,                                fd, 0);    if (newTagMap->mapAddr == MAP_FAILED) {        fprintf(stderr, "%s: mmap(%s) failed: %s\n",            OUT_TAG, fileName, strerror(errno));        goto fail;    }    newTagMap->mapLen = end;    if (processFile(newTagMap) != 0)        goto fail;    return newTagMap;fail:    android_closeEventTagMap(newTagMap);    if (fd >= 0)        close(fd);    return NULL;}/* * Close the map. */void android_closeEventTagMap(EventTagMap* map){    if (map == NULL)        return;    munmap(map->mapAddr, map->mapLen);    free(map);}/* * Look up an entry in the map. * * The entries are sorted by tag number, so we can do a binary search. */const char* android_lookupEventTag(const EventTagMap* map, int tag){    int hi, lo, mid;    lo = 0;    hi = map->numTags-1;    while (lo <= hi) {        int cmp;        mid = (lo+hi)/2;        cmp = map->tagArray[mid].tagIndex - tag;        if (cmp < 0) {            /* tag is bigger */            lo = mid + 1;        } else if (cmp > 0) {            /* tag is smaller */            hi = mid - 1;        } else {            /* found */            return map->tagArray[mid].tagStr;        }    }    return NULL;}/* * Determine whether "c" is a whitespace char. */static inline int isCharWhitespace(char c){    return (c == ' ' || c == '\n' || c == '\r' || c == '\t');}/* * Determine whether "c" is a valid tag char. */static inline int isCharValidTag(char c){    return ((c >= 'A' && c <= 'Z') ||            (c >= 'a' && c <= 'z') ||            (c >= '0' && c <= '9') ||            (c == '_'));}/* * Determine whether "c" is a valid decimal digit. */static inline int isCharDigit(char c){    return (c >= '0' && c <= '9');}/* * Crunch through the file, parsing the contents and creating a tag index. */static int processFile(EventTagMap* map){    EventTag* tagArray = NULL;    /* get a tag count */    map->numTags = countMapLines(map);    if (map->numTags < 0)        return -1;    //printf("+++ found %d tags\n", map->numTags);    /* allocate storage for the tag index array */    map->tagArray = calloc(1, sizeof(EventTag) * map->numTags);    if (map->tagArray == NULL)        return -1;    /* parse the file, null-terminating tag strings */    if (parseMapLines(map) != 0) {        fprintf(stderr, "%s: file parse failed\n", OUT_TAG);        return -1;    }    /* sort the tags and check for duplicates */    if (sortTags(map) != 0)        return -1;    return 0;}/* * Run through all lines in the file, determining whether they're blank, * comments, or possibly have a tag entry. * * This is a very "loose" scan.  We don't try to detect syntax errors here. * The later pass is more careful, but the number of tags found there must * match the number of tags found here. * * Returns the number of potential tag entries found. */static int countMapLines(const EventTagMap* map){    int numTags, unknown;    const char* cp;    const char* endp;    cp = (const char*) map->mapAddr;    endp = cp + map->mapLen;    numTags = 0;    unknown = 1;    while (cp < endp) {        if (*cp == '\n') {            unknown = 1;        } else if (unknown) {            if (isCharDigit(*cp)) {                /* looks like a tag to me */                numTags++;                unknown = 0;            } else if (isCharWhitespace(*cp)) {                /* might be leading whitespace before tag num, keep going */            } else {                /* assume comment; second pass can complain in detail */                unknown = 0;            }        } else {            /* we've made up our mind; just scan to end of line */        }        cp++;    }    return numTags;}/* * Parse the tags out of the file. */static int parseMapLines(EventTagMap* map){    int tagNum, lineStart, lineNum;    char* cp;    char* endp;    cp = (char*) map->mapAddr;    endp = cp + map->mapLen;    /* insist on EOL at EOF; simplifies parsing and null-termination */    if (*(endp-1) != '\n') {        fprintf(stderr, "%s: map file missing EOL on last line\n", OUT_TAG);        return -1;    }    tagNum = 0;    lineStart = 1;    lineNum = 1;    while (cp < endp) {        //printf("{%02x}", *cp); fflush(stdout);        if (*cp == '\n') {            lineStart = 1;            lineNum++;        } else if (lineStart) {            if (*cp == '#') {                /* comment; just scan to end */                lineStart = 0;            } else if (isCharDigit(*cp)) {                /* looks like a tag; scan it out */                if (tagNum >= map->numTags) {                    fprintf(stderr,                        "%s: more tags than expected (%d)\n", OUT_TAG, tagNum);                    return -1;                }                if (scanTagLine(&cp, &map->tagArray[tagNum], lineNum) != 0)                    return -1;                tagNum++;                lineNum++;      // we eat the '\n'                /* leave lineStart==1 */            } else if (isCharWhitespace(*cp)) {                /* looks like leading whitespace; keep scanning */            } else {                fprintf(stderr,                    "%s: unexpected chars (0x%02x) in tag number on line %d\n",                    OUT_TAG, *cp, lineNum);                return -1;            }        } else {            /* this is a blank or comment line */        }        cp++;    }    if (tagNum != map->numTags) {        fprintf(stderr, "%s: parsed %d tags, expected %d\n",            OUT_TAG, tagNum, map->numTags);        return -1;    }    return 0;}/* * Scan one tag line. * * "*pData" should be pointing to the first digit in the tag number.  On * successful return, it will be pointing to the last character in the * tag line (i.e. the character before the start of the next line). * * Returns 0 on success, nonzero on failure. */static int scanTagLine(char** pData, EventTag* tag, int lineNum){    char* cp = *pData;    char* startp;    char* endp;    unsigned long val;    startp = cp;    while (isCharDigit(*++cp))        ;    *cp = '\0';    val = strtoul(startp, &endp, 10);    assert(endp == cp);    if (endp != cp)        fprintf(stderr, "ARRRRGH\n");    tag->tagIndex = val;    while (*++cp != '\n' && isCharWhitespace(*cp))        ;    if (*cp == '\n') {        fprintf(stderr,            "%s: missing tag string on line %d\n", OUT_TAG, lineNum);        return -1;    }    tag->tagStr = cp;    while (isCharValidTag(*++cp))        ;    if (*cp == '\n') {        /* null terminate and return */        *cp = '\0';    } else if (isCharWhitespace(*cp)) {        /* CRLF or trailin spaces; zap this char, then scan for the '\n' */        *cp = '\0';        /* just ignore the rest of the line till \n        TODO: read the tag description that follows the tag name        */        while (*++cp != '\n') {        }    } else {        fprintf(stderr,            "%s: invalid tag chars on line %d\n", OUT_TAG, lineNum);        return -1;    }    *pData = cp;    //printf("+++ Line %d: got %d '%s'\n", lineNum, tag->tagIndex, tag->tagStr);    return 0;}/* * Compare two EventTags. */static int compareEventTags(const void* v1, const void* v2){    const EventTag* tag1 = (const EventTag*) v1;    const EventTag* tag2 = (const EventTag*) v2;    return tag1->tagIndex - tag2->tagIndex;}/* * Sort the EventTag array so we can do fast lookups by tag index.  After * the sort we do a quick check for duplicate tag indices. * * Returns 0 on success. */static int sortTags(EventTagMap* map){    int i;    qsort(map->tagArray, map->numTags, sizeof(EventTag), compareEventTags);    for (i = 1; i < map->numTags; i++) {        if (map->tagArray[i].tagIndex == map->tagArray[i-1].tagIndex) {            fprintf(stderr, "%s: duplicate tag entries (%d:%s and %d:%s)\n",                OUT_TAG,                map->tagArray[i].tagIndex, map->tagArray[i].tagStr,                map->tagArray[i-1].tagIndex, map->tagArray[i-1].tagStr);            return -1;        }    }    return 0;}/* * Dump the tag array for debugging. */static void dumpTags(const EventTagMap* map){    int i;    for (i = 0; i < map->numTags; i++) {        const EventTag* tag = &map->tagArray[i];        printf("  %3d: %6d '%s'\n", i, tag->tagIndex, tag->tagStr);    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -