kmadej_fast_excel_fork 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.travis.yml +28 -0
- data/CHANGELOG.md +13 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +70 -0
- data/Makefile +14 -0
- data/README.md +95 -0
- data/Rakefile +24 -0
- data/appveyor.yml +25 -0
- data/benchmarks/1k_rows.rb +59 -0
- data/benchmarks/20k_rows.rb +26 -0
- data/benchmarks/init.rb +59 -0
- data/benchmarks/memory.rb +49 -0
- data/examples/example.rb +42 -0
- data/examples/example_align.rb +23 -0
- data/examples/example_chart.rb +21 -0
- data/examples/example_colors.rb +37 -0
- data/examples/example_formula.rb +18 -0
- data/examples/example_image.rb +13 -0
- data/examples/example_styles.rb +27 -0
- data/examples/logo.png +0 -0
- data/extconf.rb +0 -0
- data/fast_excel.gemspec +20 -0
- data/lib/fast_excel.rb +600 -0
- data/lib/fast_excel/binding.rb +2819 -0
- data/lib/fast_excel/binding/chart.rb +2666 -0
- data/lib/fast_excel/binding/format.rb +1177 -0
- data/lib/fast_excel/binding/workbook.rb +338 -0
- data/lib/fast_excel/binding/worksheet.rb +1555 -0
- data/libxlsxwriter/.gitignore +49 -0
- data/libxlsxwriter/.indent.pro +125 -0
- data/libxlsxwriter/.travis.yml +25 -0
- data/libxlsxwriter/CONTRIBUTING.md +226 -0
- data/libxlsxwriter/Changes.txt +557 -0
- data/libxlsxwriter/LICENSE.txt +89 -0
- data/libxlsxwriter/Makefile +156 -0
- data/libxlsxwriter/Readme.md +78 -0
- data/libxlsxwriter/cocoapods/libxlsxwriter-umbrella.h +30 -0
- data/libxlsxwriter/cocoapods/libxlsxwriter.modulemap +7 -0
- data/libxlsxwriter/include/xlsxwriter.h +23 -0
- data/libxlsxwriter/include/xlsxwriter/app.h +79 -0
- data/libxlsxwriter/include/xlsxwriter/chart.h +3476 -0
- data/libxlsxwriter/include/xlsxwriter/common.h +372 -0
- data/libxlsxwriter/include/xlsxwriter/content_types.h +74 -0
- data/libxlsxwriter/include/xlsxwriter/core.h +51 -0
- data/libxlsxwriter/include/xlsxwriter/custom.h +52 -0
- data/libxlsxwriter/include/xlsxwriter/drawing.h +111 -0
- data/libxlsxwriter/include/xlsxwriter/format.h +1214 -0
- data/libxlsxwriter/include/xlsxwriter/hash_table.h +76 -0
- data/libxlsxwriter/include/xlsxwriter/packager.h +80 -0
- data/libxlsxwriter/include/xlsxwriter/relationships.h +77 -0
- data/libxlsxwriter/include/xlsxwriter/shared_strings.h +83 -0
- data/libxlsxwriter/include/xlsxwriter/styles.h +77 -0
- data/libxlsxwriter/include/xlsxwriter/theme.h +47 -0
- data/libxlsxwriter/include/xlsxwriter/third_party/ioapi.h +214 -0
- data/libxlsxwriter/include/xlsxwriter/third_party/queue.h +694 -0
- data/libxlsxwriter/include/xlsxwriter/third_party/tmpfileplus.h +53 -0
- data/libxlsxwriter/include/xlsxwriter/third_party/tree.h +801 -0
- data/libxlsxwriter/include/xlsxwriter/third_party/zip.h +375 -0
- data/libxlsxwriter/include/xlsxwriter/utility.h +166 -0
- data/libxlsxwriter/include/xlsxwriter/workbook.h +757 -0
- data/libxlsxwriter/include/xlsxwriter/worksheet.h +2641 -0
- data/libxlsxwriter/include/xlsxwriter/xmlwriter.h +178 -0
- data/libxlsxwriter/lib/.gitignore +0 -0
- data/libxlsxwriter/libxlsxwriter.podspec +47 -0
- data/libxlsxwriter/src/Makefile +130 -0
- data/libxlsxwriter/src/app.c +443 -0
- data/libxlsxwriter/src/chart.c +6346 -0
- data/libxlsxwriter/src/content_types.c +345 -0
- data/libxlsxwriter/src/core.c +293 -0
- data/libxlsxwriter/src/custom.c +224 -0
- data/libxlsxwriter/src/drawing.c +746 -0
- data/libxlsxwriter/src/format.c +729 -0
- data/libxlsxwriter/src/hash_table.c +223 -0
- data/libxlsxwriter/src/packager.c +948 -0
- data/libxlsxwriter/src/relationships.c +245 -0
- data/libxlsxwriter/src/shared_strings.c +266 -0
- data/libxlsxwriter/src/styles.c +1088 -0
- data/libxlsxwriter/src/theme.c +348 -0
- data/libxlsxwriter/src/utility.c +515 -0
- data/libxlsxwriter/src/workbook.c +1930 -0
- data/libxlsxwriter/src/worksheet.c +5022 -0
- data/libxlsxwriter/src/xmlwriter.c +355 -0
- data/libxlsxwriter/third_party/minizip/Makefile +44 -0
- data/libxlsxwriter/third_party/minizip/Makefile.am +45 -0
- data/libxlsxwriter/third_party/minizip/Makefile.orig +25 -0
- data/libxlsxwriter/third_party/minizip/MiniZip64_Changes.txt +6 -0
- data/libxlsxwriter/third_party/minizip/MiniZip64_info.txt +74 -0
- data/libxlsxwriter/third_party/minizip/README.txt +5 -0
- data/libxlsxwriter/third_party/minizip/configure.ac +32 -0
- data/libxlsxwriter/third_party/minizip/crypt.h +131 -0
- data/libxlsxwriter/third_party/minizip/ioapi.c +247 -0
- data/libxlsxwriter/third_party/minizip/ioapi.h +208 -0
- data/libxlsxwriter/third_party/minizip/iowin32.c +456 -0
- data/libxlsxwriter/third_party/minizip/iowin32.h +28 -0
- data/libxlsxwriter/third_party/minizip/make_vms.com +25 -0
- data/libxlsxwriter/third_party/minizip/miniunz.c +660 -0
- data/libxlsxwriter/third_party/minizip/miniunzip.1 +63 -0
- data/libxlsxwriter/third_party/minizip/minizip.1 +46 -0
- data/libxlsxwriter/third_party/minizip/minizip.c +520 -0
- data/libxlsxwriter/third_party/minizip/minizip.pc.in +12 -0
- data/libxlsxwriter/third_party/minizip/mztools.c +291 -0
- data/libxlsxwriter/third_party/minizip/mztools.h +37 -0
- data/libxlsxwriter/third_party/minizip/unzip.c +2125 -0
- data/libxlsxwriter/third_party/minizip/unzip.h +437 -0
- data/libxlsxwriter/third_party/minizip/zip.c +2007 -0
- data/libxlsxwriter/third_party/minizip/zip.h +367 -0
- data/libxlsxwriter/third_party/tmpfileplus/Makefile +42 -0
- data/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.c +342 -0
- data/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.h +53 -0
- data/libxlsxwriter/version.txt +1 -0
- data/test/date_test.rb +22 -0
- data/test/default_format_test.rb +19 -0
- data/test/format_test.rb +171 -0
- data/test/test_helper.rb +52 -0
- data/test/tmpfile_test.rb +23 -0
- data/test/worksheet_test.rb +86 -0
- metadata +182 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* libxlsxwriter
|
|
3
|
+
*
|
|
4
|
+
* Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
|
5
|
+
*
|
|
6
|
+
* xmlwriter - A libxlsxwriter library for creating Excel XLSX
|
|
7
|
+
* XML files.
|
|
8
|
+
*
|
|
9
|
+
* The xmlwriter library is used to create the XML sub-components files
|
|
10
|
+
* in the Excel XLSX file format.
|
|
11
|
+
*
|
|
12
|
+
* This library is used in preference to a more generic XML library to allow
|
|
13
|
+
* for customization and optimization for the XLSX file format.
|
|
14
|
+
*
|
|
15
|
+
* The xmlwriter functions are only used internally and do not need to be
|
|
16
|
+
* called directly by the end user.
|
|
17
|
+
*
|
|
18
|
+
*/
|
|
19
|
+
#ifndef __XMLWRITER_H__
|
|
20
|
+
#define __XMLWRITER_H__
|
|
21
|
+
|
|
22
|
+
#include <stdio.h>
|
|
23
|
+
#include <stdlib.h>
|
|
24
|
+
#include <stdint.h>
|
|
25
|
+
#include "common.h"
|
|
26
|
+
|
|
27
|
+
#define LXW_MAX_ATTRIBUTE_LENGTH 256
|
|
28
|
+
#define LXW_ATTR_32 32
|
|
29
|
+
|
|
30
|
+
#define LXW_ATTRIBUTE_COPY(dst, src) \
|
|
31
|
+
do{ \
|
|
32
|
+
strncpy(dst, src, LXW_MAX_ATTRIBUTE_LENGTH -1); \
|
|
33
|
+
dst[LXW_MAX_ATTRIBUTE_LENGTH - 1] = '\0'; \
|
|
34
|
+
} while (0)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
/* *INDENT-OFF* */
|
|
38
|
+
#ifdef __cplusplus
|
|
39
|
+
extern "C" {
|
|
40
|
+
#endif
|
|
41
|
+
/* *INDENT-ON* */
|
|
42
|
+
|
|
43
|
+
/* Attribute used in XML elements. */
|
|
44
|
+
struct xml_attribute {
|
|
45
|
+
char key[LXW_MAX_ATTRIBUTE_LENGTH];
|
|
46
|
+
char value[LXW_MAX_ATTRIBUTE_LENGTH];
|
|
47
|
+
|
|
48
|
+
/* Make the struct a queue.h list element. */
|
|
49
|
+
STAILQ_ENTRY (xml_attribute) list_entries;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/* Use queue.h macros to define the xml_attribute_list type. */
|
|
53
|
+
STAILQ_HEAD(xml_attribute_list, xml_attribute);
|
|
54
|
+
|
|
55
|
+
/* Create a new attribute struct to add to a xml_attribute_list. */
|
|
56
|
+
struct xml_attribute *lxw_new_attribute_str(const char *key,
|
|
57
|
+
const char *value);
|
|
58
|
+
struct xml_attribute *lxw_new_attribute_int(const char *key, uint32_t value);
|
|
59
|
+
struct xml_attribute *lxw_new_attribute_dbl(const char *key, double value);
|
|
60
|
+
|
|
61
|
+
/* Macro to initialize the xml_attribute_list pointers. */
|
|
62
|
+
#define LXW_INIT_ATTRIBUTES() \
|
|
63
|
+
STAILQ_INIT(&attributes)
|
|
64
|
+
|
|
65
|
+
/* Macro to add attribute string elements to xml_attribute_list. */
|
|
66
|
+
#define LXW_PUSH_ATTRIBUTES_STR(key, value) \
|
|
67
|
+
do { \
|
|
68
|
+
attribute = lxw_new_attribute_str((key), (value)); \
|
|
69
|
+
STAILQ_INSERT_TAIL(&attributes, attribute, list_entries); \
|
|
70
|
+
} while (0)
|
|
71
|
+
|
|
72
|
+
/* Macro to add attribute int values to xml_attribute_list. */
|
|
73
|
+
#define LXW_PUSH_ATTRIBUTES_INT(key, value) \
|
|
74
|
+
do { \
|
|
75
|
+
attribute = lxw_new_attribute_int((key), (value)); \
|
|
76
|
+
STAILQ_INSERT_TAIL(&attributes, attribute, list_entries); \
|
|
77
|
+
} while (0)
|
|
78
|
+
|
|
79
|
+
/* Macro to add attribute double values to xml_attribute_list. */
|
|
80
|
+
#define LXW_PUSH_ATTRIBUTES_DBL(key, value) \
|
|
81
|
+
do { \
|
|
82
|
+
attribute = lxw_new_attribute_dbl((key), (value)); \
|
|
83
|
+
STAILQ_INSERT_TAIL(&attributes, attribute, list_entries); \
|
|
84
|
+
} while (0)
|
|
85
|
+
|
|
86
|
+
/* Macro to free xml_attribute_list and attribute. */
|
|
87
|
+
#define LXW_FREE_ATTRIBUTES() \
|
|
88
|
+
while (!STAILQ_EMPTY(&attributes)) { \
|
|
89
|
+
attribute = STAILQ_FIRST(&attributes); \
|
|
90
|
+
STAILQ_REMOVE_HEAD(&attributes, list_entries); \
|
|
91
|
+
free(attribute); \
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Create the XML declaration in an XML file.
|
|
96
|
+
*
|
|
97
|
+
* @param xmlfile A FILE pointer to the output XML file.
|
|
98
|
+
*/
|
|
99
|
+
void lxw_xml_declaration(FILE * xmlfile);
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Write an XML start tag with optional attributes.
|
|
103
|
+
*
|
|
104
|
+
* @param xmlfile A FILE pointer to the output XML file.
|
|
105
|
+
* @param tag The XML tag to write.
|
|
106
|
+
* @param attributes An optional list of attributes to add to the tag.
|
|
107
|
+
*/
|
|
108
|
+
void lxw_xml_start_tag(FILE * xmlfile,
|
|
109
|
+
const char *tag,
|
|
110
|
+
struct xml_attribute_list *attributes);
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Write an XML start tag with optional un-encoded attributes.
|
|
114
|
+
* This is a minor optimization for attributes that don't need encoding.
|
|
115
|
+
*
|
|
116
|
+
* @param xmlfile A FILE pointer to the output XML file.
|
|
117
|
+
* @param tag The XML tag to write.
|
|
118
|
+
* @param attributes An optional list of attributes to add to the tag.
|
|
119
|
+
*/
|
|
120
|
+
void lxw_xml_start_tag_unencoded(FILE * xmlfile,
|
|
121
|
+
const char *tag,
|
|
122
|
+
struct xml_attribute_list *attributes);
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Write an XML end tag.
|
|
126
|
+
*
|
|
127
|
+
* @param xmlfile A FILE pointer to the output XML file.
|
|
128
|
+
* @param tag The XML tag to write.
|
|
129
|
+
*/
|
|
130
|
+
void lxw_xml_end_tag(FILE * xmlfile, const char *tag);
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Write an XML empty tag with optional attributes.
|
|
134
|
+
*
|
|
135
|
+
* @param xmlfile A FILE pointer to the output XML file.
|
|
136
|
+
* @param tag The XML tag to write.
|
|
137
|
+
* @param attributes An optional list of attributes to add to the tag.
|
|
138
|
+
*/
|
|
139
|
+
void lxw_xml_empty_tag(FILE * xmlfile,
|
|
140
|
+
const char *tag,
|
|
141
|
+
struct xml_attribute_list *attributes);
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Write an XML empty tag with optional un-encoded attributes.
|
|
145
|
+
* This is a minor optimization for attributes that don't need encoding.
|
|
146
|
+
*
|
|
147
|
+
* @param xmlfile A FILE pointer to the output XML file.
|
|
148
|
+
* @param tag The XML tag to write.
|
|
149
|
+
* @param attributes An optional list of attributes to add to the tag.
|
|
150
|
+
*/
|
|
151
|
+
void lxw_xml_empty_tag_unencoded(FILE * xmlfile,
|
|
152
|
+
const char *tag,
|
|
153
|
+
struct xml_attribute_list *attributes);
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Write an XML element containing data and optional attributes.
|
|
157
|
+
*
|
|
158
|
+
* @param xmlfile A FILE pointer to the output XML file.
|
|
159
|
+
* @param tag The XML tag to write.
|
|
160
|
+
* @param data The data section of the XML element.
|
|
161
|
+
* @param attributes An optional list of attributes to add to the tag.
|
|
162
|
+
*/
|
|
163
|
+
void lxw_xml_data_element(FILE * xmlfile,
|
|
164
|
+
const char *tag,
|
|
165
|
+
const char *data,
|
|
166
|
+
struct xml_attribute_list *attributes);
|
|
167
|
+
|
|
168
|
+
char *lxw_escape_control_characters(const char *string);
|
|
169
|
+
|
|
170
|
+
char *lxw_escape_data(const char *data);
|
|
171
|
+
|
|
172
|
+
/* *INDENT-OFF* */
|
|
173
|
+
#ifdef __cplusplus
|
|
174
|
+
}
|
|
175
|
+
#endif
|
|
176
|
+
/* *INDENT-ON* */
|
|
177
|
+
|
|
178
|
+
#endif /* __XMLWRITER_H__ */
|
|
File without changes
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
Pod::Spec.new do |s|
|
|
2
|
+
s.name = "libxlsxwriter"
|
|
3
|
+
s.version = "0.6.9"
|
|
4
|
+
s.summary = "Libxlsxwriter: A C library for creating Excel XLSX files."
|
|
5
|
+
s.ios.deployment_target = "6.0"
|
|
6
|
+
s.osx.deployment_target = "10.8"
|
|
7
|
+
|
|
8
|
+
s.description = <<-DESC
|
|
9
|
+
Libxlsxwriter is a C library that can be used to write text, numbers, formulas and hyperlinks to multiple worksheets in an Excel 2007+ XLSX file.
|
|
10
|
+
|
|
11
|
+
It supports features such as:
|
|
12
|
+
|
|
13
|
+
* 100% compatible Excel XLSX files.
|
|
14
|
+
* Full Excel formatting.
|
|
15
|
+
* Merged cells.
|
|
16
|
+
* Defined names.
|
|
17
|
+
* Autofilters.
|
|
18
|
+
* Charts.
|
|
19
|
+
* Worksheet PNG/JPEG images.
|
|
20
|
+
* Memory optimisation mode for writing large files.
|
|
21
|
+
* Source code available on [GitHub](https://github.com/jmcnamara/libxlsxwriter).
|
|
22
|
+
* FreeBSD license.
|
|
23
|
+
* ANSI C.
|
|
24
|
+
* Works with GCC, Clang, Xcode, MSVC 2015, ICC, TCC, MinGW, MingGW-w64/32.
|
|
25
|
+
* Works on Linux, FreeBSD, OpenBSD, OS X, iOS and Windows. Also works on MSYS/MSYS2 and Cygwin.
|
|
26
|
+
* Compiles for 32 and 64 bit.
|
|
27
|
+
* The only dependency is on `zlib`.
|
|
28
|
+
DESC
|
|
29
|
+
|
|
30
|
+
s.homepage = "http://libxlsxwriter.github.io"
|
|
31
|
+
s.documentation_url = "http://libxlsxwriter.github.io"
|
|
32
|
+
s.license = "FreeBSD"
|
|
33
|
+
s.author = { "John McNamara" => "jmcnamara@cpan.org" }
|
|
34
|
+
|
|
35
|
+
s.source = { :git => "https://github.com/jmcnamara/libxlsxwriter.git", :tag => "RELEASE_" + s.version.to_s }
|
|
36
|
+
s.source_files = "src/**/*.c", "third_party/**/{zip.c,ioapi.c,tmpfileplus.c}", "include/**/*.h"
|
|
37
|
+
|
|
38
|
+
s.header_dir = "xlsxwriter"
|
|
39
|
+
s.header_mappings_dir = "include/xlsxwriter"
|
|
40
|
+
s.library = "z"
|
|
41
|
+
s.compiler_flags = "-DNOCRYPT=1", "-DNOUNCRYPT=1"
|
|
42
|
+
s.pod_target_xcconfig = { 'USER_HEADER_SEARCH_PATHS' => '${PODS_ROOT}/libxlsxwriter/include' }
|
|
43
|
+
s.module_map = "cocoapods/libxlsxwriter.modulemap"
|
|
44
|
+
s.prepare_command = <<-CMD
|
|
45
|
+
cp cocoapods/libxlsxwriter-umbrella.h include/xlsxwriter/libxlsxwriter-umbrella.h
|
|
46
|
+
CMD
|
|
47
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
#
|
|
3
|
+
# Makefile for libxlsxwriter library.
|
|
4
|
+
#
|
|
5
|
+
# Copyright 2014-2017, John McNamara, jmcnamara@cpan.org
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
# Keep the output quiet by default.
|
|
9
|
+
Q=@
|
|
10
|
+
ifdef V
|
|
11
|
+
Q=
|
|
12
|
+
endif
|
|
13
|
+
|
|
14
|
+
# Directory variables.
|
|
15
|
+
OBJS_DIR = .
|
|
16
|
+
INC_DIR = ../include
|
|
17
|
+
|
|
18
|
+
# The minizip directory.
|
|
19
|
+
MINIZIP_DIR = ../third_party/minizip
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
ifdef USE_STANDARD_TMPFILE
|
|
23
|
+
# Use standard/C tmpfile().
|
|
24
|
+
CFLAGS += -DUSE_STANDARD_TMPFILE
|
|
25
|
+
else
|
|
26
|
+
# Use tmpfileplus (the default).
|
|
27
|
+
TMPFILEPLUS_DIR = ../third_party/tmpfileplus
|
|
28
|
+
TMPFILEPLUS_OBJ = $(TMPFILEPLUS_DIR)/tmpfileplus.o
|
|
29
|
+
TMPFILEPLUS_SO = $(TMPFILEPLUS_DIR)/tmpfileplus.so
|
|
30
|
+
endif
|
|
31
|
+
|
|
32
|
+
# Flags passed to compiler.
|
|
33
|
+
CFLAGS += -g -O3 -Wall -Wextra -pedantic -ansi
|
|
34
|
+
|
|
35
|
+
# Ignore icc remarks about inlining limits.
|
|
36
|
+
ifeq ($(CC),icc)
|
|
37
|
+
CFLAGS +=-diag-disable=11074,11076
|
|
38
|
+
endif
|
|
39
|
+
|
|
40
|
+
# Library names.
|
|
41
|
+
LIBXLSXWRITER_A = libxlsxwriter.a
|
|
42
|
+
LIBXLSXWRITER_SO = libxlsxwriter.so
|
|
43
|
+
|
|
44
|
+
# Library with additional non-static functions for testing.
|
|
45
|
+
LIBXLSXWRITER_TO = libxlsxwriter_test.a
|
|
46
|
+
|
|
47
|
+
# Flags passed to static linker.
|
|
48
|
+
ARFLAGS = rc
|
|
49
|
+
|
|
50
|
+
# Flags passed to dynamic linker.
|
|
51
|
+
FPIC = -fPIC
|
|
52
|
+
SOFLAGS = -shared $(FPIC)
|
|
53
|
+
|
|
54
|
+
# Get Env/OS name.
|
|
55
|
+
UNAME := $(shell uname)
|
|
56
|
+
|
|
57
|
+
# Change make options on OS X.
|
|
58
|
+
ifeq ($(UNAME), Darwin)
|
|
59
|
+
LIBXLSXWRITER_SO = libxlsxwriter.dylib
|
|
60
|
+
SOFLAGS = -dynamiclib $(FPIC) -install_name /usr/lib/$(LIBXLSXWRITER_SO)
|
|
61
|
+
endif
|
|
62
|
+
|
|
63
|
+
# Check for MinGW/MinGW64/Cygwin environments.
|
|
64
|
+
ifneq (,$(findstring MINGW, $(UNAME)))
|
|
65
|
+
MING_LIKE = y
|
|
66
|
+
endif
|
|
67
|
+
ifneq (,$(findstring MSYS, $(UNAME)))
|
|
68
|
+
MING_LIKE = y
|
|
69
|
+
endif
|
|
70
|
+
ifneq (,$(findstring CYGWIN, $(UNAME)))
|
|
71
|
+
MING_LIKE = y
|
|
72
|
+
endif
|
|
73
|
+
|
|
74
|
+
# Change make options on MinGW/MinGW64/Cygwin.
|
|
75
|
+
ifdef MING_LIKE
|
|
76
|
+
LIBXLSXWRITER_SO = libxlsxwriter.dll
|
|
77
|
+
FPIC =
|
|
78
|
+
CC = gcc
|
|
79
|
+
CFLAGS += -Wno-char-subscripts -Wno-long-long
|
|
80
|
+
endif
|
|
81
|
+
|
|
82
|
+
# Headers as dependecies.
|
|
83
|
+
HDRS = $(wildcard ../include/xlsxwriter/*.h)
|
|
84
|
+
|
|
85
|
+
# Ojects to compile.
|
|
86
|
+
SRCS = $(wildcard *.c)
|
|
87
|
+
OBJS = $(patsubst %.c,%.o,$(SRCS))
|
|
88
|
+
SOBJS = $(patsubst %.c,%.so,$(SRCS))
|
|
89
|
+
TOBJS = $(patsubst %.c,%.to,$(SRCS))
|
|
90
|
+
# End of OBJS
|
|
91
|
+
|
|
92
|
+
# Build the object files and the libraries.
|
|
93
|
+
all : $(LIBXLSXWRITER_A) $(LIBXLSXWRITER_SO)
|
|
94
|
+
$(Q)cp $(LIBXLSXWRITER_A) $(LIBXLSXWRITER_SO) ../lib
|
|
95
|
+
|
|
96
|
+
test_lib : libxlsxwriter_test.a
|
|
97
|
+
|
|
98
|
+
# The static library.
|
|
99
|
+
$(LIBXLSXWRITER_A) : $(OBJS)
|
|
100
|
+
$(Q)$(AR) $(ARFLAGS) $@ $(MINIZIP_DIR)/ioapi.o $(MINIZIP_DIR)/zip.o $(TMPFILEPLUS_OBJ) $^
|
|
101
|
+
|
|
102
|
+
# The dynamic library.
|
|
103
|
+
ifeq ($(findstring m32,$(CFLAGS)),m32)
|
|
104
|
+
ARCH = -m32
|
|
105
|
+
endif
|
|
106
|
+
|
|
107
|
+
$(LIBXLSXWRITER_SO) : $(SOBJS)
|
|
108
|
+
$(Q)$(CC) $(SOFLAGS) $(ARCH) -o $@ $(MINIZIP_DIR)/ioapi.so $(MINIZIP_DIR)/zip.so $(TMPFILEPLUS_SO) $^ -lz
|
|
109
|
+
|
|
110
|
+
# The test library.
|
|
111
|
+
$(LIBXLSXWRITER_TO) : $(TOBJS)
|
|
112
|
+
$(Q)$(AR) $(ARFLAGS) $@ $(MINIZIP_DIR)/ioapi.o $(MINIZIP_DIR)/zip.o $(TMPFILEPLUS_OBJ) $^
|
|
113
|
+
|
|
114
|
+
# Minimal target for quick compile without creating the libs.
|
|
115
|
+
test_compile : $(OBJS)
|
|
116
|
+
|
|
117
|
+
# Targets for the object files.
|
|
118
|
+
%.o : %.c $(HDRS)
|
|
119
|
+
$(Q)$(CC) -I$(INC_DIR) $(CFLAGS) $(CXXFLAGS) -c $<
|
|
120
|
+
|
|
121
|
+
%.so : %.c $(HDRS)
|
|
122
|
+
$(Q)$(CC) $(FPIC) -I$(INC_DIR) $(CFLAGS) $(CXXFLAGS) -c $< -o $@
|
|
123
|
+
|
|
124
|
+
%.to : %.c $(HDRS)
|
|
125
|
+
$(Q)$(CC) -g -O3 -DTESTING -I$(INC_DIR) $(CFLAGS) $(CXXFLAGS) -c $< -o $@
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
# Clean up any temp/build files.
|
|
129
|
+
clean :
|
|
130
|
+
$(Q)rm -f *.o *.a *.so *.to *.dylib *.dll
|
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
/*****************************************************************************
|
|
2
|
+
* app - A library for creating Excel XLSX app files.
|
|
3
|
+
*
|
|
4
|
+
* Used in conjunction with the libxlsxwriter library.
|
|
5
|
+
*
|
|
6
|
+
* Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
#include "xlsxwriter/xmlwriter.h"
|
|
11
|
+
#include "xlsxwriter/app.h"
|
|
12
|
+
#include "xlsxwriter/utility.h"
|
|
13
|
+
|
|
14
|
+
/*
|
|
15
|
+
* Forward declarations.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/*****************************************************************************
|
|
19
|
+
*
|
|
20
|
+
* Private functions.
|
|
21
|
+
*
|
|
22
|
+
****************************************************************************/
|
|
23
|
+
|
|
24
|
+
/*
|
|
25
|
+
* Create a new app object.
|
|
26
|
+
*/
|
|
27
|
+
lxw_app *
|
|
28
|
+
lxw_app_new()
|
|
29
|
+
{
|
|
30
|
+
lxw_app *app = calloc(1, sizeof(lxw_app));
|
|
31
|
+
GOTO_LABEL_ON_MEM_ERROR(app, mem_error);
|
|
32
|
+
|
|
33
|
+
app->heading_pairs = calloc(1, sizeof(struct lxw_heading_pairs));
|
|
34
|
+
GOTO_LABEL_ON_MEM_ERROR(app->heading_pairs, mem_error);
|
|
35
|
+
STAILQ_INIT(app->heading_pairs);
|
|
36
|
+
|
|
37
|
+
app->part_names = calloc(1, sizeof(struct lxw_part_names));
|
|
38
|
+
GOTO_LABEL_ON_MEM_ERROR(app->part_names, mem_error);
|
|
39
|
+
STAILQ_INIT(app->part_names);
|
|
40
|
+
|
|
41
|
+
return app;
|
|
42
|
+
|
|
43
|
+
mem_error:
|
|
44
|
+
lxw_app_free(app);
|
|
45
|
+
return NULL;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/*
|
|
49
|
+
* Free a app object.
|
|
50
|
+
*/
|
|
51
|
+
void
|
|
52
|
+
lxw_app_free(lxw_app *app)
|
|
53
|
+
{
|
|
54
|
+
lxw_heading_pair *heading_pair;
|
|
55
|
+
lxw_part_name *part_name;
|
|
56
|
+
|
|
57
|
+
if (!app)
|
|
58
|
+
return;
|
|
59
|
+
|
|
60
|
+
/* Free the lists in the App object. */
|
|
61
|
+
if (app->heading_pairs) {
|
|
62
|
+
while (!STAILQ_EMPTY(app->heading_pairs)) {
|
|
63
|
+
heading_pair = STAILQ_FIRST(app->heading_pairs);
|
|
64
|
+
STAILQ_REMOVE_HEAD(app->heading_pairs, list_pointers);
|
|
65
|
+
free(heading_pair->key);
|
|
66
|
+
free(heading_pair->value);
|
|
67
|
+
free(heading_pair);
|
|
68
|
+
}
|
|
69
|
+
free(app->heading_pairs);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (app->part_names) {
|
|
73
|
+
while (!STAILQ_EMPTY(app->part_names)) {
|
|
74
|
+
part_name = STAILQ_FIRST(app->part_names);
|
|
75
|
+
STAILQ_REMOVE_HEAD(app->part_names, list_pointers);
|
|
76
|
+
free(part_name->name);
|
|
77
|
+
free(part_name);
|
|
78
|
+
}
|
|
79
|
+
free(app->part_names);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
free(app);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/*****************************************************************************
|
|
86
|
+
*
|
|
87
|
+
* XML functions.
|
|
88
|
+
*
|
|
89
|
+
****************************************************************************/
|
|
90
|
+
|
|
91
|
+
/*
|
|
92
|
+
* Write the XML declaration.
|
|
93
|
+
*/
|
|
94
|
+
STATIC void
|
|
95
|
+
_app_xml_declaration(lxw_app *self)
|
|
96
|
+
{
|
|
97
|
+
lxw_xml_declaration(self->file);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/*
|
|
101
|
+
* Write the <Properties> element.
|
|
102
|
+
*/
|
|
103
|
+
STATIC void
|
|
104
|
+
_write_properties(lxw_app *self)
|
|
105
|
+
{
|
|
106
|
+
struct xml_attribute_list attributes;
|
|
107
|
+
struct xml_attribute *attribute;
|
|
108
|
+
char xmlns[] = LXW_SCHEMA_OFFICEDOC "/extended-properties";
|
|
109
|
+
char xmlns_vt[] = LXW_SCHEMA_OFFICEDOC "/docPropsVTypes";
|
|
110
|
+
|
|
111
|
+
LXW_INIT_ATTRIBUTES();
|
|
112
|
+
LXW_PUSH_ATTRIBUTES_STR("xmlns", xmlns);
|
|
113
|
+
LXW_PUSH_ATTRIBUTES_STR("xmlns:vt", xmlns_vt);
|
|
114
|
+
|
|
115
|
+
lxw_xml_start_tag(self->file, "Properties", &attributes);
|
|
116
|
+
|
|
117
|
+
LXW_FREE_ATTRIBUTES();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/*
|
|
121
|
+
* Write the <Application> element.
|
|
122
|
+
*/
|
|
123
|
+
STATIC void
|
|
124
|
+
_write_application(lxw_app *self)
|
|
125
|
+
{
|
|
126
|
+
lxw_xml_data_element(self->file, "Application", "Microsoft Excel", NULL);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/*
|
|
130
|
+
* Write the <DocSecurity> element.
|
|
131
|
+
*/
|
|
132
|
+
STATIC void
|
|
133
|
+
_write_doc_security(lxw_app *self)
|
|
134
|
+
{
|
|
135
|
+
lxw_xml_data_element(self->file, "DocSecurity", "0", NULL);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/*
|
|
139
|
+
* Write the <ScaleCrop> element.
|
|
140
|
+
*/
|
|
141
|
+
STATIC void
|
|
142
|
+
_write_scale_crop(lxw_app *self)
|
|
143
|
+
{
|
|
144
|
+
lxw_xml_data_element(self->file, "ScaleCrop", "false", NULL);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/*
|
|
148
|
+
* Write the <vt:lpstr> element.
|
|
149
|
+
*/
|
|
150
|
+
STATIC void
|
|
151
|
+
_write_vt_lpstr(lxw_app *self, const char *str)
|
|
152
|
+
{
|
|
153
|
+
lxw_xml_data_element(self->file, "vt:lpstr", str, NULL);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/*
|
|
157
|
+
* Write the <vt:i4> element.
|
|
158
|
+
*/
|
|
159
|
+
STATIC void
|
|
160
|
+
_write_vt_i4(lxw_app *self, const char *value)
|
|
161
|
+
{
|
|
162
|
+
lxw_xml_data_element(self->file, "vt:i4", value, NULL);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/*
|
|
166
|
+
* Write the <vt:variant> element.
|
|
167
|
+
*/
|
|
168
|
+
STATIC void
|
|
169
|
+
_write_vt_variant(lxw_app *self, const char *key, const char *value)
|
|
170
|
+
{
|
|
171
|
+
/* Write the vt:lpstr element. */
|
|
172
|
+
lxw_xml_start_tag(self->file, "vt:variant", NULL);
|
|
173
|
+
_write_vt_lpstr(self, key);
|
|
174
|
+
lxw_xml_end_tag(self->file, "vt:variant");
|
|
175
|
+
|
|
176
|
+
/* Write the vt:i4 element. */
|
|
177
|
+
lxw_xml_start_tag(self->file, "vt:variant", NULL);
|
|
178
|
+
_write_vt_i4(self, value);
|
|
179
|
+
lxw_xml_end_tag(self->file, "vt:variant");
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/*
|
|
183
|
+
* Write the <vt:vector> element for the heading pairs.
|
|
184
|
+
*/
|
|
185
|
+
STATIC void
|
|
186
|
+
_write_vt_vector_heading_pairs(lxw_app *self)
|
|
187
|
+
{
|
|
188
|
+
struct xml_attribute_list attributes;
|
|
189
|
+
struct xml_attribute *attribute;
|
|
190
|
+
lxw_heading_pair *heading_pair;
|
|
191
|
+
|
|
192
|
+
LXW_INIT_ATTRIBUTES();
|
|
193
|
+
LXW_PUSH_ATTRIBUTES_INT("size", self->num_heading_pairs * 2);
|
|
194
|
+
LXW_PUSH_ATTRIBUTES_STR("baseType", "variant");
|
|
195
|
+
|
|
196
|
+
lxw_xml_start_tag(self->file, "vt:vector", &attributes);
|
|
197
|
+
|
|
198
|
+
STAILQ_FOREACH(heading_pair, self->heading_pairs, list_pointers) {
|
|
199
|
+
_write_vt_variant(self, heading_pair->key, heading_pair->value);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
lxw_xml_end_tag(self->file, "vt:vector");
|
|
203
|
+
|
|
204
|
+
LXW_FREE_ATTRIBUTES();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/*
|
|
208
|
+
* Write the <vt:vector> element for the named parts.
|
|
209
|
+
*/
|
|
210
|
+
STATIC void
|
|
211
|
+
_write_vt_vector_lpstr_named_parts(lxw_app *self)
|
|
212
|
+
{
|
|
213
|
+
struct xml_attribute_list attributes;
|
|
214
|
+
struct xml_attribute *attribute;
|
|
215
|
+
lxw_part_name *part_name;
|
|
216
|
+
|
|
217
|
+
LXW_INIT_ATTRIBUTES();
|
|
218
|
+
LXW_PUSH_ATTRIBUTES_INT("size", self->num_part_names);
|
|
219
|
+
LXW_PUSH_ATTRIBUTES_STR("baseType", "lpstr");
|
|
220
|
+
|
|
221
|
+
lxw_xml_start_tag(self->file, "vt:vector", &attributes);
|
|
222
|
+
|
|
223
|
+
STAILQ_FOREACH(part_name, self->part_names, list_pointers) {
|
|
224
|
+
_write_vt_lpstr(self, part_name->name);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
lxw_xml_end_tag(self->file, "vt:vector");
|
|
228
|
+
|
|
229
|
+
LXW_FREE_ATTRIBUTES();
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/*
|
|
233
|
+
* Write the <HeadingPairs> element.
|
|
234
|
+
*/
|
|
235
|
+
STATIC void
|
|
236
|
+
_write_heading_pairs(lxw_app *self)
|
|
237
|
+
{
|
|
238
|
+
lxw_xml_start_tag(self->file, "HeadingPairs", NULL);
|
|
239
|
+
|
|
240
|
+
/* Write the vt:vector element. */
|
|
241
|
+
_write_vt_vector_heading_pairs(self);
|
|
242
|
+
|
|
243
|
+
lxw_xml_end_tag(self->file, "HeadingPairs");
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/*
|
|
247
|
+
* Write the <TitlesOfParts> element.
|
|
248
|
+
*/
|
|
249
|
+
STATIC void
|
|
250
|
+
_write_titles_of_parts(lxw_app *self)
|
|
251
|
+
{
|
|
252
|
+
lxw_xml_start_tag(self->file, "TitlesOfParts", NULL);
|
|
253
|
+
|
|
254
|
+
/* Write the vt:vector element. */
|
|
255
|
+
_write_vt_vector_lpstr_named_parts(self);
|
|
256
|
+
|
|
257
|
+
lxw_xml_end_tag(self->file, "TitlesOfParts");
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/*
|
|
261
|
+
* Write the <Manager> element.
|
|
262
|
+
*/
|
|
263
|
+
STATIC void
|
|
264
|
+
_write_manager(lxw_app *self)
|
|
265
|
+
{
|
|
266
|
+
lxw_doc_properties *properties = self->properties;
|
|
267
|
+
|
|
268
|
+
if (!properties)
|
|
269
|
+
return;
|
|
270
|
+
|
|
271
|
+
if (properties->manager)
|
|
272
|
+
lxw_xml_data_element(self->file, "Manager", properties->manager,
|
|
273
|
+
NULL);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/*
|
|
277
|
+
* Write the <Company> element.
|
|
278
|
+
*/
|
|
279
|
+
STATIC void
|
|
280
|
+
_write_company(lxw_app *self)
|
|
281
|
+
{
|
|
282
|
+
lxw_doc_properties *properties = self->properties;
|
|
283
|
+
|
|
284
|
+
if (properties && properties->company)
|
|
285
|
+
lxw_xml_data_element(self->file, "Company", properties->company,
|
|
286
|
+
NULL);
|
|
287
|
+
else
|
|
288
|
+
lxw_xml_data_element(self->file, "Company", "", NULL);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/*
|
|
292
|
+
* Write the <LinksUpToDate> element.
|
|
293
|
+
*/
|
|
294
|
+
STATIC void
|
|
295
|
+
_write_links_up_to_date(lxw_app *self)
|
|
296
|
+
{
|
|
297
|
+
lxw_xml_data_element(self->file, "LinksUpToDate", "false", NULL);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/*
|
|
301
|
+
* Write the <SharedDoc> element.
|
|
302
|
+
*/
|
|
303
|
+
STATIC void
|
|
304
|
+
_write_shared_doc(lxw_app *self)
|
|
305
|
+
{
|
|
306
|
+
lxw_xml_data_element(self->file, "SharedDoc", "false", NULL);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/*
|
|
310
|
+
* Write the <HyperlinkBase> element.
|
|
311
|
+
*/
|
|
312
|
+
STATIC void
|
|
313
|
+
_write_hyperlink_base(lxw_app *self)
|
|
314
|
+
{
|
|
315
|
+
lxw_doc_properties *properties = self->properties;
|
|
316
|
+
|
|
317
|
+
if (!properties)
|
|
318
|
+
return;
|
|
319
|
+
|
|
320
|
+
if (properties->hyperlink_base)
|
|
321
|
+
lxw_xml_data_element(self->file, "HyperlinkBase",
|
|
322
|
+
properties->hyperlink_base, NULL);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/*
|
|
326
|
+
* Write the <HyperlinksChanged> element.
|
|
327
|
+
*/
|
|
328
|
+
STATIC void
|
|
329
|
+
_write_hyperlinks_changed(lxw_app *self)
|
|
330
|
+
{
|
|
331
|
+
lxw_xml_data_element(self->file, "HyperlinksChanged", "false", NULL);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/*
|
|
335
|
+
* Write the <AppVersion> element.
|
|
336
|
+
*/
|
|
337
|
+
STATIC void
|
|
338
|
+
_write_app_version(lxw_app *self)
|
|
339
|
+
{
|
|
340
|
+
lxw_xml_data_element(self->file, "AppVersion", "12.0000", NULL);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/*****************************************************************************
|
|
344
|
+
*
|
|
345
|
+
* XML file assembly functions.
|
|
346
|
+
*
|
|
347
|
+
****************************************************************************/
|
|
348
|
+
|
|
349
|
+
/*
|
|
350
|
+
* Assemble and write the XML file.
|
|
351
|
+
*/
|
|
352
|
+
void
|
|
353
|
+
lxw_app_assemble_xml_file(lxw_app *self)
|
|
354
|
+
{
|
|
355
|
+
|
|
356
|
+
/* Write the XML declaration. */
|
|
357
|
+
_app_xml_declaration(self);
|
|
358
|
+
|
|
359
|
+
_write_properties(self);
|
|
360
|
+
_write_application(self);
|
|
361
|
+
_write_doc_security(self);
|
|
362
|
+
_write_scale_crop(self);
|
|
363
|
+
_write_heading_pairs(self);
|
|
364
|
+
_write_titles_of_parts(self);
|
|
365
|
+
_write_manager(self);
|
|
366
|
+
_write_company(self);
|
|
367
|
+
_write_links_up_to_date(self);
|
|
368
|
+
_write_shared_doc(self);
|
|
369
|
+
_write_hyperlink_base(self);
|
|
370
|
+
_write_hyperlinks_changed(self);
|
|
371
|
+
_write_app_version(self);
|
|
372
|
+
|
|
373
|
+
lxw_xml_end_tag(self->file, "Properties");
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/*****************************************************************************
|
|
377
|
+
*
|
|
378
|
+
* Public functions.
|
|
379
|
+
*
|
|
380
|
+
****************************************************************************/
|
|
381
|
+
|
|
382
|
+
/*
|
|
383
|
+
* Add the name of a workbook Part such as 'Sheet1' or 'Print_Titles'.
|
|
384
|
+
*/
|
|
385
|
+
void
|
|
386
|
+
lxw_app_add_part_name(lxw_app *self, const char *name)
|
|
387
|
+
{
|
|
388
|
+
lxw_part_name *part_name;
|
|
389
|
+
|
|
390
|
+
if (!name)
|
|
391
|
+
return;
|
|
392
|
+
|
|
393
|
+
part_name = calloc(1, sizeof(lxw_part_name));
|
|
394
|
+
GOTO_LABEL_ON_MEM_ERROR(part_name, mem_error);
|
|
395
|
+
|
|
396
|
+
part_name->name = lxw_strdup(name);
|
|
397
|
+
GOTO_LABEL_ON_MEM_ERROR(part_name->name, mem_error);
|
|
398
|
+
|
|
399
|
+
STAILQ_INSERT_TAIL(self->part_names, part_name, list_pointers);
|
|
400
|
+
self->num_part_names++;
|
|
401
|
+
|
|
402
|
+
return;
|
|
403
|
+
|
|
404
|
+
mem_error:
|
|
405
|
+
if (part_name) {
|
|
406
|
+
free(part_name->name);
|
|
407
|
+
free(part_name);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/*
|
|
412
|
+
* Add the name of a workbook Heading Pair such as 'Worksheets', 'Charts' or
|
|
413
|
+
* 'Named Ranges'.
|
|
414
|
+
*/
|
|
415
|
+
void
|
|
416
|
+
lxw_app_add_heading_pair(lxw_app *self, const char *key, const char *value)
|
|
417
|
+
{
|
|
418
|
+
lxw_heading_pair *heading_pair;
|
|
419
|
+
|
|
420
|
+
if (!key || !value)
|
|
421
|
+
return;
|
|
422
|
+
|
|
423
|
+
heading_pair = calloc(1, sizeof(lxw_heading_pair));
|
|
424
|
+
GOTO_LABEL_ON_MEM_ERROR(heading_pair, mem_error);
|
|
425
|
+
|
|
426
|
+
heading_pair->key = lxw_strdup(key);
|
|
427
|
+
GOTO_LABEL_ON_MEM_ERROR(heading_pair->key, mem_error);
|
|
428
|
+
|
|
429
|
+
heading_pair->value = lxw_strdup(value);
|
|
430
|
+
GOTO_LABEL_ON_MEM_ERROR(heading_pair->value, mem_error);
|
|
431
|
+
|
|
432
|
+
STAILQ_INSERT_TAIL(self->heading_pairs, heading_pair, list_pointers);
|
|
433
|
+
self->num_heading_pairs++;
|
|
434
|
+
|
|
435
|
+
return;
|
|
436
|
+
|
|
437
|
+
mem_error:
|
|
438
|
+
if (heading_pair) {
|
|
439
|
+
free(heading_pair->key);
|
|
440
|
+
free(heading_pair->value);
|
|
441
|
+
free(heading_pair);
|
|
442
|
+
}
|
|
443
|
+
}
|