diff --git a/cmake/clean b/clean
old mode 100755
new mode 100644
similarity index 80%
rename from cmake/clean
rename to clean
index d71cb22e..444a76dd
--- a/cmake/clean
+++ b/clean
@@ -5,7 +5,7 @@ import shutil
os.chdir(os.path.dirname(os.path.abspath(__file__)))
-dirs = ['../bin', '../lib', '../build']
+dirs = ['./bin', './lib', './build']
for dir in dirs:
if os.path.isdir(dir): shutil.rmtree(dir)
diff --git a/clean.bat b/clean.bat
new file mode 100644
index 00000000..60b4c7b4
--- /dev/null
+++ b/clean.bat
@@ -0,0 +1,7 @@
+@echo off
+setlocal EnableDelayedExpansion
+for /f %%i in ('where python') DO (set PYTHON=%%i) & goto :done1
+:done1
+@where python3 > nul 2>&1 && for /f %%i in ('@where python3') DO (@set PYTHON=%%i) & goto :done2
+:done2
+!PYTHON! clean
\ No newline at end of file
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
index 5e7d93dc..8b35f3d1 100644
--- a/cmake/CMakeLists.txt
+++ b/cmake/CMakeLists.txt
@@ -1,20 +1,24 @@
cmake_minimum_required(VERSION 2.8.7)
+if(NOT DEFINED CMAKE_SUPPRESS_DEVELOPER_WARNINGS)
+ set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS 1 CACHE INTERNAL "No dev warnings")
+endif()
+
project(xlnt)
if(APPLE)
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.10)
endif(APPLE)
-if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
endif()
-elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
+elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y")
-elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
endif()
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../lib)
diff --git a/cmake/configure b/cmake/configure
deleted file mode 100755
index bc4079d1..00000000
--- a/cmake/configure
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env python3
-
-import os
-import subprocess
-import sys
-
-os.chdir(os.path.dirname(os.path.abspath(__file__)))
-
-if not os.path.isdir('../build'):
- os.mkdir('../build')
-
-generator = 'Unix Makefiles'
-
-if sys.platform == 'darwin':
- generator = 'Unix Makefiles'
-elif sys.platform == 'win32':
- generator = 'Visual Studio 14 2015'
-
-subprocess.call(['cmake3', '-G', generator, '../cmake'], cwd='../build')
diff --git a/cmake/generate-tests.sh b/cmake/generate-tests
old mode 100755
new mode 100644
similarity index 100%
rename from cmake/generate-tests.sh
rename to cmake/generate-tests
diff --git a/cmake/generate-tests.bat b/cmake/generate-tests.bat
new file mode 100644
index 00000000..fa988575
--- /dev/null
+++ b/cmake/generate-tests.bat
@@ -0,0 +1,2 @@
+cd %~dp0
+../third-party/cxxtest/bin/cxxtestgen --runner=ErrorPrinter -o ../tests/runner-autogen.cpp ../tests/*.hpp
\ No newline at end of file
diff --git a/cmake/xlnt.test.cmake b/cmake/xlnt.test.cmake
index 2b599a97..a92abce4 100644
--- a/cmake/xlnt.test.cmake
+++ b/cmake/xlnt.test.cmake
@@ -18,7 +18,7 @@ source_group(helpers FILES ${TEST_HELPERS_HEADERS} ${TEST_HELPERS_SOURCES})
target_link_libraries(xlnt.test xlnt)
add_custom_target (generate-test-runner
- COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/generate-tests.sh
+ COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/generate-tests
COMMENT "Generating test runner tests/runner-autogen.cpp"
)
diff --git a/configure b/configure
new file mode 100644
index 00000000..57dd30e6
--- /dev/null
+++ b/configure
@@ -0,0 +1,41 @@
+#!/usr/bin/env python3
+
+import os
+import subprocess
+import sys
+
+def which(program):
+ def is_exe(fpath):
+ return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
+
+ fpath, fname = os.path.split(program)
+ if fpath:
+ if is_exe(program):
+ return program
+ else:
+ for path in os.environ["PATH"].split(os.pathsep):
+ path = path.strip('"')
+ exe_file = os.path.join(path, program)
+ if is_exe(exe_file):
+ return exe_file
+
+ return None
+
+os.chdir(os.path.dirname(os.path.abspath(__file__)))
+
+if not os.path.isdir('./build'):
+ os.mkdir('./build')
+
+generator = 'Unix Makefiles'
+
+if sys.platform == 'darwin':
+ generator = 'Unix Makefiles'
+elif sys.platform == 'win32':
+ generator = 'Visual Studio 14 2015'
+
+cmake = 'cmake'
+
+if which('cmake3'):
+ cmake = 'cmake3'
+
+subprocess.call([cmake, '-G', generator, '../cmake'], cwd='./build')
diff --git a/configure.bat b/configure.bat
new file mode 100644
index 00000000..27bbebc0
--- /dev/null
+++ b/configure.bat
@@ -0,0 +1,7 @@
+@echo off
+setlocal EnableDelayedExpansion
+for /f %%i in ('where python') DO (set PYTHON=%%i) & goto :done1
+:done1
+@where python3 > nul 2>&1 && for /f %%i in ('@where python3') DO (@set PYTHON=%%i) & goto :done2
+:done2
+!PYTHON! configure
\ No newline at end of file
diff --git a/include/xlnt/cell/cell.hpp b/include/xlnt/cell/cell.hpp
index 0f5e12e5..367dc364 100644
--- a/include/xlnt/cell/cell.hpp
+++ b/include/xlnt/cell/cell.hpp
@@ -83,7 +83,7 @@ class cell
///
/// Return a map of error strings such as #DIV/0! and their associated indices.
///
- static const std::unordered_map error_codes();
+ static const std::unordered_map &error_codes();
// TODO: Should it be possible to construct and use a cell without a parent worksheet?
//(cont'd) If so, it would need to be responsible for allocating and deleting its PIMPL.
diff --git a/source/cell/cell.cpp b/source/cell/cell.cpp
index b04e2815..d56df2e2 100644
--- a/source/cell/cell.cpp
+++ b/source/cell/cell.cpp
@@ -1,5 +1,5 @@
#include
-#include
+#include
#include
#include
@@ -763,7 +763,7 @@ std::string format_text(const std::string &text, const std::string &format)
namespace xlnt {
-const std::unordered_map cell::error_codes()
+const std::unordered_map &cell::error_codes()
{
static const std::unordered_map codes = { { "#NULL!", 0 }, { "#DIV/0!", 1 }, { "#VALUE!", 2 },
{ "#REF!", 3 }, { "#NAME?", 4 }, { "#NUM!", 5 },
@@ -910,7 +910,11 @@ template <>
void cell::set_value(std::string s)
{
d_->set_string(s, get_parent().get_parent().get_guess_types());
- if(!s.empty()) get_parent().get_parent().add_shared_string(s);
+
+ if (get_data_type() == type::string && !s.empty())
+ {
+ get_parent().get_parent().add_shared_string(s);
+ }
}
template <>
diff --git a/source/common/datetime.cpp b/source/common/datetime.cpp
index 58123d4d..f8bed2a3 100644
--- a/source/common/datetime.cpp
+++ b/source/common/datetime.cpp
@@ -115,12 +115,14 @@ time::time(const std::string &time_string) : hour(0), minute(0), second(0), micr
long double time::to_number() const
{
- std::size_t microseconds = static_cast(microsecond);
- microseconds += static_cast(second * 1e6);
- microseconds += static_cast(minute * 1e6 * 60);
- microseconds += static_cast(hour * 1e6 * 60 * 60);
- auto number = microseconds / (24.0L * 60 * 60 * 1e6L);
- number = std::floor(number * 1e11L + 0.5L) / 1e11L;
+ std::uint64_t microseconds = static_cast(microsecond);
+ microseconds += static_cast(second * 1e6);
+ microseconds += static_cast(minute * 1e6 * 60);
+ auto microseconds_per_hour = static_cast(1e6) * 60 * 60;
+ microseconds += static_cast(hour * microseconds_per_hour);
+ auto number = microseconds / (24.0L * microseconds_per_hour);
+ auto hundred_billion = static_cast(1e9) * 100;
+ number = std::floor(number * hundred_billion + 0.5L) / hundred_billion;
return number;
}
diff --git a/source/serialization/excel_serializer.cpp b/source/serialization/excel_serializer.cpp
index de62c4b2..f73fb04f 100644
--- a/source/serialization/excel_serializer.cpp
+++ b/source/serialization/excel_serializer.cpp
@@ -50,7 +50,9 @@ bool load_workbook(xlnt::zip_file &archive, bool guess_types, bool data_only, xl
}
xlnt::manifest_serializer ms(wb.get_manifest());
- ms.read_manifest(xlnt::xml_serializer::deserialize(archive.read(xlnt::constants::ArcContentTypes)));
+ xlnt::xml_document manifest_xml;
+ manifest_xml.from_string(archive.read(xlnt::constants::ArcContentTypes));
+ ms.read_manifest(manifest_xml);
if (ms.determine_document_type() != "excel")
{
@@ -62,7 +64,9 @@ bool load_workbook(xlnt::zip_file &archive, bool guess_types, bool data_only, xl
if(archive.has_file(xlnt::constants::ArcCore))
{
xlnt::workbook_serializer workbook_serializer_(wb);
- workbook_serializer_.read_properties_core(xlnt::xml_serializer::deserialize(archive.read(xlnt::constants::ArcCore)));
+ xlnt::xml_document core_properties_xml;
+ core_properties_xml.from_string(archive.read(xlnt::constants::ArcCore));
+ workbook_serializer_.read_properties_core(core_properties_xml);
}
auto workbook_relationships =
@@ -73,7 +77,8 @@ bool load_workbook(xlnt::zip_file &archive, bool guess_types, bool data_only, xl
wb.create_relationship(relationship.get_id(), relationship.get_target_uri(), relationship.get_type());
}
- auto xml = xlnt::xml_serializer::deserialize(archive.read(xlnt::constants::ArcWorkbook));
+ xlnt::xml_document xml;
+ xml.from_string(archive.read(xlnt::constants::ArcWorkbook));
auto root_node = xml.get_child("workbook");
@@ -87,8 +92,9 @@ bool load_workbook(xlnt::zip_file &archive, bool guess_types, bool data_only, xl
{
xlnt::shared_strings_serializer shared_strings_serializer_;
std::vector shared_strings;
- shared_strings_serializer_.read_shared_strings(
- xlnt::xml_serializer::deserialize(archive.read(xlnt::constants::ArcSharedString)), shared_strings);
+ xlnt::xml_document shared_strings_xml;
+ shared_strings_xml.from_string(archive.read(xlnt::constants::ArcSharedString));
+ shared_strings_serializer_.read_shared_strings(shared_strings_xml, shared_strings);
for (auto shared_string : shared_strings)
{
@@ -97,7 +103,9 @@ bool load_workbook(xlnt::zip_file &archive, bool guess_types, bool data_only, xl
}
xlnt::style_serializer style_reader_(wb);
- style_reader_.read_stylesheet(xlnt::xml_serializer::deserialize(archive.read(xlnt::constants::ArcStyles)));
+ xlnt::xml_document style_xml;
+ style_xml.from_string(archive.read(xlnt::constants::ArcStyles));
+ style_reader_.read_stylesheet(style_xml);
auto sheets_node = root_node.get_child("sheets");
@@ -113,7 +121,9 @@ bool load_workbook(xlnt::zip_file &archive, bool guess_types, bool data_only, xl
if(sheet_type != "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml") continue;
xlnt::worksheet_serializer worksheet_serializer(ws);
- worksheet_serializer.read_worksheet(xlnt::xml_serializer::deserialize(archive.read(ws_filename)));
+ xlnt::xml_document worksheet_xml;
+ worksheet_xml.from_string(archive.read(ws_filename));
+ worksheet_serializer.read_worksheet(worksheet_xml);
}
return true;
diff --git a/source/serialization/worksheet_serializer.cpp b/source/serialization/worksheet_serializer.cpp
index 2d259c91..ca9d93b5 100644
--- a/source/serialization/worksheet_serializer.cpp
+++ b/source/serialization/worksheet_serializer.cpp
@@ -1,3 +1,4 @@
+#include
#include
#include
@@ -124,7 +125,7 @@ bool worksheet_serializer::read_worksheet(const xml_document &xml)
std::string type = has_type ? cell_node.get_attribute("t") : "";
bool has_style = cell_node.has_attribute("s");
- int style_id = has_style ? std::stoull(cell_node.get_attribute("s")) : 0;
+ auto style_id = static_cast(has_style ? std::stoull(cell_node.get_attribute("s")) : 0LL);
bool has_formula = cell_node.has_child("f");
bool has_shared_formula = has_formula && cell_node.get_child("f").has_attribute("t") &&
@@ -145,7 +146,7 @@ bool worksheet_serializer::read_worksheet(const xml_document &xml)
}
else if (has_type && type == "s" && !has_formula) // shared string
{
- auto shared_string_index = std::stoull(value_string);
+ auto shared_string_index = static_cast(std::stoull(value_string));
auto shared_string = shared_strings.at(shared_string_index);
cell.set_value(shared_string);
}
@@ -190,7 +191,7 @@ bool worksheet_serializer::read_worksheet(const xml_document &xml)
auto max = static_cast(std::stoull(col_node.get_attribute("max")));
auto width = std::stold(col_node.get_attribute("width"));
bool custom = col_node.get_attribute("customWidth") == "1";
- auto column_style = col_node.has_attribute("style") ? std::stoull(col_node.get_attribute("style")) : 0;
+ auto column_style = static_cast(col_node.has_attribute("style") ? std::stoull(col_node.get_attribute("style")) : 0);
for (auto column = min; column <= max; column++)
{
diff --git a/source/serialization/xml_document.cpp b/source/serialization/xml_document.cpp
index 5fc63d0d..25c84fe3 100644
--- a/source/serialization/xml_document.cpp
+++ b/source/serialization/xml_document.cpp
@@ -2,6 +2,7 @@
#include
#include
+#include
#include
#include
@@ -16,6 +17,11 @@ xml_document::xml_document(const xml_document &other) : xml_document()
d_->doc.append_copy(other.d_->doc.root());
}
+xml_document::xml_document(xml_document &&other)
+{
+ std::swap(d_, other.d_);
+}
+
xml_document::~xml_document()
{
}
@@ -59,8 +65,7 @@ std::string xml_document::to_string() const
xml_document &xml_document::from_string(const std::string &xml_string)
{
- auto doc = xml_serializer::deserialize(xml_string);
- std::swap(doc.d_, d_);
+ d_->doc.load(xml_string.c_str());
return *this;
}
diff --git a/tests/helpers/helper.hpp b/tests/helpers/helper.hpp
index 9f1d5440..661ac789 100644
--- a/tests/helpers/helper.hpp
+++ b/tests/helpers/helper.hpp
@@ -49,17 +49,21 @@ public:
expected_contents = s.str();
}
- auto expected_xml = xlnt::xml_serializer::deserialize(expected_contents);
-
+ xlnt::xml_document expected_xml;
+ expected_xml.from_string(expected_contents);
+
return compare_xml(expected_xml.get_root(), observed.get_root());
}
static comparison_result compare_xml(const std::string &left_contents, const std::string &right_contents)
{
- auto left_doc = xlnt::xml_serializer::deserialize(left_contents);
- auto right_doc = xlnt::xml_serializer::deserialize(right_contents);
-
- return compare_xml(left_doc.get_root(), right_doc.get_root());
+ xlnt::xml_document left_xml;
+ left_xml.from_string(left_contents);
+
+ xlnt::xml_document right_xml;
+ right_xml.from_string(right_contents);
+
+ return compare_xml(left_xml.get_root(), right_xml.get_root());
}
static comparison_result compare_xml(const xlnt::xml_node &left, const xlnt::xml_node &right)
diff --git a/tests/test_read.hpp b/tests/test_read.hpp
index 6b083e85..e0fb484b 100644
--- a/tests/test_read.hpp
+++ b/tests/test_read.hpp
@@ -161,9 +161,7 @@ public:
auto path = PathHelper::GetDataDirectory("/reader/date_1904.xlsx");
xlnt::workbook wb;
- xlnt::excel_serializer serializer(wb);
-
- serializer.load_workbook(path);
+ wb.load(path);
return wb;
}
@@ -173,9 +171,7 @@ public:
auto path = PathHelper::GetDataDirectory("/reader/date_1900.xlsx");
xlnt::workbook wb;
- xlnt::excel_serializer serializer(wb);
-
- serializer.load_workbook(path);
+ wb.load(path);
return wb;
}