📄 readtags.cpp
字号:
info->program.author = NULL; info->program.name = NULL; info->program.url = NULL; info->program.version = NULL; } while (1) { fgetpos(file->fp, &startOfLine); if (!readTagLine(file)) break; if (strncmp(file->line.buffer, PseudoTagPrefix, prefixLength) != 0) break; else { tagEntry entry; const char *key, *value; parseTagLine(file, &entry); key = entry.name + prefixLength; value = entry.file; if (strcmp(key, "TAG_FILE_SORTED") == 0) file->sortMethod = (sortType) atoi(value); else if (strcmp(key, "TAG_FILE_FORMAT") == 0) file->format = atoi(value); else if (strcmp(key, "TAG_PROGRAM_AUTHOR") == 0) file->program.author = duplicate(value); else if (strcmp(key, "TAG_PROGRAM_NAME") == 0) file->program.name = duplicate(value); else if (strcmp(key, "TAG_PROGRAM_URL") == 0) file->program.url = duplicate(value); else if (strcmp(key, "TAG_PROGRAM_VERSION") == 0) file->program.version = duplicate(value); if (info != NULL) { info->file.format = file->format; info->file.sort = file->sortMethod; info->program.author = file->program.author; info->program.name = file->program.name; info->program.url = file->program.url; info->program.version = file->program.version; } } } fsetpos(file->fp, &startOfLine);}static void gotoFirstLogicalTag(tagFile * const file){ fpos_t startOfLine; const size_t prefixLength = strlen(PseudoTagPrefix); rewind(file->fp); while (1) { fgetpos(file->fp, &startOfLine); if (!readTagLine(file)) break; if (strncmp(file->line.buffer, PseudoTagPrefix, prefixLength) != 0) break; } fsetpos(file->fp, &startOfLine);}static tagFile *initialize(const char *const filePath, tagFileInfo * const info){ tagFile *result = (tagFile *) malloc(sizeof(tagFile)); if (result != NULL) { memset(result, 0, sizeof(tagFile)); growString(&result->line); growString(&result->name); result->fields.max = 20; result->fields.list = (tagExtensionField *) malloc(result->fields.max * sizeof(tagExtensionField)); result->fp = fopen(filePath, "r"); if (result->fp == NULL) { free(result); result = NULL; info->status.error_number = errno; } else { fseek(result->fp, 0, SEEK_END); result->size = ftell(result->fp); rewind(result->fp); readPseudoTags(result, info); info->status.opened = 1; result->initialized = 1; } } return result;}static void terminate(tagFile * const file){ fclose(file->fp); free(file->line.buffer); free(file->name.buffer); free(file->fields.list); if (file->program.author != NULL) free(file->program.author); if (file->program.name != NULL) free(file->program.name); if (file->program.url != NULL) free(file->program.url); if (file->program.version != NULL) free(file->program.version); memset(file, 0, sizeof(tagFile)); free(file);}static tagResult readNext(tagFile * const file, tagEntry * const entry){ tagResult result = TagFailure; if (file == NULL || !file->initialized) result = TagFailure; else if (!readTagLine(file)) result = TagFailure; else { if (entry != NULL) parseTagLine(file, entry); result = TagSuccess; } return result;}static const char *readFieldValue(const tagEntry * const entry, const char *const key){ const char *result = NULL; int i; if (strcmp(key, "kind") == 0) result = entry->kind; else if (strcmp(key, "file") == 0) result = EmptyString; else for (i = 0; i < entry->fields.count && result == NULL; ++i) if (strcmp(entry->fields.list[i].key, key) == 0) result = entry->fields.list[i].value; return result;}static int readTagLineSeek(tagFile * const file, const off_t pos){ int result = 0; if (fseek(file->fp, pos, SEEK_SET) == 0) { result = readTagLine(file); /* read probable partial line */ if (pos > 0 && result) result = readTagLine(file); /* read complete line */ } return result;}static int nameComparison(tagFile * const file){ int result; if (file->search.ignorecase) { if (file->search.partial) result = strnuppercmp(file->search.name, file->name.buffer, file->search.nameLength); else result = struppercmp(file->search.name, file->name.buffer); } else { if (file->search.partial) result = strncmp(file->search.name, file->name.buffer, file->search.nameLength); else result = strcmp(file->search.name, file->name.buffer); } return result;}static void findFirstNonMatchBefore(tagFile * const file){#define JUMP_BACK 512 int more_lines; int comp; off_t start = file->pos; off_t pos = start; do { if (pos < (off_t) JUMP_BACK) pos = 0; else pos = pos - JUMP_BACK; more_lines = readTagLineSeek(file, pos); comp = nameComparison(file); } while (more_lines && comp == 0 && pos > 0 && pos < start);}static tagResult findFirstMatchBefore(tagFile * const file){ tagResult result = TagFailure; int more_lines; off_t start = file->pos; findFirstNonMatchBefore(file); do { more_lines = readTagLine(file); if (nameComparison(file) == 0) result = TagSuccess; } while (more_lines && result != TagSuccess && file->pos < start); return result;}static tagResult findBinary(tagFile * const file){ tagResult result = TagFailure; off_t lower_limit = 0; off_t upper_limit = file->size; off_t last_pos = 0; off_t pos = upper_limit / 2; while (result != TagSuccess) { if (!readTagLineSeek(file, pos)) { /* in case we fell off end of file */ result = findFirstMatchBefore(file); break; } else if (pos == last_pos) { /* prevent infinite loop if we backed up to beginning of file */ break; } else { const int comp = nameComparison(file); last_pos = pos; if (comp < 0) { upper_limit = pos; pos = lower_limit + ((upper_limit - lower_limit) / 2); } else if (comp > 0) { lower_limit = pos; pos = lower_limit + ((upper_limit - lower_limit) / 2); } else if (pos == 0) result = TagSuccess; else result = findFirstMatchBefore(file); } } return result;}static tagResult findSequential(tagFile * const file){ tagResult result = TagFailure; if (file->initialized) { while (result == TagFailure && readTagLine(file)) { if (nameComparison(file) == 0) result = TagSuccess; } } return result;}static tagResult find(tagFile * const file, tagEntry * const entry, const char *const name, const int options){ tagResult result = TagFailure; file->search.name = name; file->search.nameLength = strlen(name); file->search.partial = (options & TAG_PARTIALMATCH) != 0; file->search.ignorecase = (options & TAG_IGNORECASE) != 0; fseek(file->fp, 0, SEEK_END); file->size = ftell(file->fp); rewind(file->fp); if ((file->sortMethod == TAG_SORTED && !file->search.ignorecase) || (file->sortMethod == TAG_FOLDSORTED && file->search.ignorecase)) result = findBinary(file); else result = findSequential(file); if (result != TagSuccess) file->search.pos = file->size; else { file->search.pos = file->pos; if (entry != NULL) parseTagLine(file, entry); } return result;}static tagResult findNext(tagFile * const file, tagEntry * const entry){ tagResult result = TagFailure; if ((file->sortMethod == TAG_SORTED && !file->search.ignorecase) || (file->sortMethod == TAG_FOLDSORTED && file->search.ignorecase)) { result = tagsNext(file, entry); if (result == TagSuccess && nameComparison(file) != 0) result = TagFailure; } else { result = findSequential(file); if (result == TagSuccess && entry != NULL) parseTagLine(file, entry); } return result;}/** EXTERNAL INTERFACE*/extern tagFile *tagsOpen(const char *const filePath, tagFileInfo * const info){ return initialize(filePath, info);}extern tagResult tagsSetSortType(tagFile * const file, const sortType type){ tagResult result = TagFailure; if (file != NULL && file->initialized) { file->sortMethod = type; result = TagSuccess; } return result;}extern tagResult tagsFirst(tagFile * const file, tagEntry * const entry){ tagResult result = TagFailure; if (file != NULL && file->initialized) { gotoFirstLogicalTag(file); result = readNext(file, entry); } return result;}extern tagResult tagsNext(tagFile * const file, tagEntry * const entry){ tagResult result = TagFailure; if (file != NULL && file->initialized) result = readNext(file, entry); return result;}extern const char *tagsField(const tagEntry * const entry, const char *const key){ const char *result = NULL; if (entry != NULL) result = readFieldValue(entry, key); return result;}extern tagResult tagsFind(tagFile * const file, tagEntry * const entry, const char *const name, const int options){ tagResult result = TagFailure; if (file != NULL && file->initialized) result = find(file, entry, name, options); return result;}extern tagResult tagsFindNext(tagFile * const file, tagEntry * const entry){ tagResult result = TagFailure; if (file != NULL && file->initialized) result = findNext(file, entry); return result;}extern tagResult tagsClose(tagFile * const file){ tagResult result = TagFailure; if (file != NULL && file->initialized) { terminate(file); result = TagSuccess; } return result;}/* vi:set tabstop=8 shiftwidth=4: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -