/*
* Copyright ©2026 Soham Pardeshi. All rights reserved.
* Permission is hereby granted to students registered for University of
* Washington CSE 333 for use solely during Summer Quarter 2026 for
* purposes of the course. No other use, copying, distribution, or
* modification is permitted without prior written consent. Copyrights
* for third-party components of this work must be honored. Instructors
* interested in reusing these course materials should contact the author.
*/
#ifndef HW3_LAYOUTSTRUCTS_H_
#define HW3_LAYOUTSTRUCTS_H_
#include <stdint.h>
#include <cstddef>
extern "C" {
#include "./libhw1/CSE333.h"
#include "./libhw2/MemIndex.h"
}
#include "./Utils.h"
// This header file defines the in-memory structs representing hw3 on-disk
// data structures. They are "dumb data carriers" that require no additional
// transformations; they can be written and read directly from disk. For
// that reason, the field ordering and each field's types must correspond
// exactly to the file format described in the HW3 spec.
// C/C++ will add padding to structures to place the individual
// fields on their natural byte alignment. That can lead to
// trouble: the file must be read using the same structures as
// were used to write it. Because that's so fragile, we
// turn off padding on the structures defined here:
#pragma pack(push, 1)
namespace hw3 {
//---------------------------------------------
// General types for encoded data on disk
//---------------------------------------------
// An offset within an index file.
typedef int32_t IndexFileOffset_t;
//---------------------------------------------
// Index file header
//---------------------------------------------
struct IndexFileHeader {
uint32_t magic_number; // the indicator of a well-formed header.
uint32_t checksum; // the checksum for the entire file.
int32_t doctable_bytes; // number of bytes in the contained doctable.
int32_t index_bytes; // number of bytes in the contained index.
IndexFileHeader() { } // this constructor yields uninitialized fields!
IndexFileHeader(uint32_t magic_number_arg,
uint32_t checksum_arg,
int32_t doctable_bytes_arg,
int32_t index_bytes_arg)
: magic_number(magic_number_arg),
checksum(checksum_arg),
doctable_bytes(doctable_bytes_arg),
index_bytes(index_bytes_arg) {
}
void ToDiskFormat() {
magic_number = htonl(magic_number);
checksum = htonl(checksum);
doctable_bytes = htonl(doctable_bytes);
index_bytes = htonl(index_bytes);
}
void ToHostFormat() {
magic_number = ntohl(magic_number);
checksum = ntohl(checksum);
doctable_bytes = ntohl(doctable_bytes);
index_bytes = ntohl(index_bytes);
}
};
// Offset of magic number within an IndexFileHeader struct, and also within
// the file itself.
#define MAGIC_NUMBER_OFFSET offsetof(IndexFileHeader, magic_number)
// Offset of the doctable size field within an IndexFileHeader struct
#define DT_BYTES_OFFSET offsetof(IndexFileHeader, doctable_bytes)
//---------------------------------------------
// Bucket lists
// (Used by doctable, index, and docID table)
//---------------------------------------------
struct BucketListHeader {
int32_t num_buckets; // number of buckets in the hash table
BucketListHeader() { } // this constructor doesn't initialize numBuckets!
explicit BucketListHeader(int32_t num_buckets_arg)
: num_buckets(num_buckets_arg) {
}
void ToDiskFormat() { num_buckets = htonl(num_buckets); }
void ToHostFormat() { num_buckets = ntohl(num_buckets); }
};
struct BucketRecord {
int32_t chain_num_elements; // number of elements in this
// bucket's chain.
IndexFileOffset_t position; // byte offset from the start of the
// index file, indicating where the
// bucket's chain begins.
BucketRecord() { } // this constructor doesn't initialize any fields!
BucketRecord(int32_t num_elts, IndexFileOffset_t pos)
: chain_num_elements(num_elts), position(pos) {
}
void ToDiskFormat() {
chain_num_elements = htonl(chain_num_elements);
position = htonl(position);
}
void ToHostFormat() {
chain_num_elements = ntohl(chain_num_elements);
position = ntohl(position);
}
};
struct ElementPositionRecord {
IndexFileOffset_t position; // byte offset from the start of the index file,
// indicating where the element begins.
ElementPositionRecord() { }
explicit ElementPositionRecord(IndexFileOffset_t pos)
: position(pos) {
}
void ToDiskFormat() { position = htonl(position); }
void ToHostFormat() { position = ntohl(position); }
};
//---------------------------------------------
// DocTable
//---------------------------------------------
struct DoctableElementHeader {
DocID_t doc_id;
int16_t file_name_bytes; // number of bytes needed to serialize the file
// name. note: 16-bit quantity!
DoctableElementHeader() { } // this constructor doesn't initialize any fields
DoctableElementHeader(DocID_t id, int32_t num_bytes)
: doc_id(id), file_name_bytes(num_bytes) {
}
void ToDiskFormat() {
doc_id = htonll(doc_id);
file_name_bytes = htons(file_name_bytes);
}
void ToHostFormat() {
doc_id = ntohll(doc_id);
file_name_bytes = ntohs(file_name_bytes);
}
};
//---------------------------------------------
// IndexTable
//
// Each element in the index is a WordPostings
// (see also HW2).
//---------------------------------------------
struct WordPostingsHeader {
int16_t word_bytes; // number of bytes needed to serialize the word.
int32_t postings_bytes; // number of bytes for the doctable.
WordPostingsHeader() { } // this constructor doesn't initialize any fields!
WordPostingsHeader(int16_t word_bytes_arg, int32_t postings_bytes_arg)
: word_bytes(word_bytes_arg), postings_bytes(postings_bytes_arg) { }
void ToDiskFormat() {
word_bytes = htons(word_bytes);
postings_bytes = htonl(postings_bytes);
}
void ToHostFormat() {
word_bytes = ntohs(word_bytes);
postings_bytes = ntohl(postings_bytes);
}
};
//---------------------------------------------
// DocIDTable
//---------------------------------------------
struct DocIDElementHeader {
DocID_t doc_id;
int32_t num_positions; // number of word positions stored in this element
DocIDElementHeader() { } // this constructor doesn't initialize any fields!
DocIDElementHeader(DocID_t id, int32_t num_pos)
: doc_id(id), num_positions(num_pos) { }
void ToDiskFormat() {
doc_id = htonll(doc_id);
num_positions = htonl(num_positions);
}
void ToHostFormat() {
doc_id = ntohll(doc_id);
num_positions = ntohl(num_positions);
}
};
struct DocIDElementPosition {
DocPositionOffset_t position; // byte offset into the document referenced by
// docID, indicating where the word occurs
DocIDElementPosition() { } // this constructor doesn't initialize any fields
explicit DocIDElementPosition(DocPositionOffset_t position_arg)
: position(position_arg) { }
void ToDiskFormat() { position = htonl(position); }
void ToHostFormat() { position = ntohl(position); }
};
} // namespace hw3
#pragma pack(pop)
#endif // HW3_LAYOUTSTRUCTS_H_