text: // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file. See the AUTHORS file for names of contributors.
  
  #ifndef STORAGE_LEVELDB_TABLE_FORMAT_H_
  #define STORAGE_LEVELDB_TABLE_FORMAT_H_
  
  #include <string>
  #include <stdint.h>
  #include "leveldb/slice.h"
  #include "leveldb/status.h"
  #include "leveldb/table_builder.h"
  
  namespace leveldb {
  
  class Block;
  class RandomAccessFile;
  struct ReadOptions;
  
  // BlockHandle is a pointer to the extent of a file that stores a data
  // block or a meta block.
  class BlockHandle {
  public:
      BlockHandle();
  
      // The offset of the block in the file.
      uint64_t offset() const {
          return offset_;
      }
      void set_offset(uint64_t offset) {
          offset_ = offset;
      }
  
      // The size of the stored block
      uint64_t size() const {
          return size_;
      }
      void set_size(uint64_t size) {
          size_ = size;
      }
  
      void EncodeTo(std::string* dst) const;
      Status DecodeFrom(Slice* input);
  
      // Maximum encoding length of a BlockHandle
      enum { kMaxEncodedLength = 10 + 10 };
  
  private:
      uint64_t offset_;
      uint64_t size_;
  };
  
  // Footer encapsulates the fixed information stored at the tail
  // end of every table file.
  class Footer {
  public:
      Footer() { }
  
      // The block handle for the metaindex block of the table
      const BlockHandle& metaindex_handle() const {
          return metaindex_handle_;
      }
      void set_metaindex_handle(const BlockHandle& h) {
          metaindex_handle_ = h;
      }
  
      // The block handle for the index block of the table
      const BlockHandle& index_handle() const {
          return index_handle_;
      }
      void set_index_handle(const BlockHandle& h) {
          index_handle_ = h;
      }
  
      void EncodeTo(std::string* dst) const;
      Status DecodeFrom(Slice* input);
  
      // Encoded length of a Footer.  Note that the serialization of a
      // Footer will always occupy exactly this many bytes.  It consists
      // of two block handles and a magic number.
      enum {
          kEncodedLength = 2*BlockHandle::kMaxEncodedLength + 8
      };
  
  private:
      BlockHandle metaindex_handle_;
      BlockHandle index_handle_;
  };
  
  // kTableMagicNumber was picked by running
  //    echo http://code.google.com/p/leveldb/ | sha1sum
  // and taking the leading 64 bits.
  static const uint64_t kTableMagicNumber = 0xdb4775248b80fb57ull;
  
  // 1-byte type + 32-bit crc
  static const size_t kBlockTrailerSize = 5;
  
  struct BlockContents {
      Slice data;           // Actual contents of data
      bool cachable;        // True iff data can be cached
      bool heap_allocated;  // True iff caller should delete[] data.data()
  };
  
  // Read the block identified by "handle" from "file".  On failure
  // return non-OK.  On success fill *result and return OK.
  extern Status ReadBlock(RandomAccessFile* file,
                          const ReadOptions& options,
                          const BlockHandle& handle,
                          BlockContents* result);
  
  // Implementation details follow.  Clients should ignore,
  
  inline BlockHandle::BlockHandle()
      : offset_(~static_cast<uint64_t>(0)),
        size_(~static_cast<uint64_t>(0)) {
  }
  
  }  // namespace leveldb
  
  #endif  // STORAGE_LEVELDB_TABLE_FORMAT_H_
  