From de0119d087acb4e38488d6f472fb7d4f0de26c17 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 14 Dec 2015 17:12:16 +1100 Subject: BLI_storage: util function BLI_file_read_as_mem Use for text loading and pasting from file. --- source/blender/blenkernel/BKE_text.h | 1 + source/blender/blenkernel/intern/text.c | 104 ++++++++++++-------------------- source/blender/blenlib/BLI_fileops.h | 1 + source/blender/blenlib/intern/storage.c | 33 ++++++++++ source/blender/editors/curve/editfont.c | 53 ++-------------- 5 files changed, 79 insertions(+), 113 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index 50e4fa4c41d..e4cba75ff4c 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -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); diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 964599b0454..cdc48551b11 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -152,17 +152,28 @@ static void init_undo_text(Text *text) text->undo_buf = MEM_mallocN(text->undo_len, "undo buf"); } -void BKE_text_free(Text *text) +/** + * \note caller must handle `undo_buf` and `compiled` members. + */ +void BKE_text_free_lines(Text *text) { - TextLine *tmp; - - for (tmp = text->lines.first; tmp; tmp = tmp->next) { + for (TextLine *tmp = text->lines.first, *tmp_next; tmp; tmp = tmp_next) { + tmp_next = tmp->next; MEM_freeN(tmp->line); - if (tmp->format) + if (tmp->format) { MEM_freeN(tmp->format); + } + MEM_freeN(tmp); } - - BLI_freelistN(&text->lines); + + BLI_listbase_clear(&text->lines); + + text->curl = text->sell = NULL; +} + +void BKE_text_free(Text *text) +{ + 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; - } - - fseek(fp, 0L, SEEK_END); - len = ftell(fp); - fseek(fp, 0L, SEEK_SET); - if (UNLIKELY(len == -1)) { - fclose(fp); - return NULL; + buffer = BLI_file_read_as_mem(filepath_abs, 0, &buffer_len); + if (buffer == NULL) { + return false; } - 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); diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h index 53ebc81fe22..b842c30c975 100644 --- a/source/blender/blenlib/BLI_fileops.h +++ b/source/blender/blenlib/BLI_fileops.h @@ -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 ... */ diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index f7a8664c739..a107c84d4d0 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -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. */ diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 9fba6468c98..542c7fe5d90 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -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) -- cgit v1.2.3