Skip to content

Commit

Permalink
libmbsparse: Refactor to use new mb::File classes
Browse files Browse the repository at this point in the history
Signed-off-by: Andrew Gunnerson <[email protected]>
  • Loading branch information
Andrew Gunnerson committed Jul 15, 2017
1 parent 29b8af4 commit 5345fc7
Show file tree
Hide file tree
Showing 12 changed files with 1,805 additions and 1,313 deletions.
2 changes: 1 addition & 1 deletion Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,7 @@ WARN_LOGFILE =
# spaces.
# Note: If this tag is empty the current directory is searched.

INPUT = libmbcommon libmbbootimg
INPUT = libmbcommon libmbbootimg libmbsparse

# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
Expand Down
126 changes: 38 additions & 88 deletions examples/desparse.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Andrew Gunnerson <[email protected]>
* Copyright (C) 2016-2017 Andrew Gunnerson <[email protected]>
*
* This file is part of DualBootPatcher
*
Expand All @@ -26,121 +26,71 @@
#include "mbcommon/file/standard.h"
#include "mbsparse/sparse.h"

typedef std::unique_ptr<SparseCtx, bool (*)(SparseCtx *)> ScopedSparseCtx;

struct Context
{
std::string path;
mb::StandardFile file;
};

bool cbOpen(void *userData)
{
Context *ctx = static_cast<Context *>(userData);
if (ctx->file.open(ctx->path, mb::FileOpenMode::READ_ONLY)
!= mb::FileStatus::OK) {
fprintf(stderr, "%s: Failed to open: %s\n",
ctx->path.c_str(), ctx->file.error_string().c_str());
return false;
}
return true;
}

bool cbClose(void *userData)
{
Context *ctx = static_cast<Context *>(userData);
if (ctx->file.close() != mb::FileStatus::OK) {
fprintf(stderr, "%s: Failed to close: %s\n",
ctx->path.c_str(), ctx->file.error_string().c_str());
return false;
}
return true;
}

bool cbRead(void *buf, uint64_t size, uint64_t *bytesRead, void *userData)
{
Context *ctx = static_cast<Context *>(userData);
size_t total = 0;
while (size > 0) {
size_t partial;
if (ctx->file.read(buf, size, &partial) != mb::FileStatus::OK) {
fprintf(stderr, "%s: Failed to read: %s\n",
ctx->path.c_str(), ctx->file.error_string().c_str());
return false;
}
size -= partial;
total += partial;
buf = static_cast<char *>(buf) + partial;
}
*bytesRead = total;
return true;
}

bool cbSeek(int64_t offset, int whence, void *userData)
{
Context *ctx = static_cast<Context *>(userData);
if (ctx->file.seek(offset, whence, nullptr) != mb::FileStatus::OK) {
fprintf(stderr, "%s: Failed to seek: %s\n",
ctx->path.c_str(), ctx->file.error_string().c_str());
return false;
}
return true;
}

