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

📄 ctagreader.java

📁 具有不同语法高亮的编辑器实例
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package org.fife.ctags;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;


/**
 * A class capable of reading a ctags file and searching for identifiers in it.
 * CTags are a useful little tool for things like programmers' text editors.
 * See http://ctags.sourceforge.net for more information.<p>
 *
 * This file is simply a translation of readtags.c from the Exhuberant CTags'
 * source distribution into Java.  This particular class is public domain.
 *
 * @author Robert Futrell
 * @version 0.01
 */
public class CTagReader {

	/* Options for tagsSetSortType() */
	public static final byte TAG_UNSORTED		= 1;
	public static final byte TAG_SORTED		= 2;
	public static final byte TAG_FOLDSORTED		= 3;

	/* Options for tagsFind() */
	public static final int TAG_FULLMATCH		= 0x00;
	public static final int TAG_PARTIALMATCH	= 0x01;

	public static final int TAG_OBSERVECASE		= 0x00;
	public static final int TAG_IGNORECASE		= 0x02;

	// Formerly tagResult values.
	public static final int TAGRESULT_FAILURE	= 0x00;
	public static final int TAGRESULT_SUCCESS	= 0x01;

	// Other #defines found in the code.
	private static final int JUMP_BACK			= 512;

	// Random constants.
	public static final String EmptyString = "";
	public static final String PseudoTagPrefix = "!_";


	private boolean initialized;		/* has the file been opened and this structure initialized? */
	private int format;				/* format of tag file */
	private int sortMethod;			/* how is the tag file sorted? */
	private RandomAccessFile fp;		/* pointer to file structure */
	private long pos;				/* file position of first character of `line' */
	private long size;				/* size of tag file in seekable positions */
	private String line;			/* last line read */
	private String name;			/* name of tag in last line read */

	// Was "search" struct.
	private long searchPos;			/* file position of last match for tag */
	private String searchName;		/* name of tag last searched for */
	private boolean searchPartial;	/* peforming partial match */
	private boolean searchIgnoreCase;	/* ignoring case */

	// Was "program" struct.
	private String programAuthor;		/* name of program author */
	private String programName;		/* name of program */
	private String programUrl;		/* URL of distribution */
	private String programVersion;	/* program version */



/*****************************************************************************/


	/**
	 * Creates a new CTagReader.  After this you should call
	 * <code>tagsOpen</code>.
	 */
	public CTagReader() {
	}


/*****************************************************************************/


	/**
	 * Searches for an indentifier <code>name</code> in the current ctag file.
	 *
	 * @param entry The found identifier in the ctag file if success, ???
	 *              or <code>null</code> if it wasn't found ???
	 * @param name The identifier for which you are searching.
	 * @param options A bit flag; checks for <code>TAG_PARTIALMATCH</code>
	 *                and <code>TAG_IGNORECASE</code>.
	 * @return <code>true</code> iff the identifier was found.
	 */
	private boolean find(TagEntry entry, String name, int options) throws IOException {

		boolean result = false;
		searchName = name;
		searchPartial = (options & TAG_PARTIALMATCH) != 0;
		searchIgnoreCase = (options & TAG_IGNORECASE) != 0;
		//size = fp.length();
		fp.seek(0);	// Start over at the beginning for the searches below.
		if ((sortMethod == TAG_SORTED && !searchIgnoreCase) || (sortMethod == TAG_FOLDSORTED && searchIgnoreCase))
			result = findBinary();
		else
			result = findSequential();

		if (result != true)
			searchPos = size;
		else {
			searchPos = pos;
			if (entry != null)
				entry.parseTagLine(line);
		}

		return result;

	}


/*****************************************************************************/


	private boolean findBinary() throws IOException {

		boolean result = false;
		long lower_limit = 0;
		long upper_limit = size;
		long last_pos = 0;
		long pos = upper_limit / 2;

		while (result != true) {

			if (!readTagLineSeek(pos)) {
				/* in case we fell off end of file */
				result = findFirstMatchBefore();
				break;
			}
			else if (pos == last_pos) {
				/* prevent infinite loop if we backed up to beginning of file */
				break;
			}
			else {

				int comp = nameComparison();
				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 = true;
				else
					result = findFirstMatchBefore();
			}

		}

		return result;

	}


/*****************************************************************************/


	private boolean findFirstMatchBefore() throws IOException {

		boolean result = false;
		boolean more_lines;
		long start = pos;
		findFirstNonMatchBefore();
		do {
			more_lines = readTagLine();
			if (nameComparison() == 0)
				result = true;
		} while (more_lines && result!=true && pos<start);

		return result;

	}


/*****************************************************************************/


	private void findFirstNonMatchBefore() {

		boolean more_lines;
		int comp;
		long start = pos;
		long pos = start;

		do {
			if (pos < JUMP_BACK)
				pos = 0;
			else
				pos = pos - JUMP_BACK;
			more_lines = readTagLineSeek(pos);
			comp = nameComparison();
		} while (more_lines && comp==0 && pos>0 && pos<start);

	}


/*****************************************************************************/


