初始化PHP-Xlswrite扩展

This commit is contained in:
ykxiao
2024-03-05 10:01:08 +08:00
commit 879cf9584d
2483 changed files with 1054962 additions and 0 deletions

View File

@ -0,0 +1,80 @@
/*
* libxlsxwriter
*
* Copyright 2014-2021, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* app - A libxlsxwriter library for creating Excel XLSX app files.
*
*/
#ifndef __LXW_APP_H__
#define __LXW_APP_H__
#include <stdint.h>
#include <string.h>
#include "workbook.h"
#include "common.h"
/* Define the queue.h TAILQ structs for the App structs. */
STAILQ_HEAD(lxw_heading_pairs, lxw_heading_pair);
STAILQ_HEAD(lxw_part_names, lxw_part_name);
typedef struct lxw_heading_pair {
char *key;
char *value;
STAILQ_ENTRY (lxw_heading_pair) list_pointers;
} lxw_heading_pair;
typedef struct lxw_part_name {
char *name;
STAILQ_ENTRY (lxw_part_name) list_pointers;
} lxw_part_name;
/* Struct to represent an App object. */
typedef struct lxw_app {
FILE *file;
struct lxw_heading_pairs *heading_pairs;
struct lxw_part_names *part_names;
lxw_doc_properties *properties;
uint32_t num_heading_pairs;
uint32_t num_part_names;
uint8_t doc_security;
} lxw_app;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_app *lxw_app_new(void);
void lxw_app_free(lxw_app *app);
void lxw_app_assemble_xml_file(lxw_app *self);
void lxw_app_add_part_name(lxw_app *self, const char *name);
void lxw_app_add_heading_pair(lxw_app *self, const char *key,
const char *value);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _app_xml_declaration(lxw_app *self);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_APP_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,544 @@
/*
* libxlsxwriter
*
* Copyright 2014-2021, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* chartsheet - A libxlsxwriter library for creating Excel XLSX chartsheet files.
*
*/
/**
* @page chartsheet_page The Chartsheet object
*
* The Chartsheet object represents an Excel chartsheet, which is a type of
* worksheet that only contains a chart. The Chartsheet object handles
* operations such as adding a chart and setting the page layout.
*
* See @ref chartsheet.h for full details of the functionality.
*
* @file chartsheet.h
*
* @brief Functions related to adding data and formatting to a chartsheet.
*
* The Chartsheet object represents an Excel chartsheet. It handles operations
* such as adding a chart and setting the page layout.
*
* A Chartsheet object isn't created directly. Instead a chartsheet is created
* by calling the workbook_add_chartsheet() function from a Workbook object. A
* chartsheet object functions as a worksheet and not as a chart. In order to
* have it display data a #lxw_chart object must be created and added to the
* chartsheet:
*
* @code
* #include "xlsxwriter.h"
*
* int main() {
*
* lxw_workbook *workbook = new_workbook("chartsheet.xlsx");
* lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
* lxw_chartsheet *chartsheet = workbook_add_chartsheet(workbook, NULL);
* lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_BAR);
*
* //... Set up the chart.
*
* // Add the chart to the chartsheet.
* return workbook_close(workbook);
*
* }
* @endcode
*
* @image html chartsheet.png
*
* The data for the chartsheet chart must be contained on a separate
* worksheet. That is why it is always created in conjunction with at least
* one data worksheet, as shown above.
*/
#ifndef __LXW_CHARTSHEET_H__
#define __LXW_CHARTSHEET_H__
#include <stdint.h>
#include "common.h"
#include "worksheet.h"
#include "drawing.h"
#include "utility.h"
/**
* @brief Struct to represent an Excel chartsheet.
*
* The members of the lxw_chartsheet struct aren't modified directly. Instead
* the chartsheet properties are set by calling the functions shown in
* chartsheet.h.
*/
typedef struct lxw_chartsheet {
FILE *file;
lxw_worksheet *worksheet;
lxw_chart *chart;
struct lxw_protection_obj protection;
uint8_t is_protected;
char *name;
char *quoted_name;
char *tmpdir;
uint16_t index;
uint8_t active;
uint8_t selected;
uint8_t hidden;
uint16_t *active_sheet;
uint16_t *first_sheet;
uint16_t rel_count;
STAILQ_ENTRY (lxw_chartsheet) list_pointers;
} lxw_chartsheet;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/**
* @brief Insert a chart object into a chartsheet.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
* @param chart A #lxw_chart object created via workbook_add_chart().
*
* @return A #lxw_error code.
*
* The `%chartsheet_set_chart()` function can be used to insert a chart into a
* chartsheet. The chart object must be created first using the
* `workbook_add_chart()` function and configured using the @ref chart.h
* functions.
*
* @code
* // Create the chartsheet.
* lxw_chartsheet *chartsheet = workbook_add_chartsheet(workbook, NULL);
*
* // Create a chart object.
* lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_LINE);
*
* // Add a data series to the chart.
* chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$6");
*
* // Insert the chart into the chartsheet.
* chartsheet_set_chart(chartsheet, chart);
* @endcode
*
* @image html chartsheet2.png
*
* **Note:**
*
* A chart may only be inserted once into a chartsheet or a worksheet. If
* several similar charts are required then each one must be created
* separately.
*
*/
lxw_error chartsheet_set_chart(lxw_chartsheet *chartsheet, lxw_chart *chart);
/* Not currently required since scale options aren't useful in a chartsheet. */
lxw_error chartsheet_set_chart_opt(lxw_chartsheet *chartsheet,
lxw_chart *chart,
lxw_chart_options *user_options);
/**
* @brief Make a chartsheet the active, i.e., visible chartsheet.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
*
* The `%chartsheet_activate()` function is used to specify which chartsheet
* is initially visible in a multi-sheet workbook:
*
* @code
* lxw_worksheet *worksheet1 = workbook_add_worksheet(workbook, NULL);
* lxw_chartsheet *chartsheet1 = workbook_add_chartsheet(workbook, NULL);
* lxw_chartsheet *chartsheet2 = workbook_add_chartsheet(workbook, NULL);
* lxw_chartsheet *chartsheet3 = workbook_add_chartsheet(workbook, NULL);
*
* chartsheet_activate(chartsheet3);
* @endcode
*
* @image html chartsheet_activate.png
*
* More than one chartsheet can be selected via the `chartsheet_select()`
* function, see below, however only one chartsheet can be active.
*
* The default active chartsheet is the first chartsheet.
*
* See also `worksheet_activate()`.
*
*/
void chartsheet_activate(lxw_chartsheet *chartsheet);
/**
* @brief Set a chartsheet tab as selected.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
*
* The `%chartsheet_select()` function is used to indicate that a chartsheet
* is selected in a multi-sheet workbook:
*
* @code
* chartsheet_activate(chartsheet1);
* chartsheet_select(chartsheet2);
* chartsheet_select(chartsheet3);
*
* @endcode
*
* A selected chartsheet has its tab highlighted. Selecting chartsheets is a
* way of grouping them together so that, for example, several chartsheets
* could be printed in one go. A chartsheet that has been activated via the
* `chartsheet_activate()` function will also appear as selected.
*
* See also `worksheet_select()`.
*
*/
void chartsheet_select(lxw_chartsheet *chartsheet);
/**
* @brief Hide the current chartsheet.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
*
* The `%chartsheet_hide()` function is used to hide a chartsheet:
*
* @code
* chartsheet_hide(chartsheet2);
* @endcode
*
* You may wish to hide a chartsheet in order to avoid confusing a user with
* intermediate data or calculations.
*
* @image html hide_sheet.png
*
* A hidden chartsheet can not be activated or selected so this function is
* mutually exclusive with the `chartsheet_activate()` and
* `chartsheet_select()` functions. In addition, since the first chartsheet
* will default to being the active chartsheet, you cannot hide the first
* chartsheet without activating another sheet:
*
* @code
* chartsheet_activate(chartsheet2);
* chartsheet_hide(chartsheet1);
* @endcode
*
* See also `worksheet_hide()`.
*
*/
void chartsheet_hide(lxw_chartsheet *chartsheet);
/**
* @brief Set current chartsheet as the first visible sheet tab.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
*
* The `chartsheet_activate()` function determines which chartsheet is
* initially selected. However, if there are a large number of chartsheets the
* selected chartsheet may not appear on the screen. To avoid this you can
* select the leftmost visible chartsheet tab using
* `%chartsheet_set_first_sheet()`:
*
* @code
* chartsheet_set_first_sheet(chartsheet19); // First visible chartsheet tab.
* chartsheet_activate(chartsheet20); // First visible chartsheet.
* @endcode
*
* This function is not required very often. The default value is the first
* chartsheet.
*
* See also `worksheet_set_first_sheet()`.
*
*/
void chartsheet_set_first_sheet(lxw_chartsheet *chartsheet);
/**
* @brief Set the color of the chartsheet tab.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
* @param color The tab color.
*
* The `%chartsheet_set_tab_color()` function is used to change the color of
* the chartsheet tab:
*
* @code
* chartsheet_set_tab_color(chartsheet1, LXW_COLOR_RED);
* chartsheet_set_tab_color(chartsheet2, LXW_COLOR_GREEN);
* chartsheet_set_tab_color(chartsheet3, 0xFF9900); // Orange.
* @endcode
*
* The color should be an RGB integer value, see @ref working_with_colors.
*
* See also `worksheet_set_tab_color()`.
*/
void chartsheet_set_tab_color(lxw_chartsheet *chartsheet, lxw_color_t color);
/**
* @brief Protect elements of a chartsheet from modification.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
* @param password A chartsheet password.
* @param options Chartsheet elements to protect.
*
* The `%chartsheet_protect()` function protects chartsheet elements from
* modification:
*
* @code
* chartsheet_protect(chartsheet, "Some Password", options);
* @endcode
*
* The `password` and lxw_protection pointer are both optional:
*
* @code
* chartsheet_protect(chartsheet2, NULL, my_options);
* chartsheet_protect(chartsheet3, "password", NULL);
* chartsheet_protect(chartsheet4, "password", my_options);
* @endcode
*
* Passing a `NULL` password is the same as turning on protection without a
* password. Passing a `NULL` password and `NULL` options had no effect on
* chartsheets.
*
* You can specify which chartsheet elements you wish to protect by passing a
* lxw_protection pointer in the `options` argument. In Excel chartsheets only
* have two protection options:
*
* no_content
* no_objects
*
* All parameters are off by default. Individual elements can be protected as
* follows:
*
* @code
* lxw_protection options = {
* .no_content = 1,
* .no_objects = 1,
* };
*
* chartsheet_protect(chartsheet, NULL, &options);
*
* @endcode
*
* See also worksheet_protect().
*
* **Note:** Sheet level passwords in Excel offer **very** weak
* protection. They don't encrypt your data and are very easy to
* deactivate. Full workbook encryption is not supported by `libxlsxwriter`
* since it requires a completely different file format.
*/
void chartsheet_protect(lxw_chartsheet *chartsheet, const char *password,
lxw_protection *options);
/**
* @brief Set the chartsheet zoom factor.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
* @param scale Chartsheet zoom factor.
*
* Set the chartsheet zoom factor in the range `10 <= zoom <= 400`:
*
* @code
* chartsheet_set_zoom(chartsheet, 75);
* @endcode
*
* The default zoom factor is 100. It isn't possible to set the zoom to
* "Selection" because it is calculated by Excel at run-time.
*
* See also `worksheet_set_zoom()`.
*/
void chartsheet_set_zoom(lxw_chartsheet *chartsheet, uint16_t scale);
/**
* @brief Set the page orientation as landscape.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
*
* This function is used to set the orientation of a chartsheet's printed page
* to landscape. The default chartsheet orientation is landscape, so this
* function isn't generally required:
*
* @code
* chartsheet_set_landscape(chartsheet);
* @endcode
*/
void chartsheet_set_landscape(lxw_chartsheet *chartsheet);
/**
* @brief Set the page orientation as portrait.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
*
* This function is used to set the orientation of a chartsheet's printed page
* to portrait:
*
* @code
* chartsheet_set_portrait(chartsheet);
* @endcode
*/
void chartsheet_set_portrait(lxw_chartsheet *chartsheet);
/**
* @brief Set the paper type for printing.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
* @param paper_type The Excel paper format type.
*
* This function is used to set the paper format for the printed output of a
* chartsheet:
*
* @code
* chartsheet_set_paper(chartsheet1, 1); // US Letter
* chartsheet_set_paper(chartsheet2, 9); // A4
* @endcode
*
* If you do not specify a paper type the chartsheet will print using the
* printer's default paper style.
*
* See `worksheet_set_paper()` for a full list of available paper sizes.
*/
void chartsheet_set_paper(lxw_chartsheet *chartsheet, uint8_t paper_type);
/**
* @brief Set the chartsheet margins for the printed page.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
* @param left Left margin in inches. Excel default is 0.7.
* @param right Right margin in inches. Excel default is 0.7.
* @param top Top margin in inches. Excel default is 0.75.
* @param bottom Bottom margin in inches. Excel default is 0.75.
*
* The `%chartsheet_set_margins()` function is used to set the margins of the
* chartsheet when it is printed. The units are in inches. Specifying `-1` for
* any parameter will give the default Excel value as shown above.
*
* @code
* chartsheet_set_margins(chartsheet, 1.3, 1.2, -1, -1);
* @endcode
*
*/
void chartsheet_set_margins(lxw_chartsheet *chartsheet, double left,
double right, double top, double bottom);
/**
* @brief Set the printed page header caption.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
* @param string The header string.
*
* @return A #lxw_error code.
*
* Headers and footers are generated using a string which is a combination of
* plain text and control characters
*
* @code
* chartsheet_set_header(chartsheet, "&LHello");
*
* // ---------------------------------------------------------------
* // | |
* // | Hello |
* // | |
*
*
* chartsheet_set_header(chartsheet, "&CHello");
*
* // ---------------------------------------------------------------
* // | |
* // | Hello |
* // | |
*
*
* chartsheet_set_header(chartsheet, "&RHello");
*
* // ---------------------------------------------------------------
* // | |
* // | Hello |
* // | |
*
*
* @endcode
*
* See `worksheet_set_header()` for a full explanation of the syntax of
* Excel's header formatting and control characters.
*
*/
lxw_error chartsheet_set_header(lxw_chartsheet *chartsheet,
const char *string);
/**
* @brief Set the printed page footer caption.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
* @param string The footer string.
*
* @return A #lxw_error code.
*
* The syntax of this function is the same as chartsheet_set_header().
*
*/
lxw_error chartsheet_set_footer(lxw_chartsheet *chartsheet,
const char *string);
/**
* @brief Set the printed page header caption with additional options.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
* @param string The header string.
* @param options Header options.
*
* @return A #lxw_error code.
*
* The syntax of this function is the same as chartsheet_set_header() with an
* additional parameter to specify options for the header.
*
* Currently, the only available option is the header margin:
*
* @code
*
* lxw_header_footer_options header_options = { 0.2 };
*
* chartsheet_set_header_opt(chartsheet, "Some text", &header_options);
*
* @endcode
*
*/
lxw_error chartsheet_set_header_opt(lxw_chartsheet *chartsheet,
const char *string,
lxw_header_footer_options *options);
/**
* @brief Set the printed page footer caption with additional options.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
* @param string The footer string.
* @param options Footer options.
*
* @return A #lxw_error code.
*
* The syntax of this function is the same as chartsheet_set_header_opt().
*
*/
lxw_error chartsheet_set_footer_opt(lxw_chartsheet *chartsheet,
const char *string,
lxw_header_footer_options *options);
lxw_chartsheet *lxw_chartsheet_new(lxw_worksheet_init_data *init_data);
void lxw_chartsheet_free(lxw_chartsheet *chartsheet);
void lxw_chartsheet_assemble_xml_file(lxw_chartsheet *chartsheet);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _chartsheet_xml_declaration(lxw_chartsheet *chartsheet);
STATIC void _chartsheet_write_sheet_protection(lxw_chartsheet *chartsheet);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_CHARTSHEET_H__ */