int main(int argc, char *argv[])
{
if (argc != 3) {
std::fprintf(stderr, "Usage: %s <input file> <output file>\n", argv[0]);
return EXIT_FAILURE;
}

const char *inputFile = argv[1];
const char *outputFile = argv[2];
const char *input_path = argv[1];
const char *output_path = argv[2];

Context ctx;
ctx.path = inputFile;
mb::StandardFile input_file;
mb::StandardFile output_file;
mb::sparse::SparseFile sparse_file;

ScopedSparseCtx sparseCtx(sparseCtxNew(), &sparseCtxFree);
if (!sparseCtx) {
fprintf(stderr, "Out of memory\n");
if (input_file.open(input_path, mb::FileOpenMode::READ_ONLY)
!= mb::FileStatus::OK) {
fprintf(stderr, "%s: Failed to open for reading: %s\n",
input_path, input_file.error_string().c_str());
return EXIT_FAILURE;
}

if (!sparseOpen(sparseCtx.get(), &cbOpen, &cbClose, &cbRead, &cbSeek,
nullptr, &ctx)) {
if (sparse_file.open(&input_file) != mb::FileStatus::OK) {
fprintf(stderr, "%s: %s\n",
input_path, sparse_file.error_string().c_str());
return EXIT_FAILURE;
}

mb::StandardFile file;

if (file.open(outputFile, mb::FileOpenMode::WRITE_ONLY)
if (output_file.open(output_path, mb::FileOpenMode::WRITE_ONLY)
!= mb::FileStatus::OK) {
fprintf(stderr, "%s: Failed to open for writing: %s\n",
outputFile, file.error_string().c_str());
output_path, output_file.error_string().c_str());
return EXIT_FAILURE;
}

uint64_t bytesRead;
size_t n_read;
char buf[10240];
bool ret;
while ((ret = sparseRead(sparseCtx.get(), buf, sizeof(buf), &bytesRead))
&& bytesRead > 0) {
mb::FileStatus ret;
while ((ret = sparse_file.read(buf, sizeof(buf), &n_read))
== mb::FileStatus::OK && n_read > 0) {
char *ptr = buf;
size_t bytesWritten;
while (bytesRead > 0) {
if (file.write(buf, bytesRead, &bytesWritten)
size_t n_written;

while (n_read > 0) {
if (output_file.write(buf, n_read, &n_written)
!= mb::FileStatus::OK) {
fprintf(stderr, "%s: Failed to write: %s\n",
outputFile, file.error_string().c_str());
fprintf(stderr, "%s: Failed to write file: %s\n",
output_path, output_file.error_string().c_str());
return EXIT_FAILURE;
}
bytesRead -= bytesWritten;
ptr += bytesWritten;
n_read -= n_written;
ptr += n_written;
}
}
if (!ret) {

if (ret != mb::FileStatus::OK) {
fprintf(stderr, "%s: Failed to read file: %s\n",
input_path, sparse_file.error_string().c_str());
return EXIT_FAILURE;
}

if (output_file.close() != mb::FileStatus::OK) {
fprintf(stderr, "%s: Failed to close file: %s\n",
output_path, output_file.error_string().c_str());
return EXIT_FAILURE;
}

return file.close() == mb::FileStatus::OK ? EXIT_SUCCESS : EXIT_FAILURE;
return EXIT_SUCCESS;
}
57 changes: 57 additions & 0 deletions libmbcommon/include/mbcommon/algorithm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (C) 2017 Andrew Gunnerson <[email protected]>
*
* This file is part of DualBootPatcher
*
* DualBootPatcher is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DualBootPatcher is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DualBootPatcher. If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include <algorithm>
#include <functional>

namespace mb
{

#if defined(__cpp_constexpr) && __cpp_constexpr-0 >= 201304

template<class ForwardIt, class T, class Compare=std::less<>>
ForwardIt binary_find(ForwardIt first, ForwardIt last, const T &value,
Compare comp={})
{
ForwardIt it = std::lower_bound(first, last, value, comp);
return (it != last && !bool(comp(value, *it))) ? it : last;
}

#else

template<class ForwardIt, class T>
ForwardIt binary_find(ForwardIt first, ForwardIt last, const T &value)
{
ForwardIt it = std::lower_bound(first, last, value);
return (it != last && !(value < *it)) ? it : last;
}

template<class ForwardIt, class T, class Compare>
ForwardIt binary_find(ForwardIt first, ForwardIt last, const T &value,
Compare comp)
{
ForwardIt it = std::lower_bound(first, last, value, comp);
return (it != last && !bool(comp(value, *it))) ? it : last;
}

#endif

}
2 changes: 2 additions & 0 deletions libmbsparse/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ set(MBSPARSE_TESTS_SOURCES
tests/test_sparse.cpp
)

add_definitions(-DMBSPARSE_BUILD)

set(variants)

if(MBP_TARGET_HAS_BUILDS)
Expand Down
24 changes: 24 additions & 0 deletions libmbsparse/include/mbsparse/guard_p.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright (C) 2017 Andrew Gunnerson <[email protected]>
*
* This file is part of DualBootPatcher
*
* DualBootPatcher is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DualBootPatcher is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DualBootPatcher. If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#ifndef MBSPARSE_BUILD
#error libmbsparse private headers cannot be used
#endif
85 changes: 45 additions & 40 deletions libmbsparse/include/mbsparse/sparse.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015-2016 Andrew Gunnerson <[email protected]>
* Copyright (C) 2015-2017 Andrew Gunnerson <[email protected]>
* Copyright (C) 2010 The Android Open Source Project
*
* This file is part of DualBootPatcher
Expand All @@ -20,43 +20,48 @@

#pragma once

#include "mbcommon/common.h"
#include "mbsparse/sparse_header.h"

#ifdef __cplusplus
#include <cstdio>
#else
#include <stdbool.h>
#include <stdio.h>
#endif

#ifdef __cplusplus
extern "C" {
#endif

typedef bool (*SparseOpenCb)(void *userData);
typedef bool (*SparseCloseCb)(void *userData);
typedef bool (*SparseReadCb)(void *buf, uint64_t size, uint64_t *bytesRead,
void *userData);
typedef bool (*SparseSeekCb)(int64_t offset, int whence, void *userData);
typedef bool (*SparseSkipCb)(uint64_t offset, void *userData);

struct SparseCtx;

MB_EXPORT struct SparseCtx * sparseCtxNew();
MB_EXPORT bool sparseCtxFree(struct SparseCtx *ctx);

MB_EXPORT bool sparseOpen(struct SparseCtx *ctx, SparseOpenCb openCb,
SparseCloseCb closeCb, SparseReadCb readCb,
SparseSeekCb seekCb, SparseSkipCb skipCb,
void *userData);
MB_EXPORT bool sparseClose(struct SparseCtx *ctx);
MB_EXPORT bool sparseRead(struct SparseCtx *ctx, void *buf, uint64_t size,
uint64_t *bytesRead);
MB_EXPORT bool sparseSeek(struct SparseCtx *ctx, int64_t offset, int whence);
MB_EXPORT bool sparseTell(struct SparseCtx *ctx, uint64_t *offset);
MB_EXPORT bool sparseSize(struct SparseCtx *ctx, uint64_t *size);

#ifdef __cplusplus
#include "mbcommon/file.h"

namespace mb
{
namespace sparse
{

class SparseFilePrivate;
class MB_EXPORT SparseFile : public File
{
MB_DECLARE_PRIVATE(SparseFile)

public:
SparseFile();
SparseFile(File *file);
virtual ~SparseFile();

MB_DISABLE_COPY_CONSTRUCT_AND_ASSIGN(SparseFile)
MB_DEFAULT_MOVE_CONSTRUCT_AND_ASSIGN(SparseFile)

// File open
FileStatus open(File *file);

// File size
uint64_t size();

protected:
/*! \cond INTERNAL */
SparseFile(SparseFilePrivate *priv);
SparseFile(SparseFilePrivate *priv, File *file);
/*! \endcond */

virtual FileStatus on_open() override;
virtual FileStatus on_close() override;
virtual FileStatus on_read(void *buf, size_t size,
size_t *bytes_read) override;
virtual FileStatus on_seek(int64_t offset, int whence,
uint64_t *new_offset) override;

private:
std::unique_ptr<SparseFilePrivate> _priv_ptr;
};

}
}
#endif
Loading

0 comments on commit 5345fc7

Please sign in to comment.