Repository: tesseract-ocr/tesseract
File: src/ccstruct/imagedata.cpp (C++)

Code before:
  random.set_seed(document_name_.c_str());
  int num_pages = pages_.size();
  // Execute one random swap for each page in the document.
  for (int i = 0; i < num_pages; ++i) {
    int src = random.IntRand() % num_pages;
    int dest = random.IntRand() % num_pages;
    std::swap(pages_[src], pages_[dest]);
  }
}

// Locks the pages_mutex_ and loads as many pages as will fit into max_memory_
// starting at index pages_offset_.
bool DocumentData::ReCachePages() {
  std::lock_guard<std::mutex> lock(pages_mutex_);
  // Read the file.
  set_total_pages(0);
  set_memory_used(0);
  int loaded_pages = 0;
  for (auto page : pages_) {
    delete page;
  }
  pages_.clear();
  TFile fp;
  if (!fp.Open(document_name_.c_str(), reader_) ||
      !fp.DeSerializeSize(&loaded_pages) || loaded_pages <= 0) {
    tprintf("Deserialize header failed: %s\n", document_name_.c_str());
    return false;
  }
  pages_offset_ %= loaded_pages;
  // Skip pages before the first one we want, and load the rest until max
  // memory and skip the rest after that.
  int page;
  for (page = 0; page < loaded_pages; ++page) {
    uint8_t non_null;
    if (!fp.DeSerialize(&non_null)) {
      break;
    }
    if (page < pages_offset_ ||
        (max_memory_ > 0 && memory_used() > max_memory_)) {
      if (non_null && !ImageData::SkipDeSerialize(&fp)) {
        break;
      }
    } else {
      ImageData *image_data = nullptr;
      if (non_null) {
        image_data = new ImageData;
        if (!image_data->DeSerialize(&fp)) {
          delete image_data;
          break;
        }
      }

Review comment (refactor):
Why not use [to use std::filesystem::path](https://en.cppreference.com/w/cpp/filesystem/path/extension) as in https://github.com/tesseract-ocr/tesseract/blob/b217cfcfa3b5c41e20414428e5d4700af130b192/src/training/unicharset_extractor.cpp#L74

Code after:
  // name.
  random.set_seed(document_name_.c_str());
  int num_pages = pages_.size();
  // Execute one random swap for each page in the document.
  for (int i = 0; i < num_pages; ++i) {
    int src = random.IntRand() % num_pages;
    int dest = random.IntRand() % num_pages;
    std::swap(pages_[src], pages_[dest]);
  }
}

// Locks the pages_mutex_ and loads as many pages as will fit into max_memory_
// starting at index pages_offset_.
bool DocumentData::ReCachePages() {
  std::lock_guard<std::mutex> lock(pages_mutex_);
  // Read the file.
  set_total_pages(0);
  set_memory_used(0);
  int loaded_pages = 0;
  for (auto page : pages_) {
    delete page;
  }
  pages_.clear();
#if !defined(TESSERACT_IMAGEDATA_AS_PIX)
  auto name_size = document_name_.size();
  if (name_size > 4 && document_name_.substr(name_size - 4) == ".png") {
    // PNG image given instead of LSTMF file.
    std::string gt_name = document_name_.substr(0, name_size - 3) + "gt.txt";
    std::ifstream t(gt_name);
    std::string line;
    std::getline(t, line);
    t.close();
    ImageData *image_data = ImageData::Build(document_name_.c_str(), 0, "", nullptr, 0, line.c_str(), nullptr);
    Image image = pixRead(document_name_.c_str());
    image_data->SetPix(image);
    pages_.push_back(image_data);
    loaded_pages = 1;
    pages_offset_ %= loaded_pages;
    set_total_pages(loaded_pages);
    set_memory_used(memory_used() + image_data->MemoryUsed());
#if 0
    tprintf("Loaded %zu/%d lines (%d-%zu) of document %s\n", pages_.size(),
            loaded_pages, pages_offset_ + 1, pages_offset_ + pages_.size(),
            document_name_.c_str());
#endif
    return !pages_.empty();
  }
#endif
  TFile fp;
  if (!fp.Open(document_name_.c_str(), reader_) ||
      !fp.DeSerializeSize(&loaded_pages) || loaded_pages <= 0) {