View File

@ -0,0 +1,76 @@
/*
* libxlsxwriter
*
* Copyright 2014-2021, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* comment - A libxlsxwriter library for creating Excel XLSX comment files.
*
*/
#ifndef __LXW_COMMENT_H__
#define __LXW_COMMENT_H__
#include <stdint.h>
#include "common.h"
#include "worksheet.h"
/* Define the tree.h RB structs for the red-black head types. */
RB_HEAD(lxw_author_ids, lxw_author_id);
/*
* Struct to represent a comment object.
*/
typedef struct lxw_comment {
FILE *file;
struct lxw_comment_objs *comment_objs;
struct lxw_author_ids *author_ids;
char *comment_author;
uint32_t author_id;
} lxw_comment;
/* Struct to an author id */
typedef struct lxw_author_id {
uint32_t id;
char *author;
RB_ENTRY (lxw_author_id) tree_pointers;
} lxw_author_id;
#define LXW_RB_GENERATE_AUTHOR_IDS(name, type, field, cmp) \
RB_GENERATE_INSERT_COLOR(name, type, field, static) \
RB_GENERATE_REMOVE_COLOR(name, type, field, static) \
RB_GENERATE_INSERT(name, type, field, cmp, static) \
RB_GENERATE_REMOVE(name, type, field, static) \
RB_GENERATE_FIND(name, type, field, cmp, static) \
RB_GENERATE_NEXT(name, type, field, static) \
RB_GENERATE_MINMAX(name, type, field, static) \
/* Add unused struct to allow adding a semicolon */ \
struct lxw_rb_generate_author_ids{int unused;}
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_comment *lxw_comment_new(void);
void lxw_comment_free(lxw_comment *comment);
void lxw_comment_assemble_xml_file(lxw_comment *self);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _comment_xml_declaration(lxw_comment *self);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_COMMENT_H__ */

View File

@ -0,0 +1,462 @@
/*
* libxlsxwriter
*
* Copyright 2014-2021, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*/
/**
* @file common.h
*
* @brief Common functions and defines for the libxlsxwriter library.
*
* <!-- Copyright 2014-2021, John McNamara, jmcnamara@cpan.org -->
*
*/
#ifndef __LXW_COMMON_H__
#define __LXW_COMMON_H__
#include <time.h>
#include "third_party/queue.h"
#include "third_party/tree.h"
#ifndef TESTING
#define STATIC static
#else
#define STATIC
#endif
#if __GNUC__ >= 5
#define DEPRECATED(func, msg) func __attribute__ ((deprecated(msg)))
#elif defined(_MSC_VER)
#define DEPRECATED(func, msg) __declspec(deprecated, msg) func
#else
#define DEPRECATED(func, msg) func
#endif
/** Integer data type to represent a row value. Equivalent to `uint32_t`.
*
* The maximum row in Excel is 1,048,576.
*/
typedef uint32_t lxw_row_t;
/** Integer data type to represent a column value. Equivalent to `uint16_t`.
*
* The maximum column in Excel is 16,384.
*/
typedef uint16_t lxw_col_t;
/** Boolean values used in libxlsxwriter. */
enum lxw_boolean {
/** False value. */
LXW_FALSE,
/** True value. */
LXW_TRUE,
/** False value. Used to turn off a property that is default on, in order
* to distinguish it from an uninitialized value. */
LXW_EXPLICIT_FALSE
};
/**
* @brief Error codes from libxlsxwriter functions.
*
* See the `lxw_strerror()` function for an example of how to convert the
* enum number to a descriptive error message string.
*/
typedef enum lxw_error {
/** No error. */
LXW_NO_ERROR = 0,
/** Memory error, failed to malloc() required memory. */
LXW_ERROR_MEMORY_MALLOC_FAILED,
/** Error creating output xlsx file. Usually a permissions error. */
LXW_ERROR_CREATING_XLSX_FILE,
/** Error encountered when creating a tmpfile during file assembly. */
LXW_ERROR_CREATING_TMPFILE,
/** Error reading a tmpfile. */
LXW_ERROR_READING_TMPFILE,
/** Zip generic error ZIP_ERRNO while creating the xlsx file. */
LXW_ERROR_ZIP_FILE_OPERATION,
/** Zip error ZIP_PARAMERROR while creating the xlsx file. */
LXW_ERROR_ZIP_PARAMETER_ERROR,
/** Zip error ZIP_BADZIPFILE (use_zip64 option may be required). */
LXW_ERROR_ZIP_BAD_ZIP_FILE,
/** Zip error ZIP_INTERNALERROR while creating the xlsx file. */
LXW_ERROR_ZIP_INTERNAL_ERROR,
/** File error or unknown zip error when adding sub file to xlsx file. */
LXW_ERROR_ZIP_FILE_ADD,
/** Unknown zip error when closing xlsx file. */
LXW_ERROR_ZIP_CLOSE,
/** Feature is not currently supported in this configuration. */
LXW_ERROR_FEATURE_NOT_SUPPORTED,
/** NULL function parameter ignored. */
LXW_ERROR_NULL_PARAMETER_IGNORED,
/** Function parameter validation error. */
LXW_ERROR_PARAMETER_VALIDATION,
/** Worksheet name exceeds Excel's limit of 31 characters. */
LXW_ERROR_SHEETNAME_LENGTH_EXCEEDED,
/** Worksheet name cannot contain invalid characters: '[ ] : * ? / \\' */
LXW_ERROR_INVALID_SHEETNAME_CHARACTER,
/** Worksheet name cannot start or end with an apostrophe. */
LXW_ERROR_SHEETNAME_START_END_APOSTROPHE,
/** Worksheet name is already in use. */
LXW_ERROR_SHEETNAME_ALREADY_USED,
/** Parameter exceeds Excel's limit of 32 characters. */
LXW_ERROR_32_STRING_LENGTH_EXCEEDED,
/** Parameter exceeds Excel's limit of 128 characters. */
LXW_ERROR_128_STRING_LENGTH_EXCEEDED,
/** Parameter exceeds Excel's limit of 255 characters. */
LXW_ERROR_255_STRING_LENGTH_EXCEEDED,
/** String exceeds Excel's limit of 32,767 characters. */
LXW_ERROR_MAX_STRING_LENGTH_EXCEEDED,
/** Error finding internal string index. */
LXW_ERROR_SHARED_STRING_INDEX_NOT_FOUND,
/** Worksheet row or column index out of range. */
LXW_ERROR_WORKSHEET_INDEX_OUT_OF_RANGE,
/** Maximum hyperlink length (2079) exceeded. */
LXW_ERROR_WORKSHEET_MAX_URL_LENGTH_EXCEEDED,
/** Maximum number of worksheet URLs (65530) exceeded. */
LXW_ERROR_WORKSHEET_MAX_NUMBER_URLS_EXCEEDED,
/** Couldn't read image dimensions or DPI. */
LXW_ERROR_IMAGE_DIMENSIONS,
LXW_MAX_ERRNO
} lxw_error;
/** @brief Struct to represent a date and time in Excel.
*
* Struct to represent a date and time in Excel. See @ref working_with_dates.
*/
typedef struct lxw_datetime {
/** Year : 1900 - 9999 */
int year;
/** Month : 1 - 12 */
int month;
/** Day : 1 - 31 */
int day;
/** Hour : 0 - 23 */
int hour;
/** Minute : 0 - 59 */
int min;
/** Seconds : 0 - 59.999 */
double sec;
} lxw_datetime;
enum lxw_custom_property_types {
LXW_CUSTOM_NONE,
LXW_CUSTOM_STRING,
LXW_CUSTOM_DOUBLE,
LXW_CUSTOM_INTEGER,
LXW_CUSTOM_BOOLEAN,
LXW_CUSTOM_DATETIME
};
/* Size of MD5 byte arrays. */
#define LXW_MD5_SIZE 16
/* Excel sheetname max of 31 chars. */
#define LXW_SHEETNAME_MAX 31
/* Max with all worksheet chars 4xUTF-8 bytes + start and end quotes + \0. */
#define LXW_MAX_SHEETNAME_LENGTH ((LXW_SHEETNAME_MAX * 4) + 2 + 1)
/* Max col string length. */
#define LXW_MAX_COL_NAME_LENGTH sizeof("$XFD")
/* Max row string length. */
#define LXW_MAX_ROW_NAME_LENGTH sizeof("$1048576")
/* Max cell string length. */
#define LXW_MAX_CELL_NAME_LENGTH sizeof("$XFWD$1048576")
/* Max range: $XFWD$1048576:$XFWD$1048576\0 */
#define LXW_MAX_CELL_RANGE_LENGTH (LXW_MAX_CELL_NAME_LENGTH * 2)
/* Max range formula Sheet1!$A$1:$C$5$ style. */
#define LXW_MAX_FORMULA_RANGE_LENGTH (LXW_MAX_SHEETNAME_LENGTH + LXW_MAX_CELL_RANGE_LENGTH)
/* Datetime string length. */
#define LXW_DATETIME_LENGTH sizeof("2016-12-12T23:00:00Z")
/* GUID string length. */
#define LXW_GUID_LENGTH sizeof("{12345678-1234-1234-1234-1234567890AB}\0")
#define LXW_EPOCH_1900 0
#define LXW_EPOCH_1904 1
#define LXW_UINT32_T_LENGTH sizeof("4294967296")
#define LXW_FILENAME_LENGTH 128
#define LXW_IGNORE 1
#define LXW_PORTRAIT 1
#define LXW_LANDSCAPE 0
#define LXW_SCHEMA_MS "http://schemas.microsoft.com/office/2006/relationships"
#define LXW_SCHEMA_ROOT "http://schemas.openxmlformats.org"
#define LXW_SCHEMA_DRAWING LXW_SCHEMA_ROOT "/drawingml/2006"
#define LXW_SCHEMA_OFFICEDOC LXW_SCHEMA_ROOT "/officeDocument/2006"
#define LXW_SCHEMA_PACKAGE LXW_SCHEMA_ROOT "/package/2006/relationships"
#define LXW_SCHEMA_DOCUMENT LXW_SCHEMA_ROOT "/officeDocument/2006/relationships"
#define LXW_SCHEMA_CONTENT LXW_SCHEMA_ROOT "/package/2006/content-types"
/* Use REprintf() for error handling when compiled as an R library. */
#ifdef USE_R_LANG
#include <R.h>
#define LXW_PRINTF REprintf
#define LXW_STDERR
#else
#define LXW_PRINTF fprintf
#define LXW_STDERR stderr,
#endif
#define LXW_ERROR(message) \
LXW_PRINTF(LXW_STDERR "[ERROR][%s:%d]: " message "\n", __FILE__, __LINE__)
#define LXW_MEM_ERROR() \
LXW_ERROR("Memory allocation failed.")
#define GOTO_LABEL_ON_MEM_ERROR(pointer, label) \
do { \
if (!pointer) { \
LXW_MEM_ERROR(); \
goto label; \
} \
} while (0)
#define RETURN_ON_MEM_ERROR(pointer, error) \
do { \
if (!pointer) { \
LXW_MEM_ERROR(); \
return error; \
} \
} while (0)
#define RETURN_VOID_ON_MEM_ERROR(pointer) \
do { \
if (!pointer) { \
LXW_MEM_ERROR(); \
return; \
} \
} while (0)
#define RETURN_ON_ERROR(error) \
do { \
if (error) \
return error; \
} while (0)
#define RETURN_AND_ZIPCLOSE_ON_ERROR(error) \
do { \
if (error) { \
zipClose(self->zipfile, NULL); \
return error; \
} \
} while (0)
#define LXW_WARN(message) \
LXW_PRINTF(LXW_STDERR "[WARNING]: " message "\n")
/* We can't use variadic macros here since we support ANSI C. */
#define LXW_WARN_FORMAT(message) \
LXW_PRINTF(LXW_STDERR "[WARNING]: " message "\n")
#define LXW_WARN_FORMAT1(message, var) \
LXW_PRINTF(LXW_STDERR "[WARNING]: " message "\n", var)
#define LXW_WARN_FORMAT2(message, var1, var2) \
LXW_PRINTF(LXW_STDERR "[WARNING]: " message "\n", var1, var2)
#define LXW_WARN_FORMAT3(message, var1, var2, var3) \
LXW_PRINTF(LXW_STDERR "[WARNING]: " message "\n", var1, var2, var3)
/* Chart axis type checks. */
#define LXW_WARN_CAT_AXIS_ONLY(function) \
do { \
if (!axis->is_category) { \
LXW_PRINTF(LXW_STDERR "[WARNING]: " \
function "() is only valid for category axes\n"); \
return; \
} \
} while (0)
#define LXW_WARN_VALUE_AXIS_ONLY(function) \
do { \
if (!axis->is_value) { \
LXW_PRINTF(LXW_STDERR "[WARNING]: " \
function "() is only valid for value axes\n"); \
return; \
} \
} while (0)
#define LXW_WARN_DATE_AXIS_ONLY(function) \
do { \
if (!axis->is_date) { \
LXW_PRINTF(LXW_STDERR "[WARNING]: " \
function "() is only valid for date axes\n"); \
return; \
} \
} while (0)
#define LXW_WARN_CAT_AND_DATE_AXIS_ONLY(function) \
do { \
if (!axis->is_category && !axis->is_date) { \
LXW_PRINTF(LXW_STDERR "[WARNING]: " \
function "() is only valid for category and date axes\n"); \
return; \
} \
} while (0)
#define LXW_WARN_VALUE_AND_DATE_AXIS_ONLY(function) \
do { \
if (!axis->is_value && !axis->is_date) { \
LXW_PRINTF(LXW_STDERR "[WARNING]: " \
function "() is only valid for value and date axes\n"); \
return; \
} \
} while (0)
#ifndef LXW_BIG_ENDIAN
#define LXW_UINT16_HOST(n) (n)
#define LXW_UINT32_HOST(n) (n)
#define LXW_UINT16_NETWORK(n) ((((n) & 0x00FF) << 8) | (((n) & 0xFF00) >> 8))
#define LXW_UINT32_NETWORK(n) ((((n) & 0xFF) << 24) | \
(((n) & 0xFF00) << 8) | \
(((n) & 0xFF0000) >> 8) | \
(((n) & 0xFF000000) >> 24))
#else
#define LXW_UINT16_NETWORK(n) (n)
#define LXW_UINT32_NETWORK(n) (n)
#define LXW_UINT16_HOST(n) ((((n) & 0x00FF) << 8) | (((n) & 0xFF00) >> 8))
#define LXW_UINT32_HOST(n) ((((n) & 0xFF) << 24) | \
(((n) & 0xFF00) << 8) | \
(((n) & 0xFF0000) >> 8) | \
(((n) & 0xFF000000) >> 24))
#endif
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/* Compilers that have a native snprintf() can use it directly. */
#ifdef _MSC_VER
#define LXW_HAS_SNPRINTF
#endif
#ifdef LXW_HAS_SNPRINTF
#define lxw_snprintf snprintf
#else
#define lxw_snprintf __builtin_snprintf
#endif
/* Define a snprintf for MSVC 2010. */
#if defined(_MSC_VER) && _MSC_VER < 1900
#include <stdarg.h>
#define snprintf msvc2010_snprintf
#define vsnprintf msvc2010_vsnprintf
__inline int
msvc2010_vsnprintf(char *str, size_t size, const char *format, va_list ap)
{
int count = -1;
if (size != 0)
count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
if (count == -1)
count = _vscprintf(format, ap);
return count;
}
__inline int
msvc2010_snprintf(char *str, size_t size, const char *format, ...)
{
int count;
va_list ap;
va_start(ap, format);
count = msvc2010_vsnprintf(str, size, format, ap);
va_end(ap);
return count;
}
#endif
/* Safer strcpy for fixed width char arrays. */
#define lxw_strcpy(dest, src) \
lxw_snprintf(dest, sizeof(dest), "%s", src)
/* Define the queue.h structs for the formats list. */
STAILQ_HEAD(lxw_formats, lxw_format);
/* Define the queue.h structs for the generic data structs. */
STAILQ_HEAD(lxw_tuples, lxw_tuple);
STAILQ_HEAD(lxw_custom_properties, lxw_custom_property);
typedef struct lxw_tuple {
char *key;
char *value;
STAILQ_ENTRY (lxw_tuple) list_pointers;
} lxw_tuple;
/* Define custom property used in workbook.c and custom.c. */
typedef struct lxw_custom_property {
enum lxw_custom_property_types type;
char *name;
union {
char *string;
double number;
int32_t integer;
uint8_t boolean;
lxw_datetime datetime;
} u;
STAILQ_ENTRY (lxw_custom_property) list_pointers;
} lxw_custom_property;
/* Declarations required for unit testing. */
#ifdef TESTING
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_COMMON_H__ */

