libmonaa  0.5.2
lazy_deque.hh
1 #pragma once
2 
3 #include <cassert>
4 #include <cstdio>
5 #include <deque>
6 #include <limits>
7 #include <stdexcept>
8 #include <utility>
9 
10 #include "common_types.hh"
11 
12 static inline int getOne(FILE *file, std::pair<Alphabet, double> &p) {
13  return fscanf(file, " %c %lf\n", &p.first, &p.second);
14 }
15 
16 static inline int getOneBinary(FILE *file, std::pair<Alphabet, double> &p) {
17  if (fread(&p.first, sizeof(char), 1, file)) {
18  if (fread(&p.second, sizeof(double), 1, file)) {
19  return sizeof(char) + sizeof(double);
20  }
21  }
22  return EOF;
23 }
24 
29 class LazyDeque : public std::deque<std::pair<Alphabet, double>> {
30 private:
31  std::size_t front = 0;
32  std::size_t N;
33  FILE *file;
34  int (*getElem)(FILE *, std::pair<Alphabet, double> &);
35 
36 public:
42  LazyDeque(FILE *file, bool isBinary = false)
43  : N(std::numeric_limits<std::size_t>::max()), file(file) {
44  assert(file != nullptr);
45  getElem = isBinary ? getOneBinary : getOne;
46  }
47  std::pair<Alphabet, double> operator[](std::size_t n) {
48  const std::size_t indInDeque = n - front;
49  if (n < front || n >= N ||
50  indInDeque >= std::deque<std::pair<Alphabet, double>>::size()) {
51  throw std::out_of_range("thrown at LazyDeque::operator[] ");
52  }
53  return std::deque<std::pair<Alphabet, double>>::at(indInDeque);
54  }
55  std::pair<Alphabet, double> at(std::size_t n) { return (*this)[n]; }
56  std::size_t size() const { return N; }
59  void setFront(std::size_t newFront) {
60  if (newFront < front) {
61  throw std::out_of_range("thrown at LazyDeque::setFront ");
62  }
63  const std::size_t eraseSize = std::min(
64  newFront - front, std::deque<std::pair<Alphabet, double>>::size());
65  const int readTimes = (newFront - front) - eraseSize;
66  front = newFront;
67  this->erase(this->begin(), this->begin() + eraseSize);
68  for (int i = 0; i < readTimes; i++) {
69  std::pair<Alphabet, double> elem;
70  getElem(file, elem);
71  }
72  }
73  bool fetch(std::size_t n) noexcept {
74  if (n < front || n >= N) {
75  return false;
76  }
77  const std::size_t indInDeque = n - front;
78  const int allocTimes =
79  indInDeque - std::deque<std::pair<Alphabet, double>>::size() + 1;
80  for (int i = 0; i < allocTimes; i++) {
81  std::pair<Alphabet, double> elem;
82  if (getElem(file, elem) == EOF) {
83  N = front + std::deque<std::pair<Alphabet, double>>::size();
84  return false;
85  }
86  this->push_back(elem);
87  }
88  return true;
89  }
90 };
A Wrapper of FILE Reading. This class is given to WordContainer class as its template argument.
Definition: lazy_deque.hh:29
void setFront(std::size_t newFront)
Update the internal front. The elements before the front are removed.
Definition: lazy_deque.hh:59
LazyDeque(FILE *file, bool isBinary=false)
Definition: lazy_deque.hh:42