BLI_storage: util function BLI_file_read_as_mem
Use for text loading and pasting from file.
This commit is contained in:
@@ -41,6 +41,7 @@ struct Main;
|
||||
struct Text;
|
||||
struct TextLine;
|
||||
|
||||
void BKE_text_free_lines (struct Text *text);
|
||||
void BKE_text_free (struct Text *text);
|
||||
void txt_set_undostate (int u);
|
||||
int txt_get_undostate (void);
|
||||
|
@@ -152,17 +152,28 @@ static void init_undo_text(Text *text)
|
||||
text->undo_buf = MEM_mallocN(text->undo_len, "undo buf");
|
||||
}
|
||||
|
||||
/**
|
||||
* \note caller must handle `undo_buf` and `compiled` members.
|
||||
*/
|
||||
void BKE_text_free_lines(Text *text)
|
||||
{
|
||||
for (TextLine *tmp = text->lines.first, *tmp_next; tmp; tmp = tmp_next) {
|
||||
tmp_next = tmp->next;
|
||||
MEM_freeN(tmp->line);
|
||||
if (tmp->format) {
|
||||
MEM_freeN(tmp->format);
|
||||
}
|
||||
MEM_freeN(tmp);
|
||||
}
|
||||
|
||||
BLI_listbase_clear(&text->lines);
|
||||
|
||||
text->curl = text->sell = NULL;
|
||||
}
|
||||
|
||||
void BKE_text_free(Text *text)
|
||||
{
|
||||
TextLine *tmp;
|
||||
|
||||
for (tmp = text->lines.first; tmp; tmp = tmp->next) {
|
||||
MEM_freeN(tmp->line);
|
||||
if (tmp->format)
|
||||
MEM_freeN(tmp->format);
|
||||
}
|
||||
|
||||
BLI_freelistN(&text->lines);
|
||||
BKE_text_free_lines(text);
|
||||
|
||||
if (text->name) MEM_freeN(text->name);
|
||||
MEM_freeN(text->undo_buf);
|
||||
@@ -339,63 +350,40 @@ static void text_from_buf(Text *text, const unsigned char *buffer, const int len
|
||||
|
||||
bool BKE_text_reload(Text *text)
|
||||
{
|
||||
FILE *fp;
|
||||
int len;
|
||||
unsigned char *buffer;
|
||||
TextLine *tmp;
|
||||
char str[FILE_MAX];
|
||||
size_t buffer_len;
|
||||
char filepath_abs[FILE_MAX];
|
||||
BLI_stat_t st;
|
||||
|
||||
if (!text->name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BLI_strncpy(str, text->name, FILE_MAX);
|
||||
BLI_path_abs(str, G.main->name);
|
||||
BLI_strncpy(filepath_abs, text->name, FILE_MAX);
|
||||
BLI_path_abs(filepath_abs, G.main->name);
|
||||
|
||||
fp = BLI_fopen(str, "r");
|
||||
if (fp == NULL) {
|
||||
return false;
|
||||
}
|
||||
fseek(fp, 0L, SEEK_END);
|
||||
len = ftell(fp);
|
||||
fseek(fp, 0L, SEEK_SET);
|
||||
if (UNLIKELY(len == -1)) {
|
||||
fclose(fp);
|
||||
buffer = BLI_file_read_as_mem(filepath_abs, 0, &buffer_len);
|
||||
if (buffer == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* free memory: */
|
||||
|
||||
for (tmp = text->lines.first; tmp; tmp = tmp->next) {
|
||||
MEM_freeN(tmp->line);
|
||||
if (tmp->format) MEM_freeN(tmp->format);
|
||||
}
|
||||
|
||||
BLI_freelistN(&text->lines);
|
||||
|
||||
BLI_listbase_clear(&text->lines);
|
||||
text->curl = text->sell = NULL;
|
||||
BKE_text_free_lines(text);
|
||||
txt_make_dirty(text);
|
||||
|
||||
/* clear undo buffer */
|
||||
MEM_freeN(text->undo_buf);
|
||||
init_undo_text(text);
|
||||
|
||||
buffer = MEM_mallocN(len, "text_buffer");
|
||||
/* under windows fread can return less than len bytes because
|
||||
* of CR stripping */
|
||||
len = fread(buffer, 1, len, fp);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
if (BLI_stat(str, &st) != -1) {
|
||||
if (BLI_stat(filepath_abs, &st) != -1) {
|
||||
text->mtime = st.st_mtime;
|
||||
}
|
||||
else {
|
||||
text->mtime = 0;
|
||||
}
|
||||
|
||||
text_from_buf(text, buffer, len);
|
||||
text_from_buf(text, buffer, buffer_len);
|
||||
|
||||
MEM_freeN(buffer);
|
||||
return true;
|
||||
@@ -403,31 +391,22 @@ bool BKE_text_reload(Text *text)
|
||||
|
||||
Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const bool is_internal)
|
||||
{
|
||||
FILE *fp;
|
||||
int len;
|
||||
unsigned char *buffer;
|
||||
size_t buffer_len;
|
||||
Text *ta;
|
||||
char str[FILE_MAX];
|
||||
char filepath_abs[FILE_MAX];
|
||||
BLI_stat_t st;
|
||||
|
||||
BLI_strncpy(str, file, FILE_MAX);
|
||||
BLI_strncpy(filepath_abs, file, FILE_MAX);
|
||||
if (relpath) /* can be NULL (bg mode) */
|
||||
BLI_path_abs(str, relpath);
|
||||
BLI_path_abs(filepath_abs, relpath);
|
||||
|
||||
fp = BLI_fopen(str, "r");
|
||||
if (fp == NULL) {
|
||||
return NULL;
|
||||
buffer = BLI_file_read_as_mem(filepath_abs, 0, &buffer_len);
|
||||
if (buffer == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fseek(fp, 0L, SEEK_END);
|
||||
len = ftell(fp);
|
||||
fseek(fp, 0L, SEEK_SET);
|
||||
if (UNLIKELY(len == -1)) {
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ta = BKE_libblock_alloc(bmain, ID_TXT, BLI_path_basename(str));
|
||||
ta = BKE_libblock_alloc(bmain, ID_TXT, BLI_path_basename(filepath_abs));
|
||||
|
||||
BLI_listbase_clear(&ta->lines);
|
||||
ta->curl = ta->sell = NULL;
|
||||
@@ -445,22 +424,15 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const
|
||||
|
||||
/* clear undo buffer */
|
||||
init_undo_text(ta);
|
||||
|
||||
buffer = MEM_mallocN(len, "text_buffer");
|
||||
/* under windows fread can return less than len bytes because
|
||||
* of CR stripping */
|
||||
len = fread(buffer, 1, len, fp);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
if (BLI_stat(str, &st) != -1) {
|
||||
if (BLI_stat(filepath_abs, &st) != -1) {
|
||||
ta->mtime = st.st_mtime;
|
||||
}
|
||||
else {
|
||||
ta->mtime = 0;
|
||||
}
|
||||
|
||||
text_from_buf(ta, buffer, len);
|
||||
text_from_buf(ta, buffer, buffer_len);
|
||||
|
||||
MEM_freeN(buffer);
|
||||
|
||||
|
@@ -130,6 +130,7 @@ bool BLI_file_older(const char *file1, const char *file2) ATTR_WARN_UNUSED_RES
|
||||
|
||||
/* read ascii file as lines, empty list if reading fails */
|
||||
struct LinkNode *BLI_file_read_as_lines(const char *file) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
void *BLI_file_read_as_mem(const char *filepath, size_t pad_bytes, size_t *r_size);
|
||||
void BLI_file_free_lines(struct LinkNode *lines);
|
||||
|
||||
/* this weirdo pops up in two places ... */
|
||||
|
@@ -287,6 +287,39 @@ bool BLI_is_file(const char *path)
|
||||
return (mode && !S_ISDIR(mode));
|
||||
}
|
||||
|
||||
void *BLI_file_read_as_mem(const char *filepath, size_t pad_bytes, size_t *r_size)
|
||||
{
|
||||
FILE *fp = BLI_fopen(filepath, "r");
|
||||
void *mem = NULL;
|
||||
|
||||
if (fp) {
|
||||
fseek(fp, 0L, SEEK_END);
|
||||
const long int filelen = ftell(fp);
|
||||
if (filelen == -1) {
|
||||
goto finally;
|
||||
}
|
||||
fseek(fp, 0L, SEEK_SET);
|
||||
|
||||
mem = MEM_mallocN(filelen + pad_bytes, __func__);
|
||||
if (mem == NULL) {
|
||||
goto finally;
|
||||
}
|
||||
|
||||
if (fread(mem, 1, filelen, fp) != filelen) {
|
||||
MEM_freeN(mem);
|
||||
mem = NULL;
|
||||
goto finally;
|
||||
}
|
||||
|
||||
*r_size = filelen;
|
||||
}
|
||||
|
||||
finally:
|
||||
fclose(fp);
|
||||
return mem;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads the contents of a text file and returns the lines in a linked list.
|
||||
*/
|
||||
|
@@ -345,50 +345,18 @@ static bool font_paste_utf8(bContext *C, const char *str, const size_t str_len)
|
||||
static int paste_from_file(bContext *C, ReportList *reports, const char *filename)
|
||||
{
|
||||
Object *obedit = CTX_data_edit_object(C);
|
||||
FILE *fp;
|
||||
char *strp;
|
||||
int filelen;
|
||||
size_t filelen;
|
||||
int retval;
|
||||
|
||||
fp = BLI_fopen(filename, "r");
|
||||
|
||||
if (!fp) {
|
||||
strp = BLI_file_read_as_mem(filename, 1, &filelen);
|
||||
if (strp == NULL) {
|
||||
BKE_reportf(reports, RPT_ERROR, "Failed to open file '%s'", filename);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
strp[filelen] = 0;
|
||||
|
||||
fseek(fp, 0L, SEEK_END);
|
||||
|
||||
errno = 0;
|
||||
filelen = ftell(fp);
|
||||
if (filelen == -1) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (filelen <= MAXTEXT) {
|
||||
strp = MEM_mallocN(filelen + 4, "tempstr");
|
||||
|
||||
fseek(fp, 0L, SEEK_SET);
|
||||
|
||||
/* fread() instead of read(), because windows read() converts text
|
||||
* to DOS \r\n linebreaks, causing double linebreaks in the 3d text */
|
||||
errno = 0;
|
||||
filelen = fread(strp, 1, filelen, fp);
|
||||
if (filelen == -1) {
|
||||
MEM_freeN(strp);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
strp[filelen] = 0;
|
||||
}
|
||||
else {
|
||||
strp = NULL;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
|
||||
if (strp && font_paste_utf8(C, strp, filelen)) {
|
||||
if (font_paste_utf8(C, strp, filelen)) {
|
||||
text_update_edited(C, obedit, FO_EDIT);
|
||||
retval = OPERATOR_FINISHED;
|
||||
|
||||
@@ -398,18 +366,9 @@ static int paste_from_file(bContext *C, ReportList *reports, const char *filenam
|
||||
retval = OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (strp) {
|
||||
MEM_freeN(strp);
|
||||
}
|
||||
MEM_freeN(strp);
|
||||
|
||||
return retval;
|
||||
|
||||
|
||||
/* failed to seek or read */
|
||||
fail:
|
||||
BKE_reportf(reports, RPT_ERROR, "Failed to read file '%s', %s", filename, strerror(errno));
|
||||
fclose(fp);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
static int paste_from_file_exec(bContext *C, wmOperator *op)
|
||||
|
Reference in New Issue
Block a user