View File

@ -0,0 +1,82 @@
/*
* libxlsxwriter
*
* Copyright 2014-2021, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* content_types - A libxlsxwriter library for creating Excel XLSX
* content_types files.
*
*/
#ifndef __LXW_CONTENT_TYPES_H__
#define __LXW_CONTENT_TYPES_H__
#include <stdint.h>
#include <string.h>
#include "common.h"
#define LXW_APP_PACKAGE "application/vnd.openxmlformats-package."
#define LXW_APP_DOCUMENT "application/vnd.openxmlformats-officedocument."
#define LXW_APP_MSEXCEL "application/vnd.ms-excel."
/*
* Struct to represent a content_types.
*/
typedef struct lxw_content_types {
FILE *file;
struct lxw_tuples *default_types;
struct lxw_tuples *overrides;
} lxw_content_types;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_content_types *lxw_content_types_new(void);
void lxw_content_types_free(lxw_content_types *content_types);
void lxw_content_types_assemble_xml_file(lxw_content_types *content_types);
void lxw_ct_add_default(lxw_content_types *content_types, const char *key,
const char *value);
void lxw_ct_add_override(lxw_content_types *content_types, const char *key,
const char *value);
void lxw_ct_add_worksheet_name(lxw_content_types *content_types,
const char *name);
void lxw_ct_add_chartsheet_name(lxw_content_types *content_types,
const char *name);
void lxw_ct_add_chart_name(lxw_content_types *content_types,
const char *name);
void lxw_ct_add_drawing_name(lxw_content_types *content_types,
const char *name);
void lxw_ct_add_comment_name(lxw_content_types *content_types,
const char *name);
void lxw_ct_add_vml_name(lxw_content_types *content_types);
void lxw_ct_add_shared_strings(lxw_content_types *content_types);
void lxw_ct_add_calc_chain(lxw_content_types *content_types);
void lxw_ct_add_custom_properties(lxw_content_types *content_types);
void lxw_ct_add_metadata(lxw_content_types *content_types);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _content_types_xml_declaration(lxw_content_types *self);
STATIC void _write_default(lxw_content_types *self, const char *ext,
const char *type);
STATIC void _write_override(lxw_content_types *self, const char *part_name,
const char *type);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_CONTENT_TYPES_H__ */

View File

@ -0,0 +1,51 @@
/*
* libxlsxwriter
*
* Copyright 2014-2021, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* core - A libxlsxwriter library for creating Excel XLSX core files.
*
*/
#ifndef __LXW_CORE_H__
#define __LXW_CORE_H__
#include <stdint.h>
#include "workbook.h"
#include "common.h"
/*
* Struct to represent a core.
*/
typedef struct lxw_core {
FILE *file;
lxw_doc_properties *properties;
} lxw_core;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_core *lxw_core_new(void);
void lxw_core_free(lxw_core *core);
void lxw_core_assemble_xml_file(lxw_core *self);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _core_xml_declaration(lxw_core *self);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_CORE_H__ */

View File

@ -0,0 +1,52 @@
/*
* libxlsxwriter
*
* Copyright 2014-2021, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* custom - A libxlsxwriter library for creating Excel custom property files.
*
*/
#ifndef __LXW_CUSTOM_H__
#define __LXW_CUSTOM_H__
#include <stdint.h>
#include "common.h"
/*
* Struct to represent a custom property file object.
*/
typedef struct lxw_custom {
FILE *file;
struct lxw_custom_properties *custom_properties;
uint32_t pid;
} lxw_custom;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_custom *lxw_custom_new(void);
void lxw_custom_free(lxw_custom *custom);
void lxw_custom_assemble_xml_file(lxw_custom *self);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _custom_xml_declaration(lxw_custom *self);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_CUSTOM_H__ */

View File

@ -0,0 +1,103 @@
/*
* libxlsxwriter
*
* Copyright 2014-2021, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* drawing - A libxlsxwriter library for creating Excel XLSX drawing files.
*
*/
#ifndef __LXW_DRAWING_H__
#define __LXW_DRAWING_H__
#include <stdint.h>
#include <string.h>
#include "common.h"
STAILQ_HEAD(lxw_drawing_objects, lxw_drawing_object);
enum lxw_drawing_types {
LXW_DRAWING_NONE = 0,
LXW_DRAWING_IMAGE,
LXW_DRAWING_CHART,
LXW_DRAWING_SHAPE
};
enum image_types {
LXW_IMAGE_UNKNOWN = 0,
LXW_IMAGE_PNG,
LXW_IMAGE_JPEG,
LXW_IMAGE_BMP,
LXW_IMAGE_GIF
};
/* Coordinates used in a drawing object. */
typedef struct lxw_drawing_coords {
uint32_t col;
uint32_t row;
double col_offset;
double row_offset;
} lxw_drawing_coords;
/* Object to represent the properties of a drawing. */
typedef struct lxw_drawing_object {
uint8_t type;
uint8_t anchor;
struct lxw_drawing_coords from;
struct lxw_drawing_coords to;
uint32_t col_absolute;
uint32_t row_absolute;
uint32_t width;
uint32_t height;
uint8_t shape;
uint32_t rel_index;
uint32_t url_rel_index;
char *description;
char *tip;
uint8_t decorative;
STAILQ_ENTRY (lxw_drawing_object) list_pointers;
} lxw_drawing_object;
/*
* Struct to represent a collection of drawings.
*/
typedef struct lxw_drawing {
FILE *file;
uint8_t embedded;
uint8_t orientation;
struct lxw_drawing_objects *drawing_objects;
} lxw_drawing;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_drawing *lxw_drawing_new(void);
void lxw_drawing_free(lxw_drawing *drawing);
void lxw_drawing_assemble_xml_file(lxw_drawing *self);
void lxw_free_drawing_object(struct lxw_drawing_object *drawing_object);
void lxw_add_drawing_object(lxw_drawing *drawing,
lxw_drawing_object *drawing_object);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _drawing_xml_declaration(lxw_drawing *self);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_DRAWING_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,76 @@
/*
* libxlsxwriter
*
* Copyright 2014-2021, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* hash_table - Hash table functions for libxlsxwriter.
*
*/
#ifndef __LXW_HASH_TABLE_H__
#define __LXW_HASH_TABLE_H__
#include "common.h"
/* Macro to loop over hash table elements in insertion order. */
#define LXW_FOREACH_ORDERED(elem, hash_table) \
STAILQ_FOREACH((elem), (hash_table)->order_list, lxw_hash_order_pointers)
/* List declarations. */
STAILQ_HEAD(lxw_hash_order_list, lxw_hash_element);
SLIST_HEAD(lxw_hash_bucket_list, lxw_hash_element);
/* LXW_HASH hash table struct. */
typedef struct lxw_hash_table {
uint32_t num_buckets;
uint32_t used_buckets;
uint32_t unique_count;
uint8_t free_key;
uint8_t free_value;
struct lxw_hash_order_list *order_list;
struct lxw_hash_bucket_list **buckets;
} lxw_hash_table;
/*
* LXW_HASH table element struct.
*
* The hash elements contain pointers to allow them to be stored in
* lists in the the hash table buckets and also pointers to track the
* insertion order in a separate list.
*/
typedef struct lxw_hash_element {
void *key;
void *value;
STAILQ_ENTRY (lxw_hash_element) lxw_hash_order_pointers;
SLIST_ENTRY (lxw_hash_element) lxw_hash_list_pointers;
} lxw_hash_element;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_hash_element *lxw_hash_key_exists(lxw_hash_table *lxw_hash, void *key,
size_t key_len);
lxw_hash_element *lxw_insert_hash_element(lxw_hash_table *lxw_hash, void *key,
void *value, size_t key_len);
lxw_hash_table *lxw_hash_new(uint32_t num_buckets, uint8_t free_key,
uint8_t free_value);
void lxw_hash_free(lxw_hash_table *lxw_hash);
/* Declarations required for unit testing. */
#ifdef TESTING
#endif
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_HASH_TABLE_H__ */

View File

@ -0,0 +1,49 @@
/*
* libxlsxwriter
*
* Copyright 2014-2021, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* metadata - A libxlsxwriter library for creating Excel XLSX metadata files.
*
*/
#ifndef __LXW_METADATA_H__
#define __LXW_METADATA_H__
#include <stdint.h>
#include "common.h"
/*
* Struct to represent a metadata object.
*/
typedef struct lxw_metadata {
FILE *file;
} lxw_metadata;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_metadata *lxw_metadata_new(void);
void lxw_metadata_free(lxw_metadata *metadata);
void lxw_metadata_assemble_xml_file(lxw_metadata *self);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _metadata_xml_declaration(lxw_metadata *self);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_METADATA_H__ */

View File

@ -0,0 +1,95 @@
/*
* libxlsxwriter
*
* Copyright 2014-2021, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* packager - A libxlsxwriter library for creating Excel XLSX packager files.
*
*/
#ifndef __LXW_PACKAGER_H__
#define __LXW_PACKAGER_H__
#include <stdint.h>
#ifdef USE_SYSTEM_MINIZIP
#include "minizip/zip.h"
#else
#include "third_party/zip.h"
#endif
#include "common.h"
#include "workbook.h"
#include "worksheet.h"
#include "shared_strings.h"
#include "app.h"
#include "core.h"
#include "custom.h"
#include "theme.h"
#include "styles.h"
#include "format.h"
#include "content_types.h"
#include "relationships.h"
#include "vml.h"
#include "comment.h"
#include "metadata.h"
#define LXW_ZIP_BUFFER_SIZE (16384)
/* If zip returns a ZIP_XXX error then errno is set and we can trap that in
* workbook.c. Otherwise return a default libxlsxwriter error. */
#define RETURN_ON_ZIP_ERROR(err, default_err) \
do { \
if (err == ZIP_ERRNO) \
return LXW_ERROR_ZIP_FILE_OPERATION; \
else if (err == ZIP_PARAMERROR) \
return LXW_ERROR_ZIP_PARAMETER_ERROR; \
else if (err == ZIP_BADZIPFILE) \
return LXW_ERROR_ZIP_BAD_ZIP_FILE; \
else if (err == ZIP_INTERNALERROR) \
return LXW_ERROR_ZIP_INTERNAL_ERROR; \
else \
return default_err; \
} while (0)
/*
* Struct to represent a packager.
*/
typedef struct lxw_packager {
FILE *file;
lxw_workbook *workbook;
size_t buffer_size;
zipFile zipfile;
zip_fileinfo zipfile_info;
char *filename;
char *buffer;
char *tmpdir;
uint8_t use_zip64;
} lxw_packager;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_packager *lxw_packager_new(const char *filename, char *tmpdir,
uint8_t use_zip64);
void lxw_packager_free(lxw_packager *packager);
lxw_error lxw_create_package(lxw_packager *self);
/* Declarations required for unit testing. */
#ifdef TESTING
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_PACKAGER_H__ */

View File

@ -0,0 +1,77 @@
/*
* libxlsxwriter
*
* Copyright 2014-2021, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* relationships - A libxlsxwriter library for creating Excel XLSX
* relationships files.
*
*/
#ifndef __LXW_RELATIONSHIPS_H__
#define __LXW_RELATIONSHIPS_H__
#include <stdint.h>
#include "common.h"
/* Define the queue.h STAILQ structs for the generic data structs. */
STAILQ_HEAD(lxw_rel_tuples, lxw_rel_tuple);
typedef struct lxw_rel_tuple {
char *type;
char *target;
char *target_mode;
STAILQ_ENTRY (lxw_rel_tuple) list_pointers;
} lxw_rel_tuple;
/*
* Struct to represent a relationships.
*/
typedef struct lxw_relationships {
FILE *file;
uint32_t rel_id;
struct lxw_rel_tuples *relationships;
} lxw_relationships;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_relationships *lxw_relationships_new(void);
void lxw_free_relationships(lxw_relationships *relationships);
void lxw_relationships_assemble_xml_file(lxw_relationships *self);
void lxw_add_document_relationship(lxw_relationships *self, const char *type,
const char *target);
void lxw_add_package_relationship(lxw_relationships *self, const char *type,
const char *target);
void lxw_add_ms_package_relationship(lxw_relationships *self,
const char *type, const char *target);
void lxw_add_worksheet_relationship(lxw_relationships *self, const char *type,
const char *target,
const char *target_mode);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _relationships_xml_declaration(lxw_relationships *self);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_RELATIONSHIPS_H__ */

