Blender V4.5
report.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cerrno>
10#include <cstdarg>
11#include <cstdio>
12#include <cstring>
13#include <mutex>
14
15#include "MEM_guardedalloc.h"
16
17#include "BLI_dynstr.h"
18#include "BLI_fileops.h"
19#include "BLI_listbase.h"
20#include "BLI_string.h"
21#include "BLI_string_utils.hh"
22#include "BLI_utildefines.h"
23
24#include "BLT_translation.hh"
25
26#include "BKE_global.hh" /* G.background only */
27#include "BKE_report.hh"
28
30{
31 switch (type) {
32 case RPT_DEBUG:
33 return RPT_("Debug");
34 case RPT_INFO:
35 return RPT_("Info");
36 case RPT_OPERATOR:
37 return RPT_("Operator");
38 case RPT_PROPERTY:
39 return RPT_("Property");
40 case RPT_WARNING:
41 return RPT_("Warning");
42 case RPT_ERROR:
43 return RPT_("Error");
45 return RPT_("Invalid Input Error");
47 return RPT_("Invalid Context Error");
49 return RPT_("Out Of Memory Error");
50 default:
51 return RPT_("Undefined Type");
52 }
53}
54
56{
57 if (!reports) {
58 return;
59 }
60
62
63 reports->storelevel = RPT_INFO;
64 reports->printlevel = RPT_ERROR;
65 reports->flag = flag;
66
67 reports->lock = MEM_new<std::mutex>(__func__);
68}
69
71{
72 if (!reports) {
73 return;
74 }
75
77
78 MEM_delete(reports->lock);
79 reports->lock = nullptr;
80}
81
83{
84 Report *report, *report_next;
85
86 if (!reports) {
87 return;
88 }
89
90 std::scoped_lock lock(*reports->lock);
91
92 report = static_cast<Report *>(reports->list.first);
93
94 while (report) {
95 report_next = report->next;
96 MEM_freeN(report->message);
97 MEM_freeN(report);
98 report = report_next;
99 }
100
102}
103
105{
106 reports->lock->lock();
107}
108
110{
111 reports->lock->unlock();
112}
113
114void BKE_reports_move_to_reports(ReportList *reports_dst, ReportList *reports_src)
115{
116 BLI_assert(reports_dst);
117 if (!reports_src) {
118 return;
119 }
120
121 std::scoped_lock lock(*reports_src->lock, *reports_dst->lock);
122
123 BLI_movelisttolist(&reports_dst->list, &reports_src->list);
124}
125
126void BKE_report(ReportList *reports, eReportType type, const char *_message)
127{
128 Report *report;
129 int len;
130 const char *message = RPT_(_message);
131
132 if (BKE_reports_print_test(reports, type)) {
133 printf("%s: %s\n", BKE_report_type_str(type), message);
134 fflush(stdout); /* this ensures the message is printed before a crash */
135 }
136
137 if (reports && (reports->flag & RPT_STORE) && (type >= reports->storelevel)) {
138 std::scoped_lock lock(*reports->lock);
139
140 char *message_alloc;
141 report = MEM_callocN<Report>("Report");
142 report->type = type;
143 report->typestr = BKE_report_type_str(type);
144
145 len = strlen(message);
146 message_alloc = MEM_malloc_arrayN<char>(size_t(len) + 1, "ReportMessage");
147 memcpy(message_alloc, message, sizeof(char) * (len + 1));
148 report->message = message_alloc;
149 report->len = len;
150 BLI_addtail(&reports->list, report);
151 }
152}
153
154void BKE_reportf(ReportList *reports, eReportType type, const char *_format, ...)
155{
156 Report *report;
157 va_list args;
158 const char *format = RPT_(_format);
159
160 if (BKE_reports_print_test(reports, type)) {
161 printf("%s: ", BKE_report_type_str(type));
162 va_start(args, _format);
163 vprintf(format, args);
164 va_end(args);
165 fprintf(stdout, "\n"); /* otherwise each report needs to include a \n */
166 fflush(stdout); /* this ensures the message is printed before a crash */
167 }
168
169 if (reports && (reports->flag & RPT_STORE) && (type >= reports->storelevel)) {
170 std::scoped_lock lock(*reports->lock);
171
172 report = MEM_callocN<Report>("Report");
173
174 va_start(args, _format);
175 report->message = BLI_vsprintfN(format, args);
176 va_end(args);
177
178 report->len = strlen(report->message);
179 report->type = type;
180 report->typestr = BKE_report_type_str(type);
181
182 BLI_addtail(&reports->list, report);
183 }
184}
185
189static void reports_prepend_impl(ReportList *reports, const char *prepend)
190{
191 /* Caller must ensure. */
192 BLI_assert(reports && reports->list.first);
193
194 std::scoped_lock lock(*reports->lock);
195
196 const size_t prefix_len = strlen(prepend);
197 LISTBASE_FOREACH (Report *, report, &reports->list) {
198 char *message = BLI_string_joinN(prepend, report->message);
199 MEM_freeN(report->message);
200 report->message = message;
201 report->len += prefix_len;
202 BLI_assert(report->len == strlen(message));
203 }
204}
205
206void BKE_reports_prepend(ReportList *reports, const char *prepend)
207{
208 if (!reports || !reports->list.first) {
209 return;
210 }
212}
213
214void BKE_reports_prependf(ReportList *reports, const char *prepend_format, ...)
215{
216 if (!reports || !reports->list.first) {
217 return;
218 }
219 va_list args;
220 va_start(args, prepend_format);
221 char *prepend = BLI_vsprintfN(RPT_(prepend_format), args);
222 va_end(args);
223
225
226 MEM_freeN(prepend);
227}
228
230{
231 if (!reports) {
232 return RPT_ERROR;
233 }
234
235 return eReportType(reports->printlevel);
236}
237
239{
240 if (!reports) {
241 return;
242 }
243
244 std::scoped_lock lock(*reports->lock);
245
246 reports->printlevel = level;
247}
248
250{
251 if (!reports) {
252 return RPT_ERROR;
253 }
254
255 return eReportType(reports->storelevel);
256}
257
259{
260 if (!reports) {
261 return;
262 }
263
264 std::scoped_lock lock(*reports->lock);
265
266 reports->storelevel = level;
267}
268
270{
271 DynStr *ds;
272 char *cstring;
273
274 if (!reports || !reports->list.first) {
275 return nullptr;
276 }
277
278 std::scoped_lock lock(*reports->lock);
279
280 ds = BLI_dynstr_new();
281 LISTBASE_FOREACH (Report *, report, &reports->list) {
282 if (report->type >= level) {
283 BLI_dynstr_appendf(ds, "%s: %s\n", report->typestr, report->message);
284 }
285 }
286
287 if (BLI_dynstr_get_len(ds)) {
288 cstring = BLI_dynstr_get_cstring(ds);
289 }
290 else {
291 cstring = nullptr;
292 }
293
294 BLI_dynstr_free(ds);
295 return cstring;
296}
297
299{
300 if (reports == nullptr) {
301 return true;
302 }
304 return false;
305 }
306 /* In background mode always print otherwise there are cases the errors won't be displayed,
307 * but still add to the report list since this is used for Python exception handling. */
308 if (G.background) {
309 return true;
310 }
311
312 /* Common case. */
313 return (reports->flag & RPT_PRINT) && (type >= reports->printlevel);
314}
315
317{
318 char *cstring = BKE_reports_string(reports, level);
319
320 if (cstring == nullptr) {
321 return;
322 }
323
324 /* A trailing newline is already part of `cstring`. */
325 fputs(cstring, stdout);
326 fflush(stdout);
327 MEM_freeN(cstring);
328}
329
331{
332 std::scoped_lock lock(*reports->lock);
333
334 LISTBASE_FOREACH_BACKWARD (Report *, report, &reports->list) {
335 if (ELEM(report->type, RPT_ERROR, RPT_WARNING, RPT_INFO)) {
336 return report;
337 }
338 }
339
340 return nullptr;
341}
342
344{
345 if (reports != nullptr) {
346 std::scoped_lock lock(*reports->lock);
347
348 LISTBASE_FOREACH (Report *, report, &reports->list) {
349 if (report->type >= level) {
350 return true;
351 }
352 }
353 }
354 return false;
355}
356
357bool BKE_report_write_file_fp(FILE *fp, ReportList *reports, const char *header)
358{
359 if (header) {
360 fputs(header, fp);
361 }
362
363 std::scoped_lock lock(*reports->lock);
364
365 LISTBASE_FOREACH (Report *, report, &reports->list) {
366 fprintf(fp, "%s # %s\n", report->message, report->typestr);
367 }
368
369 return true;
370}
371
372bool BKE_report_write_file(const char *filepath, ReportList *reports, const char *header)
373{
374 FILE *fp;
375
376 errno = 0;
377 fp = BLI_fopen(filepath, "wb");
378 if (fp == nullptr) {
379 fprintf(stderr,
380 "Unable to save '%s': %s\n",
381 filepath,
382 errno ? strerror(errno) : "Unknown error opening file");
383 return false;
384 }
385
387
388 fclose(fp);
389
390 return true;
391}
#define BLI_assert(a)
Definition BLI_assert.h:46
A dynamically sized string ADT.
char * BLI_dynstr_get_cstring(const DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
int BLI_dynstr_get_len(const DynStr *ds) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_dynstr.cc:36
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
File and directory operations.
FILE * BLI_fopen(const char *filepath, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void void void BLI_movelisttolist(ListBase *dst, ListBase *src) ATTR_NONNULL(1
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
char char * BLI_vsprintfN(const char *__restrict format, va_list args) ATTR_NONNULL(1
#define BLI_string_joinN(...)
#define ELEM(...)
#define RPT_(msgid)
@ RPT_PRINT_HANDLED_BY_OWNER
@ RPT_ERROR_OUT_OF_MEMORY
@ RPT_ERROR_INVALID_INPUT
@ RPT_ERROR_INVALID_CONTEXT
Read Guarded memory(de)allocation.
ReportList * reports
Definition WM_types.hh:1025
volatile int lock
#define printf(...)
format
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
bool BKE_reports_contain(ReportList *reports, eReportType level)
Definition report.cc:343
void BKE_reports_unlock(ReportList *reports)
Definition report.cc:109
bool BKE_reports_print_test(const ReportList *reports, eReportType type)
Definition report.cc:298
eReportType BKE_report_store_level(ReportList *reports)
Definition report.cc:249
bool BKE_report_write_file(const char *filepath, ReportList *reports, const char *header)
Definition report.cc:372
char * BKE_reports_string(ReportList *reports, eReportType level)
Definition report.cc:269
static void reports_prepend_impl(ReportList *reports, const char *prepend)
Definition report.cc:189
bool BKE_report_write_file_fp(FILE *fp, ReportList *reports, const char *header)
Definition report.cc:357
Report * BKE_reports_last_displayable(ReportList *reports)
Definition report.cc:330
void BKE_reports_free(ReportList *reports)
Definition report.cc:70
const char * BKE_report_type_str(eReportType type)
Definition report.cc:29
void BKE_reports_prepend(ReportList *reports, const char *prepend)
Definition report.cc:206
void BKE_report_print_level_set(ReportList *reports, eReportType level)
Definition report.cc:238
void BKE_report_store_level_set(ReportList *reports, eReportType level)
Definition report.cc:258
eReportType BKE_report_print_level(ReportList *reports)
Definition report.cc:229
void BKE_reports_clear(ReportList *reports)
Definition report.cc:82
void BKE_reportf(ReportList *reports, eReportType type, const char *_format,...)
Definition report.cc:154
void BKE_report(ReportList *reports, eReportType type, const char *_message)
Definition report.cc:126
void BKE_reports_prependf(ReportList *reports, const char *prepend_format,...)
Definition report.cc:214
void BKE_reports_lock(ReportList *reports)
Definition report.cc:104
void BKE_reports_init(ReportList *reports, int flag)
Definition report.cc:55
void BKE_reports_print(ReportList *reports, eReportType level)
Definition report.cc:316
void BKE_reports_move_to_reports(ReportList *reports_dst, ReportList *reports_src)
Definition report.cc:114
std_mutex_type * lock
struct Report * next
const char * typestr
const char * message
uint len
uint8_t flag
Definition wm_window.cc:139