blob: 1f9c75acb0af2e620375225bf8a00bfb4f90a550 [file]
// Copyright 2017 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
//
// http://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 RIEGELI_CHUNK_ENCODING_TRANSPOSE_DECODER_H_
#define RIEGELI_CHUNK_ENCODING_TRANSPOSE_DECODER_H_
#include <stddef.h>
#include <stdint.h>
#include <optional>
#include <utility>
#include <vector>
#include "absl/base/attributes.h"
#include "absl/container/fixed_array.h"
#include "absl/types/span.h"
#include "riegeli/base/object.h"
#include "riegeli/base/recycling_pool.h"
#include "riegeli/bytes/backward_writer.h"
#include "riegeli/bytes/reader.h"
#include "riegeli/chunk_encoding/field_projection.h"
namespace riegeli {
class TransposeDecoder : public Object {
public:
class Options {
public:
Options() noexcept {}
Options(const Options& that) = default;
Options& operator=(const Options& that) = default;
// Options for a global `RecyclingPool` of decompression contexts.
//
// They tune the amount of memory which is kept to speed up creation of new
// decompression sessions, and usage of a background thread to clean it.
//
// Default: `RecyclingPoolOptions()`.
Options& set_recycling_pool_options(
RecyclingPoolOptions recycling_pool_options) &
ABSL_ATTRIBUTE_LIFETIME_BOUND {
recycling_pool_options_ = recycling_pool_options;
return *this;
}
Options&& set_recycling_pool_options(
RecyclingPoolOptions recycling_pool_options) &&
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return std::move(set_recycling_pool_options(recycling_pool_options));
}
const RecyclingPoolOptions& recycling_pool_options() const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return recycling_pool_options_;
}
private:
RecyclingPoolOptions recycling_pool_options_;
};
// Creates a closed `TransposeDecoder`.
explicit TransposeDecoder(Options options = Options())
: Object(kClosed),
recycling_pool_options_(options.recycling_pool_options()) {}
TransposeDecoder(const TransposeDecoder&) = delete;
TransposeDecoder& operator=(const TransposeDecoder&) = delete;
// Resets the `TransposeDecoder` and parses the chunk.
//
// Writes concatenated record values to `dest`. Sets `limits` to sorted
// record end positions.
//
// Precondition: `dest.pos() == 0`
//
// Return values:
// * `true` - success (`ok()`)
// * `false` - failure (`!ok()`);
// if `!dest.ok()` then the problem was at `dest`
bool Decode(uint64_t num_records, uint64_t decoded_data_size,
const FieldProjection& field_projection, Reader& src,
BackwardWriter& dest, std::vector<size_t>& limits);
private:
struct StateMachineNode;
struct Context;
struct DecodingState;
bool Parse(Context& context, Reader& src,
const FieldProjection& field_projection);
// Parse data buffers in `header_reader` and `src` into `context.buffers`.
// This method is used when projection is disabled and all buffers are
// initially decompressed.
bool ParseBuffers(Context& context, Reader& header_reader, Reader& src);
// Parse data buffers in `header_reader` and `src` into `context.buckets`.
// When projection is enabled, buckets are decompressed on demand.
// `bucket_indices` contains bucket index for each buffer.
// `first_buffer_indices` contains the index of first buffer for each bucket.
bool ParseBuffersForFiltering(
Context& context, Reader& header_reader, Reader& src,
std::optional<absl::FixedArray<uint32_t>>& first_buffer_indices,
std::optional<absl::FixedArray<uint32_t>>& bucket_indices);
// Precondition: `projection_enabled`.
Reader* GetBuffer(Context& context, uint32_t bucket_index,
uint32_t index_within_bucket);
static bool ContainsImplicitLoop(
std::vector<StateMachineNode>* state_machine_nodes);
bool Decode(Context& context, uint64_t num_records, BackwardWriter& dest,
std::vector<size_t>& limits);
// Set `callback_type` in `node` based on `skipped_submessage_level`,
// `submessage_stack`, and `node.node_template`.
bool SetCallbackType(
Context& context, int skipped_submessage_level,
absl::Span<const StateMachineNode* const> submessage_stack,
StateMachineNode& node);
RecyclingPoolOptions recycling_pool_options_;
};
} // namespace riegeli
#endif // RIEGELI_CHUNK_ENCODING_TRANSPOSE_DECODER_H_