View File

@ -0,0 +1,85 @@
/*
* libxlsxwriter
*
* Copyright 2014-2021, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* shared_strings - A libxlsxwriter library for creating Excel XLSX
* sst files.
*
*/
#ifndef __LXW_SST_H__
#define __LXW_SST_H__
#include <string.h>
#include <stdint.h>
#include "common.h"
/* Define a tree.h RB structure for storing shared strings. */
RB_HEAD(sst_rb_tree, sst_element);
/* Define a queue.h structure for storing shared strings in insertion order. */
STAILQ_HEAD(sst_order_list, sst_element);
/* Wrapper around RB_GENERATE_STATIC from tree.h to avoid unused function
* warnings and to avoid portability issues with the _unused attribute. */
#define LXW_RB_GENERATE_ELEMENT(name, type, field, cmp) \
RB_GENERATE_INSERT_COLOR(name, type, field, static) \
RB_GENERATE_INSERT(name, type, field, cmp, static) \
/* Add unused struct to allow adding a semicolon */ \
struct lxw_rb_generate_element{int unused;}
/*
* Elements of the SST table. They contain pointers to allow them to
* be stored in a RB tree and also pointers to track the insertion order
* in a separate list.
*/
struct sst_element {
uint32_t index;
char *string;
uint8_t is_rich_string;
STAILQ_ENTRY (sst_element) sst_order_pointers;
RB_ENTRY (sst_element) sst_tree_pointers;
};
/*
* Struct to represent a sst.
*/
typedef struct lxw_sst {
FILE *file;
uint32_t string_count;
uint32_t unique_count;
struct sst_order_list *order_list;
struct sst_rb_tree *rb_tree;
} lxw_sst;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_sst *lxw_sst_new(void);
void lxw_sst_free(lxw_sst *sst);
struct sst_element *lxw_get_sst_index(lxw_sst *sst, const char *string,
uint8_t is_rich_string);
void lxw_sst_assemble_xml_file(lxw_sst *self);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _sst_xml_declaration(lxw_sst *self);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_SST_H__ */

View File

@ -0,0 +1,88 @@
/*
* libxlsxwriter
*
* Copyright 2014-2021, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* styles - A libxlsxwriter library for creating Excel XLSX styles files.
*
*/
#ifndef __LXW_STYLES_H__
#define __LXW_STYLES_H__
#include <stdint.h>
#include <ctype.h>
#include "format.h"
/*
* Struct to represent a styles.
*/
typedef struct lxw_styles {
FILE *file;
uint32_t font_count;
uint32_t xf_count;
uint32_t dxf_count;
uint32_t num_format_count;
uint32_t border_count;
uint32_t fill_count;
struct lxw_formats *xf_formats;
struct lxw_formats *dxf_formats;
uint8_t has_hyperlink;
uint16_t hyperlink_font_id;
uint8_t has_comments;
} lxw_styles;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_styles *lxw_styles_new(void);
void lxw_styles_free(lxw_styles *styles);
void lxw_styles_assemble_xml_file(lxw_styles *self);
void lxw_styles_write_string_fragment(lxw_styles *self, char *string);
void lxw_styles_write_rich_font(lxw_styles *styles, lxw_format *format);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _styles_xml_declaration(lxw_styles *self);
STATIC void _write_style_sheet(lxw_styles *self);
STATIC void _write_font_size(lxw_styles *self, double font_size);
STATIC void _write_font_color_theme(lxw_styles *self, uint8_t theme);
STATIC void _write_font_name(lxw_styles *self, const char *font_name,
uint8_t is_rich_string);
STATIC void _write_font_family(lxw_styles *self, uint8_t font_family);
STATIC void _write_font_scheme(lxw_styles *self, const char *font_scheme);
STATIC void _write_font(lxw_styles *self, lxw_format *format, uint8_t is_dxf,
uint8_t is_rich_string);
STATIC void _write_fonts(lxw_styles *self);
STATIC void _write_default_fill(lxw_styles *self, const char *pattern);
STATIC void _write_fills(lxw_styles *self);
STATIC void _write_border(lxw_styles *self, lxw_format *format,
uint8_t is_dxf);
STATIC void _write_borders(lxw_styles *self);
STATIC void _write_style_xf(lxw_styles *self, uint8_t has_hyperlink,
uint16_t font_id);
STATIC void _write_cell_style_xfs(lxw_styles *self);
STATIC void _write_xf(lxw_styles *self, lxw_format *format);
STATIC void _write_cell_xfs(lxw_styles *self);
STATIC void _write_cell_style(lxw_styles *self, char *name, uint8_t xf_id,
uint8_t builtin_id);
STATIC void _write_cell_styles(lxw_styles *self);
STATIC void _write_dxfs(lxw_styles *self);
STATIC void _write_table_styles(lxw_styles *self);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_STYLES_H__ */

View File

@ -0,0 +1,47 @@
/*
* libxlsxwriter
*
* Copyright 2014-2021, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* theme - A libxlsxwriter library for creating Excel XLSX theme files.
*
*/
#ifndef __LXW_THEME_H__
#define __LXW_THEME_H__
#include <stdint.h>
#include "common.h"
/*
* Struct to represent a theme.
*/
typedef struct lxw_theme {
FILE *file;
} lxw_theme;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_theme *lxw_theme_new(void);
void lxw_theme_free(lxw_theme *theme);
void lxw_theme_xml_declaration(lxw_theme *self);
void lxw_theme_assemble_xml_file(lxw_theme *self);
/* Declarations required for unit testing. */
#ifdef TESTING
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_THEME_H__ */

View File

@ -0,0 +1,26 @@
/* emyg_dtoa.h
** Copyright (C) 2015 Doug Currie
** based on dtoa_milo.h
** Copyright (C) 2014 Milo Yip
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
** THE SOFTWARE.
*/
/* Source from https://github.com/miloyip/dtoa-benchmark */
void emyg_dtoa (double value, char* buffer);

View File

@ -0,0 +1,218 @@
/* ioapi.h -- IO base function header for compress/uncompress .zip
part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
Modifications for Zip64 support
Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
For more info read MiniZip_info.txt
Changes
Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this)
Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux.
More if/def section may be needed to support other platforms
Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows.
(but you should use iowin32.c for windows instead)
*/
/* Pragma added by libxlsxwriter to avoid warnings with -pedantic -ansi. */
#ifndef _WIN32
#pragma GCC system_header
#endif
#ifndef _ZLIBIOAPI64_H
#define _ZLIBIOAPI64_H
#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
// Linux needs this to support file operation on files larger then 4+GB
// But might need better if/def to select just the platforms that needs them.
#ifndef __USE_FILE_OFFSET64
#define __USE_FILE_OFFSET64
#endif
#ifndef __USE_LARGEFILE64
#define __USE_LARGEFILE64
#endif
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#ifndef _FILE_OFFSET_BIT
#define _FILE_OFFSET_BIT 64
#endif
#endif
#include <stdio.h>
#include <stdlib.h>
#include "zlib.h"
#if defined(USE_FILE32API)
#define fopen64 fopen
#define ftello64 ftell
#define fseeko64 fseek
#else
#if defined(__FreeBSD__) || defined(__OpenBSD__)
#define fopen64 fopen
#define ftello64 ftello
#define fseeko64 fseeko
#endif
#ifdef _MSC_VER
#define fopen64 fopen
#if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))
#define ftello64 _ftelli64
#define fseeko64 _fseeki64
#else // old MSC
#define ftello64 ftell
#define fseeko64 fseek
#endif
#endif
#endif
/*
#ifndef ZPOS64_T
#ifdef _WIN32
#define ZPOS64_T fpos_t
#else
#include <stdint.h>
#define ZPOS64_T uint64_t
#endif
#endif
*/
#ifdef HAVE_MINIZIP64_CONF_H
#include "mz64conf.h"
#endif
/* a type choosen by DEFINE */
#ifdef HAVE_64BIT_INT_CUSTOM
typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T;
#else
#ifdef HAS_STDINT_H
#include "stdint.h"
typedef uint64_t ZPOS64_T;
#else
/* Maximum unsigned 32-bit value used as placeholder for zip64 */
#define MAXU32 0xffffffff
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef unsigned __int64 ZPOS64_T;
#else
typedef unsigned long long int ZPOS64_T;
#endif
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define ZLIB_FILEFUNC_SEEK_CUR (1)
#define ZLIB_FILEFUNC_SEEK_END (2)
#define ZLIB_FILEFUNC_SEEK_SET (0)
#define ZLIB_FILEFUNC_MODE_READ (1)
#define ZLIB_FILEFUNC_MODE_WRITE (2)
#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
#define ZLIB_FILEFUNC_MODE_EXISTING (4)
#define ZLIB_FILEFUNC_MODE_CREATE (8)
#ifndef ZCALLBACK
#if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
#define ZCALLBACK CALLBACK
#else
#define ZCALLBACK
#endif
#endif
/* Workaround for modified zconf.h on Gentoo system. */
#if defined(_Z_OF)
#define OF _Z_OF
#endif
typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
/* here is the "old" 32 bits structure structure */
typedef struct zlib_filefunc_def_s
{
open_file_func zopen_file;
read_file_func zread_file;
write_file_func zwrite_file;
tell_file_func ztell_file;
seek_file_func zseek_file;
close_file_func zclose_file;
testerror_file_func zerror_file;
voidpf opaque;
} zlib_filefunc_def;
typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream));
typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode));
typedef struct zlib_filefunc64_def_s
{
open64_file_func zopen64_file;
read_file_func zread_file;
write_file_func zwrite_file;
tell64_file_func ztell64_file;
seek64_file_func zseek64_file;
close_file_func zclose_file;
testerror_file_func zerror_file;
voidpf opaque;
} zlib_filefunc64_def;
void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def));
void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
/* now internal definition, only for zip.c and unzip.h */
typedef struct zlib_filefunc64_32_def_s
{
zlib_filefunc64_def zfile_func64;
open_file_func zopen32_file;
tell_file_func ztell32_file;
seek_file_func zseek32_file;
} zlib_filefunc64_32_def;
#define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
#define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
/* #define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream)) */
/* #define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode)) */
#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream))
#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream))
voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode));
long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin));
ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream));
void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32);
#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode)))
#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream)))
#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode)))
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,45 @@
/*
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
* MD5 Message-Digest Algorithm (RFC 1321).
*
* Homepage:
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* See md5.c for more information.
*/
#ifdef HAVE_OPENSSL
#include <openssl/md5.h>
#elif !defined(_MD5_H)
#define _MD5_H
/* Any 32-bit or wider unsigned integer data type will do */
typedef unsigned int MD5_u32plus;
typedef struct {
MD5_u32plus lo, hi;
MD5_u32plus a, b, c, d;
unsigned char buffer[64];
MD5_u32plus block[16];
} MD5_CTX;
extern void MD5_Init(MD5_CTX *ctx);
extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
#endif

View File