	private boolean findNext(TagEntry entry) throws IOException {

		boolean result = false;
		if ((sortMethod == TAG_SORTED && !searchIgnoreCase) ||
			(sortMethod == TAG_FOLDSORTED  &&  searchIgnoreCase))
		{
			result = tagsNext(entry);
			if (result == true  && nameComparison() != 0)
				result = false;
		}
		else {
			result = findSequential();
			if (result == true  &&  entry != null)
				entry.parseTagLine(line);
		}

		return result;

	}

/*****************************************************************************/


	private boolean findSequential() throws IOException {

		boolean result = false;
		if (initialized) {
			while (result == false  &&  readTagLine()) {
				if (nameComparison() == 0)
					result = true;
			}
		}

		return result;

	}


/*****************************************************************************/


	private int nameComparison() {

		int result;

		if (searchIgnoreCase) {
			if (searchPartial)
				//result = strnuppercmp (search.name, name,
				result = searchName.compareToIgnoreCase(name.substring(0,searchName.length()));
			else
				result = searchName.compareToIgnoreCase(name);
		}
		else {
			if (searchPartial)
				//result = strncmp (search.name, name, search.nameLength);
				result = searchName.compareTo(name.substring(0,searchName.length()));
			else
				result = searchName.compareTo(name);
		}

		return result;

	}


/*****************************************************************************/


	/**
	 * Retrieves the value associated with the extension field for a given
	 * key.  It is passed a pointer to a structure already populated with
	 * values by a previous call to <code>tagsNext()</code>,
	 * <code>tagsFind()</code>, or <code>tagsFindNext()</code>, and a string
	 * containing the key of the desired extension field. If no such field
	 * of the specified key exists, the function will return null.
	 */
	private String readFieldValue(final TagEntry entry, final String key) {

		if (key.equals("kind"))
			return entry.kind;
		else if (key.equals("file"))
			return EmptyString;

		String result = null;
		int size = entry.fieldList.size();
		for (int i=0 ;  i<size && result==null; i++)
			if (key.equals(entry.fieldList.get(i)))
				result = (String)entry.fieldList.get(i);
		return result;

	}


/*****************************************************************************/


	private boolean readNext(TagEntry entry) throws IOException {

		boolean result = false;
		if (!initialized)
			result = false;
		else if (!readTagLine())
			result = false;
		else {
			if (entry!=null)
				entry.parseTagLine(line);
			result = true;
		}

		return result;

	}


/*****************************************************************************/


	/**
	 * Reads all the "pseudo-tags" from the top of the ctag file (author, version,
	 * etc.).
	 *
	 * param file The tag file from which to get the pseudotag information.
	 * @param info The structure in which to place the information.
	 */
	private void readPseudoTags(TagFileInfo info) throws IOException {

		long startOfLine;
		final int prefixLength = PseudoTagPrefix.length();

		if (info==null)
			return;

		// Initialize the info structure.
		info.format	= 1;
		info.sort		= TAG_UNSORTED;
		info.author	= null;
		info.name		= null;
		info.url		= null;
		info.version	= null;

		// Keep reading in lines until a non-pesudotag line is read.
		while (true) {

			startOfLine = fp.getFilePointer();

			if (!readTagLine())
				break;
			if (!line.startsWith(PseudoTagPrefix))
				break;
			else {

				TagEntry entry = new TagEntry();
				String key, value;
				entry.parseTagLine(line);	// Fills in entry.
				key = entry.name.substring(prefixLength);
				value = entry.file;
				if (key.equals("TAG_FILE_SORTED"))
					sortMethod = Integer.parseInt(value);
				else if (key.equals("TAG_FILE_FORMAT"))
					format = Integer.parseInt(value);
				else if (key.equals("TAG_PROGRAM_AUTHOR"))
					programAuthor = value;
				else if (key.equals("TAG_PROGRAM_NAME"))
					programName = value;
				else if (key.equals("TAG_PROGRAM_URL"))
					programUrl = value;
				else if (key.equals("TAG_PROGRAM_VERSION"))
					programVersion = value;

				if (info!=null) {
					info.format = format;
					info.sort = sortMethod;
					info.author = programAuthor;
					info.name = programName;
					info.url = programUrl;
					info.version = programVersion;
				}

			} // End of else.

		} // End of while (true).

		// Returns file pointer to where we were initially.
		fp.seek(startOfLine);

	}


/*****************************************************************************/


	/**
	 * Reads the next line from the ctag file.  This populates the
	 * <code>line</code> field so that it can later be passed to a
	 * <code>TagEntry</code> instance using <code>parseTagLine</code>.
	 *
	 * @return <code>true</code> if the next line is successfully read, or
	 *         <code>false</code> if EOF is encountered.
	 * @throws IOException If an I/O exception occurs.
	 */
	private boolean readTagLine() throws IOException {

		line = fp.readLine();

		// Copy the name from the line into the main name field.

⌨️ 快捷键说明

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