1 /*
2 * libxlsxwriter
3 *
4 * Copyright 2014-2021, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5 */
6
7 /**
8 * @file common.h
9 *
10 * @brief Common functions and defines for the libxlsxwriter library.
11 *
12 * <!-- Copyright 2014-2021, John McNamara, jmcnamara@cpan.org -->
13 *
14 */
15 #ifndef __LXW_COMMON_H__
16 #define __LXW_COMMON_H__
17
18 #include <time.h>
19 #include "third_party/queue.h"
20 #include "third_party/tree.h"
21
22 #ifndef TESTING
23 #define STATIC static
24 #else
25 #define STATIC
26 #endif
27
28 #if __GNUC__ >= 5
29 #define DEPRECATED(func, msg) func __attribute__ ((deprecated(msg)))
30 #elif defined(_MSC_VER)
31 #define DEPRECATED(func, msg) __declspec(deprecated, msg) func
32 #else
33 #define DEPRECATED(func, msg) func
34 #endif
35
36 /** Integer data type to represent a row value. Equivalent to `uint32_t`.
37 *
38 * The maximum row in Excel is 1,048,576.
39 */
40 typedef uint32_t lxw_row_t;
41
42 /** Integer data type to represent a column value. Equivalent to `uint16_t`.
43 *
44 * The maximum column in Excel is 16,384.
45 */
46 typedef uint16_t lxw_col_t;
47
48 /** Boolean values used in libxlsxwriter. */
49 enum lxw_boolean {
50 /** False value. */
51 LXW_FALSE,
52 /** True value. */
53 LXW_TRUE,
54 /** False value. Used to turn off a property that is default on, in order
55 * to distinguish it from an uninitialized value. */
56 LXW_EXPLICIT_FALSE
57 };
58
59 /**
60 * @brief Error codes from libxlsxwriter functions.
61 *
62 * See the `lxw_strerror()` function for an example of how to convert the
63 * enum number to a descriptive error message string.
64 */
65 typedef enum lxw_error {
66
67 /** No error. */
68 LXW_NO_ERROR = 0,
69
70 /** Memory error, failed to malloc() required memory. */
71 LXW_ERROR_MEMORY_MALLOC_FAILED,
72
73 /** Error creating output xlsx file. Usually a permissions error. */
74 LXW_ERROR_CREATING_XLSX_FILE,
75
76 /** Error encountered when creating a tmpfile during file assembly. */
77 LXW_ERROR_CREATING_TMPFILE,
78
79 /** Error reading a tmpfile. */
80 LXW_ERROR_READING_TMPFILE,
81
82 /** Zip generic error ZIP_ERRNO while creating the xlsx file. */
83 LXW_ERROR_ZIP_FILE_OPERATION,
84
85 /** Zip error ZIP_PARAMERROR while creating the xlsx file. */
86 LXW_ERROR_ZIP_PARAMETER_ERROR,
87
88 /** Zip error ZIP_BADZIPFILE (use_zip64 option may be required). */
89 LXW_ERROR_ZIP_BAD_ZIP_FILE,
90
91 /** Zip error ZIP_INTERNALERROR while creating the xlsx file. */
92 LXW_ERROR_ZIP_INTERNAL_ERROR,
93
94 /** File error or unknown zip error when adding sub file to xlsx file. */
95 LXW_ERROR_ZIP_FILE_ADD,
96
97 /** Unknown zip error when closing xlsx file. */
98 LXW_ERROR_ZIP_CLOSE,
99
100 /** Feature is not currently supported in this configuration. */
101 LXW_ERROR_FEATURE_NOT_SUPPORTED,
102
103 /** NULL function parameter ignored. */
104 LXW_ERROR_NULL_PARAMETER_IGNORED,
105
106 /** Function parameter validation error. */
107 LXW_ERROR_PARAMETER_VALIDATION,
108
109 /** Worksheet name exceeds Excel's limit of 31 characters. */
110 LXW_ERROR_SHEETNAME_LENGTH_EXCEEDED,
111
112 /** Worksheet name cannot contain invalid characters: '[ ] : * ? / \\' */
113 LXW_ERROR_INVALID_SHEETNAME_CHARACTER,
114
115 /** Worksheet name cannot start or end with an apostrophe. */
116 LXW_ERROR_SHEETNAME_START_END_APOSTROPHE,
117
118 /** Worksheet name is already in use. */
119 LXW_ERROR_SHEETNAME_ALREADY_USED,
120
121 /** Parameter exceeds Excel's limit of 32 characters. */
122 LXW_ERROR_32_STRING_LENGTH_EXCEEDED,
123
124 /** Parameter exceeds Excel's limit of 128 characters. */
125 LXW_ERROR_128_STRING_LENGTH_EXCEEDED,
126
127 /** Parameter exceeds Excel's limit of 255 characters. */
128 LXW_ERROR_255_STRING_LENGTH_EXCEEDED,
129
130 /** String exceeds Excel's limit of 32,767 characters. */
131 LXW_ERROR_MAX_STRING_LENGTH_EXCEEDED,
132
133 /** Error finding internal string index. */
134 LXW_ERROR_SHARED_STRING_INDEX_NOT_FOUND,
135
136 /** Worksheet row or column index out of range. */
137 LXW_ERROR_WORKSHEET_INDEX_OUT_OF_RANGE,
138
139 /** Maximum hyperlink length (2079) exceeded. */
140 LXW_ERROR_WORKSHEET_MAX_URL_LENGTH_EXCEEDED,
141
142 /** Maximum number of worksheet URLs (65530) exceeded. */
143 LXW_ERROR_WORKSHEET_MAX_NUMBER_URLS_EXCEEDED,
144
145 /** Couldn't read image dimensions or DPI. */
146 LXW_ERROR_IMAGE_DIMENSIONS,
147
148 LXW_MAX_ERRNO
149 } lxw_error;
150
151 /** @brief Struct to represent a date and time in Excel.
152 *
153 * Struct to represent a date and time in Excel. See @ref working_with_dates.
154 */
155 typedef struct lxw_datetime {
156
157 /** Year : 1900 - 9999 */
158 int year;
159 /** Month : 1 - 12 */
160 int month;
161 /** Day : 1 - 31 */
162 int day;
163 /** Hour : 0 - 23 */
164 int hour;
165 /** Minute : 0 - 59 */
166 int min;
167 /** Seconds : 0 - 59.999 */
168 double sec;
169
170 } lxw_datetime;
171
172 enum lxw_custom_property_types {
173 LXW_CUSTOM_NONE,
174 LXW_CUSTOM_STRING,
175 LXW_CUSTOM_DOUBLE,
176 LXW_CUSTOM_INTEGER,
177 LXW_CUSTOM_BOOLEAN,
178 LXW_CUSTOM_DATETIME
179 };
180
181 /* Size of MD5 byte arrays. */
182 #define LXW_MD5_SIZE 16
183
184 /* Excel sheetname max of 31 chars. */
185 #define LXW_SHEETNAME_MAX 31
186
187 /* Max with all worksheet chars 4xUTF-8 bytes + start and end quotes + \0. */
188 #define LXW_MAX_SHEETNAME_LENGTH ((LXW_SHEETNAME_MAX * 4) + 2 + 1)
189
190 /* Max col string length. */
191 #define LXW_MAX_COL_NAME_LENGTH sizeof("$XFD")
192
193 /* Max row string length. */
194 #define LXW_MAX_ROW_NAME_LENGTH sizeof("$1048576")
195
196 /* Max cell string length. */
197 #define LXW_MAX_CELL_NAME_LENGTH sizeof("$XFWD$1048576")
198
199 /* Max range: $XFWD$1048576:$XFWD$1048576\0 */
200 #define LXW_MAX_CELL_RANGE_LENGTH (LXW_MAX_CELL_NAME_LENGTH * 2)
201
202 /* Max range formula Sheet1!$A$1:$C$5$ style. */
203 #define LXW_MAX_FORMULA_RANGE_LENGTH (LXW_MAX_SHEETNAME_LENGTH + LXW_MAX_CELL_RANGE_LENGTH)
204
205 /* Datetime string length. */
206 #define LXW_DATETIME_LENGTH sizeof("2016-12-12T23:00:00Z")
207
208 /* GUID string length. */
209 #define LXW_GUID_LENGTH sizeof("{12345678-1234-1234-1234-1234567890AB}\0")
210
211 #define LXW_EPOCH_1900 0
212 #define LXW_EPOCH_1904 1
213
214 #define LXW_UINT32_T_LENGTH sizeof("4294967296")
215 #define LXW_FILENAME_LENGTH 128
216 #define LXW_IGNORE 1
217
218 #define LXW_PORTRAIT 1
219 #define LXW_LANDSCAPE 0
220
221 #define LXW_SCHEMA_MS "http://schemas.microsoft.com/office/2006/relationships"
222 #define LXW_SCHEMA_ROOT "http://schemas.openxmlformats.org"
223 #define LXW_SCHEMA_DRAWING LXW_SCHEMA_ROOT "/drawingml/2006"
224 #define LXW_SCHEMA_OFFICEDOC LXW_SCHEMA_ROOT "/officeDocument/2006"
225 #define LXW_SCHEMA_PACKAGE LXW_SCHEMA_ROOT "/package/2006/relationships"
226 #define LXW_SCHEMA_DOCUMENT LXW_SCHEMA_ROOT "/officeDocument/2006/relationships"
227 #define LXW_SCHEMA_CONTENT LXW_SCHEMA_ROOT "/package/2006/content-types"
228
229 /* Use REprintf() for error handling when compiled as an R library. */
230 #ifdef USE_R_LANG
231 #include <R.h>
232 #define LXW_PRINTF REprintf
233 #define LXW_STDERR
234 #else
235 #define LXW_PRINTF fprintf
236 #define LXW_STDERR stderr,
237 #endif
238
239 #define LXW_ERROR(message) \
240 LXW_PRINTF(LXW_STDERR "[ERROR][%s:%d]: " message "\n", __FILE__, __LINE__)
241
242 #define LXW_MEM_ERROR() \
243 LXW_ERROR("Memory allocation failed.")
244
245 #define GOTO_LABEL_ON_MEM_ERROR(pointer, label) \
246 do { \
247 if (!pointer) { \
248 LXW_MEM_ERROR(); \
249 goto label; \
250 } \
251 } while (0)
252
253 #define RETURN_ON_MEM_ERROR(pointer, error) \
254 do { \
255 if (!pointer) { \
256 LXW_MEM_ERROR(); \
257 return error; \
258 } \
259 } while (0)
260
261 #define RETURN_VOID_ON_MEM_ERROR(pointer) \
262 do { \
263 if (!pointer) { \
264 LXW_MEM_ERROR(); \
265 return; \
266 } \
267 } while (0)
268
269 #define RETURN_ON_ERROR(error) \
270 do { \
271 if (error) \
272 return error; \
273 } while (0)
274
275 #define RETURN_AND_ZIPCLOSE_ON_ERROR(error) \
276 do { \
277 if (error) { \
278 zipClose(self->zipfile, NULL); \
279 return error; \
280 } \
281 } while (0)
282
283 #define LXW_WARN(message) \
284 LXW_PRINTF(LXW_STDERR "[WARNING]: " message "\n")
285
286 /* We can't use variadic macros here since we support ANSI C. */
287 #define LXW_WARN_FORMAT(message) \
288 LXW_PRINTF(LXW_STDERR "[WARNING]: " message "\n")
289
290 #define LXW_WARN_FORMAT1(message, var) \
291 LXW_PRINTF(LXW_STDERR "[WARNING]: " message "\n", var)
292
293 #define LXW_WARN_FORMAT2(message, var1, var2) \
294 LXW_PRINTF(LXW_STDERR "[WARNING]: " message "\n", var1, var2)
295
296 #define LXW_WARN_FORMAT3(message, var1, var2, var3) \
297 LXW_PRINTF(LXW_STDERR "[WARNING]: " message "\n", var1, var2, var3)
298
299 /* Chart axis type checks. */
300 #define LXW_WARN_CAT_AXIS_ONLY(function) \
301 do { \
302 if (!axis->is_category) { \
303 LXW_PRINTF(LXW_STDERR "[WARNING]: " \
304 function "() is only valid for category axes\n"); \
305 return; \
306 } \
307 } while (0)
308
309 #define LXW_WARN_VALUE_AXIS_ONLY(function) \
310 do { \
311 if (!axis->is_value) { \
312 LXW_PRINTF(LXW_STDERR "[WARNING]: " \
313 function "() is only valid for value axes\n"); \
314 return; \
315 } \
316 } while (0)
317
318 #define LXW_WARN_DATE_AXIS_ONLY(function) \
319 do { \
320 if (!axis->is_date) { \
321 LXW_PRINTF(LXW_STDERR "[WARNING]: " \
322 function "() is only valid for date axes\n"); \
323 return; \
324 } \
325 } while (0)
326
327 #define LXW_WARN_CAT_AND_DATE_AXIS_ONLY(function) \
328 do { \
329 if (!axis->is_category && !axis->is_date) { \
330 LXW_PRINTF(LXW_STDERR "[WARNING]: " \
331 function "() is only valid for category and date axes\n"); \
332 return; \
333 } \
334 } while (0)
335
336 #define LXW_WARN_VALUE_AND_DATE_AXIS_ONLY(function) \
337 do { \
338 if (!axis->is_value && !axis->is_date) { \
339 LXW_PRINTF(LXW_STDERR "[WARNING]: " \
340 function "() is only valid for value and date axes\n"); \
341 return; \
342 } \
343 } while (0)
344
345 #ifndef LXW_BIG_ENDIAN
346 #define LXW_UINT16_HOST(n) (n)
347 #define LXW_UINT32_HOST(n) (n)
348 #define LXW_UINT16_NETWORK(n) ((((n) & 0x00FF) << 8) | (((n) & 0xFF00) >> 8))
349 #define LXW_UINT32_NETWORK(n) ((((n) & 0xFF) << 24) | \
350 (((n) & 0xFF00) << 8) | \
351 (((n) & 0xFF0000) >> 8) | \
352 (((n) & 0xFF000000) >> 24))
353 #else
354 #define LXW_UINT16_NETWORK(n) (n)
355 #define LXW_UINT32_NETWORK(n) (n)
356 #define LXW_UINT16_HOST(n) ((((n) & 0x00FF) << 8) | (((n) & 0xFF00) >> 8))
357 #define LXW_UINT32_HOST(n) ((((n) & 0xFF) << 24) | \
358 (((n) & 0xFF00) << 8) | \
359 (((n) & 0xFF0000) >> 8) | \
360 (((n) & 0xFF000000) >> 24))
361 #endif
362
363 /* *INDENT-OFF* */
364 #ifdef __cplusplus
365 extern "C" {
366 #endif
367 /* *INDENT-ON* */
368
369 /* Compilers that have a native snprintf() can use it directly. */
370 #ifdef _MSC_VER
371 #define LXW_HAS_SNPRINTF
372 #endif
373
374 #ifdef LXW_HAS_SNPRINTF
375 #define lxw_snprintf snprintf
376 #else
377 #define lxw_snprintf __builtin_snprintf
378 #endif
379
380 /* Define a snprintf for MSVC 2010. */
381 #if defined(_MSC_VER) && _MSC_VER < 1900
382
383 #include <stdarg.h>
384 #define snprintf msvc2010_snprintf
385 #define vsnprintf msvc2010_vsnprintf
386
387 __inline int
msvc2010_vsnprintf(char * str,size_t size,const char * format,va_list ap)388 msvc2010_vsnprintf(char *str, size_t size, const char *format, va_list ap)
389 {
390 int count = -1;
391
392 if (size != 0)
393 count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
394 if (count == -1)
395 count = _vscprintf(format, ap);
396
397 return count;
398 }
399
400 __inline int
msvc2010_snprintf(char * str,size_t size,const char * format,...)401 msvc2010_snprintf(char *str, size_t size, const char *format, ...)
402 {
403 int count;
404 va_list ap;
405
406 va_start(ap, format);
407 count = msvc2010_vsnprintf(str, size, format, ap);
408 va_end(ap);
409
410 return count;
411 }
412
413 #endif
414
415 /* Safer strcpy for fixed width char arrays. */
416 #define lxw_strcpy(dest, src) \
417 lxw_snprintf(dest, sizeof(dest), "%s", src)
418
419 /* Define the queue.h structs for the formats list. */
420 STAILQ_HEAD(lxw_formats, lxw_format);
421
422 /* Define the queue.h structs for the generic data structs. */
423 STAILQ_HEAD(lxw_tuples, lxw_tuple);
424 STAILQ_HEAD(lxw_custom_properties, lxw_custom_property);
425
426 typedef struct lxw_tuple {
427 char *key;
428 char *value;
429
430 STAILQ_ENTRY (lxw_tuple) list_pointers;
431 } lxw_tuple;
432
433 /* Define custom property used in workbook.c and custom.c. */
434 typedef struct lxw_custom_property {
435
436 enum lxw_custom_property_types type;
437 char *name;
438
439 union {
440 char *string;
441 double number;
442 int32_t integer;
443 uint8_t boolean;
444 lxw_datetime datetime;
445 } u;
446
447 STAILQ_ENTRY (lxw_custom_property) list_pointers;
448
449 } lxw_custom_property;
450
451 /* Declarations required for unit testing. */
452 #ifdef TESTING
453
454 #endif /* TESTING */
455
456 /* *INDENT-OFF* */
457 #ifdef __cplusplus
458 }
459 #endif
460 /* *INDENT-ON* */
461
462 #endif /* __LXW_COMMON_H__ */
463