Merge pull request #160 from oshogbo:libxls

PiperOrigin-RevId: 443307436
Change-Id: Ic2550e45cf3f55cac9fcfce37cf669c6a6f9fc96
This commit is contained in:
Copybara-Service 2022-04-21 01:27:49 -07:00
commit d8d7d74ae2
15 changed files with 764 additions and 0 deletions

View File

@ -18,6 +18,7 @@ set(SAPI_CONTRIB_SANDBOXES
hunspell
jsonnet
libidn2
libxls
libzip
pffft
turbojpeg

View File

@ -11,6 +11,7 @@ Directory | Project
`hunspell/` | Hunspell - The most popular spellchecking library | [github.com/hunspell/hunspell](https://github.com/hunspell/hunspell) | CMake
`jsonnet/` | Jsonnet - The Data Templating Language | [github.com/google/jsonnet](https://github.com/google/jsonnet) | CMake
`libidn2/` | libidn2 - GNU IDN library | [www.gnu.org/software/libidn/#libidn2](https://www.gnu.org/software/libidn/#libidn2) | CMake
`libxls/` | libxls - Read binary Excel files from C/C++ | [https://github.com/libxls/libxls](https://github.com/libxls/libxls) | CMake
`libzip/` | libzip - operations on zip archives | [github.com/nih-at/libzip](https://github.com/nih-at/libzip) | CMake
`pffft/` | PFFFT - a pretty fast Fourier Transform | [bitbucket.org/jpommier/pffft.git](https://bitbucket.org/jpommier/pffft.git) | CMake
`turbojpeg/` | High-level JPEG library | [libjpeg-turbo.org/About/TurboJPEG](https://libjpeg-turbo.org/About/TurboJPEG) | CMake

View File

@ -0,0 +1,117 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.13..3.22)
project(sapi_libxls C CXX)
include(CTest)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
if(NOT TARGET sapi::sapi)
set(SAPI_ROOT "../.." CACHE PATH "Path to the Sandboxed API source tree")
add_subdirectory("${SAPI_ROOT}"
"${CMAKE_BINARY_DIR}/sandboxed-api-build"
EXCLUDE_FROM_ALL)
endif()
FetchContent_Declare(libxls
GIT_REPOSITORY https://github.com/libxls/libxls.git
GIT_TAG 448240067919707eb95fb009f76f3fdb439b1427
)
FetchContent_GetProperties(libxls)
if(NOT libxls_POPULATED)
FetchContent_Populate(libxls)
set(libxls_STATUS_FILE "${libxls_SOURCE_DIR}/config.status")
if(EXISTS "${libxls_STATUS_FILE}")
file(SHA256 "${libxls_STATUS_FILE}" _sapi_CONFIG_STATUS)
endif()
if(NOT _sapi_CONFIG_STATUS STREQUAL "${libxls_CONFIG_STATUS}")
message("-- Configuring libxls...")
execute_process(
COMMAND autoreconf -i
WORKING_DIRECTORY "${libxls_SOURCE_DIR}"
RESULT_VARIABLE _sapi_libxls_autoreconf_result
)
if(NOT _sapi_libxls_autoreconf_result EQUAL "0")
message(FATAL_ERROR "Configuration for libxls failed: "
"${_sapi_libxls_autoreconf_result}")
endif()
execute_process(
COMMAND ./configure --disable-dependency-tracking
--disable-shared
--quiet
WORKING_DIRECTORY "${libxls_SOURCE_DIR}"
RESULT_VARIABLE _sapi_libxls_config_result
)
if(NOT _sapi_libxls_config_result EQUAL "0")
message(FATAL_ERROR "Configuration for libxls failed: "
"${_sapi_libxls_config_result}")
endif()
file(SHA256 "${libxls_SOURCE_DIR}/config.status" _sapi_CONFIG_STATUS)
set(libxls_CONFIG_STATUS "${_sapi_CONFIG_STATUS}" CACHE INTERNAL "")
endif()
endif()
add_library(libxls STATIC
"${libxls_SOURCE_DIR}/src/endian.c"
"${libxls_SOURCE_DIR}/src/locale.c"
"${libxls_SOURCE_DIR}/src/ole.c"
"${libxls_SOURCE_DIR}/src/xls.c"
"${libxls_SOURCE_DIR}/src/xlstool.c"
)
target_include_directories(libxls PUBLIC
"${libxls_SOURCE_DIR}"
"${libxls_SOURCE_DIR}/include"
)
configure_file(xls.gen.h.in xls.gen.h)
add_sapi_library(
sapi_libxls
FUNCTIONS
xls_open_file
xls_getWorkSheet
xls_parseWorkSheet
xls_cell
xls_close_WS
xls_close_WB
xls_getError
INPUTS
"${CMAKE_BINARY_DIR}/xls.gen.h"
LIBRARY libxls
LIBRARY_NAME Libxls
NAMESPACE ""
)
add_library(sapi_contrib::libxls ALIAS sapi_libxls)
target_include_directories(sapi_libxls INTERFACE
"${PROJECT_BINARY_DIR}"
)
if(SAPI_ENABLE_EXAMPLES)
add_subdirectory(example)
endif()
if(SAPI_ENABLE_TESTS)
add_subdirectory(test)
endif()

14
contrib/libxls/README.md Normal file
View File

@ -0,0 +1,14 @@
# libxls Sandboxed API
This directory contains a ready-made sandbox for the
[libxls](https://github.com/libxls/libxls) library.
The libxls library uses Autotools and a special macro package for its
configuration. This means that on Debian based systems, the package
`autoconf-archive` needs to be installed or the configuration phase
will fail with the following error:
```
./configure: line 16126: syntax error near unexpected token `,'
./configure: line 16126: `AX_CXX_COMPILE_STDCXX_11(, optional)'
```

View File

@ -0,0 +1,24 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
add_executable(sapi_minixls
main.cc
../utils/utils_libxls.cc
)
target_link_libraries(sapi_minixls
PRIVATE sapi_libxls
absl::flags_parse
sapi::sapi
)

View File

@ -0,0 +1,89 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <fcntl.h>
#include <unistd.h>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "contrib/libxls/sandboxed.h"
#include "contrib/libxls/utils/utils_libxls.h"
ABSL_FLAG(uint32_t, sheet, 0, "sheet number");
int main(int argc, char* argv[]) {
std::string prog_name(argv[0]);
google::InitGoogleLogging(argv[0]);
std::vector<char*> args = absl::ParseCommandLine(argc, argv);
if (args.size() != 2) {
std::cerr << "Usage:\n " << prog_name << " INPUT\n";
return EXIT_FAILURE;
}
LibxlsSapiSandbox sandbox(args[1]);
if (!sandbox.Init().ok()) {
std::cerr << "Unable to start sandbox\n";
return EXIT_FAILURE;
}
absl::StatusOr<LibXlsWorkbook> wb = LibXlsWorkbook::Open(&sandbox, args[1]);
uint32_t nr_sheet = absl::GetFlag(FLAGS_sheet);
absl::StatusOr<LibXlsSheet> sheet = wb->OpenSheet(nr_sheet);
if (!sheet.ok()) {
std::cerr << "Unable to switch sheet: ";
std::cerr << sheet.status() << "\n";
return EXIT_FAILURE;
}
for (size_t row = 0; row < sheet->GetRowCount(); ++row) {
for (size_t col = 0; col < sheet->GetColCount(); ++col) {
absl::StatusOr<LibXlsCell> cell = sheet->GetCell(row, col);
if (!cell.ok()) {
std::cerr << "Unable to get cell: ";
std::cerr << cell.status() << "\n";
return EXIT_FAILURE;
}
switch (cell->type) {
case XLS_RECORD_NUMBER:
std::cout << std::setw(16) << std::get<double>(cell->value) << " | ";
break;
case XLS_RECORD_STRING:
std::cout << std::setw(16) << std::get<std::string>(cell->value)
<< " | ";
break;
case XLS_RECORD_BOOL:
std::cout << std::setw(16) << std::get<bool>(cell->value) << " | ";
break;
case XLS_RECORD_BLANK:
std::cout << std::setw(16) << " | ";
break;
case XLS_RECORD_ERROR:
std::cout << "error"
<< "\n";
break;
}
}
std::cout << "\n";
}
return EXIT_SUCCESS;
}

BIN
contrib/libxls/files/t1.xls Normal file

Binary file not shown.

BIN
contrib/libxls/files/t2.xls Normal file

Binary file not shown.

BIN
contrib/libxls/files/t3.xls Normal file

Binary file not shown.

View File

@ -0,0 +1,48 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CONTRIB_LIBXLS_SANDBOXED_H_
#define CONTRIB_LIBXLS_SANDBOXED_H_
#include <libgen.h>
#include <syscall.h>
#include <memory>
#include "sapi_libxls.sapi.h" // NOLINT(build/include)
class LibxlsSapiSandbox : public LibxlsSandbox {
public:
explicit LibxlsSapiSandbox(std::string filename)
: filename_(std::move(filename)) {}
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
sandbox2::PolicyBuilder*) override {
return sandbox2::PolicyBuilder()
.AllowDynamicStartup()
.AllowOpen()
.AllowRead()
.AllowWrite()
.AllowSystemMalloc()
.AllowExit()
.AllowSyscall(__NR_recvmsg)
.AddFile(filename_)
.BuildOrDie();
}
private:
std::string filename_;
};
#endif // CONTRIB_LIBXLS_SANDBOXED_H_

View File

@ -0,0 +1,28 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
include(GoogleTest)
add_executable(sapi_libxls_test
libxls_test.cc
../utils/utils_libxls.cc
)
target_link_libraries(sapi_libxls_test
PRIVATE sapi_libxls
sapi::temp_file
sapi::test_main
)
gtest_discover_tests(sapi_libxls_test PROPERTIES ENVIRONMENT "TEST_FILES_DIR=${PROJECT_SOURCE_DIR}/files")

View File

@ -0,0 +1,143 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "contrib/libxls/sandboxed.h"
#include "contrib/libxls/utils/utils_libxls.h"
#undef FILE // TODO(cblichmann): Artifact from generated header
#include "sandboxed_api/util/path.h"
#include "sandboxed_api/util/status_matchers.h"
namespace {
using ::sapi::IsOk;
using ::testing::Not;
struct Sheet {
int count_row;
int count_col;
double values[4][4];
};
const struct TestCase {
std::string filename;
size_t sheet_count;
struct Sheet sheet[2];
} kTestData[] = {
{
.filename = "t1.xls",
.sheet_count = 1,
.sheet =
{
{.count_row = 4,
.count_col = 2,
.values =
{
{1, 2, 0, 0},
{3, 4, 0, 0},
{5, 6, 0, 0},
{7, 8, 0, 0},
}},
},
},
{
.filename = "t2.xls",
.sheet_count = 2,
.sheet =
{
{.count_row = 2,
.count_col = 3,
.values =
{
{1, 2, 3, 0},
{4, 5, 6, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
}},
{.count_row = 2,
.count_col = 2,
.values =
{
{9, 8, 0, 0},
{7, 6, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
}},
},
},
};
class LibXlsBase : public testing::Test {
protected:
std::string GetTestFilePath(const std::string& filename) {
return sapi::file::JoinPath(test_dir_, filename);
}
void SetUp() override;
const char* test_dir_;
};
class LibXlsTestFiles : public LibXlsBase,
public testing::WithParamInterface<TestCase> {};
void LibXlsBase::SetUp() {
test_dir_ = getenv("TEST_FILES_DIR");
ASSERT_NE(test_dir_, nullptr);
}
TEST_P(LibXlsTestFiles, TestValues) {
const TestCase& tv = GetParam();
std::string test_file_path = GetTestFilePath(tv.filename);
LibxlsSapiSandbox sandbox(test_file_path);
SAPI_ASSERT_OK(sandbox.Init());
SAPI_ASSERT_OK_AND_ASSIGN(LibXlsWorkbook wb,
LibXlsWorkbook::Open(&sandbox, test_file_path));
ASSERT_EQ(wb.GetSheetCount(), tv.sheet_count);
for (int i = 0; i < tv.sheet_count; ++i) {
SAPI_ASSERT_OK_AND_ASSIGN(LibXlsSheet sheet, wb.OpenSheet(i));
ASSERT_EQ(sheet.GetRowCount(), tv.sheet[i].count_row);
ASSERT_EQ(sheet.GetColCount(), tv.sheet[i].count_col);
for (size_t row = 0; row < sheet.GetRowCount(); ++row) {
for (size_t col = 0; col < sheet.GetColCount(); ++col) {
SAPI_ASSERT_OK_AND_ASSIGN(LibXlsCell cell, sheet.GetCell(row, col));
ASSERT_EQ(cell.type, XLS_RECORD_NUMBER);
ASSERT_EQ(std::get<double>(cell.value), tv.sheet[i].values[row][col]);
}
}
}
}
INSTANTIATE_TEST_SUITE_P(LibXlsBase, LibXlsTestFiles,
testing::ValuesIn(kTestData));
TEST_F(LibXlsBase, TestFormula) {
std::string test_file_path = GetTestFilePath("t3.xls");
LibxlsSapiSandbox sandbox(test_file_path);
SAPI_ASSERT_OK(sandbox.Init());
SAPI_ASSERT_OK_AND_ASSIGN(LibXlsWorkbook wb,
LibXlsWorkbook::Open(&sandbox, test_file_path));
SAPI_ASSERT_OK_AND_ASSIGN(LibXlsSheet sheet, wb.OpenSheet(0));
SAPI_ASSERT_OK_AND_ASSIGN(LibXlsCell cell, sheet.GetCell(0, 0));
ASSERT_EQ(cell.type, XLS_RECORD_STRING);
ASSERT_EQ(std::get<std::string>(cell.value), "10.000000");
}
} // namespace

View File

@ -0,0 +1,162 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "contrib/libxls/utils/utils_libxls.h"
#include <fstream>
#include <iostream>
#include <string>
#include "contrib/libxls/sandboxed.h"
absl::Status GetError(LibxlsApi* api, xls_error_t error_code) {
SAPI_ASSIGN_OR_RETURN(const char* c_errstr, api->xls_getError(error_code));
sapi::v::RemotePtr sapi_errstr(const_cast<char*>(c_errstr));
SAPI_ASSIGN_OR_RETURN(std::string errstr,
api->GetSandbox()->GetCString(sapi_errstr));
return absl::UnavailableError(errstr);
}
absl::StatusOr<LibXlsWorkbook> LibXlsWorkbook::Open(LibxlsSapiSandbox* sandbox,
const std::string& filename,
const std::string& encode) {
if (sandbox == nullptr) {
return absl::InvalidArgumentError("Sandbox has to be defined");
}
LibxlsApi api(sandbox);
sapi::v::IntBase<xls_error_t> sapi_error;
sapi::v::CStr sapi_filename(filename.c_str());
sapi::v::CStr sapi_encode(encode.c_str());
SAPI_ASSIGN_OR_RETURN(
xlsWorkBook * wb,
api.xls_open_file(sapi_filename.PtrBefore(), sapi_encode.PtrBefore(),
sapi_error.PtrAfter()));
if (wb == nullptr) {
return GetError(&api, sapi_error.GetValue());
}
sapi::v::Struct<xlsWorkBook> sapi_wb;
sapi_wb.SetRemote(wb);
SAPI_RETURN_IF_ERROR(sandbox->TransferFromSandboxee(&sapi_wb));
return LibXlsWorkbook(sandbox, wb, sapi_wb.data().sheets.count);
}
LibXlsWorkbook::~LibXlsWorkbook() {
if (rwb_ != nullptr) {
sapi::v::RemotePtr sapi_rwb(rwb_);
LibxlsApi api(sandbox_);
api.xls_close_WB(&sapi_rwb).IgnoreError();
}
}
size_t LibXlsWorkbook::GetSheetCount() { return sheet_count_; }
absl::StatusOr<LibXlsSheet> LibXlsWorkbook::OpenSheet(uint32_t index) {
if (GetSheetCount() <= index) {
return absl::OutOfRangeError("Index out of range");
}
LibxlsApi api(sandbox_);
sapi::v::RemotePtr sapi_rwb(rwb_);
SAPI_ASSIGN_OR_RETURN(xlsWorkSheet * ws,
api.xls_getWorkSheet(&sapi_rwb, index));
if (ws == nullptr) {
return absl::UnavailableError("Unable to open sheet");
}
sapi::v::Struct<xlsWorkSheet> sapi_ws;
sapi_ws.SetRemote(ws);
SAPI_ASSIGN_OR_RETURN(xls_error_t error_code,
api.xls_parseWorkSheet(sapi_ws.PtrAfter()));
if (error_code != 0) {
return GetError(&api, error_code);
}
return LibXlsSheet(sandbox_, ws, sapi_ws.data().rows.lastrow + 1,
sapi_ws.data().rows.lastcol + 1);
}
size_t LibXlsSheet::GetRowCount() const { return row_; }
size_t LibXlsSheet::GetColCount() const { return col_; }
absl::StatusOr<std::string> LibXlsSheet::GetStr(
const sapi::v::Struct<xlsCell>& sapi_cell) {
if (sapi_cell.data().str == nullptr) {
return "";
}
sapi::v::RemotePtr sapi_str(sapi_cell.data().str);
return sandbox_->GetCString(sapi_str);
}
absl::StatusOr<LibXlsCell> LibXlsSheet::GetNewCell(
const sapi::v::Struct<xlsCell>& sapi_cell) {
int id = sapi_cell.data().id;
double d = sapi_cell.data().d;
switch (id) {
case XLS_RECORD_RK:
case XLS_RECORD_MULRK:
case XLS_RECORD_NUMBER:
return LibXlsCell{XLS_RECORD_NUMBER, d};
case XLS_RECORD_BLANK:
return LibXlsCell{XLS_RECORD_BLANK, 0.0};
case XLS_RECORD_FORMULA:
SAPI_ASSIGN_OR_RETURN(std::string cell_str, GetStr(sapi_cell));
if (cell_str == "bool") {
return LibXlsCell{XLS_RECORD_BOOL, d > 0};
} else if (cell_str == "error") {
return LibXlsCell{XLS_RECORD_ERROR, cell_str};
}
return LibXlsCell{XLS_RECORD_STRING, cell_str};
}
return absl::UnavailableError("Unknown type");
}
absl::StatusOr<LibXlsCell> LibXlsSheet::GetCell(uint32_t row, uint32_t col) {
if (row >= GetRowCount()) {
return absl::OutOfRangeError("Row out of range");
}
if (col >= GetColCount()) {
return absl::OutOfRangeError("Col out of range");
}
LibxlsApi api(sandbox_);
sapi::v::RemotePtr sapi_rws(rws_);
SAPI_ASSIGN_OR_RETURN(xlsCell * cell, api.xls_cell(&sapi_rws, row, col));
if (cell == nullptr) {
return absl::UnavailableError("Unable to get cell");
}
sapi::v::Struct<xlsCell> sapi_cell;
sapi_cell.SetRemote(cell);
SAPI_RETURN_IF_ERROR(sandbox_->TransferFromSandboxee(&sapi_cell));
return GetNewCell(sapi_cell);
}
LibXlsSheet::~LibXlsSheet() {
if (rws_ != nullptr) {
LibxlsApi api(sandbox_);
sapi::v::RemotePtr sapi_rws(rws_);
api.xls_close_WS(&sapi_rws).IgnoreError();
}
}

View File

@ -0,0 +1,110 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CONTRIB_LIBXLS_UTILS_UTILS_LIBXLS_H_
#define CONTRIB_LIBXLS_UTILS_UTILS_LIBXLS_H_
#include <fcntl.h>
#include "contrib/libxls/sandboxed.h"
#define XLS_RECORD_FORMULA 0x0006
#define XLS_RECORD_MULRK 0x00BD
#define XLS_RECORD_BLANK 0x0201
#define XLS_RECORD_NUMBER 0x0203
#define XLS_RECORD_STRING 0x0207
#define XLS_RECORD_RK 0x027E
#define XLS_RECORD_BOOL 0x9998
#define XLS_RECORD_ERROR 0x9999
struct LibXlsCell {
int type;
std::variant<double, bool, std::string> value;
};
class LibXlsSheet {
public:
size_t GetRowCount() const;
size_t GetColCount() const;
absl::StatusOr<LibXlsCell> GetCell(uint32_t row, uint32_t col);
~LibXlsSheet();
LibXlsSheet(LibXlsSheet&& other) { *this = std::move(other); }
LibXlsSheet& operator=(LibXlsSheet&& other) {
using std::swap;
if (this != &other) {
swap(sandbox_, other.sandbox_);
swap(rws_, other.rws_);
swap(row_, other.row_);
swap(col_, other.col_);
}
return *this;
}
private:
friend class LibXlsWorkbook;
LibXlsSheet(LibxlsSapiSandbox* sandbox, xlsWorkSheet* rws, size_t row,
size_t col)
: sandbox_(CHECK_NOTNULL(sandbox)), rws_(rws), row_(row), col_(col) {}
absl::StatusOr<std::string> GetStr(const sapi::v::Struct<xlsCell>& sapi_cell);
absl::StatusOr<LibXlsCell> GetNewCell(
const sapi::v::Struct<xlsCell>& sapi_cell);
LibxlsSapiSandbox* sandbox_;
xlsWorkSheet* rws_ = nullptr;
size_t row_;
size_t col_;
};
class LibXlsWorkbook {
public:
static absl::StatusOr<LibXlsWorkbook> Open(
LibxlsSapiSandbox* sandbox, const std::string& filename,
const std::string& encode = "UTF-8");
size_t GetSheetCount();
absl::StatusOr<LibXlsSheet> OpenSheet(uint32_t index);
~LibXlsWorkbook();
LibXlsWorkbook(LibXlsWorkbook&& other) { *this = std::move(other); }
LibXlsWorkbook& operator=(LibXlsWorkbook&& other) {
using std::swap;
if (this != &other) {
swap(sandbox_, other.sandbox_);
swap(rwb_, other.rwb_);
swap(sheet_count_, other.sheet_count_);
}
return *this;
}
private:
LibXlsWorkbook(LibxlsSapiSandbox* sandbox, xlsWorkBook* rwb, size_t count)
: sandbox_(CHECK_NOTNULL(sandbox)),
rwb_(CHECK_NOTNULL(rwb)),
sheet_count_(count) {}
LibxlsSapiSandbox* sandbox_;
xlsWorkBook* rwb_ = nullptr;
size_t sheet_count_;
};
#endif // CONTRIB_LIBXLS_UTILS_UTILS_LIBXLS_H_

View File

@ -0,0 +1,27 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CONTRIB_LIBXLS_XLS_GEN_H_
#define CONTRIB_LIBXLS_XLS_GEN_H_
// Workaround for libclang based interface generator
#define FILE void
#undef __cplusplus
extern "C" {
#include "${libxls_SOURCE_DIR}/include/xls.h"
}
#define __cplusplus
#undef FILE
#endif // CONTRIB_LIBXLS_XLS_GEN_H_