Blender V4.3
file_handler.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <cstring>
6
7#include "BKE_file_handler.hh"
8
9#include "BLI_path_utils.hh"
10#include "BLI_string.h"
11
12namespace blender::bke {
13
19
24
26{
27 auto itr = std::find_if(file_handlers().begin(),
28 file_handlers().end(),
29 [idname](const std::unique_ptr<FileHandlerType> &file_handler) {
30 return idname == file_handler->idname;
31 });
32 if (itr != file_handlers().end()) {
33 return itr->get();
34 }
35 return nullptr;
36}
37
38void file_handler_add(std::unique_ptr<FileHandlerType> file_handler)
39{
40 BLI_assert(file_handler_find(file_handler->idname) == nullptr);
41
43 const char char_separator = ';';
44 const char *char_begin = file_handler->file_extensions_str;
45 const char *char_end = BLI_strchr_or_end(char_begin, char_separator);
46 while (char_begin[0]) {
47 if (char_end - char_begin > 1) {
48 std::string file_extension(char_begin, char_end - char_begin);
49 file_handler->file_extensions.append(file_extension);
50 }
51 char_begin = char_end[0] ? char_end + 1 : char_end;
52 char_end = BLI_strchr_or_end(char_begin, char_separator);
53 }
54
55 file_handlers_vector().append(std::move(file_handler));
56}
57
59{
60 file_handlers_vector().remove_if(
61 [file_handler](const std::unique_ptr<FileHandlerType> &test_file_handler) {
62 return test_file_handler.get() == file_handler;
63 });
64}
65
67 const bContext *C, const blender::Span<std::string> paths)
68{
69 blender::Vector<std::string> path_extensions;
70 for (const std::string &path : paths) {
71 const char *extension = BLI_path_extension(path.c_str());
72 if (!extension) {
73 continue;
74 }
75 path_extensions.append_non_duplicates(extension);
76 }
77
79 for (const std::unique_ptr<FileHandlerType> &file_handler_ptr : file_handlers()) {
80 FileHandlerType &file_handler = *file_handler_ptr;
81 const auto &file_extensions = file_handler.file_extensions;
82 bool support_any_extension = false;
83 for (const std::string &extension : path_extensions) {
84 auto test_fn = [&extension](const std::string &test_extension) {
85 return BLI_strcaseeq(extension.c_str(), test_extension.c_str()) == 1;
86 };
87 support_any_extension = std::any_of(file_extensions.begin(), file_extensions.end(), test_fn);
88 if (support_any_extension) {
89 break;
90 }
91 }
92 if (!support_any_extension) {
93 continue;
94 }
95
96 if (!(file_handler.poll_drop && file_handler.poll_drop(C, &file_handler))) {
97 continue;
98 }
99
100 result.append(&file_handler);
101 }
102 return result;
103}
104
106 const blender::Span<std::string> paths) const
107{
109
110 for (const int idx : paths.index_range()) {
111 const char *extension = BLI_path_extension(paths[idx].c_str());
112 if (!extension) {
113 continue;
114 }
115 auto test_fn = [extension](const std::string &test_extension) {
116 return BLI_strcaseeq(extension, test_extension.c_str()) == 1;
117 };
118
119 if (std::any_of(file_extensions.begin(), file_extensions.end(), test_fn)) {
120 indices.append(idx);
121 }
122 }
123 return indices;
124}
125
127{
128 /* Spaces are supported but do not allow all characters to be blank. */
129 const bool all_blank = name.is_empty() ||
130 std::all_of(name.begin(), name.end(), [](char c) { return c == ' '; });
131
132 char filename[FILE_MAXFILE];
133 STRNCPY(filename, all_blank ? "untitled" : name.c_str());
135 sizeof(filename),
136 file_extensions.is_empty() ? "" : file_extensions.first().c_str());
138
139 return filename;
140}
141
142} // namespace blender::bke
#define BLI_assert(a)
Definition BLI_assert.h:50
#define FILE_MAXFILE
bool BLI_path_extension_ensure(char *path, size_t path_maxncpy, const char *ext) ATTR_NONNULL(1
bool BLI_path_make_safe_filename(char *filename) ATTR_NONNULL(1)
const char * BLI_path_extension(const char *filepath) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
#define STRNCPY(dst, src)
Definition BLI_string.h:593
char char size_t char const char * BLI_strchr_or_end(const char *str, char ch) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1)
Definition string.c:927
int BLI_strcaseeq(const char *a, const char *b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
bool is_empty() const
void append_non_duplicates(const T &value)
const T & first() const
static ushort indices[]
FileHandlerType * file_handler_find(StringRef idname)
void file_handler_add(std::unique_ptr< FileHandlerType > file_handler)
static Vector< std::unique_ptr< FileHandlerType > > & file_handlers_vector()
blender::Vector< FileHandlerType * > file_handlers_poll_file_drop(const bContext *C, const blender::Span< std::string > paths)
void file_handler_remove(FileHandlerType *file_handler)
Span< std::unique_ptr< FileHandlerType > > file_handlers()
Vector< std::string > file_extensions
bool(* poll_drop)(const bContext *C, FileHandlerType *file_handle_type)
std::string get_default_filename(const StringRefNull name)
blender::Vector< int64_t > filter_supported_paths(const blender::Span< std::string > paths) const