@ -0,0 +1,694 @@
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)queue.h 8.5 (Berkeley) 8/20/94
* $FreeBSD$
*/
#ifndef _SYS_QUEUE_H_
#define _SYS_QUEUE_H_
/* #include <sys/cdefs.h> */
/*
* This file defines four types of data structures: singly-linked lists,
* singly-linked tail queues, lists and tail queues.
*
* A singly-linked list is headed by a single forward pointer. The elements
* are singly linked for minimum space and pointer manipulation overhead at
* the expense of O(n) removal for arbitrary elements. New elements can be
* added to the list after an existing element or at the head of the list.
* Elements being removed from the head of the list should use the explicit
* macro for this purpose for optimum efficiency. A singly-linked list may
* only be traversed in the forward direction. Singly-linked lists are ideal
* for applications with large datasets and few or no removals or for
* implementing a LIFO queue.
*
* A singly-linked tail queue is headed by a pair of pointers, one to the
* head of the list and the other to the tail of the list. The elements are
* singly linked for minimum space and pointer manipulation overhead at the
* expense of O(n) removal for arbitrary elements. New elements can be added
* to the list after an existing element, at the head of the list, or at the
* end of the list. Elements being removed from the head of the tail queue
* should use the explicit macro for this purpose for optimum efficiency.
* A singly-linked tail queue may only be traversed in the forward direction.
* Singly-linked tail queues are ideal for applications with large datasets
* and few or no removals or for implementing a FIFO queue.
*
* A list is headed by a single forward pointer (or an array of forward
* pointers for a hash table header). The elements are doubly linked
* so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before
* or after an existing element or at the head of the list. A list
* may be traversed in either direction.
*
* A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or
* after an existing element, at the head of the list, or at the end of
* the list. A tail queue may be traversed in either direction.
*
* For details on the use of these macros, see the queue(3) manual page.
*
*
* SLIST LIST STAILQ TAILQ
* _HEAD + + + +
* _HEAD_INITIALIZER + + + +
* _ENTRY + + + +
* _INIT + + + +
* _EMPTY + + + +
* _FIRST + + + +
* _NEXT + + + +
* _PREV - + - +
* _LAST - - + +
* _FOREACH + + + +
* _FOREACH_FROM + + + +
* _FOREACH_SAFE + + + +
* _FOREACH_FROM_SAFE + + + +
* _FOREACH_REVERSE - - - +
* _FOREACH_REVERSE_FROM - - - +
* _FOREACH_REVERSE_SAFE - - - +
* _FOREACH_REVERSE_FROM_SAFE - - - +
* _INSERT_HEAD + + + +
* _INSERT_BEFORE - + - +
* _INSERT_AFTER + + + +
* _INSERT_TAIL - - + +
* _CONCAT - - + +
* _REMOVE_AFTER + - + -
* _REMOVE_HEAD + - + -
* _REMOVE + + + +
* _SWAP + + + +
*
*/
#ifdef QUEUE_MACRO_DEBUG
/* Store the last 2 places the queue element or head was altered */
struct qm_trace {
unsigned long lastline;
unsigned long prevline;
const char *lastfile;
const char *prevfile;
};
#define TRACEBUF struct qm_trace trace;
#define TRACEBUF_INITIALIZER { __FILE__, __LINE__, NULL, 0 } ,
#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
#define QMD_TRACE_HEAD(head) do { \
(head)->trace.prevline = (head)->trace.lastline; \
(head)->trace.prevfile = (head)->trace.lastfile; \
(head)->trace.lastline = __LINE__; \
(head)->trace.lastfile = __FILE__; \
} while (0)
#define QMD_TRACE_ELEM(elem) do { \
(elem)->trace.prevline = (elem)->trace.lastline; \
(elem)->trace.prevfile = (elem)->trace.lastfile; \
(elem)->trace.lastline = __LINE__; \
(elem)->trace.lastfile = __FILE__; \
} while (0)
#else
#define QMD_TRACE_ELEM(elem)
#define QMD_TRACE_HEAD(head)
#define QMD_SAVELINK(name, link)
#define TRACEBUF
#define TRACEBUF_INITIALIZER
#define TRASHIT(x)
#endif /* QUEUE_MACRO_DEBUG */
/*
* Singly-linked List declarations.
*/
#define SLIST_HEAD(name, type) \
struct name { \
struct type *slh_first; /* first element */ \
}
#define SLIST_HEAD_INITIALIZER(head) \
{ NULL }
#define SLIST_ENTRY(type) \
struct { \
struct type *sle_next; /* next element */ \
}
/*
* Singly-linked List functions.
*/
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
#define SLIST_FIRST(head) ((head)->slh_first)
#define SLIST_FOREACH(var, head, field) \
for ((var) = SLIST_FIRST((head)); \
(var); \
(var) = SLIST_NEXT((var), field))
#define SLIST_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
(var); \
(var) = SLIST_NEXT((var), field))
#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = SLIST_FIRST((head)); \
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
(var) = (tvar))
#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
(var) = (tvar))
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
for ((varp) = &SLIST_FIRST((head)); \
((var) = *(varp)) != NULL; \
(varp) = &SLIST_NEXT((var), field))
#define SLIST_INIT(head) do { \
SLIST_FIRST((head)) = NULL; \
} while (0)
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
SLIST_NEXT((slistelm), field) = (elm); \
} while (0)
#define SLIST_INSERT_HEAD(head, elm, field) do { \
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
SLIST_FIRST((head)) = (elm); \
} while (0)
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define SLIST_REMOVE(head, elm, type, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
if (SLIST_FIRST((head)) == (elm)) { \
SLIST_REMOVE_HEAD((head), field); \
} \
else { \
struct type *curelm = SLIST_FIRST((head)); \
while (SLIST_NEXT(curelm, field) != (elm)) \
curelm = SLIST_NEXT(curelm, field); \
SLIST_REMOVE_AFTER(curelm, field); \
} \
TRASHIT(*oldnext); \
} while (0)
#define SLIST_REMOVE_AFTER(elm, field) do { \
SLIST_NEXT(elm, field) = \
SLIST_NEXT(SLIST_NEXT(elm, field), field); \
} while (0)
#define SLIST_REMOVE_HEAD(head, field) do { \
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
} while (0)
#define SLIST_SWAP(head1, head2, type) do { \
struct type *swap_first = SLIST_FIRST(head1); \
SLIST_FIRST(head1) = SLIST_FIRST(head2); \
SLIST_FIRST(head2) = swap_first; \
} while (0)
/*
* Singly-linked Tail queue declarations.
*/
#define STAILQ_HEAD(name, type) \
struct name { \
struct type *stqh_first;/* first element */ \
struct type **stqh_last;/* addr of last next element */ \
}
#define STAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).stqh_first }
#define STAILQ_ENTRY(type) \
struct { \
struct type *stqe_next; /* next element */ \
}
/*
* Singly-linked Tail queue functions.
*/
#define STAILQ_CONCAT(head1, head2) do { \
if (!STAILQ_EMPTY((head2))) { \
*(head1)->stqh_last = (head2)->stqh_first; \
(head1)->stqh_last = (head2)->stqh_last; \
STAILQ_INIT((head2)); \
} \
} while (0)
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
#define STAILQ_FIRST(head) ((head)->stqh_first)
#define STAILQ_FOREACH(var, head, field) \
for((var) = STAILQ_FIRST((head)); \
(var); \
(var) = STAILQ_NEXT((var), field))
#define STAILQ_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
(var); \
(var) = STAILQ_NEXT((var), field))
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = STAILQ_FIRST((head)); \
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define STAILQ_INIT(head) do { \
STAILQ_FIRST((head)) = NULL; \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_NEXT((tqelm), field) = (elm); \
} while (0)
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_FIRST((head)) = (elm); \
} while (0)
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
STAILQ_NEXT((elm), field) = NULL; \
*(head)->stqh_last = (elm); \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
#define STAILQ_LAST(head, type, field) \
(STAILQ_EMPTY((head)) ? NULL : \
__containerof((head)->stqh_last, struct type, field.stqe_next))
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
#define STAILQ_REMOVE(head, elm, type, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
if (STAILQ_FIRST((head)) == (elm)) { \
STAILQ_REMOVE_HEAD((head), field); \
} \
else { \
struct type *curelm = STAILQ_FIRST((head)); \
while (STAILQ_NEXT(curelm, field) != (elm)) \
curelm = STAILQ_NEXT(curelm, field); \
STAILQ_REMOVE_AFTER(head, curelm, field); \
} \
TRASHIT(*oldnext); \
} while (0)
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
if ((STAILQ_NEXT(elm, field) = \
STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
#define STAILQ_REMOVE_HEAD(head, field) do { \
if ((STAILQ_FIRST((head)) = \
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_SWAP(head1, head2, type) do { \
struct type *swap_first = STAILQ_FIRST(head1); \
struct type **swap_last = (head1)->stqh_last; \
STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \
(head1)->stqh_last = (head2)->stqh_last; \
STAILQ_FIRST(head2) = swap_first; \
(head2)->stqh_last = swap_last; \
if (STAILQ_EMPTY(head1)) \
(head1)->stqh_last = &STAILQ_FIRST(head1); \
if (STAILQ_EMPTY(head2)) \
(head2)->stqh_last = &STAILQ_FIRST(head2); \
} while (0)
/*
* List declarations.
*/
#define LIST_HEAD(name, type) \
struct name { \
struct type *lh_first; /* first element */ \
}
#define LIST_HEAD_INITIALIZER(head) \
{ NULL }
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
/*
* List functions.
*/
#if (defined(_KERNEL) && defined(INVARIANTS))
#define QMD_LIST_CHECK_HEAD(head, field) do { \
if (LIST_FIRST((head)) != NULL && \
LIST_FIRST((head))->field.le_prev != \
&LIST_FIRST((head))) \
panic("Bad list head %p first->prev != head", (head)); \
} while (0)
#define QMD_LIST_CHECK_NEXT(elm, field) do { \
if (LIST_NEXT((elm), field) != NULL && \
LIST_NEXT((elm), field)->field.le_prev != \
&((elm)->field.le_next)) \
panic("Bad link elm %p next->prev != elm", (elm)); \
} while (0)
#define QMD_LIST_CHECK_PREV(elm, field) do { \
if (*(elm)->field.le_prev != (elm)) \
panic("Bad link elm %p prev->next != elm", (elm)); \
} while (0)
#else
#define QMD_LIST_CHECK_HEAD(head, field)
#define QMD_LIST_CHECK_NEXT(elm, field)
#define QMD_LIST_CHECK_PREV(elm, field)
#endif /* (_KERNEL && INVARIANTS) */
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
#define LIST_FIRST(head) ((head)->lh_first)
#define LIST_FOREACH(var, head, field) \
for ((var) = LIST_FIRST((head)); \
(var); \
(var) = LIST_NEXT((var), field))
#define LIST_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
(var); \
(var) = LIST_NEXT((var), field))
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = LIST_FIRST((head)); \
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
(var) = (tvar))
#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
(var) = (tvar))
#define LIST_INIT(head) do { \
LIST_FIRST((head)) = NULL; \
} while (0)
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
QMD_LIST_CHECK_NEXT(listelm, field); \
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
LIST_NEXT((listelm), field)->field.le_prev = \
&LIST_NEXT((elm), field); \
LIST_NEXT((listelm), field) = (elm); \
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
} while (0)
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
QMD_LIST_CHECK_PREV(listelm, field); \
(elm)->field.le_prev = (listelm)->field.le_prev; \
LIST_NEXT((elm), field) = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
} while (0)
#define LIST_INSERT_HEAD(head, elm, field) do { \
QMD_LIST_CHECK_HEAD((head), field); \
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
LIST_FIRST((head)) = (elm); \
(elm)->field.le_prev = &LIST_FIRST((head)); \
} while (0)
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_PREV(elm, head, type, field) \
((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \
__containerof((elm)->field.le_prev, struct type, field.le_next))
#define LIST_REMOVE(elm, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.le_next); \
QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
QMD_LIST_CHECK_NEXT(elm, field); \
QMD_LIST_CHECK_PREV(elm, field); \
if (LIST_NEXT((elm), field) != NULL) \
LIST_NEXT((elm), field)->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
TRASHIT(*oldnext); \
TRASHIT(*oldprev); \
} while (0)
#define LIST_SWAP(head1, head2, type, field) do { \
struct type *swap_tmp = LIST_FIRST((head1)); \
LIST_FIRST((head1)) = LIST_FIRST((head2)); \
LIST_FIRST((head2)) = swap_tmp; \
if ((swap_tmp = LIST_FIRST((head1))) != NULL) \
swap_tmp->field.le_prev = &LIST_FIRST((head1)); \
if ((swap_tmp = LIST_FIRST((head2))) != NULL) \
swap_tmp->field.le_prev = &LIST_FIRST((head2)); \
} while (0)
/*
* Tail queue declarations.
*/
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
TRACEBUF \
}
#define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first, TRACEBUF_INITIALIZER }
#define TAILQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
TRACEBUF \
}
/*
* Tail queue functions.
*/
#if (defined(_KERNEL) && defined(INVARIANTS))
#define QMD_TAILQ_CHECK_HEAD(head, field) do { \
if (!TAILQ_EMPTY(head) && \
TAILQ_FIRST((head))->field.tqe_prev != \
&TAILQ_FIRST((head))) \
panic("Bad tailq head %p first->prev != head", (head)); \
} while (0)
#define QMD_TAILQ_CHECK_TAIL(head, field) do { \
if (*(head)->tqh_last != NULL) \
panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \
} while (0)
#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \
if (TAILQ_NEXT((elm), field) != NULL && \
TAILQ_NEXT((elm), field)->field.tqe_prev != \
&((elm)->field.tqe_next)) \
panic("Bad link elm %p next->prev != elm", (elm)); \
} while (0)
#define QMD_TAILQ_CHECK_PREV(elm, field) do { \
if (*(elm)->field.tqe_prev != (elm)) \
panic("Bad link elm %p prev->next != elm", (elm)); \
} while (0)
#else
#define QMD_TAILQ_CHECK_HEAD(head, field)
#define QMD_TAILQ_CHECK_TAIL(head, headname)
#define QMD_TAILQ_CHECK_NEXT(elm, field)
#define QMD_TAILQ_CHECK_PREV(elm, field)
#endif /* (_KERNEL && INVARIANTS) */
#define TAILQ_CONCAT(head1, head2, field) do { \
if (!TAILQ_EMPTY(head2)) { \
*(head1)->tqh_last = (head2)->tqh_first; \
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
(head1)->tqh_last = (head2)->tqh_last; \
TAILQ_INIT((head2)); \
QMD_TRACE_HEAD(head1); \
QMD_TRACE_HEAD(head2); \
} \
} while (0)
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_FOREACH(var, head, field) \
for ((var) = TAILQ_FIRST((head)); \
(var); \
(var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
(var); \
(var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = TAILQ_FIRST((head)); \
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for ((var) = TAILQ_LAST((head), headname); \
(var); \
(var) = TAILQ_PREV((var), headname, field))
#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
(var); \
(var) = TAILQ_PREV((var), headname, field))
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
for ((var) = TAILQ_LAST((head), headname); \
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
(var) = (tvar))
#define TAILQ_INIT(head) do { \
TAILQ_FIRST((head)) = NULL; \
(head)->tqh_last = &TAILQ_FIRST((head)); \
QMD_TRACE_HEAD(head); \
} while (0)
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
QMD_TAILQ_CHECK_NEXT(listelm, field); \
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
TAILQ_NEXT((elm), field)->field.tqe_prev = \
&TAILQ_NEXT((elm), field); \
else { \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
QMD_TRACE_HEAD(head); \
} \
TAILQ_NEXT((listelm), field) = (elm); \
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
QMD_TRACE_ELEM(&(elm)->field); \
QMD_TRACE_ELEM(&listelm->field); \
} while (0)
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
QMD_TAILQ_CHECK_PREV(listelm, field); \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
TAILQ_NEXT((elm), field) = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
QMD_TRACE_ELEM(&(elm)->field); \
QMD_TRACE_ELEM(&listelm->field); \
} while (0)
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
QMD_TAILQ_CHECK_HEAD(head, field); \
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
TAILQ_FIRST((head))->field.tqe_prev = \
&TAILQ_NEXT((elm), field); \
else \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
TAILQ_FIRST((head)) = (elm); \
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
QMD_TRACE_HEAD(head); \
QMD_TRACE_ELEM(&(elm)->field); \
} while (0)
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
QMD_TAILQ_CHECK_TAIL(head, field); \
TAILQ_NEXT((elm), field) = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
QMD_TRACE_HEAD(head); \
QMD_TRACE_ELEM(&(elm)->field); \
} while (0)
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_REMOVE(head, elm, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
QMD_TAILQ_CHECK_NEXT(elm, field); \
QMD_TAILQ_CHECK_PREV(elm, field); \
if ((TAILQ_NEXT((elm), field)) != NULL) \
TAILQ_NEXT((elm), field)->field.tqe_prev = \
(elm)->field.tqe_prev; \
else { \
(head)->tqh_last = (elm)->field.tqe_prev; \
QMD_TRACE_HEAD(head); \
} \
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
TRASHIT(*oldnext); \
TRASHIT(*oldprev); \
QMD_TRACE_ELEM(&(elm)->field); \
} while (0)
#define TAILQ_SWAP(head1, head2, type, field) do { \
struct type *swap_first = (head1)->tqh_first; \
struct type **swap_last = (head1)->tqh_last; \
(head1)->tqh_first = (head2)->tqh_first; \
(head1)->tqh_last = (head2)->tqh_last; \
(head2)->tqh_first = swap_first; \
(head2)->tqh_last = swap_last; \
if ((swap_first = (head1)->tqh_first) != NULL) \
swap_first->field.tqe_prev = &(head1)->tqh_first; \
else \
(head1)->tqh_last = &(head1)->tqh_first; \
if ((swap_first = (head2)->tqh_first) != NULL) \
swap_first->field.tqe_prev = &(head2)->tqh_first; \
else \
(head2)->tqh_last = &(head2)->tqh_first; \
} while (0)
#endif /* !_SYS_QUEUE_H_ */

View File

