summaryrefslogtreecommitdiff
path: root/src/database/file_gatherer.cpp
blob: dde363bd73424c5aa92afb9524b24596ce6021b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/*
 * Copyright 2023 jacqueline <me@jacqueline.id.au>
 *
 * SPDX-License-Identifier: GPL-3.0-only
 */

#include "file_gatherer.hpp"

#include <deque>
#include <functional>
#include <sstream>
#include <string>

#include "ff.h"

#include "memory_resource.hpp"
#include "spi.hpp"

namespace database {

static_assert(sizeof(TCHAR) == sizeof(char), "TCHAR must be CHAR");

auto FileGathererImpl::FindFiles(
    const std::string& root,
    std::function<void(const std::string&, const FILINFO&)> cb) -> void {
  std::deque<std::string> to_explore;
  to_explore.push_back(root);

  while (!to_explore.empty()) {
    std::string next_path_str = to_explore.front();
    to_explore.pop_front();

    const TCHAR* next_path = static_cast<const TCHAR*>(next_path_str.c_str());

    FF_DIR dir;
    FRESULT res;
    {
      auto lock = drivers::acquire_spi();
      res = f_opendir(&dir, next_path);
    }
    if (res != FR_OK) {
      // TODO: log.
      continue;
    }

    for (;;) {
      FILINFO info;
      {
        auto lock = drivers::acquire_spi();
        res = f_readdir(&dir, &info);
      }
      if (res != FR_OK || info.fname[0] == 0) {
        // No more files in the directory.
        break;
      } else if (info.fattrib & (AM_HID | AM_SYS) || info.fname[0] == '.') {
        // System or hidden file. Ignore it and move on.
        continue;
      } else {
        std::string full_path;
        full_path += next_path_str;
        full_path += "/";
        full_path += info.fname;

        if (info.fattrib & AM_DIR) {
          // This is a directory. Add it to the explore queue.
          to_explore.push_back(full_path);
        } else {
          // This is a file! Let the callback know about it.
          // std::invoke(cb, full_path.str(), info);
          std::invoke(cb, full_path, info);
        }
      }
    }

    auto lock = drivers::acquire_spi();
    f_closedir(&dir);
  }
}

}  // namespace database