restructure

pull/3/head
Thomas Fussell 2014-05-09 15:54:06 -04:00
parent 26892bf42b
commit 913551920f
62 changed files with 2338 additions and 5979 deletions

View File

@ -1,89 +0,0 @@
/*
Copyright (c) 2012-2014 Thomas Fussell
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.
*/
#pragma once
#include <ostream>
#include <string>
struct tm;
namespace xlnt {
class style;
class worksheet;
struct cell_struct;
struct coordinate
{
std::string column;
int row;
};
class cell
{
public:
enum class type
{
null,
numeric,
string,
date,
formula,
boolean,
error
};
static coordinate coordinate_from_string(const std::string &address);
static int column_index_from_string(const std::string &column_string);
static std::string get_column_letter(int column_index);
static std::string absolute_coordinate(const std::string &absolute_address);
cell(const cell &copy);
cell(worksheet &ws, const std::string &column, int row);
cell(worksheet &ws, const std::string &column, int row, const std::string &value);
~cell();
cell &operator=(int value);
cell &operator=(double value);
cell &operator=(const std::string &value);
cell &operator=(const char *value);
cell &operator=(const tm &value);
friend bool operator==(const std::string &comparand, const cell &cell);
friend bool operator==(const char *comparand, const cell &cell);
friend bool operator==(const tm &comparand, const cell &cell);
std::string to_string() const;
bool is_date() const;
style &get_style();
type get_data_type();
private:
cell_struct *root_;
};
inline std::ostream &operator<<(std::ostream &stream, const cell &cell)
{
return stream << cell.to_string();
}
} // namespace xlnt

View File

@ -1,30 +0,0 @@
/*
Copyright (c) 2012-2014 Thomas Fussell
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.
*/
#pragma once
namespace xlnt {
class style
{
};
} // namespace xlnt

View File

@ -1,30 +0,0 @@
/*
Copyright (c) 2012-2014 Thomas Fussell
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.
*/
#pragma once
namespace xlnt {
class style
{
};
} // namespace xlnt

View File

@ -1,30 +0,0 @@
/*
Copyright (c) 2012-2014 Thomas Fussell
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.
*/
#pragma once
namespace xlnt {
class style
{
};
} // namespace xlnt

View File

