feat(cpp/core): añadir file_poll_diff pure
This commit is contained in:
@@ -17,9 +17,10 @@ add_imgui_app(primitives_gallery
|
|||||||
${CMAKE_SOURCE_DIR}/functions/core/timeline.cpp
|
${CMAKE_SOURCE_DIR}/functions/core/timeline.cpp
|
||||||
demos_sql.cpp
|
demos_sql.cpp
|
||||||
demos_scientific.cpp
|
demos_scientific.cpp
|
||||||
# text_editor + file_watcher (issue 0025)
|
# text_editor + file_watcher (issue 0025) + file_poll_diff pure (issue 0045)
|
||||||
${CMAKE_SOURCE_DIR}/functions/core/text_editor.cpp
|
${CMAKE_SOURCE_DIR}/functions/core/text_editor.cpp
|
||||||
${CMAKE_SOURCE_DIR}/functions/core/file_watcher.cpp
|
${CMAKE_SOURCE_DIR}/functions/core/file_watcher.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/functions/core/file_poll_diff.cpp
|
||||||
${CMAKE_SOURCE_DIR}/vendor/imgui_text_edit/TextEditor.cpp
|
${CMAKE_SOURCE_DIR}/vendor/imgui_text_edit/TextEditor.cpp
|
||||||
# sql_workbench (issue 0032) + sql_parse pure (issue 0045)
|
# sql_workbench (issue 0032) + sql_parse pure (issue 0045)
|
||||||
${CMAKE_SOURCE_DIR}/functions/core/sql_workbench.cpp
|
${CMAKE_SOURCE_DIR}/functions/core/sql_workbench.cpp
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ add_imgui_app(text_editor_smoke
|
|||||||
main.cpp
|
main.cpp
|
||||||
${CMAKE_SOURCE_DIR}/functions/core/text_editor.cpp
|
${CMAKE_SOURCE_DIR}/functions/core/text_editor.cpp
|
||||||
${CMAKE_SOURCE_DIR}/functions/core/file_watcher.cpp
|
${CMAKE_SOURCE_DIR}/functions/core/file_watcher.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/functions/core/file_poll_diff.cpp
|
||||||
${CMAKE_SOURCE_DIR}/vendor/imgui_text_edit/TextEditor.cpp
|
${CMAKE_SOURCE_DIR}/vendor/imgui_text_edit/TextEditor.cpp
|
||||||
)
|
)
|
||||||
target_include_directories(text_editor_smoke PRIVATE
|
target_include_directories(text_editor_smoke PRIVATE
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
#include "core/file_poll_diff.h"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
namespace fn_ui {
|
||||||
|
|
||||||
|
FileDiff file_poll_diff(const std::vector<FileEntry>& before,
|
||||||
|
const std::vector<FileEntry>& after) {
|
||||||
|
FileDiff out;
|
||||||
|
|
||||||
|
// Index before by path para lookup O(1).
|
||||||
|
std::unordered_map<std::string, const FileEntry*> idx_before;
|
||||||
|
idx_before.reserve(before.size());
|
||||||
|
for (const auto& e : before) {
|
||||||
|
idx_before[e.path] = &e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recorrer after: clasificar added/modified.
|
||||||
|
std::unordered_set<std::string> seen_in_after;
|
||||||
|
seen_in_after.reserve(after.size());
|
||||||
|
for (const auto& e : after) {
|
||||||
|
seen_in_after.insert(e.path);
|
||||||
|
auto it = idx_before.find(e.path);
|
||||||
|
if (it == idx_before.end()) {
|
||||||
|
out.added.push_back(e.path);
|
||||||
|
} else {
|
||||||
|
const FileEntry* prev = it->second;
|
||||||
|
if (prev->size != e.size || prev->mtime != e.mtime) {
|
||||||
|
out.modified.push_back(e.path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recorrer before: detectar removed (paths que no estan en after).
|
||||||
|
for (const auto& e : before) {
|
||||||
|
if (seen_in_after.find(e.path) == seen_in_after.end()) {
|
||||||
|
out.removed.push_back(e.path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace fn_ui
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// file_poll_diff — diff puro entre dos snapshots de filesystem.
|
||||||
|
//
|
||||||
|
// Pareja natural de file_watcher: en plataformas sin inotify/RDCW (o cuando
|
||||||
|
// se quiere fallback portable), el caller toma snapshots periodicos via
|
||||||
|
// stat()/opendir() y los compara con esta funcion para emitir eventos
|
||||||
|
// added/modified/removed. Sin I/O, sin estado.
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace fn_ui {
|
||||||
|
|
||||||
|
struct FileEntry {
|
||||||
|
std::string path;
|
||||||
|
uint64_t size = 0;
|
||||||
|
int64_t mtime = 0; // unix seconds
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FileDiff {
|
||||||
|
std::vector<std::string> added;
|
||||||
|
std::vector<std::string> modified; // size o mtime distinto
|
||||||
|
std::vector<std::string> removed;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Pura: calcula diff entre dos snapshots por path. Asume entries con paths
|
||||||
|
// unicos en cada snapshot. Orden de los vectores: el orden en que aparecen
|
||||||
|
// los paths en `after` (added/modified) y en `before` (removed).
|
||||||
|
FileDiff file_poll_diff(const std::vector<FileEntry>& before,
|
||||||
|
const std::vector<FileEntry>& after);
|
||||||
|
|
||||||
|
} // namespace fn_ui
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
---
|
||||||
|
name: file_poll_diff
|
||||||
|
kind: function
|
||||||
|
lang: cpp
|
||||||
|
domain: core
|
||||||
|
version: "1.0.0"
|
||||||
|
purity: pure
|
||||||
|
signature: "fn_ui::FileDiff fn_ui::file_poll_diff(const std::vector<fn_ui::FileEntry>& before, const std::vector<fn_ui::FileEntry>& after)"
|
||||||
|
description: "Diff puro entre dos snapshots de filesystem (path/size/mtime). Devuelve vectores added/modified/removed. Sin I/O. Pareja del file_watcher para fallback portable basado en polling."
|
||||||
|
tags: [filesystem, diff, poll, snapshot, pure]
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
returns: []
|
||||||
|
returns_optional: false
|
||||||
|
error_type: ""
|
||||||
|
imports: []
|
||||||
|
tested: true
|
||||||
|
tests: ["file_poll_diff detects added/modified/removed", "file_poll_diff: empty inputs", "file_poll_diff: identical snapshots"]
|
||||||
|
test_file_path: "cpp/tests/test_file_poll_diff.cpp"
|
||||||
|
file_path: "cpp/functions/core/file_poll_diff.cpp"
|
||||||
|
params:
|
||||||
|
- name: before
|
||||||
|
desc: "Snapshot anterior. Vector de FileEntry {path, size, mtime}, paths unicos"
|
||||||
|
- name: after
|
||||||
|
desc: "Snapshot actual. Mismo formato. Paths unicos"
|
||||||
|
output: "FileDiff con tres vectores de paths: added (en after y no en before), modified (path comun pero size o mtime distinto), removed (en before y no en after)."
|
||||||
|
---
|
||||||
|
|
||||||
|
# file_poll_diff
|
||||||
|
|
||||||
|
Logica pura para calcular cambios de filesystem entre dos snapshots. Sin
|
||||||
|
I/O, sin estado: el caller hace `stat()`/`opendir()` por su lado, construye
|
||||||
|
los `FileEntry`, y esta funcion los compara.
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace fn_ui {
|
||||||
|
|
||||||
|
struct FileEntry {
|
||||||
|
std::string path;
|
||||||
|
uint64_t size = 0;
|
||||||
|
int64_t mtime = 0; // unix seconds
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FileDiff {
|
||||||
|
std::vector<std::string> added;
|
||||||
|
std::vector<std::string> modified;
|
||||||
|
std::vector<std::string> removed;
|
||||||
|
};
|
||||||
|
|
||||||
|
FileDiff file_poll_diff(const std::vector<FileEntry>& before,
|
||||||
|
const std::vector<FileEntry>& after);
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Reglas
|
||||||
|
|
||||||
|
- Comparacion por `path` exacto.
|
||||||
|
- "Modified": al menos uno de `size` o `mtime` cambia.
|
||||||
|
- Asume paths unicos por snapshot (la funcion no deduplica).
|
||||||
|
- Complejidad: O(N+M) con un `unordered_map<string, const FileEntry*>` para
|
||||||
|
indexar `before`.
|
||||||
|
|
||||||
|
## Cuando usar
|
||||||
|
|
||||||
|
- En plataformas donde `file_watcher` no tiene backend nativo (stub) y se
|
||||||
|
necesita un fallback basado en polling.
|
||||||
|
- Para consolidar bursts de eventos: tomar dos snapshots en el tiempo y
|
||||||
|
reportar solo el cambio neto (sin los intermedios).
|
||||||
|
- Tests del watcher: simular cambios de FS sin tocar disco.
|
||||||
|
|
||||||
|
## Por que pura
|
||||||
|
|
||||||
|
No abre archivos, no llama `stat`, no usa el reloj. Misma entrada produce la
|
||||||
|
misma salida — testeable sin fixtures de FS.
|
||||||
Reference in New Issue
Block a user