@ -0,0 +1,53 @@
/* $Id: tmpfileplus.h $ */
/*
* $Date: 2016-06-01 03:31Z $
* $Revision: 2.0.0 $
* $Author: dai $
*/
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright (c) 2012-16 David Ireland, DI Management Services Pty Ltd
* <http://www.di-mgt.com.au/contact/>.
*/
#if _MSC_VER > 1000
#pragma once
#endif
#ifndef TMPFILEPLUS_H_
#define TMPFILEPLUS_H_
#include <stdio.h>
/** Create a unique temporary file.
@param dir (optional) directory to create file. If NULL use default TMP directory.
@param prefix (optional) prefix for file name. If NULL use "tmp.".
@param pathname (optional) pointer to a buffer to receive the temp filename.
Allocated using `malloc()`; user to free. Ignored if NULL.
@param keep If `keep` is nonzero and `pathname` is not NULL, then keep the file after closing.
Otherwise file is automatically deleted when closed.
@return Pointer to stream opened in binary read/write (w+b) mode, or a null pointer on error.
@exception ENOMEM Not enough memory to allocate filename.
*/
FILE *tmpfileplus(const char *dir, const char *prefix, char **pathname, int keep);
/** Create a unique temporary file with filename stored in a fixed-length buffer.
@param dir (optional) directory to create file. If NULL use default directory.
@param prefix (optional) prefix for file name. If NULL use "tmp.".
@param pathnamebuf (optional) buffer to receive full pathname of temporary file. Ignored if NULL.
@param pathsize Size of buffer to receive filename and its terminating null character.
@param keep If `keep` is nonzero and `pathname` is not NULL, then keep the file after closing.
Otherwise file is automatically deleted when closed.
@return Pointer to stream opened in binary read/write (w+b) mode, or a null pointer on error.
@exception E2BIG Resulting filename is too big for the buffer `pathnamebuf`.
*/
FILE *tmpfileplus_f(const char *dir, const char *prefix, char *pathnamebuf, size_t pathsize, int keep);
#define TMPFILE_KEEP 1
#endif /* end TMPFILEPLUS_H_ */

View File