@ -1,65 +0,0 @@
/*
# Copyright(c) 2010 - 2011 openpyxl
#
# 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.
*/
#pragma once
#include <string>
#include <unordered_map>
namespace xlnt {
// Constants for fixed paths in a file and xml namespace urls.
const int MIN_ROW = 0;
const int MIN_COLUMN = 0;
const int MAX_COLUMN = 16384;
const int MAX_ROW = 1048576;
// constants
const std::string PACKAGE_PROPS = "docProps";
const std::string PACKAGE_XL = "xl";
const std::string PACKAGE_RELS = "_rels";
const std::string PACKAGE_THEME = PACKAGE_XL + "/" + "theme";
const std::string PACKAGE_WORKSHEETS = PACKAGE_XL + "/" + "worksheets";
const std::string PACKAGE_DRAWINGS = PACKAGE_XL + "/" + "drawings";
const std::string PACKAGE_CHARTS = PACKAGE_XL + "/" + "charts";
const std::string ARC_CONTENT_TYPES = "[Content_Types].xml";
const std::string ARC_ROOT_RELS = PACKAGE_RELS + "/.rels";
const std::string ARC_WORKBOOK_RELS = PACKAGE_XL + "/" + PACKAGE_RELS + "/workbook.xml.rels";
const std::string ARC_CORE = PACKAGE_PROPS + "/core.xml";
const std::string ARC_APP = PACKAGE_PROPS + "/app.xml";
const std::string ARC_WORKBOOK = PACKAGE_XL + "/workbook.xml";
const std::string ARC_STYLE = PACKAGE_XL + "/styles.xml";
const std::string ARC_THEME = PACKAGE_THEME + "/theme1.xml";
const std::string ARC_SHARED_STRINGS = PACKAGE_XL + "/sharedStrings.xml";
std::unordered_map<std::string, std::string> NAMESPACES = {
{"cp", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties"},
{"dc", "http://purl.org/dc/elements/1.1/"},
{"dcterms", "http://purl.org/dc/terms/"},
{"dcmitype", "http://purl.org/dc/dcmitype/"},
{"xsi", "http://www.w3.org/2001/XMLSchema-instance"},
{"vt", "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"},
{"xml", "http://www.w3.org/XML/1998/namespace"}
};
} // namespace xlnt

View File

@ -1,30 +0,0 @@
/*
Copyright (c) 2012-2014 Thomas Fussell
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.
*/
#pragma once
namespace xlnt {
class style
{
};
} // namespace xlnt

View File

@ -1,30 +0,0 @@
/*
Copyright (c) 2012-2014 Thomas Fussell
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.
*/
#pragma once
namespace xlnt {
class style
{
};
} // namespace xlnt

View File

View File

@ -1,54 +0,0 @@
/*
Copyright (c) 2012-2014 Thomas Fussell
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.
*/
#pragma once
#include <memory>
#include <string>
#include <vector>
namespace xlnt {
struct workbook_struct;
class worksheet;
class workbook
{
public:
workbook();
workbook(const workbook &) = delete;
const workbook &operator=(const workbook &) = delete;
worksheet get_sheet_by_name(const std::string &sheet_name);
worksheet get_active();
worksheet create_sheet();
worksheet create_sheet(std::size_t index);
std::vector<std::string> get_sheet_names() const;
std::vector<worksheet>::iterator begin();
std::vector<worksheet>::iterator end();
worksheet operator[](const std::string &name);
void save(const std::string &filename);
private:
workbook_struct *root_;
};
} // namespace xlnt

View File

@ -1,112 +0,0 @@
/*
Copyright (c) 2012-2014 Thomas Fussell
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.
*/
#pragma once
#include <set>
#include <string>
#include <vector>
#include <unordered_map>
namespace xlnt {
class cell;
class relationship;
class workbook;
struct worksheet_struct;
typedef std::vector<std::vector<cell>> range;
class worksheet
{
public:
enum class Break
{
None = 0,
Row = 1,
Column = 2
};
enum class SheetState
{
Visible,
Hidden,
VeryHidden
};
enum class PaperSize
{
Letter = 1,
LetterSmall = 2,
Tabloid = 3,
Ledger = 4,
Legal = 5,
Statement = 6,
Executive = 7,
A3 = 8,
A4 = 9,
A4Small = 10,
A5 = 11
};
enum class Orientation
{
Portrait,
Landscape
};
worksheet(workbook &parent_workbook, const std::string &title = "");
void operator=(const worksheet &other);
cell operator[](const std::string &address);
std::string to_string() const;
workbook &get_parent() const;
void garbage_collect();
std::set<cell> get_cell_collection();
std::string get_title() const;
void set_title(const std::string &title);
cell get_freeze_panes() const;
void set_freeze_panes(cell top_left_cell);
void set_freeze_panes(const std::string &top_left_coordinate);
void unfreeze_panes();
xlnt::cell cell(const std::string &coordinate);
xlnt::cell cell(int row, int column);
int get_highest_row() const;
int get_highest_column() const;
std::string calculate_dimension() const;
range range(const std::string &range_string, int row_offset, int column_offset);
relationship create_relationship(const std::string &relationship_type);
//void add_chart(chart chart);
void merge_cells(const std::string &range_string);
void merge_cells(int start_row, int start_column, int end_row, int end_column);
void unmerge_cells(const std::string &range_string);
void unmerge_cells(int start_row, int start_column, int end_row, int end_column);
void append(const std::vector<xlnt::cell> &cells);
void append(const std::unordered_map<std::string, xlnt::cell> &cells);
void append(const std::unordered_map<int, xlnt::cell> &cells);
xlnt::range rows() const;
xlnt::range columns() const;
bool operator==(const worksheet &other);
private:
worksheet_struct *root_;
};
} // namespace xlnt

View File

@ -1,156 +0,0 @@
#include <ctime>
#include "cell.h"
#include "worksheet.h"
namespace xlnt {
struct cell_struct
{
cell_struct() : type(cell::type::null)
{
}
cell_struct(worksheet *ws, const std::string &column, int row)
: type(cell::type::null), parent_worksheet(ws),
column(xlnt::cell::column_index_from_string(column) - 1), row(row)
{
}
std::string to_string() const
{
switch(type)
{
case cell::type::numeric: return std::to_string(numeric_value);
case cell::type::boolean: return bool_value ? "true" : "false";
case cell::type::string: return string_value;
default: throw std::runtime_error("bad enum");
}
}
cell::type type;
union
{
long double numeric_value;
bool bool_value;
};
tm date_value;
std::string string_value;
worksheet *parent_worksheet;
int column;
int row;
};
cell::cell(const cell &copy)
{
root_ = copy.root_;
}
coordinate cell::coordinate_from_string(const std::string &address)
{
if(address == "A1")
{
return {"A", 1};
}
return {"A", 1};
}
int cell::column_index_from_string(const std::string &column_string)
{
return column_string[0] - 'A';
}
std::string cell::get_column_letter(int column_index)
{
return std::string(1, (char)('A' + column_index - 1));
}
bool cell::is_date() const
{
return root_->type == type::date;
}
bool operator==(const char *comparand, const cell &cell)
{
return std::string(comparand) == cell;
}
bool operator==(const std::string &comparand, const cell &cell)
{
return cell.root_->type == cell::type::string && cell.root_->string_value == comparand;
}
bool operator==(const tm &comparand, const cell &cell)
{
return cell.root_->type == cell::type::date && cell.root_->date_value.tm_hour == comparand.tm_hour;
}
std::string cell::absolute_coordinate(const std::string &absolute_address)
{
return absolute_address;
}
cell::cell(worksheet &ws, const std::string &column, int row) : root_(new cell_struct(&ws, column, row))
{
}
cell::cell(worksheet &ws, const std::string &column, int row, const std::string &value) : root_(new cell_struct(&ws, column, row))
{
*this = value;
}
cell::type cell::get_data_type()
{
return root_->type;
}
cell &cell::operator=(int value)
{
root_->type = type::numeric;
root_->numeric_value = value;
return *this;
}
cell &cell::operator=(double value)
{
root_->type = type::numeric;
root_->numeric_value = value;
return *this;
}
cell &cell::operator=(const std::string &value)
{
root_->type = type::string;
root_->string_value = value;
return *this;
}
cell &cell::operator=(const char *value)
{
return *this = std::string(value);
}
cell &cell::operator=(const tm &value)
{
root_->type = type::date;
root_->date_value = value;
return *this;
}
cell::~cell()
{
delete root_;
}
std::string cell::to_string() const
{
return root_->to_string();
}
} // namespace xlnt

View File

@ -1,129 +0,0 @@
#include <algorithm>
#include <fstream>
#include <unordered_map>
#include "workbook.h"
#include "worksheet.h"
#include "packaging/package.h"
namespace xlnt {
struct workbook_struct
{
workbook_struct(workbook *parent) : parent_(parent)
{
worksheets_.emplace_back(*parent, "Sheet1");
active_name_ = "Sheet1";
}
worksheet get_sheet_by_name(const std::string &name)
{
auto match = std::find_if(worksheets_.begin(), worksheets_.end(), [=](const worksheet &w) { return w.get_title() == name; });
return *match;
}
worksheet get_active()
{
return get_sheet_by_name(active_name_);
}
std::vector<worksheet>::iterator begin()
{
return worksheets_.begin();
}
std::vector<worksheet>::iterator end()
{
return worksheets_.end();
}
std::vector<std::string> get_sheet_names() const
{
std::vector<std::string> names;
for(auto sheet : worksheets_)
{
names.push_back(sheet.get_title());
}
return names;
}
worksheet create_sheet()
{
worksheets_.emplace_back(*parent_, "Sheet");
worksheets_.back().set_title("Sheet" + std::to_string(worksheets_.size()));
return worksheets_.back();
}
worksheet create_sheet(std::size_t index)
{
worksheets_.emplace(worksheets_.begin() + index, *parent_, "Sheet");
worksheets_[index].set_title("Sheet" + std::to_string(worksheets_.size()));
return worksheets_[index];
}
void save(const std::string &filename)
{
auto package = package::open(filename);
package.close();
}
std::vector<worksheet> worksheets_;
std::string active_name_;
workbook *parent_;
};
workbook::workbook() : root_(new workbook_struct(this))
{
}
worksheet workbook::get_sheet_by_name(const std::string &name)
{
if(root_ == nullptr)
{
throw std::runtime_error("workbook not initialized");
}
return root_->get_sheet_by_name(name);
}
worksheet workbook::get_active()
{
return root_->get_active();
}
worksheet workbook::create_sheet()
{
return root_->create_sheet();
}
worksheet workbook::create_sheet(std::size_t index)
{
return root_->create_sheet(index);
}
std::vector<worksheet>::iterator workbook::begin()
{
return root_->begin();
}
std::vector<worksheet>::iterator workbook::end()
{
return root_->end();
}
std::vector<std::string> workbook::get_sheet_names() const
{
return root_->get_sheet_names();
}
worksheet workbook::operator[](const std::string &name)
{
return get_sheet_by_name(name);
}
void workbook::save(const std::string &filename)
{
root_->save(filename);
}
} // namespace xlnt

View File

@ -1,380 +0,0 @@
#include <unordered_map>
#include "worksheet.h"
#include "workbook.h"
#include "cell.h"
#include "packaging/relationship.h"
namespace xlnt {
namespace {
class not_implemented : public std::runtime_error
{
public:
not_implemented() : std::runtime_error("error: not implemented")
{
}
};
// Convert a column number into a column letter (3 -> 'C')
// Right shift the column col_idx by 26 to find column letters in reverse
// order.These numbers are 1 - based, and can be converted to ASCII
// ordinals by adding 64.
std::string get_column_letter(int column_index)
{
// these indicies corrospond to A->ZZZ and include all allowed
// columns
if(column_index < 1 || column_index > 18278)
{
auto msg = "Column index out of bounds: " + column_index;
throw std::runtime_error(msg);
}
auto temp = column_index;
std::string column_letter = "";
while(temp > 0)
{
int quotient = temp / 26, remainder = temp % 26;
// check for exact division and borrow if needed
if(remainder == 0)
{
quotient -= 1;
remainder = 26;
}
column_letter = std::string(1, char(remainder + 64)) + column_letter;
temp = quotient;
}
return column_letter;
}
}
struct worksheet_struct
{
worksheet_struct(workbook &parent_workbook, worksheet &owner, const std::string &title)
: parent_(parent_workbook), title_(title), freeze_panes_(owner, "A", 1), owner_(owner)
{
}
void garbage_collect()
{
throw not_implemented();
}
std::set<cell> get_cell_collection()
{
throw not_implemented();
}
std::string get_title() const
{
throw not_implemented();
}
void set_title(const std::string &title)
{
title_ = title;
}
cell get_freeze_panes() const
{
throw not_implemented();
}
void set_freeze_panes(cell top_left_cell)
{
throw not_implemented();
}
void set_freeze_panes(const std::string &top_left_coordinate)
{
freeze_panes_ = cell(top_left_coordinate);
}
void unfreeze_panes()
{
throw not_implemented();
}
xlnt::cell cell(const std::string &coordinate)
{
if(cell_map_.find(coordinate) == cell_map_.end())
{
auto coord = xlnt::cell::coordinate_from_string(coordinate);
cells_.emplace_back(owner_, coord.column, coord.row);
cell_map_[coordinate] = &cells_.back();
}
return *cell_map_[coordinate];
}
xlnt::cell cell(int row, int column)
{
return cell(get_column_letter(column + 1) + std::to_string(row + 1));
}
int get_highest_row() const
{
throw not_implemented();
}
int get_highest_column() const
{
throw not_implemented();
}
std::string calculate_dimension() const
{
throw not_implemented();
}
range range(const std::string &range_string, int /*row_offset*/, int /*column_offset*/)
{
auto colon_index = range_string.find(':');
if(colon_index != std::string::npos)
{
auto min_range = range_string.substr(0, colon_index);
auto max_range = range_string.substr(colon_index + 1);
xlnt::range r;
r.push_back(std::vector<xlnt::cell>());
r[0].push_back(cell(min_range));
r[0].push_back(cell(max_range));
return r;
}
throw not_implemented();
}
relationship create_relationship(const std::string &relationship_type)
{
relationships_.push_back(relationship(relationship_type));
return relationships_.back();
}
//void add_chart(chart chart);
void merge_cells(const std::string &/*range_string*/)
{
throw not_implemented();
}
void merge_cells(int /*start_row*/, int /*start_column*/, int /*end_row*/, int /*end_column*/)
{
throw not_implemented();
}
void unmerge_cells(const std::string &/*range_string*/)
{
throw not_implemented();
}
void unmerge_cells(int /*start_row*/, int /*start_column*/, int /*end_row*/, int /*end_column*/)
{
throw not_implemented();
}
void append(const std::vector<xlnt::cell> &cells)
{
for(auto cell : cells)
{
*cell_map_["a"] = cell;
}
}
void append(const std::unordered_map<std::string, xlnt::cell> &cells)
{
for(auto cell : cells)
{
*cell_map_[cell.first] = cell.second;
}
}
void append(const std::unordered_map<int, xlnt::cell> &cells)
{
for(auto cell : cells)
{
*cell_map_[get_column_letter(cell.first + 1)] = cell.second;
}
}
xlnt::range rows() const
{
throw not_implemented();
}
xlnt::range columns() const
{
throw not_implemented();
}
void operator=(const worksheet_struct &other) = delete;
workbook &parent_;
std::string title_;
xlnt::cell freeze_panes_;
std::vector<xlnt::cell> cells_;
std::unordered_map<std::string, xlnt::cell *> cell_map_;
std::vector<relationship> relationships_;
worksheet &owner_;
};
worksheet::worksheet(workbook &parent_workbook, const std::string &title)
: root_(nullptr)
{
root_ = new worksheet_struct(parent_workbook, *this, title);
}
std::string worksheet::to_string() const
{
return "<Worksheet \"" + root_->title_ + "\">";
}
workbook &worksheet::get_parent() const
{
return root_->parent_;
}
void worksheet::garbage_collect()
{
root_->garbage_collect();
}
std::set<cell> worksheet::get_cell_collection()
{
return root_->get_cell_collection();
}
std::string worksheet::get_title() const
{
return root_->title_;
}
void worksheet::set_title(const std::string &title)
{
root_->title_ = title;
}
cell worksheet::get_freeze_panes() const
{
return root_->freeze_panes_;
}
void worksheet::set_freeze_panes(xlnt::cell top_left_cell)
{
root_->set_freeze_panes(top_left_cell);
}
void worksheet::set_freeze_panes(const std::string &top_left_coordinate)
{
root_->set_freeze_panes(top_left_coordinate);
}
void worksheet::unfreeze_panes()
{
root_->unfreeze_panes();
}
xlnt::cell worksheet::cell(const std::string &coordinate)
{
return root_->cell(coordinate);
}
xlnt::cell worksheet::cell(int row, int column)
{
return root_->cell(row, column);
}
int worksheet::get_highest_row() const
{
return root_->get_highest_row();
}
int worksheet::get_highest_column() const
{
return root_->get_highest_column();
}
std::string worksheet::calculate_dimension() const
{
return root_->calculate_dimension();
}
range worksheet::range(const std::string &range_string, int row_offset, int column_offset)
{
return root_->range(range_string, row_offset, column_offset);
}
relationship worksheet::create_relationship(const std::string &relationship_type)
{
return root_->create_relationship(relationship_type);
}
//void worksheet::add_chart(chart chart);
void worksheet::merge_cells(const std::string &range_string)
{
root_->merge_cells(range_string);
}
void worksheet::merge_cells(int start_row, int start_column, int end_row, int end_column)
{
root_->merge_cells(start_row, start_column, end_row, end_column);
}
void worksheet::unmerge_cells(const std::string &range_string)
{
root_->unmerge_cells(range_string);
}
void worksheet::unmerge_cells(int start_row, int start_column, int end_row, int end_column)
{
root_->unmerge_cells(start_row, start_column, end_row, end_column);
}
void worksheet::append(const std::vector<xlnt::cell> &cells)
{
root_->append(cells);
}
void worksheet::append(const std::unordered_map<std::string, xlnt::cell> &cells)
{
root_->append(cells);
}
void worksheet::append(const std::unordered_map<int, xlnt::cell> &cells)
{
root_->append(cells);
}
xlnt::range worksheet::rows() const
{
return root_->rows();
}
xlnt::range worksheet::columns() const
{
return root_->columns();
}
bool worksheet::operator==(const worksheet &other)
{
return root_ == other.root_;
}
void worksheet::operator=(const worksheet &other)
{
root_ = other.root_;
}
cell worksheet::operator[](const std::string &address)
{
return cell(address);
}
} // namespace xlnt

View File

@ -1,502 +0,0 @@
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <vector>
#include "color.h"
#include "enum_iterator.h"
namespace xlnt {
const color color::AliceBlue = color::from_argb(255, 240, 248, 255);
const color color::AntiqueWhite = color::from_argb(255, 250, 235, 215);
const color color::Aqua = color::from_argb(255, 0, 255, 255);
const color color::Aquamarine = color::from_argb(255, 127, 255, 212);
const color color::Azure = color::from_argb(255, 240, 255, 255);
const color color::Beige = color::from_argb(255, 245, 245, 220);
const color color::Bisque = color::from_argb(255, 255, 228, 196);
const color color::Black = color::from_argb(255, 0, 0, 0);
const color color::BlanchedAlmond = color::from_argb(255, 255, 235, 205);
const color color::Blue = color::from_argb(255, 0, 0, 255);
const color color::BlueViolet = color::from_argb(255, 138, 43, 226);
const color color::Brown = color::from_argb(255, 165, 42, 42);
const color color::BurlyWood = color::from_argb(255, 222, 184, 135);
const color color::CadetBlue = color::from_argb(255, 95, 158, 160);
const color color::Chartreuse = color::from_argb(255, 127, 255, 0);
const color color::Chocolate = color::from_argb(255, 210, 105, 30);
const color color::Coral = color::from_argb(255, 255, 127, 80);
const color color::CornflowerBlue = color::from_argb(255, 100, 149, 237);
const color color::Cornsilk = color::from_argb(255, 255, 248, 220);
const color color::Crimson = color::from_argb(255, 220, 20, 60);
const color color::Cyan = color::from_argb(255, 0, 255, 255);
const color color::DarkBlue = color::from_argb(255, 0, 0, 139);
const color color::DarkCyan = color::from_argb(255, 0, 139, 139);
const color color::DarkGoldenrod = color::from_argb(255, 184, 134, 11);
const color color::DarkGray = color::from_argb(255, 169, 169, 169);
const color color::DarkGreen = color::from_argb(255, 0, 100, 0);
const color color::DarkKhaki = color::from_argb(255, 189, 183, 107);
const color color::DarkMagenta = color::from_argb(255, 139, 0, 139);
const color color::DarkOliveGreen = color::from_argb(255, 85, 107, 47);
const color color::DarkOrange = color::from_argb(255, 255, 140, 0);
const color color::DarkOrchid = color::from_argb(255, 153, 50, 204);
const color color::DarkRed = color::from_argb(255, 139, 0, 0);
const color color::DarkSalmon = color::from_argb(255, 233, 150, 122);
const color color::DarkSeaGreen = color::from_argb(255, 143, 188, 143);
const color color::DarkSlateBlue = color::from_argb(255, 72, 61, 139);
const color color::DarkSlateGray = color::from_argb(255, 47, 79, 79);
const color color::DarkTurquoise = color::from_argb(255, 0, 206, 209);
const color color::DarkViolet = color::from_argb(255, 148, 0, 211);
const color color::DeepPink = color::from_argb(255, 255, 20, 147);
const color color::DeepSkyBlue = color::from_argb(255, 0, 191, 255);
const color color::DimGray = color::from_argb(255, 105, 105, 105);
const color color::DodgerBlue = color::from_argb(255, 30, 144, 255);
const color color::Firebrick = color::from_argb(255, 178, 34, 34);
const color color::FloralWhite = color::from_argb(255, 255, 250, 240);
const color color::ForestGreen = color::from_argb(255, 34, 139, 34);
const color color::Fuchsia = color::from_argb(255, 255, 0, 255);
const color color::Gainsboro = color::from_argb(255, 220, 220, 220);
const color color::GhostWhite = color::from_argb(255, 248, 248, 255);
const color color::Gold = color::from_argb(255, 255, 215, 0);
const color color::Goldenrod = color::from_argb(255, 218, 165, 32);
const color color::Gray = color::from_argb(255, 128, 128, 128);
const color color::Green = color::from_argb(255, 0, 128, 0);
const color color::GreenYellow = color::from_argb(255, 173, 255, 47);
const color color::Honeydew = color::from_argb(255, 240, 255, 240);
const color color::HotPink = color::from_argb(255, 255, 105, 180);
const color color::IndianRed = color::from_argb(255, 205, 92, 92);
const color color::Indigo = color::from_argb(255, 75, 0, 130);
const color color::Ivory = color::from_argb(255, 255, 255, 240);
const color color::Khaki = color::from_argb(255, 240, 230, 140);
const color color::Lavender = color::from_argb(255, 230, 230, 250);
const color color::LavenderBlush = color::from_argb(255, 255, 240, 245);
const color color::LawnGreen = color::from_argb(255, 124, 252, 0);
const color color::LemonChiffon = color::from_argb(255, 255, 250, 205);
const color color::LightBlue = color::from_argb(255, 173, 216, 230);
const color color::LightCoral = color::from_argb(255, 240, 128, 128);
const color color::LightCyan = color::from_argb(255, 224, 255, 255);
const color color::LightGoldenrodYellow = color::from_argb(255, 250, 250, 210);
const color color::LightGray = color::from_argb(255, 211, 211, 211);
const color color::LightGreen = color::from_argb(255, 144, 238, 144);
const color color::LightPink = color::from_argb(255, 255, 182, 193);
const color color::LightSalmon = color::from_argb(255, 255, 160, 122);
const color color::LightSeaGreen = color::from_argb(255, 32, 178, 170);
const color color::LightSkyBlue = color::from_argb(255, 135, 206, 250);
const color color::LightSlateGray = color::from_argb(255, 119, 136, 153);
const color color::LightSteelBlue = color::from_argb(255, 176, 196, 222);
const color color::LightYellow = color::from_argb(255, 255, 255, 224);
const color color::Lime = color::from_argb(255, 0, 255, 0);
const color color::LimeGreen = color::from_argb(255, 50, 205, 50);
const color color::Linen = color::from_argb(255, 250, 240, 230);
const color color::Magenta = color::from_argb(255, 255, 0, 255);
const color color::Maroon = color::from_argb(255, 128, 0, 0);
const color color::MediumAquamarine = color::from_argb(255, 102, 205, 170);
const color color::MediumBlue = color::from_argb(255, 0, 0, 205);
const color color::MediumOrchid = color::from_argb(255, 186, 85, 211);
const color color::MediumPurple = color::from_argb(255, 147, 112, 219);
const color color::MediumSeaGreen = color::from_argb(255, 60, 179, 113);
const color color::MediumSlateBlue = color::from_argb(255, 123, 104, 238);
const color color::MediumSpringGreen = color::from_argb(255, 0, 250, 154);
const color color::MediumTurquoise = color::from_argb(255, 72, 209, 204);
const color color::MediumVioletRed = color::from_argb(255, 199, 21, 133);
const color color::MidnightBlue = color::from_argb(255, 25, 25, 112);
const color color::MintCream = color::from_argb(255, 245, 255, 250);
const color color::MistyRose = color::from_argb(255, 255, 228, 225);
const color color::Moccasin = color::from_argb(255, 255, 228, 181);
const color color::NavajoWhite = color::from_argb(255, 255, 222, 173);
const color color::Navy = color::from_argb(255, 0, 0, 128);
const color color::OldLace = color::from_argb(255, 253, 245, 230);
const color color::Olive = color::from_argb(255, 128, 128, 0);
const color color::OliveDrab = color::from_argb(255, 107, 142, 35);
const color color::Orange = color::from_argb(255, 255, 165, 0);
const color color::OrangeRed = color::from_argb(255, 255, 69, 0);
const color color::Orchid = color::from_argb(255, 218, 112, 214);
const color color::PaleGoldenrod = color::from_argb(255, 238, 232, 170);
const color color::PaleGreen = color::from_argb(255, 152, 251, 152);
const color color::PaleTurquoise = color::from_argb(255, 175, 238, 238);
const color color::PaleVioletRed = color::from_argb(255, 219, 112, 147);
const color color::PapayaWhip = color::from_argb(255, 255, 239, 213);
const color color::PeachPuff = color::from_argb(255, 255, 218, 185);
const color color::Peru = color::from_argb(255, 205, 133, 63);
const color color::Pink = color::from_argb(255, 255, 192, 203);
const color color::Plum = color::from_argb(255, 221, 160, 221);
const color color::PowderBlue = color::from_argb(255, 176, 224, 230);
const color color::Purple = color::from_argb(255, 128, 0, 128);
const color color::Red = color::from_argb(255, 255, 0, 0);
const color color::RosyBrown = color::from_argb(255, 188, 143, 143);
const color color::RoyalBlue = color::from_argb(255, 65, 105, 225);
const color color::SaddleBrown = color::from_argb(255, 139, 69, 19);
const color color::Salmon = color::from_argb(255, 250, 128, 114);
const color color::SandyBrown = color::from_argb(255, 244, 164, 96);
const color color::SeaGreen = color::from_argb(255, 46, 139, 87);
const color color::SeaShell = color::from_argb(255, 255, 245, 238);
const color color::Sienna = color::from_argb(255, 160, 82, 45);
const color color::Silver = color::from_argb(255, 192, 192, 192);
const color color::SkyBlue = color::from_argb(255, 135, 206, 235);
const color color::SlateBlue = color::from_argb(255, 106, 90, 205);
const color color::SlateGray = color::from_argb(255, 112, 128, 144);
const color color::Snow = color::from_argb(255, 255, 250, 250);
const color color::SpringGreen = color::from_argb(255, 0, 255, 127);
const color color::SteelBlue = color::from_argb(255, 70, 130, 180);
const color color::Tan = color::from_argb(255, 210, 180, 140);
const color color::Teal = color::from_argb(255, 0, 128, 128);
const color color::Thistle = color::from_argb(255, 216, 191, 216);
const color color::Tomato = color::from_argb(255, 255, 99, 71);
const color color::Transparent = color::from_argb(0, 0, 0, 0);
const color color::Turquoise = color::from_argb(255, 64, 224, 208);
const color color::Violet = color::from_argb(255, 238, 130, 238);
const color color::Wheat = color::from_argb(255, 245, 222, 179);
const color color::White = color::from_argb(255, 255, 255, 255);
const color color::WhiteSmoke = color::from_argb(255, 245, 245, 245);
const color color::Yellow = color::from_argb(255, 255, 255, 0);
const color color::YellowGreen = color::from_argb(255, 154, 205, 50);
const color color::Empty;
color color::from_argb(uint32_t argb)
{
return color(uint8_t(argb >> 24), uint8_t(argb >> 16), uint8_t(argb >> 8), uint8_t(argb));
}
color color::from_argb(uint8_t alpha, color base)
{
return color(alpha, base.red_, base.green_, base.blue_);
}
color color::from_argb(uint8_t r, uint8_t g, uint8_t b)
{
return color(255, r, g, b);
}
color color::from_argb(uint8_t a, uint8_t r, uint8_t g, uint8_t b)
{
return color(a, r, g, b);
}
color color::from_known_color(known_color color)
{
switch(color)
{
case known_color::AliceBlue: return AliceBlue;
case known_color::AntiqueWhite: return AntiqueWhite;
case known_color::Aqua: return Aqua;
case known_color::Aquamarine: return Aquamarine;
case known_color::Azure: return Azure;
case known_color::Beige: return Beige;
case known_color::Bisque: return Bisque;
case known_color::Black: return Black;
case known_color::BlanchedAlmond: return BlanchedAlmond;
case known_color::Blue: return Blue;
case known_color::BlueViolet: return BlueViolet;
case known_color::Brown: return Brown;
case known_color::BurlyWood: return BurlyWood;
case known_color::CadetBlue: return CadetBlue;
case known_color::Chartreuse: return Chartreuse;
case known_color::Chocolate: return Chocolate;
case known_color::Coral: return Coral;
case known_color::CornflowerBlue: return CornflowerBlue;
case known_color::Cornsilk: return Cornsilk;
case known_color::Crimson: return Crimson;
case known_color::Cyan: return Cyan;
case known_color::DarkBlue: return DarkBlue;
case known_color::DarkCyan: return DarkCyan;
case known_color::DarkGoldenrod: return DarkGoldenrod;
case known_color::DarkGray: return DarkGray;
case known_color::DarkGreen: return DarkGreen;
case known_color::DarkKhaki: return DarkKhaki;
case known_color::DarkMagenta: return DarkMagenta;
case known_color::DarkOliveGreen: return DarkOliveGreen;
case known_color::DarkOrange: return DarkOrange;
case known_color::DarkOrchid: return DarkOrchid;
case known_color::DarkRed: return DarkRed;
case known_color::DarkSalmon: return DarkSalmon;
case known_color::DarkSeaGreen: return DarkSeaGreen;
case known_color::DarkSlateBlue: return DarkSlateBlue;
case known_color::DarkSlateGray: return DarkSlateGray;
case known_color::DarkTurquoise: return DarkTurquoise;
case known_color::DarkViolet: return DarkViolet;
case known_color::DeepPink: return DeepPink;
case known_color::DeepSkyBlue: return DeepSkyBlue;
case known_color::DimGray: return DimGray;
case known_color::DodgerBlue: return DodgerBlue;
case known_color::Firebrick: return Firebrick;
case known_color::FloralWhite: return FloralWhite;
case known_color::ForestGreen: return ForestGreen;
case known_color::Fuchsia: return Fuchsia;
case known_color::Gainsboro: return Gainsboro;
case known_color::GhostWhite: return GhostWhite;
case known_color::Gold: return Gold;
case known_color::Goldenrod: return Goldenrod;
case known_color::Gray: return Gray;
case known_color::Green: return Green;
case known_color::GreenYellow: return GreenYellow;
case known_color::Honeydew: return Honeydew;
case known_color::HotPink: return HotPink;
case known_color::IndianRed: return IndianRed;
case known_color::Indigo: return Indigo;
case known_color::Ivory: return Ivory;
case known_color::Khaki: return Khaki;
case known_color::Lavender: return Lavender;
case known_color::LavenderBlush: return LavenderBlush;
case known_color::LawnGreen: return LawnGreen;
case known_color::LemonChiffon: return LemonChiffon;
case known_color::LightBlue: return LightBlue;
case known_color::LightCoral: return LightCoral;
case known_color::LightCyan: return LightCyan;
case known_color::LightGoldenrodYellow: return LightGoldenrodYellow;
case known_color::LightGray: return LightGray;
case known_color::LightGreen: return LightGreen;
case known_color::LightPink: return LightPink;
case known_color::LightSalmon: return LightSalmon;
case known_color::LightSeaGreen: return LightSeaGreen;
case known_color::LightSkyBlue: return LightSkyBlue;
case known_color::LightSlateGray: return LightSlateGray;
case known_color::LightSteelBlue: return LightSteelBlue;
case known_color::LightYellow: return LightYellow;
case known_color::Lime: return Lime;
case known_color::LimeGreen: return LimeGreen;
case known_color::Linen: return Linen;
case known_color::Magenta: return Magenta;
case known_color::Maroon: return Maroon;
case known_color::MediumAquamarine: return MediumAquamarine;
case known_color::MediumBlue: return MediumBlue;
case known_color::MediumOrchid: return MediumOrchid;
case known_color::MediumPurple: return MediumPurple;
case known_color::MediumSeaGreen: return MediumSeaGreen;
case known_color::MediumSlateBlue: return MediumSlateBlue;
case known_color::MediumSpringGreen: return MediumSpringGreen;
case known_color::MediumTurquoise: return MediumTurquoise;
case known_color::MediumVioletRed: return MediumVioletRed;
case known_color::MidnightBlue: return MidnightBlue;
case known_color::MintCream: return MintCream;
case known_color::MistyRose: return MistyRose;
case known_color::Moccasin: return Moccasin;
case known_color::NavajoWhite: return NavajoWhite;
case known_color::Navy: return Navy;
case known_color::OldLace: return OldLace;
case known_color::Olive: return Olive;
case known_color::OliveDrab: return OliveDrab;
case known_color::Orange: return Orange;
case known_color::OrangeRed: return OrangeRed;
case known_color::Orchid: return Orchid;
case known_color::PaleGoldenrod: return PaleGoldenrod;
case known_color::PaleGreen: return PaleGreen;
case known_color::PaleTurquoise: return PaleTurquoise;
case known_color::PaleVioletRed: return PaleVioletRed;
case known_color::PapayaWhip: return PapayaWhip;
case known_color::PeachPuff: return PeachPuff;
case known_color::Peru: return Peru;
case known_color::Pink: return Pink;
case known_color::Plum: return Plum;
case known_color::PowderBlue: return PowderBlue;
case known_color::Purple: return Purple;
case known_color::Red: return Red;
case known_color::RosyBrown: return RosyBrown;
case known_color::RoyalBlue: return RoyalBlue;
case known_color::SaddleBrown: return SaddleBrown;
case known_color::Salmon: return Salmon;
case known_color::SandyBrown: return SandyBrown;
case known_color::SeaGreen: return SeaGreen;
case known_color::SeaShell: return SeaShell;
case known_color::Sienna: return Sienna;
case known_color::Silver: return Silver;
case known_color::SkyBlue: return SkyBlue;
case known_color::SlateBlue: return SlateBlue;
case known_color::SlateGray: return SlateGray;
case known_color::Snow: return Snow;
case known_color::SpringGreen: return SpringGreen;
case known_color::SteelBlue: return SteelBlue;
case known_color::Tan: return Tan;
case known_color::Teal: return Teal;
case known_color::Thistle: return Thistle;
case known_color::Tomato: return Tomato;
case known_color::Turquoise: return Turquoise;
case known_color::Violet: return Violet;
case known_color::Wheat: return Wheat;
case known_color::White: return White;
case known_color::WhiteSmoke: return WhiteSmoke;
case known_color::Yellow: return Yellow;
case known_color::YellowGreen: return YellowGreen;
}
throw std::runtime_error("unknown known_color");
}
color color::from_name(const std::string &name)
{
for(auto current_color : enum_iterator<known_color>())
{
if(to_string(current_color) == name)
{
return from_known_color(current_color);
}
}
return Empty;
}
bool color::equals(color b) const
{
if(is_empty_)
{
return b.is_empty_;
}
return !b.is_empty_ && alpha_ == b.alpha_ && red_ == b.red_ && green_ == b.green_ && blue_ == b.blue_;
}
struct hsv
{
float h;
float s;
float v;
};
hsv RGBtoHSV(float red, float green, float blue)
{
hsv r;
float min = std::min({red, green, blue});
float max = std::max({red, green, blue});
r.v = max; // v
float delta = max - min;
if(max != 0)
{
r.s = delta / max; // s
}
else
{
// r = g = b = 0 // s = 0, v is undefined
r.s = 0;
r.h = -1;
return r;
}
if(red == max)
{
r.h = (green - blue) / delta; // between yellow & magenta
}
else if(green == max)
{
r.h = 2 + (blue - red) / delta; // between cyan & yellow
}
else
{
r.h = 4 + (red - green) / delta; // between magenta & cyan
}
r.h *= 60; // degrees
if(r.h < 0)
{
r.h += 360;
}
return r;
}
float color::get_brightness() const
{
return RGBtoHSV(red_, green_, blue_).v;
}
float color::get_hue() const
{
return RGBtoHSV(red_, green_, blue_).h;
}
float color::getsaturation() const
{
return RGBtoHSV(red_, green_, blue_).s;
}
bool color::is_known_color() const
{
try
{
to_known_color();
return true;
}
catch(...)
{
return false;
}
}
bool color::is_system_color() const
{
static const std::vector<known_color> system_colors = {
known_color::ActiveBorder,
known_color::ActiveCaption,
known_color::ActiveCaptionText,
known_color::AppWorkspace,
known_color::ButtonFace,
known_color::ButtonHighlight,
known_color::ButtonShadow,
known_color::Control,
known_color::ControlDark,
known_color::ControlDarkDark,
known_color::ControlLight,
known_color::ControlLightLight,
known_color::ControlText,
known_color::Desktop,
known_color::GradientActiveCaption,
known_color::GradientInactiveCaption,
known_color::GrayText,
known_color::Highlight,
known_color::HighlightText,
known_color::HotTrack,
known_color::InactiveBorder,
known_color::InactiveCaption,
known_color::InactiveCaptionText,
known_color::Info,
known_color::InfoText,
known_color::Menu,
known_color::MenuBar,
known_color::MenuHighlight,
known_color::MenuText,
known_color::ScrollBar,
known_color::Window,
known_color::WindowFrame,
known_color::WindowText
};
try
{
return std::find(system_colors.begin(), system_colors.end(), to_known_color()) != system_colors.end();
}
catch(...)
{
return false;
}
}
uint32_t color::to_argb() const
{
uint32_t argb = alpha_;
argb = argb << 8 | red_;
argb = argb << 8 | green_;
argb = argb << 8 | blue_;
return argb;
}
known_color color::to_known_color() const
{
for(auto current_color : enum_iterator<known_color>())
{
if(from_known_color(current_color) == *this)
{
return current_color;
}
}
return known_color::Unknown;
}
std::string color::get_name() const
{
try
{
return to_string(to_known_color());
}
catch(...)
{
std::stringstream stream;
stream << "#" << std::setfill('0') << std::setw(2) << std::hex;
stream << alpha_ << red_ << green_ << blue_;
return stream.str();
}
}
} // namespace xlnt

File diff suppressed because it is too large Load Diff

View File

@ -1,49 +0,0 @@
#pragma once
#include <iterator>
namespace xlnt {
template<class enum_type>
class enum_iterator {
private:
enum_type value;
typedef typename std::underlying_type<enum_type>::type under;
public:
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef enum_type value_type;
typedef enum_type reference;
typedef enum_type* pointer;
typedef std::random_access_iterator_tag iterator_category;
enum_iterator() :value() {}
enum_iterator(const enum_iterator& rhs) : value(rhs.value) {}
explicit enum_iterator(enum_type value_) : value(value_) {}
~enum_iterator() {}
enum_iterator& operator=(const enum_iterator& rhs) { value = rhs.valud; return *this; }
enum_iterator& operator++() { value = (enum_type)(under(value) + 1); return *this; }
enum_iterator operator++(int){ enum_iterator r(*this); ++*this; return r; }
enum_iterator& operator+=(size_type o) { value = (enum_type)(under(value) + o); return *this; }
friend enum_iterator operator+(const enum_iterator& it, size_type o) { return enum_iterator((enum_type)(under(it) + o)); }
friend enum_iterator operator+(size_type o, const enum_iterator& it) { return enum_iterator((enum_type)(under(it) + o)); }
enum_iterator& operator--() { value = (enum_type)(under(value) - 1); return *this; }
enum_iterator operator--(int) { enum_iterator r(*this); --*this; return r; }
enum_iterator& operator-=(size_type o) { value = (enum_type)(under(value) + o); return *this; }
friend enum_iterator operator-(const enum_iterator& it, size_type o) { return enum_iterator((enum_type)(under(it) - o)); }
friend difference_type operator-(enum_iterator lhs, enum_iterator rhs) { return under(lhs.value) - under(rhs.value); }
reference operator*() const { return value; }
reference operator[](size_type o) const { return (enum_type)(under(value) + o); }
const enum_type* operator->() const { return &value; }
friend bool operator==(const enum_iterator& lhs, const enum_iterator& rhs) { return lhs.value == rhs.value; }
friend bool operator!=(const enum_iterator& lhs, const enum_iterator& rhs) { return lhs.value != rhs.value; }
friend bool operator<(const enum_iterator& lhs, const enum_iterator& rhs) { return lhs.value<rhs.value; }
friend bool operator>(const enum_iterator& lhs, const enum_iterator& rhs) { return lhs.value>rhs.value; }
friend bool operator<=(const enum_iterator& lhs, const enum_iterator& rhs) { return lhs.value <= rhs.value; }
friend bool operator>=(const enum_iterator& lhs, const enum_iterator& rhs) { return lhs.value >= rhs.value; }
friend void swap(const enum_iterator& lhs, const enum_iterator& rhs) { std::swap(lhs.value, rhs.value); }
enum_iterator begin() { return enum_iterator<enum_type>(enum_type::First); }
enum_iterator end() { return enum_iterator<enum_type>(enum_type::Last); }
};
} // namespace xlnt

View File

@ -1,148 +0,0 @@
#pragma once
#include <stdexcept>
namespace xlnt {
/// <summary>
/// Represents a value type that may or may not have an assigned value.
/// </summary>
template<typename T>
struct nullable
{
public:
/// <summary>
/// Initializes a new instance of the nullable&lt;T&gt; structure with a "null" value.
/// </summary>
nullable() : has_value_(false) {}
/// <summary>
/// Initializes a new instance of the nullable&lt;T&gt; structure to the specified value.
/// </summary>
nullable(const T &value) : has_value_(true), value_(value) {}
/// <summary>
/// gets a value indicating whether the current nullable&lt;T&gt; object has a valid value of its underlying type.
/// </summary>
bool has_value() const { return has_value_; }
/// <summary>
/// gets the value of the current nullable&lt;T&gt; object if it has been assigned a valid underlying value.
/// </summary>
T get_value() const
{
if(!has_value())
{
throw std::runtime_error("invalid operation");
}
return value_;
}
/// <summary>
/// Indicates whether the current nullable&lt;T&gt; object is equal to a specified object.
/// </summary>
bool equals(const nullable<T> &other) const
{
if(!has_value())
{
return !other.has_value();
}
if(other.has_value())
{
return get_value() == other.get_value();
}
return false;
}
/// <summary>
/// Retrieves the value of the current nullable&lt;T&gt; object, or the object's default value.
/// </summary>
T get_value_or_default()
{
if(has_value())
{
return get_value();
}
return T();
}
/// <summary>
/// Retrieves the value of the current nullable&lt;T&gt; object or the specified default value.
/// </summary>
T get_value_or_default(const T &default_)
{
if(has_value())
{
return get_value();
}
return default_;
}
/// <summary>
/// Returns the value of a specified nullable&lt;T&gt; value.
/// </summary>
operator T() const
{
return get_value();
}
/// <summary>
/// Indicates whether the current nullable&lt;T&gt; object is equal to a specified object.
/// </summary>
bool operator==(nullptr_t) const
{
return !has_value_;
}
/// <summary>
/// Indicates whether the current nullable&lt;T&gt; object is not equal to a specified object.
/// </summary>
bool operator!=(nullptr_t) const
{
return has_value_;
}
/// <summary>
/// Indicates whether the current nullable&lt;T&gt; object is equal to a specified object.
/// </summary>
bool operator==(T other) const
{
return has_value_ && other == value_;
}
/// <summary>
/// Indicates whether the current nullable&lt;T&gt; object is not equal to a specified object.
/// </summary>
bool operator!=(T other) const
{
return has_value_ && other != value_;
}
/// <summary>
/// Indicates whether the current nullable&lt;T&gt; object is equal to a specified object.
/// </summary>
bool operator==(const nullable<T> &other) const
{
return equals(other);
}
/// <summary>
/// Indicates whether the current nullable&lt;T&gt; object is not equal to a specified object.
/// </summary>
bool operator!=(const nullable<T> &other) const
{
return !(*this == other);
}
private:
bool has_value_;
T value_;
};
} // namespace xlnt

View File

@ -1,32 +0,0 @@
#pragma once
namespace xlnt {
/// <summary>
/// Specifies the compression level for content that is stored in a part.
/// </summary>
enum class compression_option
{
/// <summary>
/// Compression is optimized for performance.
/// </summary>
Fast,
/// <summary>
/// Compression is optimized for size.
/// </summary>
Maximum,
/// <summary>
/// Compression is optimized for a balance between size and performance.
/// </summary>
Normal,
/// <summary>
/// Compression is turned off.
/// </summary>
NotCompressed,
/// <summary>
/// Compression is optimized for high performance.
/// </summary>
SuperFast
};
} // namespace xlnt

View File

@ -1,24 +0,0 @@
#pragma once
#include <string>
namespace xlnt {
/// <summary>
/// Provides static methods for the creation, copying, deletion, moving, and opening of a single file, and aids in the creation of FileStream objects.
/// </summary>
class file
{
public:
/// <summary>
/// Copies an existing file to a new file. Overwriting a file of the same name is allowed.
/// </summary>
static void copy(const std::string &source, const std::string &destination, bool overwrite = false);
/// <summary>
/// Determines whether the specified file exists.
/// </summary>
static bool exists(const std::string &path);
};
} // namespace xlnt

View File

@ -1,28 +0,0 @@
#pragma once
namespace xlnt {
/// <summary>
/// Defines constants for read, write, or read / write access to a file.
/// </summary>
enum class file_access
{
/// <summary>
/// Read access to the file. Data can be read from the file. Combine with Write for read/write access.
/// </summary>
Read = 0x01,
/// <summary>
/// Read and write access to the file. Data can be written to and read from the file.
/// </summary>
ReadWrite = 0x02,
/// <summary>
/// Write access to the file. Data can be written to the file. Combine with Read for read/write access.
/// </summary>
Write = 0x04,
/// <summary>
/// Inherit access for part from enclosing package.
/// </summary>
FromPackage = 0x08
};
} // namespace xlnt

View File

@ -1,36 +0,0 @@
#pragma once
namespace xlnt {
/// <summary>
/// Specifies how the operating system should open a file.
/// </summary>
enum class file_mode
{
/// <summary>
/// Opens the file if it exists and seeks to the end of the file, or creates a new file.This requires FileIOPermissionAccess.Append permission.file_mode.Append can be used only in conjunction with file_access.Write.Trying to seek to a position before the end of the file throws an IOException exception, and any attempt to read fails and throws a NotSupportedException exception.
/// </summary>
Append,
/// <summary>
/// Specifies that the operating system should create a new file. If the file already exists, it will be overwritten. This requires FileIOPermissionAccess.Write permission. file_mode.Create is equivalent to requesting that if the file does not exist, use CreateNew; otherwise, use Truncate. If the file already exists but is a hidden file, an UnauthorizedAccessException exception is thrown.
/// </summary>
Create,
/// <summary>
/// Specifies that the operating system should create a new file. This requires FileIOPermissionAccess.Write permission. If the file already exists, an IOException exception is thrown.
/// </summary>
CreateNew,
/// <summary>
/// Specifies that the operating system should open an existing file. The ability to open the file is dependent on the value specified by the file_access enumeration. A System.IO.FileNotFoundException exception is thrown if the file does not exist.
/// </summary>
Open,
/// <summary>
/// Specifies that the operating system should open a file if it exists; otherwise, a new file should be created. If the file is opened with file_access.Read, FileIOPermissionAccess.Read permission is required. If the file access is file_access.Write, FileIOPermissionAccess.Write permission is required. If the file is opened with file_access.ReadWrite, both FileIOPermissionAccess.Read and FileIOPermissionAccess.Write permissions are required.
/// </summary>
OpenOrCreate,
/// <summary>
/// Specifies that the operating system should open an existing file. When the file is opened, it should be truncated so that its size is zero bytes. This requires FileIOPermissionAccess.Write permission. Attempts to read from a file opened with file_mode.Truncate cause an ArgumentException exception.
/// </summary>
Truncate
};
} // namespace xlnt

View File

@ -1,43 +0,0 @@
#pragma once
namespace xlnt {
/// <summary>
/// Contains constants for controlling the kind of access other FileStream objects can have to the same file.
/// </summary>
enum class file_share
{
/// <summary>
/// Allows subsequent deleting of a file.
/// </summary>
Delete,
/// <summary>
/// Makes the file handle inheritable by child processes. This is not directly supported by Win32.
/// </summary>
Inheritable,
/// <summary>
/// Declines sharing of the current file. Any request to open the file (by this process or another process) will
/// fail until the file is closed.
/// </summary>
None,
/// <summary>
/// Allows subsequent opening of the file for reading. If this flag is not specified, any request to open the file
/// for reading (by this process or another process) will fail until the file is closed. However, even if this flag
/// is specified, additional permissions might still be needed to access the file.
/// </summary>
Read,
/// <summary>
/// Allows subsequent opening of the file for reading or writing. If this flag is not specified, any request to
/// open the file for reading or writing (by this process or another process) will fail until the file is closed.
/// However, even if this flag is specified, additional permissions might still be needed to access the file.
/// </summary>
ReadWrite,
/// <summary>
/// Allows subsequent opening of the file for writing. If this flag is not specified, any request to open the file
/// for writing (by this process or another process) will fail until the file is closed. However, even if this flag
/// is specified, additional permissions might still be needed to access the file.
/// </summary>
Write
};
} // namespace xlnt

View File

@ -1,23 +0,0 @@
#pragma once
#include <opc/opc.h>
namespace xlnt {
class opc_callback_handler
{
public:
static int read(void *context, char *buffer, int length);
static int write(void *context, const char *buffer, int length);
static int close(void *context);
static opc_ofs_t seek(void *context, opc_ofs_t ofs);
static int trim(void *context, opc_ofs_t new_size);
static int flush(void *context);
};
} // namespace xlnt

View File

@ -1,30 +0,0 @@
#pragma once
#include <array>
#include <iostream>
#include <opc/opc.h>
namespace xlnt {
class opc_streambuf : public std::streambuf
{
public:
opc_streambuf(opcContainer *container, const std::string &part_name);
opc_streambuf(const opc_streambuf &) = delete;
opc_streambuf &operator=(const opc_streambuf &) = delete;
private:
int_type underflow();
int_type uflow();
int_type pbackfail(int_type ch);
std::streamsize showmanyc();
int_type overflow(int_type ch);
int sync();
opcContainer *container_;
std::string part_name_;
std::array<char, 1024> buffer_;
};
} // namespace xlnt

View File

@ -1,393 +0,0 @@
#include <array>
#include <functional>
#include <iostream>
#include "package.h"
#include "file.h"
#include "part.h"
namespace xlnt {
struct package_struct
{
package *parent_;
opcContainer *opc_container_;
std::iostream &stream_;
std::fstream file_stream_;
file_mode package_mode_;
file_access package_access_;
std::vector<xmlChar> container_buffer_;
bool open_;
package_properties package_properties_;
bool streaming_;
file_access get_file_open_access() const
{
if(!open_)
{
throw std::runtime_error("The package is not open");
}
return package_access_;
}
package_properties get_package_properties() const
{
if(!open_)
{
throw std::runtime_error("The package is not open");
}
return package_properties_;
}
package_struct(package *parent, std::iostream &stream, file_mode package_mode, file_access package_access)
: parent_(parent), stream_(stream), container_buffer_(4096), package_mode_(package_mode), package_access_(package_access)
{
open_container();
}
package_struct(package *parent, const std::string &path, file_mode package_mode, file_access package_access)
: parent_(parent), stream_(file_stream_), container_buffer_(4096), package_mode_(package_mode), package_access_(package_access)
{
switch(package_mode)
{
case file_mode::Append:
switch(package_access)
{
case file_access::Read: throw std::runtime_error("Append can only be used with file_access.Write");
case file_access::ReadWrite: throw std::runtime_error("Append can only be used with file_access.Write");
case file_access::Write:
file_stream_.open(path, std::ios::binary | std::ios::app | std::ios::out);
break;
}
break;
case file_mode::Create:
switch(package_access)
{
case file_access::Read:
file_stream_.open(path, std::ios::binary | std::ios::in);
break;
case file_access::ReadWrite:
file_stream_.open(path, std::ios::binary | std::ios::in | std::ios::out);
break;
case file_access::Write:
file_stream_.open(path, std::ios::binary | std::ios::out);
break;
}
break;
case file_mode::CreateNew:
if(!file::exists(path))
{
throw std::runtime_error("File already exists");
}
switch(package_access)
{
case file_access::Read:
file_stream_.open(path, std::ios::binary | std::ios::in);
break;
case file_access::ReadWrite:
file_stream_.open(path, std::ios::binary | std::ios::in | std::ios::out);
break;
case file_access::Write:
file_stream_.open(path, std::ios::binary | std::ios::out);
break;
}
break;
case file_mode::Open:
if(!file::exists(path))
{
throw std::runtime_error("Can't open non-existent file");
}
switch(package_access)
{
case file_access::Read:
file_stream_.open(path, std::ios::binary | std::ios::in);
break;
case file_access::ReadWrite:
file_stream_.open(path, std::ios::binary | std::ios::in | std::ios::out);
break;
case file_access::Write:
file_stream_.open(path, std::ios::binary | std::ios::out);
break;
}
break;
case file_mode::OpenOrCreate:
switch(package_access)
{
case file_access::Read:
file_stream_.open(path, std::ios::binary | std::ios::in);
break;
case file_access::ReadWrite:
file_stream_.open(path, std::ios::binary | std::ios::in | std::ios::out);
break;
case file_access::Write:
file_stream_.open(path, std::ios::binary | std::ios::out);
break;
}
break;
case file_mode::Truncate:
if(!file::exists(path))
{
throw std::runtime_error("Can't truncate non-existent file");
}
switch(package_access)
{
case file_access::Read:
file_stream_.open(path, std::ios::binary | std::ios::trunc | std::ios::in);
break;
case file_access::ReadWrite:
file_stream_.open(path, std::ios::binary | std::ios::trunc | std::ios::in | std::ios::out);
break;
case file_access::Write:
file_stream_.open(path, std::ios::binary | std::ios::trunc | std::ios::out);
break;
}
break;
}
open_container();
}
void open_container()
{
opcContainerOpenMode m;
switch(package_access_)
{
case file_access::Read:
m = opcContainerOpenMode::OPC_OPEN_READ_ONLY;
break;
case file_access::ReadWrite:
m = opcContainerOpenMode::OPC_OPEN_READ_WRITE;
break;
case file_access::Write:
m = opcContainerOpenMode::OPC_OPEN_WRITE_ONLY;
break;
default:
throw std::runtime_error("unknown file access");
}
opc_container_ = opcContainerOpenIO(&read_callback, &write_callback,
&close_callback, &seek_callback,
&trim_callback, &flush_callback, this, 4096, m, this);
open_ = true;
}
~package_struct()
{
close();
}
void close()
{
if(open_)
{
open_ = false;
opcContainerClose(opc_container_, opcContainerCloseMode::OPC_CLOSE_NOW);
opc_container_ = nullptr;
}
}
part create_part(const uri &/*part_uri*/, const std::string &/*content_type*/, compression_option /*compression*/)
{
return part();
}
void delete_part(const uri &/*part_uri*/)
{
}
void flush()
{
stream_.flush();
}
part get_part(const uri &part_uri)
{
return part(*parent_, part_uri, opc_container_);
}
part_collection get_parts()
{
return part_collection();
}
int write(char *buffer, int length)
{
stream_.read(buffer, length);
auto bytes_read = stream_.gcount();
return static_cast<int>(bytes_read);
}
int read(const char *buffer, int length)
{
auto before = stream_.tellp();
stream_.write(buffer, length);
auto bytes_written = stream_.tellp() - before;
return static_cast<int>(bytes_written);
}
std::ios::pos_type seek(std::ios::pos_type offset)
{
stream_.clear();
stream_.seekg(offset);
auto current_position = stream_.tellg();
if(stream_.eof())
{
std::cout << "eof" << std::endl;
}
if(stream_.fail())
{
std::cout << "fail" << std::endl;
}
if(stream_.bad())
{
std::cout << "bad" << std::endl;
}
return current_position;
}
int trim(std::ios::pos_type /*new_size*/)
{
return 0;
}
static int read_callback(void *context, char *buffer, int length)
{
auto object = static_cast<package_struct *>(context);
return object->write(buffer, length);
}
static int write_callback(void *context, const char *buffer, int length)
{
auto object = static_cast<package_struct *>(context);
return object->read(buffer, length);
}
static int close_callback(void *context)
{
auto object = static_cast<package_struct *>(context);
object->close();
return 0;
}
static opc_ofs_t seek_callback(void *context, opc_ofs_t ofs)
{
auto object = static_cast<package_struct *>(context);
return static_cast<opc_ofs_t>(object->seek(ofs));
}
static int trim_callback(void *context, opc_ofs_t new_size)
{
auto object = static_cast<package_struct *>(context);
return object->trim(new_size);
}
static int flush_callback(void *context)
{
auto object = static_cast<package_struct *>(context);
object->flush();
return 0;
}
};
file_access package::get_file_open_access() const
{
return root_->get_file_open_access();
}
package_properties package::get_package_properties() const
{
return root_->get_package_properties();
}
package package::open(std::iostream &stream, file_mode package_mode, file_access package_access)
{
return package(stream, package_mode, package_access);
}
package package::open(const std::string &path, file_mode package_mode, file_access package_access, file_share /*package_share*/)
{
return package(path, package_mode, package_access);
}
package::package(std::iostream &stream, file_mode package_mode, file_access package_access)
: root_(new package_struct(this, stream, package_mode, package_access))
{
open_container();
}
package::package(const std::string &path, file_mode package_mode, file_access package_access)
: root_(new package_struct(this, path, package_mode, package_access))
{
}
void package::open_container()
{
root_->open_container();
}
void package::close()
{
root_->close();
}
part package::create_part(const uri &part_uri, const std::string &content_type, compression_option compression)
{
return root_->create_part(part_uri, content_type, compression);
}
void package::delete_part(const uri &part_uri)
{
root_->delete_part(part_uri);
}
void package::flush()
{
root_->flush();
}
part package::get_part(const uri &part_uri)
{
return root_->get_part(part_uri);
}
part_collection package::get_parts()
{
return root_->get_parts();
}
int package::write(char *buffer, int length)
{
return root_->write(buffer, length);
}
int package::read(const char *buffer, int length)
{
return root_->read(buffer, length);
}
std::ios::pos_type package::seek(std::ios::pos_type offset)
{
return root_->seek(offset);
}
int package::trim(std::ios::pos_type new_size)
{
return root_->trim(new_size);
}
bool package::operator==(const package &comparand) const
{
return root_ == comparand.root_;
}
bool package::operator==(const nullptr_t &) const
{
return root_ == nullptr;
}
} // namespace xlnt

View File

@ -1,138 +0,0 @@
#pragma once
#include <fstream>
#include <memory>
#include <opc/opc.h>
#include <opc/container.h>
#include "compression_option.h"
#include "file_access.h"
#include "file_mode.h"
#include "file_share.h"
#include "opc_callback_handler.h"
#include "package_properties.h"
#include "part.h"
#include "relationship.h"
#include "target_mode.h"
#include "uri.h"
namespace xlnt {
struct package_struct;
/// <summary>
/// Implements a derived subclass of the abstract Package base class—the ZipPackage class uses a
/// ZIP archive as the container store. This class should not be inherited.
/// </summary>
class package
{
public:
/// <summary>
/// Opens a package with a given IO stream, file mode, and file access setting.
/// </summary>
static package open(std::iostream &stream, file_mode package_mode, file_access package_access);
/// <summary>
/// Opens a package at a given path using a given file mode, file access, and file share setting.
/// </summary>
static package open(const std::string &path, file_mode package_mode = file_mode::OpenOrCreate,
file_access package_access = file_access::ReadWrite, file_share package_share = file_share::None);
/// <summary>
/// Saves and closes the package plus all underlying part streams.
/// </summary>
void close();
/// <summary>
/// Creates a new part with a given URI, content type, and compression option.
/// </summary>
part create_part(const uri &part_uri, const std::string &content_type, compression_option compression = compression_option::Normal);
/// <summary>
/// Creates a package-level relationship to a part with a given URI, target mode, relationship type, and identifier (ID).
/// </summary>
relationship create_relationship(const uri &part_uri, target_mode target_mode, const std::string &relationship_type, const std::string &id);
/// <summary>
/// Deletes a part with a given URI from the package.
/// </summary>
void delete_part(const uri &part_uri);
/// <summary>
/// Deletes a package-level relationship.
/// </summary>
void delete_relationship(const std::string &id);
/// <summary>
/// Saves the contents of all parts and relationships that are contained in the package.
/// </summary>
void flush();
/// <summary>
/// Returns the part with a given URI.
/// </summary>
part get_part(const uri &part_uri);
/// <summary>
/// Returns a collection of all the parts in the package.
/// </summary>
part_collection get_parts();
/// <summary>
///
/// </summary>
relationship get_relationship(const std::string &id);
/// <summary>
/// Returns the package-level relationship with a given identifier.
/// </summary>
relationship_collection get_relationships();
/// <summary>
/// Returns a collection of all the package-level relationships that match a given RelationshipType.
/// </summary>
relationship_collection get_relationships(const std::string &relationship_type);
/// <summary>
/// Indicates whether a part with a given URI is in the package.
/// </summary>
bool part_exists(const uri &part_uri);
/// <summary>
/// Indicates whether a package-level relationship with a given ID is contained in the package.
/// </summary>
bool relationship_exists(const std::string &id);
/// <summary>
/// gets the file access setting for the package.
/// </summary>
file_access get_file_open_access() const;
/// <summary>
/// gets the core properties of the package.
/// </summary>
package_properties get_package_properties() const;
bool operator==(const package &comparand) const;
bool operator==(const nullptr_t &) const;
private:
friend opc_callback_handler;
package(std::iostream &stream, file_mode package_mode, file_access package_access);
package(const std::string &path, file_mode package_mode, file_access package_access);
void open_container();
int write(char *buffer, int length);
int read(const char *buffer, int length);
std::ios::pos_type seek(std::ios::pos_type ofs);
int trim(std::ios::pos_type new_size);
std::shared_ptr<package_struct> root_;
};
} // namespace xlnt

View File

@ -1,198 +0,0 @@
#pragma once
#include <ctime>
#include <string>
#include "../misc/nullable.h"
namespace xlnt {
/// <summary>
/// Represents the core properties of a Package.
/// </summary>
class package_properties
{
public:
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_category() const { return category_; }
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_category(const std::string &category) { category_ = category; }
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_content_status() const { return category_; }
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_content_status(const std::string &category) { category_ = category; }
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_content_type() const { return category_; }
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_content_type(const std::string &category) { category_ = category; }
/// <summary>
/// gets the category of the Package.
/// </summary>
nullable<tm> get_created() const { return created_; }
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_created(const nullable<tm> &created) { created_ = created; }
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_creator() const { return category_; }
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_creator(const std::string &category) { category_ = category; }
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_description() const { return category_; }
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_description(const std::string &category) { category_ = category; }
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_identifier() const { return category_; }
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_identifier(const std::string &category) { category_ = category; }
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_keywords() const { return category_; }
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_keywords(const std::string &category) { category_ = category; }
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_language() const { return category_; }
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_language(const std::string &category) { category_ = category; }
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_last_modified_by() const { return category_; }
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_last_modified_by (const std::string &category) { category_ = category; }
/// <summary>
/// gets the category of the Package.
/// </summary>
nullable<tm> get_last_printed() const { return created_; }
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_last_printed(const nullable<tm> &created) { created_ = created; }
/// <summary>
/// gets the category of the Package.
/// </summary>
nullable<tm> get_modified() const { return created_; }
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_modified(const nullable<tm> &created) { created_ = created; }
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_revision() const { return category_; }
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_revision(const std::string &category) { category_ = category; }
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string getsubject() const { return category_; }
/// <summary>
/// sets the category of the Package.
/// </summary>
void setsubject(const std::string &category) { category_ = category; }
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_title() const { return category_; }
/// Ssummary>
/// gets the category of the Package.
/// </summary>
void set_title(const std::string &category) { category_ = category; }
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_version() const { return category_; }
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_version(const std::string &category) { category_ = category; }
protected:
friend class package;
private:
std::string category_;
std::string content_status_;
std::string content_type_;
nullable<tm> created_;
std::string creator_;
std::string description_;
std::string identifier_;
std::string keywords_;
std::string language_;
std::string last_modified_by_;
nullable<tm> last_printed_;
nullable<tm> modified_;
std::string revision_;
std::string subject_;
std::string title_;
std::string version_;
};
} // namespace xlnt

View File

@ -1,173 +0,0 @@
#include "part.h"
namespace xlnt {
struct part_struct
{
/// <summary>
/// Initializes a new instance of the part class with a specified parent Package, part URI, MIME content type, and compression_option.
/// </summary>
part_struct(package &package, const uri &uri_part, const std::string &mime_type = "", compression_option compression = compression_option::NotCompressed)
: package_(package),
uri_(uri_part),
content_type_(mime_type),
compression_option_(compression)
{}
part_struct(package &package, const uri &uri, opcContainer *container)
: package_(package),
uri_(uri),
container_(container)
{}
/// <summary>
/// gets the compression option of the part content stream.
/// </summary>
compression_option get_compression_option() const { return compression_option_; }
/// <summary>
/// gets the MIME type of the content stream.
/// </summary>
std::string get_content_type() const;
/// <summary>
/// gets the parent Package of the part.
/// </summary>
package &get_package() const { return package_; }
/// <summary>
/// gets the URI of the part.
/// </summary>
uri get_uri() const { return uri_; }
/// <summary>
/// Creates a part-level relationship between this part to a specified target part or external resource.
/// </summary>
std::shared_ptr<relationship> create_relationship(const uri &target_uri, target_mode target_mode, const std::string &relationship_type);
/// <summary>
/// Deletes a specified part-level relationship.
/// </summary>
void delete_relationship(const std::string &id);
/// <summary>
/// Returns the relationship that has a specified Id.
/// </summary>
relationship get_relationship(const std::string &id);
/// <summary>
/// Returns a collection of all the relationships that are owned by this part.
/// </summary>
relationship_collection get_relationships();
/// <summary>
/// Returns a collection of the relationships that match a specified RelationshipType.
/// </summary>
relationship_collection get_relationship_by_type(const std::string &relationship_type);
std::string read()
{
std::string ss;
auto part_stream = opcContainerOpenInputStream(container_, (xmlChar*)get_uri().get_OriginalString().c_str());
std::array<xmlChar, 1024> buffer;
auto bytes_read = opcContainerReadInputStream(part_stream, buffer.data(), static_cast<opc_uint32_t>(buffer.size()));
if(bytes_read > 0)
{
ss.append(std::string(buffer.begin(), buffer.begin() + bytes_read));
while(bytes_read == buffer.size())
{
auto bytes_read = opcContainerReadInputStream(part_stream, buffer.data(), static_cast<opc_uint32_t>(buffer.size()));
ss.append(std::string(buffer.begin(), buffer.begin() + bytes_read));
}
}
opcContainerCloseInputStream(part_stream);
return ss;
}
void write(const std::string &data)
{
auto name = get_uri().get_OriginalString();
auto name_pointer = name.c_str();
auto part_stream = opcContainerCreateOutputStream(container_, (xmlChar*)name_pointer, opcCompressionOption_t::OPC_COMPRESSIONOPTION_NORMAL);
std::stringstream ss(data);
std::array<xmlChar, 1024> buffer;
while(ss)
{
ss.get((char*)buffer.data(), 1024);
auto count = ss.gcount();
if(count > 0)
{
opcContainerWriteOutputStream(part_stream, buffer.data(), static_cast<opc_uint32_t>(count));
}
}
opcContainerCloseOutputStream(part_stream);
}
/// <summary>
/// Returns a value that indicates whether this part owns a relationship with a specified Id.
/// </summary>
bool relationship_exists(const std::string &id) const;
/// <summary>
/// Returns true if the given Id string is a valid relationship identifier.
/// </summary>
bool is_valid_xml_id(const std::string &id);
void operator=(const part_struct &other);
compression_option compression_option_;
std::string content_type_;
package &package_;
uri uri_;
opcContainer *container_;
};
part::part() : root_(nullptr)
{
}
part::part(package &package, const uri &uri, opcContainer *container) : root_(new part_struct(package, uri, container))
{
}
std::string part::get_content_type() const
{
return "";
}
std::string part::read()
{
if(root_ == nullptr)
{
return "";
}
return root_->read();
}
void part::write(const std::string &data)
{
if(root_ == nullptr)
{
return;
}
return root_->write(data);
}
bool part::operator==(const part &comparand) const
{
return root_ == comparand.root_;
}
bool part::operator==(const nullptr_t &) const
{
return root_ == nullptr;
}
} // namespace xlnt

View File

@ -1,105 +0,0 @@
#pragma once
#include <array>
#include <sstream>
#include <opc/opc.h>
#include "uri.h"
#include "compression_option.h"
#include "relationship.h"
#include "target_mode.h"
#include "file_mode.h"
#include "file_access.h"
namespace xlnt {
struct part_struct;
/// <summary>
/// Represents a part that is stored in a ZipPackage.
/// </summary>
class part
{
public:
/// <summary>
/// Initializes a new instance of the part class with a specified parent Package, part URI, MIME content type, and compression_option.
/// </summary>
part(package &package, const uri &uri_part, const std::string &mime_type = "", compression_option compression = compression_option::NotCompressed);
part &operator=(const part &) = delete;
/// <summary>
/// gets the compression option of the part content stream.
/// </summary>
compression_option get_compression_option() const;
/// <summary>
/// gets the MIME type of the content stream.
/// </summary>
std::string get_content_type() const;
/// <summary>
/// gets the parent Package of the part.
/// </summary>
package &get_package() const;
/// <summary>
/// gets the URI of the part.
/// </summary>
uri get_uri() const;
/// <summary>
/// Creates a part-level relationship between this part to a specified target part or external resource.
/// </summary>
std::shared_ptr<relationship> create_relationship(const uri &target_uri, target_mode target_mode, const std::string &relationship_type);
/// <summary>
/// Deletes a specified part-level relationship.
/// </summary>
void delete_relationship(const std::string &id);
/// <summary>
/// Returns the relationship that has a specified Id.
/// </summary>
relationship get_relationship(const std::string &id);
/// <summary>
/// Returns a collection of all the relationships that are owned by this part.
/// </summary>
relationship_collection get_relationships();
/// <summary>
/// Returns a collection of the relationships that match a specified RelationshipType.
/// </summary>
relationship_collection get_relationship_by_type(const std::string &relationship_type);
/// <summary>
/// Returns all the content of this part.
/// </summary>
std::string read();
/// <summary>
/// Writes the given data to the part stream.
/// </summary>
void write(const std::string &data);
/// <summary>
/// Returns a value that indicates whether this part owns a relationship with a specified Id.
/// </summary>
bool relationship_exists(const std::string &id) const;
bool operator==(const part &comparand) const;
bool operator==(const nullptr_t &) const;
private:
friend struct package_struct;
part();
part(package &package, const uri &uri, opcContainer *container);
part_struct *root_;
};
typedef std::vector<part> part_collection;
} // namespace xlnt

View File

@ -1,36 +0,0 @@
/*
Copyright (c) 2012-2014 Thomas Fussell
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.
*/
#pragma once
#include <string>
#include "workbook.h"
namespace xlnt {
class reader
{
public:
static workbook load_workbook(const std::string &filename);
};
} // namespace xlnt

View File

@ -1,73 +0,0 @@
#pragma once
#include <memory>
#include <string>
#include <vector>
#include "target_mode.h"
#include "uri.h"
namespace xlnt {
class package;
/// <summary>
/// Represents an association between a source Package or part, and a target object which can be a part or external resource.
/// </summary>
class relationship
{
public:
enum class type
{
hyperlink,
drawing,
worksheet,
sharedStrings,
styles,
theme
};
relationship(const std::string &type) : source_uri_(""), target_uri_("")
{
if(type == "hyperlink")
{
type_ = type::hyperlink;
}
}
/// <summary>
/// gets a string that identifies the relationship.
/// </summary>
std::string get_id() const { return id_; }
/// <summary>
/// gets the URI of the package or part that owns the relationship.
/// </summary>
uri getsource_uri() const { return source_uri_; }
/// <summary>
/// gets a value that indicates whether the target of the relationship is or External to the Package.
/// </summary>
target_mode get_target_mode() const { return target_mode_; }
/// <summary>
/// gets the URI of the target resource of the relationship.
/// </summary>
uri get_target_uri() const { return target_uri_; }
private:
friend class package;
relationship(const std::string &id, package &package, const std::string &relationship_type_, uri source_uri, target_mode target_mode, uri target_uri);
relationship &operator=(const relationship &rhs) = delete;
std::string id_;
type type_;
uri source_uri_;
target_mode target_mode_;
uri target_uri_;
};
typedef std::vector<std::shared_ptr<relationship>> relationship_collection;
} // namespace xlnt

View File

@ -1,20 +0,0 @@
#pragma once
namespace xlnt {
/// <summary>
/// Specifies whether the target of a relationship is inside or outside the Package.
/// </summary>
enum class target_mode
{
/// <summary>
/// The relationship references a part that is inside the package.
/// </summary>
External,
/// <summary>
/// The relationship references a resource that is external to the package.
/// </summary>
Internal
};
} // namespace xlnt

View File

@ -1,397 +0,0 @@
#include <sstream>
#include "uri.h"
namespace xlnt {
namespace {
#ifdef _WIN32
const char platform_path_separator = '\\';
#else
const char platform_path_separator = '/';
#endif
int get_DefaultPort(const std::string &scheme)
{
if(scheme == "ftp") return 21;
if(scheme == "sftp") return 22;
if(scheme == "ssh") return 22;
if(scheme == "telnet") return 23;
if(scheme == "smtp") return 25;
if(scheme == "dns") return 53;
if(scheme == "gopher") return 70;
if(scheme == "http") return 80;
if(scheme == "pop3") return 110;
if(scheme == "nntp") return 119;
if(scheme == "snmp") return 161;
if(scheme == "imap") return 143;
if(scheme == "irc") return 194;
if(scheme == "https") return 443;
if(scheme == "smtps") return 465;
return -1;
}
}
uri::uri(const std::string &uri_string, uri_kind uri_kind)
: original_string_(uri_string),
kind_(uri_kind)
{
Parse();
}
uri &uri::operator=(const uri &rhs)
{
original_string_ = rhs.original_string_;
kind_ = rhs.kind_;
Parse();
return *this;
}
bool uri::IsAbsoluteuri() const
{
if(kind_ == uri_kind::Absolute)
{
return true;
}
if(kind_ == uri_kind::Relative)
{
return false;
}
if(original_string_.size() == 0)
{
return false;
}
auto scheme_separator = std::find(original_string_.begin(), original_string_.end(), ':');
if(scheme_separator == original_string_.end())
{
return false;
}
if(original_string_[0] == '.')
{
return false;
}
return true;
}
void uri::Parse()
{
if(IsAbsoluteuri())
{
ParseAbsolute();
}
else
{
ParseRelative();
}
}
void uri::ParseAbsolute()
{
auto scheme_separator = std::find(original_string_.begin(), original_string_.end(), ':');
if(scheme_separator == original_string_.end())
{
throw std::runtime_error("absolute uri must contain a scheme followed by a colon");
}
scheme_ = std::string(original_string_.begin(), scheme_separator);
port_ = get_DefaultPort(scheme_);
std::string hier_part(scheme_separator + 1, original_string_.end());
auto query_separator = std::find(hier_part.begin(), hier_part.end(), '?');
if(query_separator != hier_part.end())
{
query_ = std::string(query_separator + 1, hier_part.end());
hier_part = std::string(hier_part.begin(), query_separator);
}
auto fragment_separator = std::find(hier_part.begin(), hier_part.end(), '#');
if(fragment_separator != hier_part.end())
{
fragment_ = std::string(fragment_separator + 1, hier_part.end());
hier_part = std::string(hier_part.begin(), fragment_separator);
}
else
{
fragment_separator = std::find(query_.begin(), query_.end(), '#');
if(fragment_separator != query_.end())
{
fragment_ = std::string(fragment_separator + 1, query_.end());
query_ = std::string(query_.begin(), fragment_separator);
}
}
if(hier_part.size() > 2 && hier_part[0] == '/' && hier_part[1] == '/')
{
auto path_separator = std::find(hier_part.begin() + 2, hier_part.end(), '/');
if(path_separator != hier_part.end())
{
authority_ = std::string(hier_part.begin() + 2, path_separator);
absolute_path_ = std::string(path_separator, hier_part.end());
if(absolute_path_[0] == '/')
{
if(absolute_path_[1] == '/')
{
throw std::runtime_error("path can't start with //");
}
}
}
else
{
authority_ = hier_part.substr(2);
absolute_path_ = "";
}
ParseAuthority();
is_file_ = scheme_ == "file";
char abs_path_separator = absolute_path_.find('/') != std::string::npos ? '/' : '\\';
if(is_file_)
{
local_path_ = std::string(2, platform_path_separator) + authority_;
}
if(absolute_path_.size() > 0)
{
std::stringstream ss(absolute_path_);
std::string part;
while(std::getline(ss, part, abs_path_separator))
{
if(segments_.size() > 0)
{
if(is_file_)
{
segments_.back().append(1, platform_path_separator);
local_path_.append(1, platform_path_separator);
}
else
{
segments_.back().append(1, abs_path_separator);
local_path_.append(1, abs_path_separator);
}
}
segments_.push_back(part);
local_path_.append(part);
}
}
user_escaped_ = false;
is_unc_ = is_file_ && host_.size() > 0;
is_default_port_ = get_DefaultPort(scheme_) == port_;
is_loopback_ = host_ == "127.0.0.1" || host_ == "localhost" || host_ == "loopback" || host_.size() == 0;
path_and_query_ = absolute_path_ + "?" + query_;
absolute_uri_ = scheme_ + "://";
if(user_info_.size() > 0)
{
absolute_uri_ += user_info_ + "@";
}
absolute_uri_ += host_;
if(!is_default_port_)
{
absolute_uri_ += ":" + std::to_string(port_);
}
absolute_uri_ += absolute_path_;
if(query_.size() > 0)
{
absolute_uri_ += "?" + query_;
}
if(fragment_.size() > 0)
{
absolute_uri_ += "#" + fragment_;
}
}
}
void uri::ParseRelative()
{
absolute_path_ = "";
absolute_uri_ = "";
authority_ = "";
dns_safe_host_ = "";
fragment_ = "";
host_ = "";
host_name_type_ = uri_host_name_type::Unknown;
is_default_port_ = false;
is_file_ = false;
is_loopback_ = false;
is_unc_ = false;
local_path_ = "";
path_and_query_ = "";
port_ = -1;
query_ = "";
scheme_ = "";
user_escaped_ = false;
user_info_ = "";
}
void uri::ParseAuthority()
{
if(authority_.size() == 0)
{
return;
}
host_ = authority_;
auto user_info_separator = std::find(host_.begin(), host_.end(), '@');
if(user_info_separator != host_.end())
{
user_info_ = std::string(host_.begin(), user_info_separator);
host_ = std::string(user_info_separator + 1, host_.end());
}
auto port_separator_index = host_.find_last_of(':');
if(port_separator_index != std::string::npos)
{
port_ = std::stoi(host_.substr(port_separator_index + 1));
host_ = host_.substr(0, port_separator_index);
}
dns_safe_host_ = host_;
if(host_.find(':') == std::string::npos)
{
host_name_type_ = uri_host_name_type::Dns;
}
else
{
host_name_type_ = uri_host_name_type::IPv4;
}
}
std::string uri::get_AbsolutePath() const
{
ThrowIfNotAbsolute();
return absolute_path_;
}
std::string uri::get_Absoluteuri() const
{
ThrowIfNotAbsolute();
return absolute_uri_;
}
std::string uri::get_Authority() const
{
ThrowIfNotAbsolute();
return authority_;
}
std::string uri::get_DnsSafeHost() const
{
ThrowIfNotAbsolute();
return dns_safe_host_;
}
std::string uri::get_Fragment() const
{
ThrowIfNotAbsolute();
return fragment_;
}
std::string uri::get_Host() const
{
ThrowIfNotAbsolute();
return host_;
}
uri_host_name_type uri::get_HostNameType() const
{
ThrowIfNotAbsolute();
return host_name_type_;
}
bool uri::IsDefaultPort() const
{
ThrowIfNotAbsolute();
return is_default_port_;
}
bool uri::IsFile() const
{
ThrowIfNotAbsolute();
return is_file_;
}
bool uri::IsLoopback() const
{
ThrowIfNotAbsolute();
return is_loopback_;
}
bool uri::IsUnc() const
{
ThrowIfNotAbsolute();
return is_unc_;
}
std::string uri::get_LocalPath() const
{
ThrowIfNotAbsolute();
return local_path_;
}
std::string uri::get_OriginalString() const
{
return original_string_;
}
std::string uri::get_PathAndQuery() const
{
ThrowIfNotAbsolute();
return path_and_query_;
}
int uri::get_Port() const
{
ThrowIfNotAbsolute();
return port_;
}
std::string uri::get_Query() const
{
ThrowIfNotAbsolute();
return query_;
}
std::string uri::get_Scheme() const
{
ThrowIfNotAbsolute();
return scheme_;
}
std::vector<std::string> uri::get_Segments() const
{
ThrowIfNotAbsolute();
return segments_;
}
bool uri::get_UserEscaped() const
{
return user_escaped_;
}
std::string uri::get_UserInfo() const
{
ThrowIfNotAbsolute();
return user_info_;
}
void uri::ThrowIfNotAbsolute() const
{
if(!IsAbsoluteuri())
{
throw std::runtime_error("InvalidOperationException: This instance represents a relative URI, and this property is valid only for absolute URIs.");
}
}
} // namespace xlnt

View File

@ -1,485 +0,0 @@
#pragma once
#include <string>
#include <vector>
namespace xlnt {
/// <summary>
/// Defines the kinds of uris for the uri::IsWellFormeduriString(std::tring, uri_kind) and several other uri methods.
/// </summary>
enum class uri_kind
{
/// <summary>
/// The uri is an absolute uri.
/// </summary>
Absolute,
/// <summary>
/// The uri is a relative uri.
/// </summary>
Relative,
/// <summary>
/// The kind of the uri is indeterminate.
/// </summary>
RelativeOrAbsolute
};
/// <summary>
/// Defines host name types for the uri.CheckHostName method.
/// </summary>
enum class uri_host_name_type
{
/// <summary>
/// The host is set, but the type cannot be determined.
/// </summary>
Basic,
/// <summary>
/// The host name is a domain name system (DNS) style host name.
/// </summary>
Dns,
/// <summary>
/// The host name is an Internet Protocol (IP) version 4 host address.
/// </summary>
IPv4,
/// <summary>
/// The host name is an Internet Protocol (IP) version 6 host address.
/// </summary>
IPv6,
/// <summary>
/// The type of the host name is not supplied.
/// </summary>
Unknown
};
/// <summary>
/// Specifies the parts of a uri.
/// </summary>
enum class uri_components
{
/// <summary>
/// The Scheme, UserInfo, Host, Port, LocalPath, Query, and Fragment data.
/// </summary>
Absoluteuri,
/// <summary>
/// The Fragment data.
/// </summary>
Fragment,
/// <summary>
/// The Host data.
/// </summary>
Host,
/// <summary>
/// The Host and Port data. If no port data is in the uri and a default port has been assigned to the Scheme, the default port is returned. If there is no default port, -1 is returned.
/// </summary>
HostAndPort,
/// <summary>
/// The Scheme, Host, Port, LocalPath, and Query data.
/// </summary>
HttpRequesturi,
/// <summary>
/// Specifies that the delimiter should be included.
/// </summary>
KeepDelimiter,
/// <summary>
/// The normalized form of the Host.
/// </summary>
NormalizedHost,
/// <summary>
/// The LocalPath data.
/// </summary>
Path,
/// <summary>
/// The LocalPath and Query data. Also see PathAndQuery.
/// </summary>
PathAndQuery,
/// <summary>
/// The Port data.
/// </summary>
Port,
/// <summary>
/// The Query data.
/// </summary>
Query,
/// <summary>
/// The Scheme data.
/// </summary>
Scheme,
/// <summary>
/// The Scheme, Host, and Port data.
/// </summary>
SchemeAndServer,
/// <summary>
/// The Port data. If no port data is in the uri and a default port has been assigned to the Scheme, the default port is returned. If there is no default port, -1 is returned.
/// </summary>
StrongPort,
/// <summary>
/// The UserInfo data.
/// </summary>
UserInfo
};
/// <summary>
/// Controls how URI information is escaped.
/// </summary>
enum class uri_format
{
/// <summary>
/// Characters that have a reserved meaning in the requested URI components remain escaped. All others are not escaped. See Remarks.
/// </summary>
SafeUnescaped,
/// <summary>
/// No escaping is performed.
/// </summary>
Unescaped,
/// <summary>
/// Escaping is performed according to the rules in RFC 2396.
/// </summary>
uriEscaped
};
/// <summary>
/// Specifies the culture, case, and sort rules to be used by certain overloads of the String.Compare and String._equals methods
/// </summary>
enum class string_comparison
{
/// <summary>
/// Compare strings using culture-sensitive sort rules and the current culture.
/// </summary>
CurrentCulture,
/// <summary>
/// Compare strings using culture-sensitive sort rules, the current culture, and ignoring the case of the strings being compared.
/// </summary>
CurrentCultureIgnoreCase,
/// <summary>
/// Compare strings using culture-sensitive sort rules and the invariant culture.
/// </summary>
InvariantCulture,
/// <summary>
/// Compare strings using culture-sensitive sort rules, the invariant culture, and ignoring the case of the strings being compared.
/// </summary>
InvariantCultureIgnoreCase,
/// <summary>
/// Compare strings using ordinal sort rules.
/// </summary>
Ordinal,
/// <summary>
/// Compare strings using ordinal sort rules and ignoring the case of the strings being compared.
/// </summary>
OrdinalIgnoreCase
};
/// <summary>
/// Defines the parts of a URI for the uri::get_LeftPart method.
/// </summary>
enum class uri_partial
{
/// <summary>
/// The scheme and authority segments of the URI.
/// </summary>
Authority,
/// <summary>
/// The scheme, authority, and path segments of the URI.
/// </summary>
Path,
/// <summary>
/// The scheme, authority, path, and query segments of the URI.
/// </summary>
Query,
/// <summary>
/// The scheme segment of the URI.
/// </summary>
Scheme
};
/// <summary>
/// Provides an object representation of a uniform resource identifier (URI) and easy access to the parts of the URI.
/// </summary>
class uri
{
public:
/// <summary>
/// Determines whether the specified host name is a valid DNS name.
/// </summary>
static uri_host_name_type CheckHostName(const std::string &name);
/// <summary>
/// Determines whether the specified scheme name is valid.
/// </summary>
static bool CheckSchemeName(const std::string &scheme_name);
/// <summary>
/// Compares the specified parts of two URIs using the specified comparison rules.
/// </summary>
static int Compare(const uri &uri1, const uri &uri2, const uri_components &parts_to_compare,
uri_format compare_format, string_comparison comparison_type);
/// <summary>
/// Converts a string to its escaped representation.
/// </summary>
static std::string EscapeDataString(const std::string &string_to_escape);
/// <summary>
/// Converts a URI string to its escaped representation.
/// </summary>
static std::string EscapeuriString(const std::string &string_to_escape);
/// <summary>
/// gets the decimal value of a hexadecimal digit.
/// </summary>
static int FromHex(char digit);
/// <summary>
/// Converts a specified character into its hexadecimal equivalent.
/// </summary>
static std::string HexEscape(char character);
/// <summary>
/// Converts a specified hexadecimal representation of a character to the character.
/// </summary>
static char HexUnescape(const std::string &pattern, int &index);
/// <summary>
/// Determines whether a specified character is a valid hexadecimal digit.
/// </summary>
static bool IsHexDigit(char character);
/// <summary>
/// Determines whether a character in a string is hexadecimal encoded.
/// </summary>
static bool IsHexEncoding(const std::string &pattern, int index);
/// <summary>
/// Indicates whether the string is well-formed by attempting to construct a URI with the string and ensures that the string does not require further escaping.
/// </summary>
static bool IsWellFormeduriString(const std::string &uri_string, uri_kind uri_kind);
/// <summary>
/// Creates a new uri using the specified String instance and a uri_kind.
/// </summary>
static bool TryCreate(const std::string &uri_string, uri_kind uri_kind, uri &result);
/// <summary>
/// Creates a new uri using the specified base and relative String instances.
/// </summary>
static bool TryCreate(const uri &base_uri, const std::string &relative_uri, uri &result);
/// <summary>
/// Creates a new uri using the specified base and relative uri instances.
/// </summary>
static bool TryCreate(const uri &base_uri, const uri &relative_uri, uri &result);
/// <summary>
/// Converts a string to its unescaped representation.
/// </summary>
static std::string UnescapeDataString(const std::string &string_to_unescape);
/// <summary>
/// Initializes a new instance of the uri class with the specified URI. This constructor allows you to specify if the URI string is a relative URI, absolute URI, or is indeterminate.
/// </summary>
uri(const std::string &uri_string, uri_kind uri_kind = uri_kind::Absolute);
/// <summary>
/// Initializes a new instance of the uri class based on the specified base URI and relative URI string.
/// </summary>
uri(const uri &base_uri, const std::string &relative_uri);
/// <summary>
/// Initializes a new instance of the uri class based on the combination of a specified base uri instance and a relative uri instance.
/// </summary>
uri(const uri &base_uri, const uri &relative_uri);
/// <summary>
///
/// </summary>
uri &operator=(const uri &);
/// <summary>
/// gets the absolute path of the URI.
/// </summary>
std::string get_AbsolutePath() const;
/// <summary>
/// gets the absolute URI.
/// </summary>
std::string get_Absoluteuri() const;
/// <summary>
/// gets the Domain Name System (DNS) host name or IP address and the port number for a server.
/// </summary>
std::string get_Authority() const;
/// <summary>
/// gets an unescaped host name that is safe to use for DNS resolution.
/// </summary>
std::string get_DnsSafeHost() const;
/// <summary>
/// gets the escaped URI fragment.
/// </summary>
std::string get_Fragment() const;
/// <summary>
/// gets the host component of this instance.
/// </summary>
std::string get_Host() const;
/// <summary>
/// gets the type of the host name specified in the URI.
/// </summary>
uri_host_name_type get_HostNameType() const;
/// <summary>
/// gets whether the uri instance is absolute.
/// </summary>
bool IsAbsoluteuri() const;
/// <summary>
/// gets whether the port value of the URI is the default for this scheme.
/// </summary>
bool IsDefaultPort() const;
/// <summary>
/// gets a value indicating whether the specified uri is a file URI.
/// </summary>
bool IsFile() const;
/// <summary>
/// gets whether the specified uri references the local host.
/// </summary>
bool IsLoopback() const;
/// <summary>
/// gets whether the specified uri is a universal naming convention (UNC) path.
/// </summary>
bool IsUnc() const;
/// <summary>
/// gets a local operating-system representation of a file name.
/// </summary>
std::string get_LocalPath() const;
/// <summary>
/// gets the original URI string that was passed to the uri constructor.
/// </summary>
std::string get_OriginalString() const;
/// <summary>
/// gets the AbsolutePath and Query properties separated by a question mark (?).
/// </summary>
std::string get_PathAndQuery() const;
/// <summary>
/// gets the port number of this URI.
/// </summary>
int get_Port() const;
/// <summary>
/// gets any query information included in the specified URI.
/// </summary>
std::string get_Query() const;
/// <summary>
/// gets the scheme name for this URI.
/// </summary>
std::string get_Scheme() const;
/// <summary>
/// gets an array containing the path segments that make up the specified URI.
/// </summary>
std::vector<std::string> get_Segments() const;
/// <summary>
/// Indicates that the URI string was completely escaped before the uri instance was created.
/// </summary>
bool get_UserEscaped() const;
/// <summary>
/// gets the user name, password, or other user-specific information associated with the specified URI.
/// </summary>
std::string get_UserInfo() const;
/// <summary>
/// Compares two uri instances for equality.
/// </summary>
bool Equals(const uri &comparand);
/// <summary>
/// gets the specified components of the current instance using the specified escaping for special characters.
/// </summary>
std::string get_Components(uri_components components, uri_format format);
/// <summary>
/// gets the specified portion of a uri instance.
/// </summary>
std::string get_LeftPart(uri_partial part);
/// <summary>
/// Determines whether the current uri instance is a base of the specified uri instance.
/// </summary>
bool IsBaseOf(const uri &uri);
/// <summary>
/// Indicates whether the string used to construct this uri was well-formed and is not required to be further escaped.
/// </summary>
bool IsWellFormedOriginalString();
/// <summary>
/// Determines the difference between two uri instances.
/// </summary>
uri MakeRelativeuri(const uri &uri);
private:
void Parse();
void ParseAbsolute();
void ParseRelative();
void ParseAuthority();
void ThrowIfNotAbsolute() const;
std::string original_string_;
uri_kind kind_;
std::string absolute_path_;
std::string absolute_uri_;
std::string authority_;
std::string dns_safe_host_;
std::string fragment_;
std::string host_;
uri_host_name_type host_name_type_;
bool is_default_port_;
bool is_file_;
bool is_unc_;
bool is_loopback_;
std::string local_path_;
std::string path_and_query_;
int port_;
std::string query_;
std::string scheme_;
std::vector<std::string> segments_;
bool user_escaped_;
std::string user_info_;
};
} // namespace xlnt

View File

@ -1,49 +0,0 @@
#include <cassert>
#include <Shlwapi.h>
#include <Windows.h>
#include "../file.h"
namespace xlnt {
void file::copy(const std::string &source, const std::string &destination, bool overwrite)
{
assert(source.size() + 1 < MAX_PATH);
assert(destination.size() + 1 < MAX_PATH);
std::wstring source_wide(source.begin(), source.end());
std::wstring destination_wide(destination.begin(), destination.end());
BOOL result = CopyFile(source_wide.c_str(), destination_wide.c_str(), !overwrite);
if(result == 0)
{
DWORD error = GetLastError();
if(error == ERROR_ACCESS_DENIED)
{
throw std::runtime_error("Access is denied");
}
if(error == ERROR_ENCRYPTION_FAILED)
{
throw std::runtime_error("The specified file could not be encrypted");
}
if(error == ERROR_FILE_NOT_FOUND)
{
throw std::runtime_error("The source file wasn't found");
}
if(!overwrite)
{
throw std::runtime_error("The destination file already exists");
}
throw std::runtime_error("Unknown error");
}
}
bool file::exists(const std::string &path)
{
std::wstring path_wide(path.begin(), path.end());
return PathFileExists(path_wide.c_str()) && !PathIsDirectory(path_wide.c_str());
}
} // namespace xlnt

View File

@ -1,36 +0,0 @@
/*
Copyright (c) 2012-2014 Thomas Fussell
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.
*/
#pragma once
#include <string>
#include "workbook.h"
namespace xlnt {
class writer
{
public:
static void save_workbook(const workbook &workbook, const std::string &filename);
};
} // namespace xlnt

View File

@ -4,10 +4,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/cell.h>
#include <xlnt/style.h>
#include <xlnt/workbook.h>
#include <xlnt/worksheet.h>
#include "../xlnt.h"
class CellTestSuite : public CxxTest::TestSuite
{
@ -86,8 +83,8 @@ public:
void test_initial_value()
{
xlnt::workbook wb;
xlnt::worksheet ws(wb);
xlnt::cell cell(ws, "A", 1, "17.5");
auto ws = wb.get_active();
xlnt::cell cell(ws);
TS_ASSERT_EQUALS(xlnt::cell::type::numeric, cell.get_data_type());
}

View File

@ -3,8 +3,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/workbook.h>
#include <xlnt/worksheet.h>
#include "../xlnt.h"
class ChartTestSuite : public CxxTest::TestSuite
{

View File

@ -3,8 +3,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/workbook.h>
#include <xlnt/worksheet.h>
#include "../xlnt.h"
class DumpTestSuite : public CxxTest::TestSuite
{

View File

@ -3,9 +3,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/cell.h>
#include <xlnt/workbook.h>
#include <xlnt/worksheet.h>
#include "../xlnt.h"
class IntegrationTestSuite : public CxxTest::TestSuite
{

View File

@ -3,8 +3,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/workbook.h>
#include <xlnt/worksheet.h>
#include "../xlnt.h"
class IterTestSuite : public CxxTest::TestSuite
{

View File

@ -3,8 +3,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/workbook.h>
#include <xlnt/worksheet.h>
#include "../xlnt.h"
class MetaTestSuite : public CxxTest::TestSuite
{

View File

@ -3,8 +3,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/workbook.h>
#include <xlnt/worksheet.h>
#include "../xlnt.h"
class NamedRangeTestSuite : public CxxTest::TestSuite
{

View File

@ -3,7 +3,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include "../misc/nullable.h"
#include "../xlnt.h"
class NullableTestSuite : public CxxTest::TestSuite
{

View File

@ -3,8 +3,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/workbook.h>
#include <xlnt/worksheet.h>
#include "../xlnt.h"
class NumberFormatTestSuite : public CxxTest::TestSuite
{

View File

@ -2,8 +2,7 @@
#include <cxxtest/TestSuite.h>
#include "../packaging/file.h"
#include "../packaging/package.h"
#include "../xlnt.h"
#include "pugixml.hpp"
class PackageTestSuite : public CxxTest::TestSuite

View File

@ -3,8 +3,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/workbook.h>
#include <xlnt/worksheet.h>
#include "../xlnt.h"
class PasswordHashTestSuite : public CxxTest::TestSuite
{

View File

@ -3,8 +3,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/workbook.h>
#include <xlnt/worksheet.h>
#include "../xlnt.h"
class PropsTestSuite : public CxxTest::TestSuite
{

View File

@ -3,8 +3,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/workbook.h>
#include <xlnt/worksheet.h>
#include "../xlnt.h"
class ReadTestSuite : public CxxTest::TestSuite
{

View File

@ -3,8 +3,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/workbook.h>
#include <xlnt/worksheet.h>
#include "../xlnt.h"
class StringsTestSuite : public CxxTest::TestSuite
{

View File

@ -3,8 +3,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/workbook.h>
#include <xlnt/worksheet.h>
#include "../xlnt.h"
class StyleTestSuite : public CxxTest::TestSuite
{

View File

@ -3,8 +3,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/workbook.h>
#include <xlnt/worksheet.h>
#include "../xlnt.h"
class ThemeTestSuite : public CxxTest::TestSuite
{

View File

@ -3,8 +3,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/workbook.h>
#include <xlnt/worksheet.h>
#include "../xlnt.h"
class UnicodeTestSuite : public CxxTest::TestSuite
{

View File

@ -1,7 +1,8 @@
#pragma once
#include <cxxtest/TestSuite.h>
#include "../packaging/uri.h"
#include "../xlnt.h"
class uriTestSuite : public CxxTest::TestSuite
{

View File

@ -3,8 +3,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/workbook.h>
#include <xlnt/worksheet.h>
#include "../xlnt.h"
class WorkbookTestSuite : public CxxTest::TestSuite
{

View File

@ -3,8 +3,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/workbook.h>
#include <xlnt/worksheet.h>
#include "../xlnt.h"
class WorksheetTestSuite : public CxxTest::TestSuite
{

View File

@ -3,8 +3,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/workbook.h>
#include <xlnt/worksheet.h>
#include "../xlnt.h"
class WriteTestSuite : public CxxTest::TestSuite
{

File diff suppressed because it is too large Load Diff

1100
source/xlnt.cpp Normal file

File diff suppressed because it is too large Load Diff

944
source/xlnt.h Normal file
View File

@ -0,0 +1,944 @@
#pragma once
#include <ostream>
#include <set>
#include <string>
#include <unordered_map>
#include <vector>
#include <opc/opc.h>
#include <opc/container.h>
struct tm;
namespace xlnt {
struct cell_struct;
struct worksheet_struct;
struct package_impl;
class style;
class worksheet;
class worksheet;
class cell;
class relationship;
class workbook;
class package;
const int MIN_ROW = 0;
const int MIN_COLUMN = 0;
const int MAX_COLUMN = 16384;
const int MAX_ROW = 1048576;
// constants
const std::string PACKAGE_PROPS = "docProps";
const std::string PACKAGE_XL = "xl";
const std::string PACKAGE_RELS = "_rels";
const std::string PACKAGE_THEME = PACKAGE_XL + "/" + "theme";
const std::string PACKAGE_WORKSHEETS = PACKAGE_XL + "/" + "worksheets";
const std::string PACKAGE_DRAWINGS = PACKAGE_XL + "/" + "drawings";
const std::string PACKAGE_CHARTS = PACKAGE_XL + "/" + "charts";
const std::string ARC_CONTENT_TYPES = "[Content_Types].xml";
const std::string ARC_ROOT_RELS = PACKAGE_RELS + "/.rels";
const std::string ARC_WORKBOOK_RELS = PACKAGE_XL + "/" + PACKAGE_RELS + "/workbook.xml.rels";
const std::string ARC_CORE = PACKAGE_PROPS + "/core.xml";
const std::string ARC_APP = PACKAGE_PROPS + "/app.xml";
const std::string ARC_WORKBOOK = PACKAGE_XL + "/workbook.xml";
const std::string ARC_STYLE = PACKAGE_XL + "/styles.xml";
const std::string ARC_THEME = PACKAGE_THEME + "/theme1.xml";
const std::string ARC_SHARED_STRINGS = PACKAGE_XL + "/sharedStrings.xml";
std::unordered_map<std::string, std::string> NAMESPACES = {
{"cp", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties"},
{"dc", "http://purl.org/dc/elements/1.1/"},
{"dcterms", "http://purl.org/dc/terms/"},
{"dcmitype", "http://purl.org/dc/dcmitype/"},
{"xsi", "http://www.w3.org/2001/XMLSchema-instance"},
{"vt", "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"},
{"xml", "http://www.w3.org/XML/1998/namespace"}
};
/// <summary>
/// Specifies the compression level for content that is stored in a part.
/// </summary>
enum class compression_option
{
/// <summary>
/// Compression is optimized for performance.
/// </summary>
Fast,
/// <summary>
/// Compression is optimized for size.
/// </summary>
Maximum,
/// <summary>
/// Compression is optimized for a balance between size and performance.
/// </summary>
Normal,
/// <summary>
/// Compression is turned off.
/// </summary>
NotCompressed,
/// <summary>
/// Compression is optimized for high performance.
/// </summary>
SuperFast
};
/// <summary>
/// Defines constants for read, write, or read / write access to a file.
/// </summary>
enum class file_access
{
/// <summary>
/// Read access to the file. Data can be read from the file. Combine with Write for read/write access.
/// </summary>
Read = 0x01,
/// <summary>
/// Read and write access to the file. Data can be written to and read from the file.
/// </summary>
ReadWrite = 0x02,
/// <summary>
/// Write access to the file. Data can be written to the file. Combine with Read for read/write access.
/// </summary>
Write = 0x04,
/// <summary>
/// Inherit access for part from enclosing package.
/// </summary>
FromPackage = 0x08
};
/// <summary>
/// Specifies how the operating system should open a file.
/// </summary>
enum class file_mode
{
/// <summary>
/// Opens the file if it exists and seeks to the end of the file, or creates a new file.This requires FileIOPermissionAccess.Append permission.file_mode.Append can be used only in conjunction with file_access.Write.Trying to seek to a position before the end of the file throws an IOException exception, and any attempt to read fails and throws a NotSupportedException exception.
/// </summary>
Append,
/// <summary>
/// Specifies that the operating system should create a new file. If the file already exists, it will be overwritten. This requires FileIOPermissionAccess.Write permission. file_mode.Create is equivalent to requesting that if the file does not exist, use CreateNew; otherwise, use Truncate. If the file already exists but is a hidden file, an UnauthorizedAccessException exception is thrown.
/// </summary>
Create,
/// <summary>
/// Specifies that the operating system should create a new file. This requires FileIOPermissionAccess.Write permission. If the file already exists, an IOException exception is thrown.
/// </summary>
CreateNew,
/// <summary>
/// Specifies that the operating system should open an existing file. The ability to open the file is dependent on the value specified by the file_access enumeration. A System.IO.FileNotFoundException exception is thrown if the file does not exist.
/// </summary>
Open,
/// <summary>
/// Specifies that the operating system should open a file if it exists; otherwise, a new file should be created. If the file is opened with file_access.Read, FileIOPermissionAccess.Read permission is required. If the file access is file_access.Write, FileIOPermissionAccess.Write permission is required. If the file is opened with file_access.ReadWrite, both FileIOPermissionAccess.Read and FileIOPermissionAccess.Write permissions are required.
/// </summary>
OpenOrCreate,
/// <summary>
/// Specifies that the operating system should open an existing file. When the file is opened, it should be truncated so that its size is zero bytes. This requires FileIOPermissionAccess.Write permission. Attempts to read from a file opened with file_mode.Truncate cause an ArgumentException exception.
/// </summary>
Truncate
};
/// <summary>
/// Contains constants for controlling the kind of access other FileStream objects can have to the same file.
/// </summary>
enum class file_share
{
/// <summary>
/// Allows subsequent deleting of a file.
/// </summary>
Delete,
/// <summary>
/// Makes the file handle inheritable by child processes. This is not directly supported by Win32.
/// </summary>
Inheritable,
/// <summary>
/// Declines sharing of the current file. Any request to open the file (by this process or another process) will
/// fail until the file is closed.
/// </summary>
None,
/// <summary>
/// Allows subsequent opening of the file for reading. If this flag is not specified, any request to open the file
/// for reading (by this process or another process) will fail until the file is closed. However, even if this flag
/// is specified, additional permissions might still be needed to access the file.
/// </summary>
Read,
/// <summary>
/// Allows subsequent opening of the file for reading or writing. If this flag is not specified, any request to
/// open the file for reading or writing (by this process or another process) will fail until the file is closed.
/// However, even if this flag is specified, additional permissions might still be needed to access the file.
/// </summary>
ReadWrite,
/// <summary>
/// Allows subsequent opening of the file for writing. If this flag is not specified, any request to open the file
/// for writing (by this process or another process) will fail until the file is closed. However, even if this flag
/// is specified, additional permissions might still be needed to access the file.
/// </summary>
Write
};
/// <summary>
/// Specifies whether the target of a relationship is inside or outside the Package.
/// </summary>
enum class target_mode
{
/// <summary>
/// The relationship references a part that is inside the package.
/// </summary>
External,
/// <summary>
/// The relationship references a resource that is external to the package.
/// </summary>
Internal
};
/// <summary>
/// Represents a value type that may or may not have an assigned value.
/// </summary>
template<typename T>
struct nullable
{
public:
/// <summary>
/// Initializes a new instance of the nullable&lt;T&gt; structure with a "null" value.
/// </summary>
nullable() : has_value_(false) {}
/// <summary>
/// Initializes a new instance of the nullable&lt;T&gt; structure to the specified value.
/// </summary>
nullable(const T &value) : has_value_(true), value_(value) {}
/// <summary>
/// gets a value indicating whether the current nullable&lt;T&gt; object has a valid value of its underlying type.
/// </summary>
bool has_value() const { return has_value_; }
/// <summary>
/// gets the value of the current nullable&lt;T&gt; object if it has been assigned a valid underlying value.
/// </summary>
T get_value() const
{
if(!has_value())
{
throw std::runtime_error("invalid operation");
}
return value_;
}
/// <summary>
/// Indicates whether the current nullable&lt;T&gt; object is equal to a specified object.
/// </summary>
bool equals(const nullable<T> &other) const
{
if(!has_value())
{
return !other.has_value();
}
if(other.has_value())
{
return get_value() == other.get_value();
}
return false;
}
/// <summary>
/// Retrieves the value of the current nullable&lt;T&gt; object, or the object's default value.
/// </summary>
T get_value_or_default()
{
if(has_value())
{
return get_value();
}
return T();
}
/// <summary>
/// Retrieves the value of the current nullable&lt;T&gt; object or the specified default value.
/// </summary>
T get_value_or_default(const T &default_)
{
if(has_value())
{
return get_value();
}
return default_;
}
/// <summary>
/// Returns the value of a specified nullable&lt;T&gt; value.
/// </summary>
operator T() const
{
return get_value();
}
/// <summary>
/// Indicates whether the current nullable&lt;T&gt; object is equal to a specified object.
/// </summary>
bool operator==(nullptr_t) const
{
return !has_value_;
}
/// <summary>
/// Indicates whether the current nullable&lt;T&gt; object is not equal to a specified object.
/// </summary>
bool operator!=(nullptr_t) const
{
return has_value_;
}
/// <summary>
/// Indicates whether the current nullable&lt;T&gt; object is equal to a specified object.
/// </summary>
bool operator==(T other) const
{
return has_value_ && other == value_;
}
/// <summary>
/// Indicates whether the current nullable&lt;T&gt; object is not equal to a specified object.
/// </summary>
bool operator!=(T other) const
{
return has_value_ && other != value_;
}
/// <summary>
/// Indicates whether the current nullable&lt;T&gt; object is equal to a specified object.
/// </summary>
bool operator==(const nullable<T> &other) const
{
return equals(other);
}
/// <summary>
/// Indicates whether the current nullable&lt;T&gt; object is not equal to a specified object.
/// </summary>
bool operator!=(const nullable<T> &other) const
{
return !(*this == other);
}
private:
bool has_value_;
T value_;
};
/// <summary>
/// Provides static methods for the creation, copying, deletion, moving, and opening of a single file, and aids in the creation of FileStream objects.
/// </summary>
class file
{
public:
/// <summary>
/// Copies an existing file to a new file. Overwriting a file of the same name is allowed.
/// </summary>
static void copy(const std::string &source, const std::string &destination, bool overwrite = false);
/// <summary>
/// Determines whether the specified file exists.
/// </summary>
static bool exists(const std::string &path);
};
/// <summary>
/// Represents an association between a source Package or part, and a target object which can be a part or external resource.
/// </summary>
class relationship
{
public:
enum class type
{
hyperlink,
drawing,
worksheet,
sharedStrings,
styles,
theme
};
relationship(const std::string &type) : source_uri_(""), target_uri_("")
{
if(type == "hyperlink")
{
type_ = type::hyperlink;
}
}
/// <summary>
/// gets a string that identifies the relationship.
/// </summary>
std::string get_id() const { return id_; }
/// <summary>
/// gets the URI of the package or part that owns the relationship.
/// </summary>
std::string get_source_uri() const { return source_uri_; }
/// <summary>
/// gets a value that indicates whether the target of the relationship is or External to the Package.
/// </summary>
target_mode get_target_mode() const { return target_mode_; }
/// <summary>
/// gets the URI of the target resource of the relationship.
/// </summary>
std::string get_target_uri() const { return target_uri_; }
private:
friend class package;
relationship(const std::string &id, package &package, const std::string &relationship_type_, const std::string &source_uri, target_mode target_mode, const std::string &target_uri);
relationship &operator=(const relationship &rhs) = delete;
type type_;
std::string id_;
std::string source_uri_;
std::string target_uri_;
target_mode target_mode_;
};
typedef std::vector<relationship> relationship_collection;
class opc_callback_handler
{
public:
static int read(void *context, char *buffer, int length);
static int write(void *context, const char *buffer, int length);
static int close(void *context);
static opc_ofs_t seek(void *context, opc_ofs_t ofs);
static int trim(void *context, opc_ofs_t new_size);
static int flush(void *context);
};
struct part_struct;
/// <summary>
/// Represents a part that is stored in a ZipPackage.
/// </summary>
class part
{
public:
/// <summary>
/// Initializes a new instance of the part class with a specified parent Package, part URI, MIME content type, and compression_option.
/// </summary>
part(package_impl &package, const std::string &uri_part, const std::string &mime_type = "", compression_option compression = compression_option::NotCompressed);
part &operator=(const part &) = delete;
/// <summary>
/// gets the compression option of the part content stream.
/// </summary>
compression_option get_compression_option() const;
/// <summary>
/// gets the MIME type of the content stream.
/// </summary>
std::string get_content_type() const;
/// <summary>
/// gets the parent Package of the part.
/// </summary>
package &get_package() const;
/// <summary>
/// gets the URI of the part.
/// </summary>
std::string get_uri() const;
/// <summary>
/// Creates a part-level relationship between this part to a specified target part or external resource.
/// </summary>
relationship create_relationship(const std::string &target_uri, target_mode target_mode, const std::string &relationship_type);
/// <summary>
/// Deletes a specified part-level relationship.
/// </summary>
void delete_relationship(const std::string &id);
/// <summary>
/// Returns the relationship that has a specified Id.
/// </summary>
relationship get_relationship(const std::string &id);
/// <summary>
/// Returns a collection of all the relationships that are owned by this part.
/// </summary>
relationship_collection get_relationships();
/// <summary>
/// Returns a collection of the relationships that match a specified RelationshipType.
/// </summary>
relationship_collection get_relationship_by_type(const std::string &relationship_type);
/// <summary>
/// Returns all the content of this part.
/// </summary>
std::string read();
/// <summary>
/// Writes the given data to the part stream.
/// </summary>
void write(const std::string &data);
/// <summary>
/// Returns a value that indicates whether this part owns a relationship with a specified Id.
/// </summary>
bool relationship_exists(const std::string &id) const;
bool operator==(const part &comparand) const;
bool operator==(const nullptr_t &) const;
private:
friend struct package_impl;
part(part_struct *root);
part(package_impl &package, const std::string &uri, opcContainer *container);
part_struct *root_;
};
typedef std::vector<part> part_collection;
/// <summary>
/// Implements a derived subclass of the abstract Package base class—the ZipPackage class uses a
/// ZIP archive as the container store. This class should not be inherited.
/// </summary>
class package
{
public:
/// <summary>
/// Opens a package with a given IO stream, file mode, and file access setting.
/// </summary>
static package open(std::iostream &stream, file_mode package_mode, file_access package_access);
/// <summary>
/// Opens a package at a given path using a given file mode, file access, and file share setting.
/// </summary>
static package open(const std::string &path, file_mode package_mode = file_mode::OpenOrCreate,
file_access package_access = file_access::ReadWrite, file_share package_share = file_share::None);
/// <summary>
/// Saves and closes the package plus all underlying part streams.
/// </summary>
void close();
/// <summary>
/// Creates a new part with a given URI, content type, and compression option.
/// </summary>
part create_part(const std::string &part_uri, const std::string &content_type, compression_option compression = compression_option::Normal);
/// <summary>
/// Creates a package-level relationship to a part with a given URI, target mode, relationship type, and identifier (ID).
/// </summary>
relationship create_relationship(const std::string &part_uri, target_mode target_mode, const std::string &relationship_type, const std::string &id);
/// <summary>
/// Deletes a part with a given URI from the package.
/// </summary>
void delete_part(const std::string &part_uri);
/// <summary>
/// Deletes a package-level relationship.
/// </summary>
void delete_relationship(const std::string &id);
/// <summary>
/// Saves the contents of all parts and relationships that are contained in the package.
/// </summary>
void flush();
/// <summary>
/// Returns the part with a given URI.
/// </summary>
part get_part(const std::string &part_uri);
/// <summary>
/// Returns a collection of all the parts in the package.
/// </summary>
part_collection get_parts();
/// <summary>
///
/// </summary>
relationship get_relationship(const std::string &id);
/// <summary>
/// Returns the package-level relationship with a given identifier.
/// </summary>
relationship_collection get_relationships();
/// <summary>
/// Returns a collection of all the package-level relationships that match a given RelationshipType.
/// </summary>
relationship_collection get_relationships(const std::string &relationship_type);
/// <summary>
/// Indicates whether a part with a given URI is in the package.
/// </summary>
bool part_exists(const std::string &part_uri);
/// <summary>
/// Indicates whether a package-level relationship with a given ID is contained in the package.
/// </summary>
bool relationship_exists(const std::string &id);
/// <summary>
/// gets the file access setting for the package.
/// </summary>
file_access get_file_open_access() const;
bool operator==(const package &comparand) const;
bool operator==(const nullptr_t &) const;
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_category() const;
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_category(const std::string &category);
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_content_status() const;
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_content_status(const std::string &category);
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_content_type() const;
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_content_type(const std::string &category);
/// <summary>
/// gets the category of the Package.
/// </summary>
nullable<tm> get_created() const;
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_created(const nullable<tm> &created);
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_creator() const;
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_creator(const std::string &category);
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_description() const;
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_description(const std::string &category);
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_identifier() const;
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_identifier(const std::string &category);
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_keywords() const;
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_keywords(const std::string &category);
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_language() const;
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_language(const std::string &category);
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_last_modified_by() const;
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_last_modified_by(const std::string &category);
/// <summary>
/// gets the category of the Package.
/// </summary>
nullable<tm> get_last_printed() const;
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_last_printed(const nullable<tm> &created);
/// <summary>
/// gets the category of the Package.
/// </summary>
nullable<tm> get_modified() const;
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_modified(const nullable<tm> &created);
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_revision() const;
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_revision(const std::string &category);
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string getsubject() const;
/// <summary>
/// sets the category of the Package.
/// </summary>
void setsubject(const std::string &category);
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_title() const;
/// Ssummary>
/// gets the category of the Package.
/// </summary>
void set_title(const std::string &category);
/// <summary>
/// gets the category of the Package.
/// </summary>
std::string get_version() const;
/// <summary>
/// sets the category of the Package.
/// </summary>
void set_version(const std::string &category);
private:
friend opc_callback_handler;
package(std::iostream &stream, file_mode package_mode, file_access package_access);
package(const std::string &path, file_mode package_mode, file_access package_access);
void open_container();
int write(char *buffer, int length);
int read(const char *buffer, int length);
std::ios::pos_type seek(std::ios::pos_type ofs);
int trim(std::ios::pos_type new_size);
package_impl *impl_;
};
struct coordinate
{
std::string column;
int row;
};
class cell
{
public:
enum class type
{
null,
numeric,
string,
date,
formula,
boolean,
error
};
static coordinate coordinate_from_string(const std::string &address);
static int column_index_from_string(const std::string &column_string);
static std::string get_column_letter(int column_index);
static std::string absolute_coordinate(const std::string &absolute_address);
cell();
~cell();
cell &operator=(int value);
cell &operator=(double value);
cell &operator=(const std::string &value);
cell &operator=(const char *value);
cell &operator=(const tm &value);
friend bool operator==(const std::string &comparand, const cell &cell);
friend bool operator==(const char *comparand, const cell &cell);
friend bool operator==(const tm &comparand, const cell &cell);
std::string to_string() const;
bool is_date() const;
style &get_style();
type get_data_type();
private:
friend struct worksheet_struct;
cell(cell_struct *root);
cell_struct *root_;
};
inline std::ostream &operator<<(std::ostream &stream, const cell &cell)
{
return stream << cell.to_string();
}
typedef std::vector<std::vector<cell>> range;
class worksheet
{
public:
enum class Break
{
None = 0,
Row = 1,
Column = 2
};
enum class SheetState
{
Visible,
Hidden,
VeryHidden
};
enum class PaperSize
{
Letter = 1,
LetterSmall = 2,
Tabloid = 3,
Ledger = 4,
Legal = 5,
Statement = 6,
Executive = 7,
A3 = 8,
A4 = 9,
A4Small = 10,
A5 = 11
};
enum class Orientation
{
Portrait,
Landscape
};
void operator=(const worksheet &other);
cell operator[](const std::string &address);
std::string to_string() const;
workbook &get_parent() const;
void garbage_collect();
std::set<cell> get_cell_collection();
std::string get_title() const;
void set_title(const std::string &title);
cell get_freeze_panes() const;
void set_freeze_panes(cell top_left_cell);
void set_freeze_panes(const std::string &top_left_coordinate);
void unfreeze_panes();
xlnt::cell cell(const std::string &coordinate);
xlnt::cell cell(int row, int column);
int get_highest_row() const;
int get_highest_column() const;
std::string calculate_dimension() const;
range range(const std::string &range_string, int row_offset, int column_offset);
relationship create_relationship(const std::string &relationship_type);
//void add_chart(chart chart);
void merge_cells(const std::string &range_string);
void merge_cells(int start_row, int start_column, int end_row, int end_column);
void unmerge_cells(const std::string &range_string);
void unmerge_cells(int start_row, int start_column, int end_row, int end_column);
void append(const std::vector<xlnt::cell> &cells);
void append(const std::unordered_map<std::string, xlnt::cell> &cells);
void append(const std::unordered_map<int, xlnt::cell> &cells);
xlnt::range rows() const;
xlnt::range columns() const;
bool operator==(const worksheet &other) const;
bool operator!=(const worksheet &other) const;
bool operator==(nullptr_t) const;
bool operator!=(nullptr_t) const;
private:
friend class workbook;
worksheet(worksheet_struct *root);
worksheet_struct *root_;
};
class workbook
{
public:
workbook();
workbook(const workbook &) = delete;
const workbook &operator=(const workbook &) = delete;
worksheet get_sheet_by_name(const std::string &sheet_name);
worksheet get_active();
worksheet create_sheet();
worksheet create_sheet(std::size_t index);
std::vector<std::string> get_sheet_names() const;
std::vector<worksheet>::iterator begin();
std::vector<worksheet>::iterator end();
worksheet operator[](const std::string &name);
void save(const std::string &filename);
private:
worksheet active_worksheet_;
std::vector<worksheet> worksheets_;
};
} // namespace xlnt