Blender V5.0
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
12#include "BLT_translation.hh"
13
14namespace blender::bke {
15
21
26
28{
29 const auto *itr = std::find_if(file_handlers().begin(),
30 file_handlers().end(),
31 [idname](const std::unique_ptr<FileHandlerType> &file_handler) {
32 return idname == file_handler->idname;
33 });
34 if (itr != file_handlers().end()) {
35 return itr->get();
36 }
37 return nullptr;
38}
39
40void file_handler_add(std::unique_ptr<FileHandlerType> file_handler)
41{
42 BLI_assert(file_handler_find(file_handler->idname) == nullptr);
43
45 const char char_separator = ';';
46 const char *char_begin = file_handler->file_extensions_str;
47 const char *char_end = BLI_strchr_or_end(char_begin, char_separator);
48 while (char_begin[0]) {
49 if (char_end - char_begin > 1) {
50 std::string file_extension(char_begin, char_end - char_begin);
51 file_handler->file_extensions.append(file_extension);
52 }
53 char_begin = char_end[0] ? char_end + 1 : char_end;
54 char_end = BLI_strchr_or_end(char_begin, char_separator);
55 }
56
57 file_handlers_vector().append(std::move(file_handler));
58}
59
61{
62 file_handlers_vector().remove_if(
63 [file_handler](const std::unique_ptr<FileHandlerType> &test_file_handler) {
64 return test_file_handler.get() == file_handler;
65 });
66}
67
69 const bContext *C, const blender::Span<std::string> paths)
70{
71 blender::Vector<std::string> path_extensions;
72 for (const std::string &path : paths) {
73 const char *extension = BLI_path_extension(path.c_str());
74 if (!extension) {
75 continue;
76 }
77 path_extensions.append_non_duplicates(extension);
78 }
79
81 for (const std::unique_ptr<FileHandlerType> &file_handler_ptr : file_handlers()) {
82 FileHandlerType &file_handler = *file_handler_ptr;
83 const auto &file_extensions = file_handler.file_extensions;
84 bool support_any_extension = false;
85 for (const std::string &extension : path_extensions) {
86 auto test_fn = [&extension](const std::string &test_extension) {
87 return BLI_strcaseeq(extension.c_str(), test_extension.c_str()) == 1;
88 };
89 support_any_extension = std::any_of(file_extensions.begin(), file_extensions.end(), test_fn);
90 if (support_any_extension) {
91 break;
92 }
93 }
94 if (!support_any_extension) {
95 continue;
96 }
97
98 if (!(file_handler.poll_drop && file_handler.poll_drop(C, &file_handler))) {
99 continue;
100 }
101
102 result.append(&file_handler);
103 }
104 return result;
105}
106
108 const blender::Span<std::string> paths) const
109{
111
112 for (const int idx : paths.index_range()) {
113 const char *extension = BLI_path_extension(paths[idx].c_str());
114 if (!extension) {
115 continue;
116 }
117 auto test_fn = [extension](const std::string &test_extension) {
118 return BLI_strcaseeq(extension, test_extension.c_str()) == 1;
119 };
120
121 if (std::any_of(file_extensions.begin(), file_extensions.end(), test_fn)) {
122 indices.append(idx);
123 }
124 }
125 return indices;
126}
127
129{
130 /* Spaces are supported but do not allow all characters to be blank. */
131 const bool all_blank = name.is_empty() ||
132 std::all_of(name.begin(), name.end(), [](char c) { return c == ' '; });
133
134 char filename[FILE_MAXFILE];
135 STRNCPY(filename, all_blank ? DATA_("Untitled") : name.c_str());
137 sizeof(filename),
138 file_extensions.is_empty() ? "" : file_extensions.first().c_str());
140
141 return filename;
142}
143
144} // namespace blender::bke
#define BLI_assert(a)
Definition BLI_assert.h:46
#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
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.cc:931
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
int BLI_strcaseeq(const char *a, const char *b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
#define DATA_(msgid)
#define C
Definition RandGen.cpp:29
iter begin(iter)
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
void append_non_duplicates(const T &value)
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()
const char * name
std::string get_default_filename(StringRefNull name)
Vector< std::string > file_extensions
bool(* poll_drop)(const bContext *C, FileHandlerType *file_handle_type)
blender::Vector< int64_t > filter_supported_paths(const blender::Span< std::string > paths) const