78#include <fmt/format.h>
85#define DNA_DEPRECATED_ALLOW
139#define U (*((const UserDef *)&U))
145#define GENERATE_DEBUG_BLEND_FILE 0
146#define DEBUG_BLEND_FILE_SUFFIX ".debug.txt"
151#define MEM_BUFFER_SIZE MEM_SIZE_OPTIMAL(1 << 17)
152#define MEM_CHUNK_SIZE MEM_SIZE_OPTIMAL(1 << 15)
154#define ZSTD_BUFFER_SIZE (1 << 21)
155#define ZSTD_CHUNK_SIZE (1 << 20)
157#define ZSTD_COMPRESSION_LEVEL 3
177 virtual bool open(
const char *filepath) = 0;
179 virtual bool write(
const void *buf,
size_t buf_len) = 0;
187 bool open(
const char *filepath)
override;
188 bool close()
override;
189 bool write(
const void *buf,
size_t buf_len)
override;
210 return (
::close(file_handle) != -1);
214 return ::write(file_handle, buf, buf_len) == buf_len;
229 bool write_error =
false;
234 bool open(
const char *filepath)
override;
235 bool close()
override;
236 bool write(
const void *buf,
size_t buf_len)
override;
239 struct ZstdWriteBlockTask;
240 void write_task(ZstdWriteBlockTask *task);
241 void write_u32_le(uint32_t val);
242 void write_seekable_frames();
255 task->
ww->write_task(task);
260void ZstdWriteWrap::write_task(ZstdWriteBlockTask *task)
262 size_t out_buf_len = ZSTD_compressBound(task->size);
263 void *out_buf =
MEM_mallocN(out_buf_len,
"Zstd out buffer");
264 size_t out_size = ZSTD_compress(
271 while (next_frame != task->frame_number) {
275 if (ZSTD_isError(out_size)) {
279 if (base_wrap.write(out_buf, out_size)) {
300 if (!base_wrap.open(filepath)) {
313void ZstdWriteWrap::write_u32_le(uint32_t val)
318 base_wrap.write(&val,
sizeof(uint32_t));
329void ZstdWriteWrap::write_seekable_frames()
332 write_u32_le(0x184D2A5E);
338 const uint32_t frame_size = num_frames * 8 + 9;
339 write_u32_le(frame_size);
343 write_u32_le(frame->compressed_size);
344 write_u32_le(frame->uncompressed_size);
348 write_u32_le(num_frames);
349 const char flags = 0;
350 base_wrap.write(&flags, 1);
351 write_u32_le(0x8F92EAB1);
362 write_seekable_frames();
365 return base_wrap.close() && !write_error;
376 memcpy(task->
data, buf, buf_len);
377 task->
size = buf_len;
426#ifdef USE_WRITE_DATA_LEN
473 WriteData *wd = MEM_new<WriteData>(__func__);
479 if ((ww ==
nullptr) || (ww->
use_buf)) {
500 if (memlen > INT_MAX) {
514 if (!wd->
ww->
write(mem, memlen)) {
562#ifdef USE_WRITE_DATA_LEN
563 wd->write_len +=
len;
581 adr = (
const char *)adr + writelen;
611 if (current !=
nullptr) {
660 const MemFileChunk *prev_memchunk = curr_memchunk !=
nullptr ?
664 (prev_memchunk !=
nullptr &&
723 "Same identifier (old address) used several times for a same ID, skipping this "
724 "block to avoid critical corruption of the Blender file.");
733 if constexpr (
sizeof(
void *) == 4) {
737 bh.
old = uint32_t(uintptr_t(bhead.
old));
748 mywrite(wd, &bhead,
sizeof(bhead));
761 if (bhead.
len > std::numeric_limits<
decltype(bh.
len)>
::max()) {
762 CLOG_ERROR(&
LOG,
"Written .blend file is corrupt, because a memory block is too large.");
777 if (adr ==
nullptr ||
data ==
nullptr || nr == 0) {
790 CLOG_ERROR(&
LOG,
"Cannot write chunks bigger than INT_MAX.");
800 bh.
len = len_in_bytes;
815 WriteData *wd,
const int filecode,
const int struct_nr,
const int64_t nr,
const void *adr)
822 fmt::memory_buffer buf;
823 fmt::appender dst{buf};
825 fmt::format_to(dst,
"<Raw Data> at {} ({} bytes)\n", adr,
len);
827 constexpr int bytes_per_row = 8;
828 const int len_digits = std::to_string(std::max<size_t>(0,
len - 1)).size();
830 for (
size_t i = 0;
i <
len;
i++) {
831 if (
i % bytes_per_row == 0) {
832 fmt::format_to(dst,
" {:{}}: ",
i, len_digits);
834 fmt::format_to(dst,
"{:02x} ",
reinterpret_cast<const uint8_t *
>(adr)[
i]);
835 if (
i % bytes_per_row == bytes_per_row - 1) {
836 fmt::format_to(dst,
"\n");
839 if (
len % bytes_per_row != 0) {
840 fmt::format_to(dst,
"\n");
851 if (adr ==
nullptr ||
len == 0) {
900static void writelist_id(
WriteData *wd,
const int filecode,
const char *structname,
const ListBase *lb)
906 if (struct_nr == -1) {
907 printf(
"error: can't find SDNA code <%s>\n", structname);
919#define writestruct_at_address(wd, filecode, struct_id, nr, adr, data) \
920 writestruct_at_address_nr( \
921 wd, filecode, blender::dna::sdna_struct_id_get<struct_id>(), nr, adr, data)
923#define writestruct(wd, filecode, struct_id, nr, adr) \
924 writestruct_nr(wd, filecode, blender::dna::sdna_struct_id_get<struct_id>(), nr, adr)
939 const bool use_active_win,
952 if (use_active_win) {
961 if (window ==
nullptr) {
971 *r_scene = (window) ? window->
scene :
nullptr;
991 Scene *curscene =
nullptr;
1000 data.sfra = sce->r.sfra;
1001 data.efra = sce->r.efra;
1002 memset(
data.scene_name, 0,
sizeof(
data.scene_name));
1032 if (kmdi->remove_item) {
1035 if (kmdi->add_item) {
1150 linked_ids_by_library.
add(id->
lib,
id);
1156 Library &library = *library_ptr;
1161 for (
ID *
id : ids) {
1166 ids_used_from_library.
append(
id);
1170 ids_used_from_library.
append(
id);
1175 bool should_write_library =
false;
1177 should_write_library =
true;
1182 should_write_library =
true;
1185 should_write_library = !ids_used_from_library.
is_empty();
1188 if (!should_write_library) {
1196 for (
ID *
id : ids_used_from_library) {
1199 "Data-block '%s' from lib '%s' is not linkable, but is flagged as "
1202 library.
runtime->filepath_abs);
1211#ifdef WITH_BUILDINFO
1231 memset(fg.
_pad, 0,
sizeof(fg.
_pad));
1255 memcpy(fg.
subvstr, subvstr, 4);
1260#ifdef WITH_BUILDINFO
1294 ID *temp_id =
static_cast<ID *
>(buffer_.buffer());
1300 id.recalc_up_to_undo_push =
id.recalc_after_undo_push;
1301 id.recalc_after_undo_push = 0;
1306 if (is_placeholder) {
1310 temp_id->
lib =
id.lib;
1312 temp_id->
flag =
id.flag;
1337 temp_id->
prev =
nullptr;
1338 temp_id->
next =
nullptr;
1342 temp_id->
newid =
nullptr;
1400 std::stringstream ss;
1402 ss << header_size_in_bytes;
1408 const std::string header = ss.str();
1409 BLI_assert(header.size() == header_size_in_bytes);
1413 const char pointer_size_char =
sizeof(
void *) == 8 ?
'-' :
'_';
1417 std::stringstream ss;
1419 ss << pointer_size_char;
1422 const std::string header = ss.str();
1430 mywrite(wd, header.data(), header.size());
1479 Key *shape_key =
reinterpret_cast<Key *
>(id);
1483 if (shape_key->
from ==
nullptr || shape_key->
from->
us == 0) {
1495 local_ids_to_write.
append(
id);
1498 return local_ids_to_write;
1511 const int write_flags,
1512 const bool use_userdef,
1514 std::ostream *debug_dst)
1581 for (
ID *
id : local_ids_to_write) {
1590 for (
ID *
id : local_ids_to_write) {
1598 for (
ID *
id : local_ids_to_write) {
1634 int version_number =
min_ii(99,
U.versions);
1636 if (version_number == 0) {
1640 if (strlen(filepath) < 2) {
1645 while (version_number > 1) {
1646 SNPRINTF(filepath_tmp1,
"%s%d", filepath, version_number - 1);
1648 SNPRINTF(filepath_tmp2,
"%s%d", filepath, version_number);
1660 SNPRINTF(filepath_tmp1,
"%s%d", filepath, version_number);
1679 reports,
RPT_DEBUG,
"Checking validity of current .blend file *BEFORE* save to disk");
1686 "Critical data corruption: Conflicts and/or otherwise invalid data-blocks names "
1687 "(see console for details)");
1703 reports,
RPT_DEBUG,
"Checking validity of current .blend file *BEFORE* save to disk");
1709 const char *filepath,
1710 const int write_flags,
1721 const bool use_save_versions =
params->use_save_versions;
1722 const bool use_save_as_copy =
params->use_save_as_copy;
1723 const bool use_userdef =
params->use_userdef;
1725 const bool relbase_valid = (mainvar->
filepath[0] !=
'\0');
1736 void *path_list_backup =
nullptr;
1743 SNPRINTF(tempname,
"%s@", filepath);
1745 if (ww.
open(tempname) ==
false) {
1747 reports,
RPT_ERROR,
"Cannot open file %s for writing: %s", tempname, strerror(errno));
1753 if (relbase_valid ==
false) {
1762 if (relbase_valid ==
false) {
1772 if (relbase_valid) {
1784 if (relbase_valid && (
BLI_path_cmp(dir_dst, dir_src) == 0)) {
1790 if (relbase_valid ==
false) {
1801 char mainvar_filepath_orig[
FILE_MAX];
1810 switch (remap_mode) {
1834#if GENERATE_DEBUG_BLEND_FILE
1837 std::ostream *debug_dst = &debug_dst_file;
1839 std::ostream *debug_dst =
nullptr;
1844 mainvar, &ww,
nullptr,
nullptr, write_flags, use_userdef, thumb, debug_dst);
1862 if (use_save_versions) {
1877 STRNCPY(
G.filepath_last_blend, filepath);
1889 const char *filepath,
1890 const int write_flags,
1906 bool use_userdef =
false;
1909 mainvar,
nullptr, compare, current, write_flags, use_userdef,
nullptr,
nullptr);
1929 const char *struct_name,
1931 const void *data_ptr)
1947 const int struct_id,
1948 const void *address,
1949 const void *data_ptr)
1957 const int struct_id,
1958 const void *address,
1959 const void *data_ptr)
1965 const int struct_id,
1967 const void *data_ptr)
1973 const int struct_id,
1975 const void *address,
1976 const void *data_ptr)
1997 const int struct_id,
1998 const void *id_address,
2062 if (data_ptr !=
nullptr) {
2069 const size_t approximate_size_in_bytes,
2073 if (
data ==
nullptr) {
2078 if (sharing_info !=
nullptr) {
2080 memfile.
shared_storage = MEM_new<MemFileSharedStorage>(__func__);
2091 if (sharing_info !=
nullptr) {
void BKE_asset_catalog_path_list_blend_write(BlendWriter *writer, const ListBase &catalog_path_list)
#define BLENDER_FILE_SUBVERSION
#define BLENDER_FILE_MIN_VERSION
#define BLENDER_FILE_VERSION
#define BLENDER_FILE_MIN_SUBVERSION
void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *reports, BPathSummary *r_summary=nullptr)
void * BKE_bpath_list_backup(Main *bmain, eBPathForeachFlag flag)
void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *reports, BPathSummary *r_summary=nullptr)
void BKE_bpath_list_restore(Main *bmain, eBPathForeachFlag flag, void *path_list_handle)
void BKE_bpath_relative_rebase(Main *bmain, const char *basedir_src, const char *basedir_dst, ReportList *reports, BPathSummary *r_summary=nullptr)
@ BKE_BPATH_FOREACH_PATH_SKIP_LINKED
@ BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE
void BKE_bpath_list_free(void *path_list_handle)
#define G_FILE_FLAG_ALL_RUNTIME
void IDP_BlendWrite(BlendWriter *writer, const IDProperty *prop)
const IDTypeInfo * BKE_idtype_get_info_from_id(const ID *id)
bool BKE_idtype_idcode_is_linkable(short idcode)
@ IDTYPE_FLAGS_NEVER_UNUSED
ViewLayer * BKE_view_layer_find(const Scene *scene, const char *layer_name)
void id_lib_extern(ID *id)
#define MAIN_ID_SESSION_UID_UNSET
void id_lib_indirect_weak_link(ID *id)
void BKE_main_id_refcount_recompute(Main *bmain, bool do_linked_only)
void BKE_lib_override_library_operations_create(Main *bmain, ID *local, int *r_report_flags)
LibraryForeachIDCallbackFlag
@ IDWALK_CB_DIRECT_WEAK_LINK
@ IDWALK_CB_INDIRECT_USAGE
void BKE_library_foreach_ID_link(Main *bmain, ID *id, blender::FunctionRef< LibraryIDLinkCallback > callback, void *user_data, LibraryForeachIDFlag flag)
#define FOREACH_MAIN_ID_END
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
bool BKE_main_namemap_validate_and_fix(Main &bmain)
void BKE_preferences_extension_repo_write_data(struct BlendWriter *writer, const bUserExtensionRepo *repo)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
bScreen * BKE_workspace_active_screen_get(const WorkSpaceInstanceHook *hook) GETTER_ATTRS
#define BLI_assert_unreachable()
#define BLI_STATIC_ASSERT(a, msg)
#define BLI_assert_msg(a, msg)
BLI_INLINE void BLI_endian_switch_uint32(unsigned int *val) ATTR_NONNULL(1)
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
int BLI_rename_overwrite(const char *from, const char *to) ATTR_NONNULL()
int BLI_open(const char *filepath, int oflag, int pmode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
File and directory operations.
#define LISTBASE_FOREACH(type, var, list)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
ATTR_WARN_UNUSED_RESULT const size_t num
int BLI_path_normalize(char *path) ATTR_NONNULL(1)
bool BLI_path_is_abs_from_cwd(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
bool BLI_path_is_rel(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
void void BLI_path_split_dir_part(const char *filepath, char *dir, size_t dir_maxncpy) ATTR_NONNULL(1
#define SNPRINTF(dst, format,...)
char * STRNCPY(char(&dst)[N], const char *src)
void BLI_condition_notify_all(ThreadCondition *cond)
void BLI_mutex_end(ThreadMutex *mutex)
void BLI_threadpool_remove(struct ListBase *threadbase, void *callerdata)
void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex)
void BLI_threadpool_init(struct ListBase *threadbase, void *(*do_thread)(void *), int tot)
void BLI_mutex_init(ThreadMutex *mutex)
pthread_cond_t ThreadCondition
void BLI_condition_end(ThreadCondition *cond)
int BLI_system_thread_count(void)
void BLI_threadpool_end(struct ListBase *threadbase)
void BLI_condition_init(ThreadCondition *cond)
void BLI_mutex_lock(ThreadMutex *mutex)
void BLI_mutex_unlock(ThreadMutex *mutex)
int BLI_available_threads(struct ListBase *threadbase)
void BLI_threadpool_insert(struct ListBase *threadbase, void *callerdata)
pthread_mutex_t ThreadMutex
#define UNUSED_VARS_NDEBUG(...)
Compatibility-like things for windows.
Utilities ensuring .blend file (i.e. Main) is in valid state during write and/or read process.
bool BLO_main_validate_libraries(Main *bmain, ReportList *reports)
bool BLO_main_validate_shapekeys(Main *bmain, ReportList *reports)
#define BLO_write_struct(writer, struct_name, data_ptr)
bool BLO_write_is_undo(BlendWriter *writer)
external readfile function prototypes.
#define BLEN_THUMB_MEMSIZE_FILE(_x, _y)
void BLO_memfile_chunk_add(MemFileWriteData *mem_data, const char *buf, size_t size)
void BLO_memfile_write_init(MemFileWriteData *mem_data, MemFile *written_memfile, MemFile *reference_memfile)
void BLO_memfile_write_finalize(MemFileWriteData *mem_data)
external writefile.cc function prototypes.
@ BLO_WRITE_PATH_REMAP_NONE
@ BLO_WRITE_PATH_REMAP_RELATIVE_ALL
@ BLO_WRITE_PATH_REMAP_ABSOLUTE
@ BLO_WRITE_PATH_REMAP_RELATIVE
#define CLOG_ERROR(clg_ref,...)
@ ID_TAG_NO_USER_REFCOUNT
@ ID_FLAG_INDIRECT_WEAK_LINK
blenloader genfile private function prototypes
const struct SDNA * DNA_sdna_current_get(void)
int DNA_struct_find_with_alias(const struct SDNA *sdna, const char *str)
int DNA_struct_size(const struct SDNA *sdna, int struct_index)
#define SDNA_RAW_DATA_STRUCT_INDEX
@ USER_MENU_TYPE_OPERATOR
#define USER_EXPERIMENTAL_TEST(userdef, member)
Read Guarded memory(de)allocation.
BMesh const char void * data
ulong build_commit_timestamp
unsigned long long int uint64_t
bool add(const Key &key, const Value &value)
Value lookup_default(const Key &key, const Value &default_value) const
bool write(const void *buf, size_t buf_len) override
bool open(const char *filepath) override
virtual bool open(const char *filepath)=0
virtual bool write(const void *buf, size_t buf_len)=0
ZstdWriteWrap(WriteWrap &base_wrap)
bool open(const char *filepath) override
bool write(const void *buf, size_t buf_len) override
Span< Value > lookup(const Key &key) const
void add(const Key &key, const Value &value)
void append(const T &value)
#define ID_IS_OVERRIDE_LIBRARY_VIRTUAL(_id)
#define ID_IS_OVERRIDE_LIBRARY_REAL(_id)
#define ID_IS_LINKED(_id)
#define ID_LINK_PLACEHOLDER
#define ID_TAG_KEEP_ON_UNDO
void * MEM_mallocN(size_t len, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
void print_structs_at_address(const SDNA &sdna, int struct_id, const void *data, const void *address, int64_t element_num, std::ostream &stream)
int sdna_struct_id_get_max()
BLO_Write_IDBuffer(ID &id, bool is_undo, bool is_placeholder)
struct ViewLayer * cur_view_layer
uint64_t build_commit_timestamp
struct bScreen * curscreen
IDTypeBlendWriteFunction blend_write
unsigned int recalc_up_to_undo_push
struct ID_Runtime runtime
LibraryForeachIDCallbackFlag cb_flag
struct PackedFile * packedfile
LibraryRuntimeHandle * runtime
blender::Map< const void *, const blender::ImplicitSharingInfo * > map
blender::Map< uint, MemFileChunk * > id_session_uid_mapping
MemFile * written_memfile
uint current_id_session_uid
MemFileChunk * reference_current_chunk
MemFileSharedStorage * shared_storage
char scene_name[MAX_ID_NAME - 2]
ListBase script_directories
struct ListBase asset_shelves_settings
struct ListBase user_keymaps
struct ListBase autoexec_paths
struct ListBase user_keyconfig_prefs
struct ListBase extension_repos
struct ListBase user_menus
struct ListBase asset_libraries
blender::Set< const void * > per_id_addresses_set
struct WriteData::@003367157356032066050035016000215324233317107207 buffer
blender::Set< const void * > per_id_written_shared_addresses
struct WriteData::@071070113236362355236315113135160313344315264366 validation_data
uint32_t uncompressed_size
ZstdWriteBlockTask * prev
static void * write_task(void *userdata)
ZstdWriteBlockTask * next
struct WorkSpaceInstanceHook * workspace_hook
void BLO_write_double_array(BlendWriter *writer, const int64_t num, const double *data_ptr)
void BLO_write_uint32_array(BlendWriter *writer, const int64_t num, const uint32_t *data_ptr)
static void writedata_do_write(WriteData *wd, const void *mem, const size_t memlen)
static void writestruct_at_address_nr(WriteData *wd, const int filecode, const int struct_nr, const int64_t nr, const void *adr, const void *data)
void blo_write_id_struct(BlendWriter *writer, const int struct_id, const void *id_address, const ID *id)
int BLO_get_struct_id_by_name(const BlendWriter *writer, const char *struct_name)
static void mywrite_id_begin(WriteData *wd, ID *id)
#define ZSTD_COMPRESSION_LEVEL
static void write_thumb(WriteData *wd, const BlendThumbnail *thumb)
#define writestruct(wd, filecode, struct_id, nr, adr)
static void current_screen_compat(Main *mainvar, const bool use_active_win, bScreen **r_screen, Scene **r_scene, ViewLayer **r_view_layer)
void BLO_write_pointer_array(BlendWriter *writer, const int64_t num, const void *data_ptr)
void BLO_write_struct_array_by_name(BlendWriter *writer, const char *struct_name, const int64_t array_size, const void *data_ptr)
void BLO_write_struct_at_address_by_id(BlendWriter *writer, const int struct_id, const void *address, const void *data_ptr)
static bool write_file_handle(Main *mainvar, WriteWrap *ww, MemFile *compare, MemFile *current, const int write_flags, const bool use_userdef, const BlendThumbnail *thumb, std::ostream *debug_dst)
static void writelist_nr(WriteData *wd, const int filecode, const int struct_nr, const ListBase *lb)
static std::string get_blend_file_header()
void BLO_write_int32_array(BlendWriter *writer, const int64_t num, const int32_t *data_ptr)
void BLO_write_struct_by_name(BlendWriter *writer, const char *struct_name, const void *data_ptr)
static void writedata_free(WriteData *wd)
#define DEBUG_BLEND_FILE_SUFFIX
static void write_keymapitem(BlendWriter *writer, const wmKeyMapItem *kmi)
static void write_id(WriteData *wd, ID *id)
static bool do_history(const char *filepath, ReportList *reports)
static void write_renderinfo(WriteData *wd, Main *mainvar)
void BLO_write_struct_list_by_id(BlendWriter *writer, const int struct_id, const ListBase *list)
static void write_userdef(BlendWriter *writer, const UserDef *userdef)
#define writestruct_at_address(wd, filecode, struct_id, nr, adr, data)
static void write_file_main_validate_pre(Main *bmain, ReportList *reports)
void BLO_write_float_array(BlendWriter *writer, const int64_t num, const float *data_ptr)
static void writestruct_nr(WriteData *wd, const int filecode, const int struct_nr, const int64_t nr, const void *adr)
static void write_file_main_validate_post(Main *bmain, ReportList *reports)
void BLO_write_struct_by_id(BlendWriter *writer, const int struct_id, const void *data_ptr)
void BLO_write_struct_array_at_address_by_id(BlendWriter *writer, const int struct_id, const int64_t array_size, const void *address, const void *data_ptr)
static void writedata(WriteData *wd, const int filecode, const size_t len, const void *adr)
void BLO_write_string(BlendWriter *writer, const char *data_ptr)
static WriteData * writedata_new(WriteWrap *ww)
void BLO_write_int8_array(BlendWriter *writer, const int64_t num, const int8_t *data_ptr)
void BLO_write_int16_array(BlendWriter *writer, const int64_t num, const int16_t *data_ptr)
void BLO_write_uint8_array(BlendWriter *writer, const int64_t num, const uint8_t *data_ptr)
static void write_libraries(WriteData *wd, Main *bmain)
static void write_global(WriteData *wd, const int fileflags, Main *mainvar)
static bool write_at_address_validate(WriteData *wd, const int filecode, const void *address)
void BLO_write_char_array(BlendWriter *writer, const int64_t num, const char *data_ptr)
static bool mywrite_end(WriteData *wd)
static void mywrite_flush(WriteData *wd)
static blender::Vector< ID * > gather_local_ids_to_write(Main *bmain, const bool is_undo)
static void mywrite_id_end(WriteData *wd, ID *)
static void write_blend_file_header(WriteData *wd)
bool BLO_write_file(Main *mainvar, const char *filepath, const int write_flags, const BlendFileWriteParams *params, ReportList *reports)
static void write_raw_data_in_debug_file(WriteData *wd, const size_t len, const void *adr)
static void write_id_placeholder(WriteData *wd, ID *id)
void BLO_write_struct_array_by_id(BlendWriter *writer, const int struct_id, const int64_t array_size, const void *data_ptr)
bool BLO_write_is_undo(BlendWriter *writer)
static int write_id_direct_linked_data_process_cb(LibraryIDLinkCallbackData *cb_data)
static void mywrite(WriteData *wd, const void *adr, size_t len)
void BLO_write_raw(BlendWriter *writer, const size_t size_in_bytes, const void *data_ptr)
bool BLO_write_file_mem(Main *mainvar, MemFile *compare, MemFile *current, const int write_flags)
static WriteData * mywrite_begin(WriteWrap *ww, MemFile *compare, MemFile *current)
void BLO_write_struct_list_by_name(BlendWriter *writer, const char *struct_name, ListBase *list)
static void write_bhead(WriteData *wd, const BHead &bhead)
static bool BLO_write_file_impl(Main *mainvar, const char *filepath, const int write_flags, const BlendFileWriteParams *params, ReportList *reports, WriteWrap &ww)
void BLO_write_shared(BlendWriter *writer, const void *data, const size_t approximate_size_in_bytes, const blender::ImplicitSharingInfo *sharing_info, const blender::FunctionRef< void()> write_fn)
void BLO_write_struct_at_address_by_id_with_filecode(BlendWriter *writer, const int filecode, const int struct_id, const void *address, const void *data_ptr)
void BLO_write_float3_array(BlendWriter *writer, const int64_t num, const float *data_ptr)