BLI_storage: util function BLI_file_read_as_mem
authorCampbell Barton <ideasman42@gmail.com>
Mon, 14 Dec 2015 06:12:16 +0000 (17:12 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Mon, 14 Dec 2015 06:16:23 +0000 (17:16 +1100)
Use for text loading and pasting from file.

source/blender/blenkernel/BKE_text.h
source/blender/blenkernel/intern/text.c
source/blender/blenlib/BLI_fileops.h
source/blender/blenlib/intern/storage.c
source/blender/editors/curve/editfont.c

index 50e4fa4c41d1c51d96d8bfe99b5f82fa409f08e4..e4cba75ff4c115ceadbd08f88fe307972adfaa1b 100644 (file)
@@ -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);
index 964599b0454a33e2c110d254aa68ab3de0655a2b..cdc48551b11e44365295fbae45a91adf817cdfa8 100644 (file)
@@ -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);
 
index 53ebc81fe222e4e645db16360fc0f4c93f54c30a..b842c30c97528800e8fd51d36bb4513100d22020 100644 (file)
@@ -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 ... */
index f7a8664c7399fe13fff099483dcd84f704b8b34f..a107c84d4d046f389d3d4adfbe461d615704b348 100644 (file)
@@ -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.
  */
index 9fba6468c98ebfc7c6147329748a4d27f8f5532e..542c7fe5d90f4ea1ce9be8ddd36d4a391df84276 100644 (file)
@@ -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)