read: implement openBuffer() using openInputFile()
In addition, add automatic memory MIO opening to read.c for small files and remove the same optimization from Geany. Simplify tm_ctags_parse() as the memory/file branches are identical now.
This commit is contained in:
parent
2f4d43ac93
commit
aafb127024
@ -574,7 +574,7 @@ static bool createTagsForFile (const char *const fileName,
|
||||
{
|
||||
bool retried = false;
|
||||
|
||||
if (openInputFile (fileName, language))
|
||||
if (openInputFile (fileName, language, NULL))
|
||||
{
|
||||
|
||||
makeFileTag (fileName);
|
||||
|
@ -401,10 +401,46 @@ static bool parseLineDirective (char *s)
|
||||
* Input file I/O operations
|
||||
*/
|
||||
|
||||
#define MAX_IN_MEMORY_FILE_SIZE (1024*1024)
|
||||
|
||||
extern MIO *getMio (const char *const fileName, const char *const openMode,
|
||||
bool memStreamRequired)
|
||||
{
|
||||
FILE *src;
|
||||
fileStatus *st;
|
||||
unsigned long size;
|
||||
unsigned char *data;
|
||||
|
||||
st = eStat (fileName);
|
||||
size = st->size;
|
||||
eStatFree (st);
|
||||
if ((!memStreamRequired)
|
||||
&& (size > MAX_IN_MEMORY_FILE_SIZE || size == 0))
|
||||
return mio_new_file (fileName, openMode);
|
||||
|
||||
src = fopen (fileName, openMode);
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
data = eMalloc (size);
|
||||
if (fread (data, 1, size, src) != size)
|
||||
{
|
||||
eFree (data);
|
||||
fclose (src);
|
||||
if (memStreamRequired)
|
||||
return NULL;
|
||||
else
|
||||
return mio_new_file (fileName, openMode);
|
||||
}
|
||||
fclose (src);
|
||||
return mio_new_memory (data, size, eRealloc, eFree);
|
||||
}
|
||||
|
||||
/* This function opens an input file, and resets the line counter. If it
|
||||
* fails, it will display an error message and leave the File.mio set to NULL.
|
||||
*/
|
||||
extern bool openInputFile (const char *const fileName, const langType language)
|
||||
extern bool openInputFile (const char *const fileName, const langType language,
|
||||
MIO *mio)
|
||||
{
|
||||
const char *const openMode = "rb";
|
||||
bool opened = false;
|
||||
@ -417,7 +453,8 @@ extern bool openInputFile (const char *const fileName, const langType language)
|
||||
File.mio = NULL;
|
||||
}
|
||||
|
||||
File.mio = mio_new_file (fileName, openMode);
|
||||
File.mio = mio? mio_ref (mio): getMio (fileName, openMode, true);
|
||||
|
||||
if (File.mio == NULL)
|
||||
error (WARNING | PERROR, "cannot open \"%s\"", fileName);
|
||||
else
|
||||
@ -447,43 +484,15 @@ extern bool openInputFile (const char *const fileName, const langType language)
|
||||
* This func is NOT THREAD SAFE.
|
||||
* The user should not tamper with the buffer while this func is executing.
|
||||
*/
|
||||
extern bool bufferOpen (unsigned char *buffer, size_t buffer_size,
|
||||
const char *const fileName, const langType language )
|
||||
extern bool bufferOpen (const char *const fileName, const langType language,
|
||||
unsigned char *buffer, size_t buffer_size)
|
||||
{
|
||||
bool opened = false;
|
||||
|
||||
/* Check whether a file of a buffer were already open, then close them.
|
||||
*/
|
||||
if (File.mio != NULL) {
|
||||
mio_free (File.mio); /* close any open source file */
|
||||
File.mio = NULL;
|
||||
}
|
||||
|
||||
/* check if we got a good buffer */
|
||||
if (buffer == NULL || buffer_size == 0) {
|
||||
opened = false;
|
||||
return opened;
|
||||
}
|
||||
|
||||
opened = true;
|
||||
|
||||
File.mio = mio_new_memory (buffer, buffer_size, NULL, NULL);
|
||||
setInputFileName (fileName);
|
||||
mio_getpos (File.mio, &StartOfLine);
|
||||
mio_getpos (File.mio, &File.filePosition);
|
||||
File.currentLine = NULL;
|
||||
File.input.lineNumber = 0L;
|
||||
|
||||
if (File.line != NULL)
|
||||
vStringClear (File.line);
|
||||
|
||||
setSourceFileParameters (vStringNewInit (fileName), language);
|
||||
File.source.lineNumber = 0L;
|
||||
|
||||
verbose ("OPENING %s as %s language %sfile\n", fileName,
|
||||
getLanguageName (language),
|
||||
File.source.isHeader ? "include " : "");
|
||||
MIO *mio;
|
||||
bool opened;
|
||||
|
||||
mio = mio_new_memory (buffer, buffer_size, NULL, NULL);
|
||||
opened = openInputFile (fileName, language, mio);
|
||||
mio_free (mio);
|
||||
return opened;
|
||||
}
|
||||
|
||||
|
@ -70,15 +70,21 @@ extern kindOption *getInputLanguageFileKind (void);
|
||||
extern bool doesInputLanguageRequestAutomaticFQTag (void);
|
||||
|
||||
extern void freeInputFileResources (void);
|
||||
extern bool openInputFile (const char *const fileName, const langType language);
|
||||
/* Stream opend by getMio can be passed to openInputFile as the 3rd
|
||||
argument. If the 3rd argument is NULL, openInputFile calls getMio
|
||||
internally. The 3rd argument is introduced for reusing mio object
|
||||
created in parser guessing stage. */
|
||||
extern bool openInputFile (const char *const fileName, const langType language, MIO *mio);
|
||||
extern bool bufferOpen (const char *const fileName, const langType language,
|
||||
unsigned char *buffer, size_t buffer_size);
|
||||
extern MIO *getMio (const char *const fileName, const char *const openMode,
|
||||
bool memStreamRequired);
|
||||
extern void closeInputFile (void);
|
||||
extern int getcFromInputFile (void);
|
||||
extern int getNthPrevCFromInputFile (unsigned int nth, int def);
|
||||
extern int skipToCharacterInInputFile (int c);
|
||||
extern void ungetcToInputFile (int c);
|
||||
extern const unsigned char *readLineFromInputFile (void);
|
||||
extern bool bufferOpen (unsigned char *buffer, size_t buffer_size,
|
||||
const char *const fileName, const langType language );
|
||||
|
||||
extern const char *getSourceFileTagPath (void);
|
||||
extern const char *getSourceLanguageName (void);
|
||||
|
@ -69,27 +69,13 @@ void tm_ctags_parse(guchar *buffer, gsize buffer_size,
|
||||
while (retry && passCount < 3)
|
||||
{
|
||||
pass_callback(user_data);
|
||||
if (!buffer && openInputFile (file_name, lang))
|
||||
if ((!buffer && openInputFile (file_name, lang, NULL)) ||
|
||||
(buffer && bufferOpen (file_name, lang, buffer, buffer_size)))
|
||||
{
|
||||
if (LanguageTable [lang]->parser != NULL)
|
||||
{
|
||||
LanguageTable [lang]->parser ();
|
||||
closeInputFile ();
|
||||
retry = FALSE;
|
||||
break;
|
||||
}
|
||||
else if (LanguageTable [lang]->parser2 != NULL)
|
||||
retry = LanguageTable [lang]->parser2 (passCount);
|
||||
closeInputFile ();
|
||||
}
|
||||
else if (buffer && bufferOpen (buffer, buffer_size, file_name, lang))
|
||||
{
|
||||
if (LanguageTable [lang]->parser != NULL)
|
||||
{
|
||||
LanguageTable [lang]->parser ();
|
||||
closeInputFile ();
|
||||
retry = FALSE;
|
||||
break;
|
||||
}
|
||||
else if (LanguageTable [lang]->parser2 != NULL)
|
||||
retry = LanguageTable [lang]->parser2 (passCount);
|
||||
@ -98,7 +84,7 @@ void tm_ctags_parse(guchar *buffer, gsize buffer_size,
|
||||
else
|
||||
{
|
||||
g_warning("Unable to open %s", file_name);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
++ passCount;
|
||||
}
|
||||
|
@ -790,8 +790,6 @@ gboolean tm_source_file_parse(TMSourceFile *source_file, guchar* text_buf, gsize
|
||||
{
|
||||
const char *file_name;
|
||||
gboolean retry = TRUE;
|
||||
gboolean parse_file = FALSE;
|
||||
gboolean free_buf = FALSE;
|
||||
|
||||
if ((NULL == source_file) || (NULL == source_file->file_name))
|
||||
{
|
||||
@ -807,40 +805,18 @@ gboolean tm_source_file_parse(TMSourceFile *source_file, guchar* text_buf, gsize
|
||||
|
||||
file_name = source_file->file_name;
|
||||
|
||||
if (!use_buffer)
|
||||
{
|
||||
GStatBuf s;
|
||||
|
||||
/* load file to memory and parse it from memory unless the file is too big */
|
||||
if (g_stat(file_name, &s) != 0 || s.st_size > 10*1024*1024)
|
||||
parse_file = TRUE;
|
||||
else
|
||||
{
|
||||
if (!g_file_get_contents(file_name, (gchar**)&text_buf, (gsize*)&buf_size, NULL))
|
||||
{
|
||||
g_warning("Unable to open %s", file_name);
|
||||
return FALSE;
|
||||
}
|
||||
free_buf = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!parse_file && (NULL == text_buf || 0 == buf_size))
|
||||
if (use_buffer && (NULL == text_buf || 0 == buf_size))
|
||||
{
|
||||
/* Empty buffer, "parse" by setting empty tag array */
|
||||
tm_tags_array_free(source_file->tags_array, FALSE);
|
||||
if (free_buf)
|
||||
g_free(text_buf);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
tm_tags_array_free(source_file->tags_array, FALSE);
|
||||
|
||||
tm_ctags_parse(parse_file ? NULL : text_buf, buf_size, file_name,
|
||||
tm_ctags_parse(use_buffer ? text_buf : NULL, buf_size, file_name,
|
||||
source_file->lang, ctags_new_tag, ctags_pass_start, source_file);
|
||||
|
||||
if (free_buf)
|
||||
g_free(text_buf);
|
||||
return !retry;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user