Blender V5.0
blo_core_blend_header.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2025 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <cctype>
6#include <cstdlib>
7#include <cstring>
8
10#include "BLI_filereader.h"
11
12#include "BLO_core_bhead.hh"
14
26
28{
29 char header_bytes[MAX_SIZEOFBLENDERHEADER];
30 /* We read the minimal number of header bytes first. If necessary, the remaining bytes are read
31 * below. */
32 int64_t readsize = file->read(file, header_bytes, MIN_SIZEOFBLENDERHEADER);
33 if (readsize != MIN_SIZEOFBLENDERHEADER) {
34 return BlenderHeaderInvalid{};
35 }
36 if (!STREQLEN(header_bytes, "BLENDER", 7)) {
37 return BlenderHeaderInvalid{};
38 }
39 /* If the first 7 bytes are BLENDER, it is very likely that this is a newer version of the
40 * blend-file format. If the rest of the decode fails, we can still report that this was a
41 * Blender file of a potentially future version. */
42
43 BlenderHeader header;
44 /* In the old header format, the next bytes indicate the pointer size. In the new format a
45 * version number comes next. */
46 const bool is_legacy_header = ELEM(header_bytes[7], '_', '-');
47
48 if (is_legacy_header) {
49 header.file_format_version = 0;
50 switch (header_bytes[7]) {
51 case '_':
52 header.pointer_size = 4;
53 break;
54 case '-':
55 header.pointer_size = 8;
56 break;
57 default:
58 return BlenderHeaderUnknown{};
59 }
60 switch (header_bytes[8]) {
61 case 'v':
62 header.endian = L_ENDIAN;
63 break;
64 case 'V':
65 header.endian = B_ENDIAN;
66 break;
67 default:
68 return BlenderHeaderUnknown{};
69 }
70 if (!isdigit(header_bytes[9]) || !isdigit(header_bytes[10]) || !isdigit(header_bytes[11])) {
71 return BlenderHeaderUnknown{};
72 }
73 char version_str[4];
74 memcpy(version_str, header_bytes + 9, 3);
75 version_str[3] = '\0';
76 header.file_version = atoi(version_str);
77 return header;
78 }
79
80 if (!isdigit(header_bytes[7]) || !isdigit(header_bytes[8])) {
81 return BlenderHeaderUnknown{};
82 }
83 char header_size_str[3];
84 memcpy(header_size_str, header_bytes + 7, 2);
85 header_size_str[2] = '\0';
86 const int header_size = atoi(header_size_str);
87 if (header_size != MAX_SIZEOFBLENDERHEADER) {
88 return BlenderHeaderUnknown{};
89 }
90
91 /* Read remaining header bytes. */
92 const int64_t remaining_bytes_to_read = header_size - MIN_SIZEOFBLENDERHEADER;
93 readsize = file->read(file, header_bytes + MIN_SIZEOFBLENDERHEADER, remaining_bytes_to_read);
94 if (readsize != remaining_bytes_to_read) {
95 return BlenderHeaderUnknown{};
96 }
97 if (header_bytes[9] != '-') {
98 return BlenderHeaderUnknown{};
99 }
100 header.pointer_size = 8;
101 if (!isdigit(header_bytes[10]) || !isdigit(header_bytes[11])) {
102 return BlenderHeaderUnknown{};
103 }
104 char blend_file_version_format_str[3];
105 memcpy(blend_file_version_format_str, header_bytes + 10, 2);
106 blend_file_version_format_str[2] = '\0';
107 header.file_format_version = atoi(blend_file_version_format_str);
108 if (header.file_format_version != 1) {
109 return BlenderHeaderUnknown{};
110 }
111 if (header_bytes[12] != 'v') {
112 return BlenderHeaderUnknown{};
113 }
114 header.endian = L_ENDIAN;
115 if (!isdigit(header_bytes[13]) || !isdigit(header_bytes[14]) || !isdigit(header_bytes[15]) ||
116 !isdigit(header_bytes[16]))
117 {
118 return BlenderHeaderUnknown{};
119 }
120 char version_str[5];
121 memcpy(version_str, header_bytes + 13, 4);
122 version_str[4] = '\0';
123 header.file_version = std::atoi(version_str);
124 return header;
125}
#define BLI_assert(a)
Definition BLI_assert.h:46
#define B_ENDIAN
#define L_ENDIAN
Wrapper for reading from various sources (e.g. raw files, compressed files, memory....
#define STREQLEN(a, b, n)
#define ELEM(...)
BHeadType
#define MAX_SIZEOFBLENDERHEADER
#define BLEND_FILE_FORMAT_VERSION_0
#define MIN_SIZEOFBLENDERHEADER
#define BLEND_FILE_FORMAT_VERSION_1
std::variant< BlenderHeaderInvalid, BlenderHeaderUnknown, BlenderHeader > BlenderHeaderVariant
BlenderHeaderVariant BLO_readfile_blender_header_decode(FileReader *file)
long long int int64_t
BHeadType bhead_type() const
FileReaderReadFn read