@ -0,0 +1,801 @@
/* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $ */
/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
/* $FreeBSD$ */
/*-
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SYS_TREE_H_
#define _SYS_TREE_H_
/* #include <sys/cdefs.h> */
/*
* This file defines data structures for different types of trees:
* splay trees and red-black trees.
*
* A splay tree is a self-organizing data structure. Every operation
* on the tree causes a splay to happen. The splay moves the requested
* node to the root of the tree and partly rebalances it.
*
* This has the benefit that request locality causes faster lookups as
* the requested nodes move to the top of the tree. On the other hand,
* every lookup causes memory writes.
*
* The Balance Theorem bounds the total access time for m operations
* and n inserts on an initially empty tree as O((m + n)lg n). The
* amortized cost for a sequence of m accesses to a splay tree is O(lg n);
*
* A red-black tree is a binary search tree with the node color as an
* extra attribute. It fulfills a set of conditions:
* - every search path from the root to a leaf consists of the
* same number of black nodes,
* - each red node (except for the root) has a black parent,
* - each leaf node is black.
*
* Every operation on a red-black tree is bounded as O(lg n).
* The maximum height of a red-black tree is 2lg (n+1).
*/
#define SPLAY_HEAD(name, type) \
struct name { \
struct type *sph_root; /* root of the tree */ \
}
#define SPLAY_INITIALIZER(root) \
{ NULL }
#define SPLAY_INIT(root) do { \
(root)->sph_root = NULL; \
} while (/*CONSTCOND*/ 0)
#define SPLAY_ENTRY(type) \
struct { \
struct type *spe_left; /* left element */ \
struct type *spe_right; /* right element */ \
}
#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
#define SPLAY_ROOT(head) (head)->sph_root
#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
} while (/*CONSTCOND*/ 0)
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
} while (/*CONSTCOND*/ 0)
#define SPLAY_LINKLEFT(head, tmp, field) do { \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
tmp = (head)->sph_root; \
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
} while (/*CONSTCOND*/ 0)
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
tmp = (head)->sph_root; \
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
} while (/*CONSTCOND*/ 0)
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
} while (/*CONSTCOND*/ 0)
/* Generates prototypes and inline functions */
#define SPLAY_PROTOTYPE(name, type, field, cmp) \
void name##_SPLAY(struct name *, struct type *); \
void name##_SPLAY_MINMAX(struct name *, int); \
struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
\
/* Finds the node with the same key as elm */ \
static __inline struct type * \
name##_SPLAY_FIND(struct name *head, struct type *elm) \
{ \
if (SPLAY_EMPTY(head)) \
return(NULL); \
name##_SPLAY(head, elm); \
if ((cmp)(elm, (head)->sph_root) == 0) \
return (head->sph_root); \
return (NULL); \
} \
\
static __inline struct type * \
name##_SPLAY_NEXT(struct name *head, struct type *elm) \
{ \
name##_SPLAY(head, elm); \
if (SPLAY_RIGHT(elm, field) != NULL) { \
elm = SPLAY_RIGHT(elm, field); \
while (SPLAY_LEFT(elm, field) != NULL) { \
elm = SPLAY_LEFT(elm, field); \
} \
} else \
elm = NULL; \
return (elm); \
} \
\
static __inline struct type * \
name##_SPLAY_MIN_MAX(struct name *head, int val) \
{ \
name##_SPLAY_MINMAX(head, val); \
return (SPLAY_ROOT(head)); \
}
/* Main splay operation.
* Moves node close to the key of elm to top
*/
#define SPLAY_GENERATE(name, type, field, cmp) \
struct type * \
name##_SPLAY_INSERT(struct name *head, struct type *elm) \
{ \
if (SPLAY_EMPTY(head)) { \
SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
} else { \
int __comp; \
name##_SPLAY(head, elm); \
__comp = (cmp)(elm, (head)->sph_root); \
if(__comp < 0) { \
SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
SPLAY_RIGHT(elm, field) = (head)->sph_root; \
SPLAY_LEFT((head)->sph_root, field) = NULL; \
} else if (__comp > 0) { \
SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
SPLAY_LEFT(elm, field) = (head)->sph_root; \
SPLAY_RIGHT((head)->sph_root, field) = NULL; \
} else \
return ((head)->sph_root); \
} \
(head)->sph_root = (elm); \
return (NULL); \
} \
\
struct type * \
name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
{ \
struct type *__tmp; \
if (SPLAY_EMPTY(head)) \
return (NULL); \
name##_SPLAY(head, elm); \
if ((cmp)(elm, (head)->sph_root) == 0) { \
if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
} else { \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
name##_SPLAY(head, elm); \
SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
} \
return (elm); \
} \
return (NULL); \
} \
\
void \
name##_SPLAY(struct name *head, struct type *elm) \
{ \
struct type __node, *__left, *__right, *__tmp; \
int __comp; \
\
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
__left = __right = &__node; \
\
while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
if (__comp < 0) { \
__tmp = SPLAY_LEFT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if ((cmp)(elm, __tmp) < 0){ \
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
break; \
} \
SPLAY_LINKLEFT(head, __right, field); \
} else if (__comp > 0) { \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if ((cmp)(elm, __tmp) > 0){ \
SPLAY_ROTATE_LEFT(head, __tmp, field); \
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
break; \
} \
SPLAY_LINKRIGHT(head, __left, field); \
} \
} \
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
} \
\
/* Splay with either the minimum or the maximum element \
* Used to find minimum or maximum element in tree. \
*/ \
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
{ \
struct type __node, *__left, *__right, *__tmp; \
\
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
__left = __right = &__node; \
\
while (1) { \
if (__comp < 0) { \
__tmp = SPLAY_LEFT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if (__comp < 0){ \
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
break; \
} \
SPLAY_LINKLEFT(head, __right, field); \
} else if (__comp > 0) { \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if (__comp > 0) { \
SPLAY_ROTATE_LEFT(head, __tmp, field); \
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
break; \
} \
SPLAY_LINKRIGHT(head, __left, field); \
} \
} \
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
}
#define SPLAY_NEGINF -1
#define SPLAY_INF 1
#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
: name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
: name##_SPLAY_MIN_MAX(x, SPLAY_INF))
#define SPLAY_FOREACH(x, name, head) \
for ((x) = SPLAY_MIN(name, head); \
(x) != NULL; \
(x) = SPLAY_NEXT(name, head, x))
/* Macros that define a red-black tree */
#define RB_HEAD(name, type) \
struct name { \
struct type *rbh_root; /* root of the tree */ \
}
#define RB_INITIALIZER(root) \
{ NULL }
#define RB_INIT(root) do { \
(root)->rbh_root = NULL; \
} while (/*CONSTCOND*/ 0)
#define RB_BLACK 0
#define RB_RED 1
#define RB_ENTRY(type) \
struct { \
struct type *rbe_left; /* left element */ \
struct type *rbe_right; /* right element */ \
struct type *rbe_parent; /* parent element */ \
int rbe_color; /* node color */ \
}
#define RB_LEFT(elm, field) (elm)->field.rbe_left
#define RB_RIGHT(elm, field) (elm)->field.rbe_right
#define RB_PARENT(elm, field) (elm)->field.rbe_parent
#define RB_COLOR(elm, field) (elm)->field.rbe_color
#define RB_ROOT(head) (head)->rbh_root
#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
#define RB_SET(elm, parent, field) do { \
RB_PARENT(elm, field) = parent; \
RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
RB_COLOR(elm, field) = RB_RED; \
} while (/*CONSTCOND*/ 0)
#define RB_SET_BLACKRED(black, red, field) do { \
RB_COLOR(black, field) = RB_BLACK; \
RB_COLOR(red, field) = RB_RED; \
} while (/*CONSTCOND*/ 0)
#ifndef RB_AUGMENT
#define RB_AUGMENT(x) do {} while (0)
#endif
#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
(tmp) = RB_RIGHT(elm, field); \
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
} \
RB_AUGMENT(elm); \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
else \
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
} else \
(head)->rbh_root = (tmp); \
RB_LEFT(tmp, field) = (elm); \
RB_PARENT(elm, field) = (tmp); \
RB_AUGMENT(tmp); \
if ((RB_PARENT(tmp, field))) \
RB_AUGMENT(RB_PARENT(tmp, field)); \
} while (/*CONSTCOND*/ 0)
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
(tmp) = RB_LEFT(elm, field); \
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
} \
RB_AUGMENT(elm); \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
else \
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
} else \
(head)->rbh_root = (tmp); \
RB_RIGHT(tmp, field) = (elm); \
RB_PARENT(elm, field) = (tmp); \
RB_AUGMENT(tmp); \
if ((RB_PARENT(tmp, field))) \
RB_AUGMENT(RB_PARENT(tmp, field)); \
} while (/*CONSTCOND*/ 0)
/* Generates prototypes and inline functions */
#define RB_PROTOTYPE(name, type, field, cmp) \
RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
RB_PROTOTYPE_INSERT_COLOR(name, type, attr); \
RB_PROTOTYPE_REMOVE_COLOR(name, type, attr); \
RB_PROTOTYPE_INSERT(name, type, attr); \
RB_PROTOTYPE_REMOVE(name, type, attr); \
RB_PROTOTYPE_FIND(name, type, attr); \
RB_PROTOTYPE_NFIND(name, type, attr); \
RB_PROTOTYPE_NEXT(name, type, attr); \
RB_PROTOTYPE_PREV(name, type, attr); \
RB_PROTOTYPE_MINMAX(name, type, attr);
#define RB_PROTOTYPE_INSERT_COLOR(name, type, attr) \
attr void name##_RB_INSERT_COLOR(struct name *, struct type *)
#define RB_PROTOTYPE_REMOVE_COLOR(name, type, attr) \
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *)
#define RB_PROTOTYPE_REMOVE(name, type, attr) \
attr struct type *name##_RB_REMOVE(struct name *, struct type *)
#define RB_PROTOTYPE_INSERT(name, type, attr) \
attr struct type *name##_RB_INSERT(struct name *, struct type *)
#define RB_PROTOTYPE_FIND(name, type, attr) \
attr struct type *name##_RB_FIND(struct name *, struct type *)
#define RB_PROTOTYPE_NFIND(name, type, attr) \
attr struct type *name##_RB_NFIND(struct name *, struct type *)
#define RB_PROTOTYPE_NEXT(name, type, attr) \
attr struct type *name##_RB_NEXT(struct type *)
#define RB_PROTOTYPE_PREV(name, type, attr) \
attr struct type *name##_RB_PREV(struct type *)
#define RB_PROTOTYPE_MINMAX(name, type, attr) \
attr struct type *name##_RB_MINMAX(struct name *, int)
/* Main rb operation.
* Moves node close to the key of elm to top
*/
#define RB_GENERATE(name, type, field, cmp) \
RB_GENERATE_INTERNAL(name, type, field, cmp,)
#define RB_GENERATE_STATIC(name, type, field, cmp) \
RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static)
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
RB_GENERATE_INSERT_COLOR(name, type, field, attr) \
RB_GENERATE_REMOVE_COLOR(name, type, field, attr) \
RB_GENERATE_INSERT(name, type, field, cmp, attr) \
RB_GENERATE_REMOVE(name, type, field, attr) \
RB_GENERATE_FIND(name, type, field, cmp, attr) \
RB_GENERATE_NFIND(name, type, field, cmp, attr) \
RB_GENERATE_NEXT(name, type, field, attr) \
RB_GENERATE_PREV(name, type, field, attr) \
RB_GENERATE_MINMAX(name, type, field, attr)
#define RB_GENERATE_INSERT_COLOR(name, type, field, attr) \
attr void \
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
{ \
struct type *parent, *gparent, *tmp; \
while ((parent = RB_PARENT(elm, field)) != NULL && \
RB_COLOR(parent, field) == RB_RED) { \
gparent = RB_PARENT(parent, field); \
if (parent == RB_LEFT(gparent, field)) { \
tmp = RB_RIGHT(gparent, field); \
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
RB_COLOR(tmp, field) = RB_BLACK; \
RB_SET_BLACKRED(parent, gparent, field);\
elm = gparent; \
continue; \
} \
if (RB_RIGHT(parent, field) == elm) { \
RB_ROTATE_LEFT(head, parent, tmp, field);\
tmp = parent; \
parent = elm; \
elm = tmp; \
} \
RB_SET_BLACKRED(parent, gparent, field); \
RB_ROTATE_RIGHT(head, gparent, tmp, field); \
} else { \
tmp = RB_LEFT(gparent, field); \
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
RB_COLOR(tmp, field) = RB_BLACK; \
RB_SET_BLACKRED(parent, gparent, field);\
elm = gparent; \
continue; \
} \
if (RB_LEFT(parent, field) == elm) { \
RB_ROTATE_RIGHT(head, parent, tmp, field);\
tmp = parent; \
parent = elm; \
elm = tmp; \
} \
RB_SET_BLACKRED(parent, gparent, field); \
RB_ROTATE_LEFT(head, gparent, tmp, field); \
} \
} \
RB_COLOR(head->rbh_root, field) = RB_BLACK; \
}
#define RB_GENERATE_REMOVE_COLOR(name, type, field, attr) \
attr void \
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
{ \
struct type *tmp; \
while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
elm != RB_ROOT(head)) { \
if (RB_LEFT(parent, field) == elm) { \
tmp = RB_RIGHT(parent, field); \
if (RB_COLOR(tmp, field) == RB_RED) { \
RB_SET_BLACKRED(tmp, parent, field); \
RB_ROTATE_LEFT(head, parent, tmp, field);\
tmp = RB_RIGHT(parent, field); \
} \
if ((RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
(RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
RB_COLOR(tmp, field) = RB_RED; \
elm = parent; \
parent = RB_PARENT(elm, field); \
} else { \
if (RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
struct type *oleft; \
if ((oleft = RB_LEFT(tmp, field)) \
!= NULL) \
RB_COLOR(oleft, field) = RB_BLACK;\
RB_COLOR(tmp, field) = RB_RED; \
RB_ROTATE_RIGHT(head, tmp, oleft, field);\
tmp = RB_RIGHT(parent, field); \
} \
RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
RB_COLOR(parent, field) = RB_BLACK; \
if (RB_RIGHT(tmp, field)) \
RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
RB_ROTATE_LEFT(head, parent, tmp, field);\
elm = RB_ROOT(head); \
break; \
} \
} else { \
tmp = RB_LEFT(parent, field); \
if (RB_COLOR(tmp, field) == RB_RED) { \
RB_SET_BLACKRED(tmp, parent, field); \
RB_ROTATE_RIGHT(head, parent, tmp, field);\
tmp = RB_LEFT(parent, field); \
} \
if ((RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
(RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
RB_COLOR(tmp, field) = RB_RED; \
elm = parent; \
parent = RB_PARENT(elm, field); \
} else { \
if (RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
struct type *oright; \
if ((oright = RB_RIGHT(tmp, field)) \
!= NULL) \
RB_COLOR(oright, field) = RB_BLACK;\
RB_COLOR(tmp, field) = RB_RED; \
RB_ROTATE_LEFT(head, tmp, oright, field);\
tmp = RB_LEFT(parent, field); \
} \
RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
RB_COLOR(parent, field) = RB_BLACK; \
if (RB_LEFT(tmp, field)) \
RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
RB_ROTATE_RIGHT(head, parent, tmp, field);\
elm = RB_ROOT(head); \
break; \
} \
} \
} \
if (elm) \
RB_COLOR(elm, field) = RB_BLACK; \
}
#define RB_GENERATE_REMOVE(name, type, field, attr) \
attr struct type * \
name##_RB_REMOVE(struct name *head, struct type *elm) \
{ \
struct type *child, *parent, *old = elm; \
int color; \
if (RB_LEFT(elm, field) == NULL) \
child = RB_RIGHT(elm, field); \
else if (RB_RIGHT(elm, field) == NULL) \
child = RB_LEFT(elm, field); \
else { \
struct type *left; \
elm = RB_RIGHT(elm, field); \
while ((left = RB_LEFT(elm, field)) != NULL) \
elm = left; \
child = RB_RIGHT(elm, field); \
parent = RB_PARENT(elm, field); \
color = RB_COLOR(elm, field); \
if (child) \
RB_PARENT(child, field) = parent; \
if (parent) { \
if (RB_LEFT(parent, field) == elm) \
RB_LEFT(parent, field) = child; \
else \
RB_RIGHT(parent, field) = child; \
RB_AUGMENT(parent); \
} else \
RB_ROOT(head) = child; \
if (RB_PARENT(elm, field) == old) \
parent = elm; \
(elm)->field = (old)->field; \
if (RB_PARENT(old, field)) { \
if (RB_LEFT(RB_PARENT(old, field), field) == old)\
RB_LEFT(RB_PARENT(old, field), field) = elm;\
else \
RB_RIGHT(RB_PARENT(old, field), field) = elm;\
RB_AUGMENT(RB_PARENT(old, field)); \
} else \
RB_ROOT(head) = elm; \
RB_PARENT(RB_LEFT(old, field), field) = elm; \
if (RB_RIGHT(old, field)) \
RB_PARENT(RB_RIGHT(old, field), field) = elm; \
if (parent) { \
left = parent; \
do { \
RB_AUGMENT(left); \
} while ((left = RB_PARENT(left, field)) != NULL); \
} \
goto color; \
} \
parent = RB_PARENT(elm, field); \
color = RB_COLOR(elm, field); \
if (child) \
RB_PARENT(child, field) = parent; \
if (parent) { \
if (RB_LEFT(parent, field) == elm) \
RB_LEFT(parent, field) = child; \
else \
RB_RIGHT(parent, field) = child; \
RB_AUGMENT(parent); \
} else \
RB_ROOT(head) = child; \
color: \
if (color == RB_BLACK) \
name##_RB_REMOVE_COLOR(head, parent, child); \
return (old); \
} \
#define RB_GENERATE_INSERT(name, type, field, cmp, attr) \
/* Inserts a node into the RB tree */ \
attr struct type * \
name##_RB_INSERT(struct name *head, struct type *elm) \
{ \
struct type *tmp; \
struct type *parent = NULL; \
int comp = 0; \
tmp = RB_ROOT(head); \
while (tmp) { \
parent = tmp; \
comp = (cmp)(elm, parent); \
if (comp < 0) \
tmp = RB_LEFT(tmp, field); \
else if (comp > 0) \
tmp = RB_RIGHT(tmp, field); \
else \
return (tmp); \
} \
RB_SET(elm, parent, field); \
if (parent != NULL) { \
if (comp < 0) \
RB_LEFT(parent, field) = elm; \
else \
RB_RIGHT(parent, field) = elm; \
RB_AUGMENT(parent); \
} else \
RB_ROOT(head) = elm; \
name##_RB_INSERT_COLOR(head, elm); \
return (NULL); \
}
#define RB_GENERATE_FIND(name, type, field, cmp, attr) \
/* Finds the node with the same key as elm */ \
attr struct type * \
name##_RB_FIND(struct name *head, struct type *elm) \
{ \
struct type *tmp = RB_ROOT(head); \
int comp; \
while (tmp) { \
comp = cmp(elm, tmp); \
if (comp < 0) \
tmp = RB_LEFT(tmp, field); \
else if (comp > 0) \
tmp = RB_RIGHT(tmp, field); \
else \
return (tmp); \
} \
return (NULL); \
}
#define RB_GENERATE_NFIND(name, type, field, cmp, attr) \
/* Finds the first node greater than or equal to the search key */ \
attr struct type * \
name##_RB_NFIND(struct name *head, struct type *elm) \
{ \
struct type *tmp = RB_ROOT(head); \
struct type *res = NULL; \
int comp; \
while (tmp) { \
comp = cmp(elm, tmp); \
if (comp < 0) { \
res = tmp; \
tmp = RB_LEFT(tmp, field); \
} \
else if (comp > 0) \
tmp = RB_RIGHT(tmp, field); \
else \
return (tmp); \
} \
return (res); \
}
#define RB_GENERATE_NEXT(name, type, field, attr) \
/* ARGSUSED */ \
attr struct type * \
name##_RB_NEXT(struct type *elm) \
{ \
if (RB_RIGHT(elm, field)) { \
elm = RB_RIGHT(elm, field); \
while (RB_LEFT(elm, field)) \
elm = RB_LEFT(elm, field); \
} else { \
if (RB_PARENT(elm, field) && \
(elm == RB_LEFT(RB_PARENT(elm, field), field))) \
elm = RB_PARENT(elm, field); \
else { \
while (RB_PARENT(elm, field) && \
(elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
elm = RB_PARENT(elm, field); \
elm = RB_PARENT(elm, field); \
} \
} \
return (elm); \
}
#define RB_GENERATE_PREV(name, type, field, attr) \
/* ARGSUSED */ \
attr struct type * \
name##_RB_PREV(struct type *elm) \
{ \
if (RB_LEFT(elm, field)) { \
elm = RB_LEFT(elm, field); \
while (RB_RIGHT(elm, field)) \
elm = RB_RIGHT(elm, field); \
} else { \
if (RB_PARENT(elm, field) && \
(elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
elm = RB_PARENT(elm, field); \
else { \
while (RB_PARENT(elm, field) && \
(elm == RB_LEFT(RB_PARENT(elm, field), field)))\
elm = RB_PARENT(elm, field); \
elm = RB_PARENT(elm, field); \
} \
} \
return (elm); \
}
#define RB_GENERATE_MINMAX(name, type, field, attr) \
attr struct type * \
name##_RB_MINMAX(struct name *head, int val) \
{ \
struct type *tmp = RB_ROOT(head); \
struct type *parent = NULL; \
while (tmp) { \
parent = tmp; \
if (val < 0) \
tmp = RB_LEFT(tmp, field); \
else \
tmp = RB_RIGHT(tmp, field); \
} \
return (parent); \
}
#define RB_NEGINF -1
#define RB_INF 1
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
#define RB_PREV(name, x, y) name##_RB_PREV(y)
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
#define RB_FOREACH(x, name, head) \
for ((x) = RB_MIN(name, head); \
(x) != NULL; \
(x) = name##_RB_NEXT(x))
#define RB_FOREACH_FROM(x, name, y) \
for ((x) = (y); \
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
(x) = (y))
#define RB_FOREACH_SAFE(x, name, head, y) \
for ((x) = RB_MIN(name, head); \
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
(x) = (y))
#define RB_FOREACH_REVERSE(x, name, head) \
for ((x) = RB_MAX(name, head); \
(x) != NULL; \
(x) = name##_RB_PREV(x))
#define RB_FOREACH_REVERSE_FROM(x, name, y) \
for ((x) = (y); \
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
(x) = (y))
#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \
for ((x) = RB_MAX(name, head); \
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
(x) = (y))
#endif /* _SYS_TREE_H_ */

View File

@ -0,0 +1,375 @@
/* zip.h -- IO on .zip files using zlib
Version 1.1, February 14h, 2010
part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
Modifications for Zip64 support
Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
For more info read MiniZip_info.txt
---------------------------------------------------------------------------
Condition of use and distribution are the same than zlib :
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
---------------------------------------------------------------------------
Changes
See header of zip.h
*/
/* Pragma added by libxlsxwriter to avoid warnings with -pedantic -ansi. */
#ifndef _WIN32
#pragma GCC system_header
#endif
#ifndef _zip12_H
#define _zip12_H
#ifdef __cplusplus
extern "C" {
#endif
/* #define HAVE_BZIP2 */
#ifndef _ZLIB_H
#include "zlib.h"
#endif
#ifndef _ZLIBIOAPI_H
#include "ioapi.h"
#endif
/* Encryption not required by libxlsxwriter. */
#ifndef NOCRYPT
#define NOCRYPT
#endif
#ifndef NOUNCRYPT
#define NOUNCRYPT
#endif
#ifdef HAVE_BZIP2
#include "bzlib.h"
#endif
#define Z_BZIP2ED 12
#if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
/* like the STRICT of WIN32, we define a pointer that cannot be converted
from (void*) without cast */
typedef struct TagzipFile__ { int unused; } zipFile__;
typedef zipFile__ *zipFile;
#else
typedef voidp zipFile;
#endif
#define ZIP_OK (0)
#define ZIP_EOF (0)
#define ZIP_ERRNO (Z_ERRNO)
#define ZIP_PARAMERROR (-102)
#define ZIP_BADZIPFILE (-103)
#define ZIP_INTERNALERROR (-104)
#ifndef DEF_MEM_LEVEL
# if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
# else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
# endif
#endif
/* default memLevel */
/* tm_zip contain date/time info */
typedef struct tm_zip_s
{
uInt tm_sec; /* seconds after the minute - [0,59] */
uInt tm_min; /* minutes after the hour - [0,59] */
uInt tm_hour; /* hours since midnight - [0,23] */
uInt tm_mday; /* day of the month - [1,31] */
uInt tm_mon; /* months since January - [0,11] */
uInt tm_year; /* years - [1980..2044] */
} tm_zip;
typedef struct
{
tm_zip tmz_date; /* date in understandable format */
uLong dosDate; /* if dos_date == 0, tmu_date is used */
/* uLong flag; */ /* general purpose bit flag 2 bytes */
uLong internal_fa; /* internal file attributes 2 bytes */
uLong external_fa; /* external file attributes 4 bytes */
} zip_fileinfo;
typedef const char* zipcharpc;
#define APPEND_STATUS_CREATE (0)
#define APPEND_STATUS_CREATEAFTER (1)
#define APPEND_STATUS_ADDINZIP (2)
extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));
extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append));
/*
Create a zipfile.
pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on
an Unix computer "zlib/zlib113.zip".
if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip
will be created at the end of the file.
(useful if the file contain a self extractor code)
if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will
add files in existing zip (be sure you don't add file that doesn't exist)
If the zipfile cannot be opened, the return value is NULL.
Else, the return value is a zipFile Handle, usable with other function
of this zip package.
*/
/* Note : there is no delete function into a zipfile.
If you want delete file into a zipfile, you must open a zipfile, and create another
Of couse, you can use RAW reading and writing to copy the file you did not want delte
*/
extern zipFile ZEXPORT zipOpen2 OF((const char *pathname,
int append,
zipcharpc* globalcomment,
zlib_filefunc_def* pzlib_filefunc_def));
extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname,
int append,
zipcharpc* globalcomment,
zlib_filefunc64_def* pzlib_filefunc_def));
extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level));
extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int zip64));
/*
Open a file in the ZIP for writing.
filename : the filename in zip (if NULL, '-' without quote will be used
*zipfi contain supplemental information
if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
contains the extrafield data the the local header
if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
contains the extrafield data the the local header
if comment != NULL, comment contain the comment string
method contain the compression method (0 for store, Z_DEFLATED for deflate)
level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
zip64 is set to 1 if a zip64 extended information block should be added to the local file header.
this MUST be '1' if the uncompressed size is >= 0xffffffff.
*/
extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw));
extern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int zip64));
/*
Same than zipOpenNewFileInZip, except if raw=1, we write raw file
*/
extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int windowBits,
int memLevel,
int strategy,
const char* password,
uLong crcForCrypting));
extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int windowBits,
int memLevel,
int strategy,
const char* password,
uLong crcForCrypting,
int zip64
));
/*
Same than zipOpenNewFileInZip2, except
windowBits,memLevel,,strategy : see parameter strategy in deflateInit2
password : crypting password (NULL for no crypting)
crcForCrypting : crc of file to compress (needed for crypting)
*/
extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int windowBits,
int memLevel,
int strategy,
const char* password,
uLong crcForCrypting,
uLong versionMadeBy,
uLong flagBase
));
extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int windowBits,
int memLevel,
int strategy,
const char* password,
uLong crcForCrypting,
uLong versionMadeBy,
uLong flagBase,
int zip64
));
/*
Same than zipOpenNewFileInZip4, except
versionMadeBy : value for Version made by field
flag : value for flag field (compression level info will be added)
*/
extern int ZEXPORT zipWriteInFileInZip OF((zipFile file,
const void* buf,
unsigned len));
/*
Write data in the zipfile
*/
extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
/*
Close the current file in the zipfile
*/
extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
uLong uncompressed_size,
uLong crc32));
extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file,
ZPOS64_T uncompressed_size,
uLong crc32));
/*
Close the current file in the zipfile, for file opened with
parameter raw=1 in zipOpenNewFileInZip2
uncompressed_size and crc32 are value for the uncompressed size
*/
extern int ZEXPORT zipClose OF((zipFile file,
const char* global_comment));
/*
Close the zipfile
*/
extern int ZEXPORT zipRemoveExtraInfoBlock OF((char* pData, int* dataLen, short sHeader));
/*
zipRemoveExtraInfoBlock - Added by Mathias Svensson
Remove extra information block from a extra information data for the local file header or central directory header
It is needed to remove ZIP64 extra information blocks when before data is written if using RAW mode.
0x0001 is the signature header for the ZIP64 extra information blocks
usage.
Remove ZIP64 Extra information from a central director extra field data
zipRemoveExtraInfoBlock(pCenDirExtraFieldData, &nCenDirExtraFieldDataLen, 0x0001);
Remove ZIP64 Extra information from a Local File Header extra field data
zipRemoveExtraInfoBlock(pLocalHeaderExtraFieldData, &nLocalHeaderExtraFieldDataLen, 0x0001);
*/
#ifdef __cplusplus
}
#endif
#endif /* _zip64_H */

