| 293 | } |
| 294 | |
| 295 | std::vector<DocumentChunk> DocumentProcessor::process_file(const std::string& file_path) { |
| 296 | if (!fs::exists(file_path) || !fs::is_regular_file(file_path)) { |
| 297 | fprintf(stderr, "[DOC] File not found: %s\n", file_path.c_str()); |
| 298 | return {}; |
| 299 | } |
| 300 | |
| 301 | std::string ext = fs::path(file_path).extension().string(); |
| 302 | std::transform(ext.begin(), ext.end(), ext.begin(), |
| 303 | [](unsigned char c) { return std::tolower(c); }); |
| 304 | |
| 305 | if (ext == ".pdf") return process_pdf(file_path); |
| 306 | if (ext == ".docx") return process_docx(file_path); |
| 307 | if (ext == ".doc") { |
| 308 | fprintf(stderr, "[DOC] .doc (legacy Word) not supported — save as .docx or .pdf\n"); |
| 309 | return {}; |
| 310 | } |
| 311 | |
| 312 | // Treat as plain text |
| 313 | std::ifstream ifs(file_path); |
| 314 | if (!ifs) { |
| 315 | fprintf(stderr, "[DOC] Failed to read %s\n", file_path.c_str()); |
| 316 | return {}; |
| 317 | } |
| 318 | std::string content((std::istreambuf_iterator<char>(ifs)), |
| 319 | std::istreambuf_iterator<char>()); |
| 320 | std::string filename = fs::path(file_path).filename().string(); |
| 321 | auto chunks = process_text(content, filename); |
| 322 | fprintf(stderr, "[DOC] Extracted %zu chunks from %s\n", chunks.size(), filename.c_str()); |
| 323 | return chunks; |
| 324 | } |
| 325 | |
| 326 | std::vector<DocumentChunk> DocumentProcessor::process_path(const std::string& path) { |
| 327 | if (fs::is_regular_file(path)) |