1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8#include "File.h"
9#include "llvm/Support/FileSystem.h"
10#include "llvm/Support/Path.h"
11
12namespace clang {
13namespace doc {
14
15llvm::Error copyFile(llvm::StringRef FilePath, llvm::StringRef OutDirectory) {
16 llvm::SmallString<128> PathWrite;
17 llvm::sys::path::native(path: OutDirectory, result&: PathWrite);
18 llvm::sys::path::append(path&: PathWrite, a: llvm::sys::path::filename(path: FilePath));
19 llvm::SmallString<128> PathRead;
20 llvm::sys::path::native(path: FilePath, result&: PathRead);
21 std::error_code FileErr = llvm::sys::fs::copy_file(From: PathRead, To: PathWrite);
22 if (FileErr) {
23 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
24 S: "error creating file " +
25 llvm::sys::path::filename(path: FilePath) +
26 ": " + FileErr.message() + "\n");
27 }
28 return llvm::Error::success();
29}
30
31llvm::SmallString<128> computeRelativePath(llvm::StringRef Destination,
32 llvm::StringRef Origin) {
33 // If Origin is empty, the relative path to the Destination is its complete
34 // path.
35 if (Origin.empty())
36 return Destination;
37
38 // The relative path is an empty path if both directories are the same.
39 if (Destination == Origin)
40 return {};
41
42 // These iterators iterate through each of their parent directories
43 llvm::sys::path::const_iterator FileI = llvm::sys::path::begin(path: Destination);
44 llvm::sys::path::const_iterator FileE = llvm::sys::path::end(path: Destination);
45 llvm::sys::path::const_iterator DirI = llvm::sys::path::begin(path: Origin);
46 llvm::sys::path::const_iterator DirE = llvm::sys::path::end(path: Origin);
47 // Advance both iterators until the paths differ. Example:
48 // Destination = A/B/C/D
49 // Origin = A/B/E/F
50 // FileI will point to C and DirI to E. The directories behind them is the
51 // directory they share (A/B).
52 while (FileI != FileE && DirI != DirE && *FileI == *DirI) {
53 ++FileI;
54 ++DirI;
55 }
56 llvm::SmallString<128> Result; // This will hold the resulting path.
57 // Result has to go up one directory for each of the remaining directories in
58 // Origin
59 while (DirI != DirE) {
60 llvm::sys::path::append(path&: Result, a: "..");
61 ++DirI;
62 }
63 // Result has to append each of the remaining directories in Destination
64 while (FileI != FileE) {
65 llvm::sys::path::append(path&: Result, a: *FileI);
66 ++FileI;
67 }
68 return Result;
69}
70
71} // namespace doc
72} // namespace clang
73

source code of clang-tools-extra/clang-doc/support/File.cpp