View File

@ -0,0 +1,257 @@
/*
* libxlsxwriter
*
* Copyright 2014-2021, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*/
/**
* @file utility.h
*
* @brief Utility functions for libxlsxwriter.
*
* <!-- Copyright 2014-2021, John McNamara, jmcnamara@cpan.org -->
*
*/
#ifndef __LXW_UTILITY_H__
#define __LXW_UTILITY_H__
#include <stdint.h>
#ifndef _MSC_VER
#include <strings.h>
#endif
#include "common.h"
#include "xmlwriter.h"
/**
* @brief Convert an Excel `A1` cell string into a `(row, col)` pair.
*
* Convert an Excel `A1` cell string into a `(row, col)` pair.
*
* This is a little syntactic shortcut to help with worksheet layout:
*
* @code
* worksheet_write_string(worksheet, CELL("A1"), "Foo", NULL);
*
* //Same as:
* worksheet_write_string(worksheet, 0, 0, "Foo", NULL);
* @endcode
*
* @note
*
* This macro shouldn't be used in performance critical situations since it
* expands to two function calls.
*/
#define CELL(cell) \
lxw_name_to_row(cell), lxw_name_to_col(cell)
/**
* @brief Convert an Excel `A:B` column range into a `(col1, col2)` pair.
*
* Convert an Excel `A:B` column range into a `(col1, col2)` pair.
*
* This is a little syntactic shortcut to help with worksheet layout:
*
* @code
* worksheet_set_column(worksheet, COLS("B:D"), 20, NULL, NULL);
*
* // Same as:
* worksheet_set_column(worksheet, 1, 3, 20, NULL, NULL);
* @endcode
*
*/
#define COLS(cols) \
lxw_name_to_col(cols), lxw_name_to_col_2(cols)
/**
* @brief Convert an Excel `A1:B2` range into a `(first_row, first_col,
* last_row, last_col)` sequence.
*
* Convert an Excel `A1:B2` range into a `(first_row, first_col, last_row,
* last_col)` sequence.
*
* This is a little syntactic shortcut to help with worksheet layout.
*
* @code
* worksheet_print_area(worksheet, 0, 0, 41, 10); // A1:K42.
*
* // Same as:
* worksheet_print_area(worksheet, RANGE("A1:K42"));
* @endcode
*/
#define RANGE(range) \
lxw_name_to_row(range), lxw_name_to_col(range), \
lxw_name_to_row_2(range), lxw_name_to_col_2(range)
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/**
* @brief Retrieve the library version.
*
* @return The "X.Y.Z" version string.
*
* Get the library version as a "X.Y.Z" version string
*
* @code
* printf("Libxlsxwriter version = %s\n", lxw_version());
* @endcode
*
*/
const char *lxw_version(void);
/**
* @brief Retrieve the library version ID.
*
* @return The version ID.
*
* Get the library version such as "X.Y.Z" as a XYZ integer.
*
* @code
* printf("Libxlsxwriter version id = %d\n", lxw_version_id());
* @endcode
*
*/
uint16_t lxw_version_id(void);
/**
* @brief Converts a libxlsxwriter error number to a string.
*
* The `%lxw_strerror` function converts a libxlsxwriter error number defined
* by #lxw_error to a pointer to a string description of the error.
* Similar to the standard library strerror(3) function.
*
* For example:
*
* @code
* lxw_error error = workbook_close(workbook);
*
* if (error)
* printf("Error in workbook_close().\n"
* "Error %d = %s\n", error, lxw_strerror(error));
* @endcode
*
* This would produce output like the following if the target file wasn't
* writable:
*
* Error in workbook_close().
* Error 2 = Error creating output xlsx file. Usually a permissions error.
*
* @param error_num The error number returned by a libxlsxwriter function.
*
* @return A pointer to a statically allocated string. Do not free.
*/
char *lxw_strerror(lxw_error error_num);
/* Create a quoted version of the worksheet name */
char *lxw_quote_sheetname(const char *str);
void lxw_col_to_name(char *col_name, lxw_col_t col_num, uint8_t absolute);
void lxw_rowcol_to_cell(char *cell_name, lxw_row_t row, lxw_col_t col);
void lxw_rowcol_to_cell_abs(char *cell_name,
lxw_row_t row,
lxw_col_t col, uint8_t abs_row, uint8_t abs_col);
void lxw_rowcol_to_range(char *range,
lxw_row_t first_row, lxw_col_t first_col,
lxw_row_t last_row, lxw_col_t last_col);
void lxw_rowcol_to_range_abs(char *range,
lxw_row_t first_row, lxw_col_t first_col,
lxw_row_t last_row, lxw_col_t last_col);
void lxw_rowcol_to_formula_abs(char *formula, const char *sheetname,
lxw_row_t first_row, lxw_col_t first_col,
lxw_row_t last_row, lxw_col_t last_col);
uint32_t lxw_name_to_row(const char *row_str);
uint16_t lxw_name_to_col(const char *col_str);
uint32_t lxw_name_to_row_2(const char *row_str);
uint16_t lxw_name_to_col_2(const char *col_str);
/**
* @brief Converts a #lxw_datetime to an Excel datetime number.
*
* @param datetime A pointer to a #lxw_datetime struct.
*
* @return A double representing an Excel datetime.
*
* The `%lxw_datetime_to_excel_datetime()` function converts a datetime in
* #lxw_datetime to an Excel datetime number:
*
* @code
* lxw_datetime datetime = {2013, 2, 28, 12, 0, 0.0};
*
* double excel_datetime = lxw_datetime_to_excel_date(&datetime);
* @endcode
*
* See @ref working_with_dates for more details on the Excel datetime format.
*/
double lxw_datetime_to_excel_datetime(lxw_datetime *datetime);
double lxw_datetime_to_excel_date_epoch(lxw_datetime *datetime,
uint8_t date_1904);
/**
* @brief Converts a unix datetime to an Excel datetime number.
*
* @param unixtime Unix time (seconds since 1970-01-01)
*
* @return A double representing an Excel datetime.
*
* The `%lxw_unixtime_to_excel_date()` function converts a unix datetime to
* an Excel datetime number:
*
* @code
* double excel_datetime = lxw_unixtime_to_excel_date(946684800);
* @endcode
*
* See @ref working_with_dates for more details.
*/
double lxw_unixtime_to_excel_date(int64_t unixtime);
double lxw_unixtime_to_excel_date_epoch(int64_t unixtime, uint8_t date_1904);
char *lxw_strdup(const char *str);
char *lxw_strdup_formula(const char *formula);
size_t lxw_utf8_strlen(const char *str);
void lxw_str_tolower(char *str);
/* Define a portable version of strcasecmp(). */
#ifdef _MSC_VER
#define lxw_strcasecmp _stricmp
#else
#define lxw_strcasecmp strcasecmp
#endif
FILE *lxw_tmpfile(char *tmpdir);
FILE *lxw_fopen(const char *filename, const char *mode);
/* Use the third party dtoa function to avoid locale issues with sprintf
* double formatting. Otherwise we use a simple macro that falls back to the
* default c-lib sprintf.
*/
#ifdef USE_DTOA_LIBRARY
int lxw_sprintf_dbl(char *data, double number);
#else
#define lxw_sprintf_dbl(data, number) \
lxw_snprintf(data, LXW_ATTR_32, "%.16G", number)
#endif
uint16_t lxw_hash_password(const char *password);
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_UTILITY_H__ */

View File

@ -0,0 +1,55 @@
/*
* libxlsxwriter
*
* Copyright 2014-2021, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* vml - A libxlsxwriter library for creating Excel XLSX vml files.
*
*/
#ifndef __LXW_VML_H__
#define __LXW_VML_H__
#include <stdint.h>
#include "common.h"
#include "worksheet.h"
/*
* Struct to represent a vml object.
*/
typedef struct lxw_vml {
FILE *file;
uint8_t type;
struct lxw_comment_objs *button_objs;
struct lxw_comment_objs *comment_objs;
struct lxw_comment_objs *image_objs;
char *vml_data_id_str;
uint32_t vml_shape_id;
uint8_t comment_display_default;
} lxw_vml;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_vml *lxw_vml_new(void);
void lxw_vml_free(lxw_vml *vml);
void lxw_vml_assemble_xml_file(lxw_vml *self);
/* Declarations required for unit testing. */
#ifdef TESTING
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_VML_H__ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,184 @@
/*
* libxlsxwriter
*
* Copyright 2014-2021, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* xmlwriter - A libxlsxwriter library for creating Excel XLSX
* XML files.
*
* The xmlwriter library is used to create the XML sub-components files
* in the Excel XLSX file format.
*
* This library is used in preference to a more generic XML library to allow
* for customization and optimization for the XLSX file format.
*
* The xmlwriter functions are only used internally and do not need to be
* called directly by the end user.
*
*/
#ifndef __XMLWRITER_H__
#define __XMLWRITER_H__
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "utility.h"
#define LXW_MAX_ATTRIBUTE_LENGTH 2080 /* Max URL length. */
#define LXW_ATTR_32 32
#define LXW_ATTRIBUTE_COPY(dst, src) \
do{ \
strncpy(dst, src, LXW_MAX_ATTRIBUTE_LENGTH -1); \
dst[LXW_MAX_ATTRIBUTE_LENGTH - 1] = '\0'; \
} while (0)
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/* Attribute used in XML elements. */
struct xml_attribute {
char key[LXW_MAX_ATTRIBUTE_LENGTH];
char value[LXW_MAX_ATTRIBUTE_LENGTH];
/* Make the struct a queue.h list element. */
STAILQ_ENTRY (xml_attribute) list_entries;
};
/* Use queue.h macros to define the xml_attribute_list type. */
STAILQ_HEAD(xml_attribute_list, xml_attribute);
/* Create a new attribute struct to add to a xml_attribute_list. */
struct xml_attribute *lxw_new_attribute_str(const char *key,
const char *value);
struct xml_attribute *lxw_new_attribute_int(const char *key, uint32_t value);
struct xml_attribute *lxw_new_attribute_dbl(const char *key, double value);
/* Macro to initialize the xml_attribute_list pointers. */
#define LXW_INIT_ATTRIBUTES() \
STAILQ_INIT(&attributes)
/* Macro to add attribute string elements to xml_attribute_list. */
#define LXW_PUSH_ATTRIBUTES_STR(key, value) \
do { \
attribute = lxw_new_attribute_str((key), (value)); \
STAILQ_INSERT_TAIL(&attributes, attribute, list_entries); \
} while (0)
/* Macro to add attribute int values to xml_attribute_list. */
#define LXW_PUSH_ATTRIBUTES_INT(key, value) \
do { \
attribute = lxw_new_attribute_int((key), (value)); \
STAILQ_INSERT_TAIL(&attributes, attribute, list_entries); \
} while (0)
/* Macro to add attribute double values to xml_attribute_list. */
#define LXW_PUSH_ATTRIBUTES_DBL(key, value) \
do { \
attribute = lxw_new_attribute_dbl((key), (value)); \
STAILQ_INSERT_TAIL(&attributes, attribute, list_entries); \
} while (0)
/* Macro to free xml_attribute_list and attribute. */
#define LXW_FREE_ATTRIBUTES() \
do { \
while (!STAILQ_EMPTY(&attributes)) { \
attribute = STAILQ_FIRST(&attributes); \
STAILQ_REMOVE_HEAD(&attributes, list_entries); \
free(attribute); \
} \
} while (0)
/**
* Create the XML declaration in an XML file.
*
* @param xmlfile A FILE pointer to the output XML file.
*/
void lxw_xml_declaration(FILE * xmlfile);
/**
* Write an XML start tag with optional attributes.
*
* @param xmlfile A FILE pointer to the output XML file.
* @param tag The XML tag to write.
* @param attributes An optional list of attributes to add to the tag.
*/
void lxw_xml_start_tag(FILE * xmlfile,
const char *tag,
struct xml_attribute_list *attributes);
/**
* Write an XML start tag with optional un-encoded attributes.
* This is a minor optimization for attributes that don't need encoding.
*
* @param xmlfile A FILE pointer to the output XML file.
* @param tag The XML tag to write.
* @param attributes An optional list of attributes to add to the tag.
*/
void lxw_xml_start_tag_unencoded(FILE * xmlfile,
const char *tag,
struct xml_attribute_list *attributes);
/**
* Write an XML end tag.
*
* @param xmlfile A FILE pointer to the output XML file.
* @param tag The XML tag to write.
*/
void lxw_xml_end_tag(FILE * xmlfile, const char *tag);
/**
* Write an XML empty tag with optional attributes.
*
* @param xmlfile A FILE pointer to the output XML file.
* @param tag The XML tag to write.
* @param attributes An optional list of attributes to add to the tag.
*/
void lxw_xml_empty_tag(FILE * xmlfile,
const char *tag,
struct xml_attribute_list *attributes);
/**
* Write an XML empty tag with optional un-encoded attributes.
* This is a minor optimization for attributes that don't need encoding.
*
* @param xmlfile A FILE pointer to the output XML file.
* @param tag The XML tag to write.
* @param attributes An optional list of attributes to add to the tag.
*/
void lxw_xml_empty_tag_unencoded(FILE * xmlfile,
const char *tag,
struct xml_attribute_list *attributes);
/**
* Write an XML element containing data and optional attributes.
*
* @param xmlfile A FILE pointer to the output XML file.
* @param tag The XML tag to write.
* @param data The data section of the XML element.
* @param attributes An optional list of attributes to add to the tag.
*/
void lxw_xml_data_element(FILE * xmlfile,
const char *tag,
const char *data,
struct xml_attribute_list *attributes);
void lxw_xml_rich_si_element(FILE * xmlfile, const char *string);
uint8_t lxw_has_control_characters(const char *string);
char *lxw_escape_control_characters(const char *string);
char *lxw_escape_url_characters(const char *string, uint8_t escape_hash);
char *lxw_escape_data(const char *data);
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __XMLWRITER_H__ */