LCOV - code coverage report
Current view: top level - core/filesystem - SPFilepath.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 35 46 76.1 %
Date: 2024-05-12 00:16:13 Functions: 4 6 66.7 %

          Line data    Source code
       1             : /**
       2             : Copyright (c) 2022 Roman Katuntsev <sbkarr@stappler.org>
       3             : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       4             : 
       5             : Permission is hereby granted, free of charge, to any person obtaining a copy
       6             : of this software and associated documentation files (the "Software"), to deal
       7             : in the Software without restriction, including without limitation the rights
       8             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       9             : copies of the Software, and to permit persons to whom the Software is
      10             : furnished to do so, subject to the following conditions:
      11             : 
      12             : The above copyright notice and this permission notice shall be included in
      13             : all copies or substantial portions of the Software.
      14             : 
      15             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      18             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      20             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      21             : THE SOFTWARE.
      22             : **/
      23             : 
      24             : #ifndef STAPPLER_FILESYSTEM_SPFILEPATH_H_
      25             : #define STAPPLER_FILESYSTEM_SPFILEPATH_H_
      26             : 
      27             : #include "SPStringView.h"
      28             : #include "SPSpanView.h"
      29             : 
      30             : namespace STAPPLER_VERSIONIZED stappler {
      31             : 
      32             : using FilePath = ValueWrapper<StringView, class FilePathTag>;
      33             : 
      34             : }
      35             : 
      36             : namespace STAPPLER_VERSIONIZED stappler::filepath {
      37             : 
      38             : // check if filepath is absolute
      39             : bool isAbsolute(StringView path);
      40             : 
      41             : bool isCanonical(StringView path);
      42             : 
      43             : // check if filepath is in application bundle
      44             : bool isBundled(StringView path);
      45             : 
      46             : // check if filepath above it's current root
      47             : bool isAboveRoot(StringView path);
      48             : 
      49             : // check for ".", ".." and double slashes in path
      50             : bool validatePath(StringView path);
      51             : 
      52             : // remove any ".", ".." and double slashes from path
      53             : template <typename Interface>
      54             : auto reconstructPath(StringView path) -> typename Interface::StringType;
      55             : 
      56             : // returns current absolute path for file (canonical prefix will be decoded), this path should not be cached
      57             : // if writable flag is false, platform path will be returned with canonical prefix %PLATFORM%
      58             : // if writable flag is true, system should resolve platform prefix to absolute path, if possible
      59             : // if platform path can not be resolved (etc, it's in archive or another FS), empty string will be returned
      60             : template <typename Interface>
      61             : auto absolute(StringView, bool writable = false) -> typename Interface::StringType;
      62             : 
      63             : // encodes path for long-term storage (default application dirs will be replaced with canonical prefix,
      64             : // like %CACHE%/dir)
      65             : template <typename Interface>
      66             : auto canonical(StringView path) -> typename Interface::StringType;
      67             : 
      68             : // extract root from path by removing last component (/dir/file.tar.bz -> /dir)
      69             : StringView root(StringView path);
      70             : 
      71             : // extract last component (/dir/file.tar.bz -> file.tar.bz)
      72             : StringView lastComponent(StringView path);
      73             : StringView lastComponent(StringView path, size_t allowedComponents);
      74             : 
      75             : // extract full filename extension (/dir/file.tar.gz -> tar.gz)
      76             : StringView fullExtension(StringView path);
      77             : 
      78             : // extract last filename extension (/dir/file.tar.gz -> gz)
      79             : StringView lastExtension(StringView path);
      80             : 
      81             : // /dir/file.tar.bz -> file
      82             : StringView name(StringView path);
      83             : 
      84             : // /dir/file.tar.bz -> 2
      85             : size_t extensionCount(StringView path);
      86             : 
      87             : template <typename Interface>
      88             : auto split(StringView) -> typename Interface::template VectorType<StringView>;
      89             : 
      90             : void split(StringView, const Callback<void(StringView)> &);
      91             : 
      92             : // merges two path component, removes or adds '/' where needed
      93             : template <typename Interface>
      94             : auto _merge(StringView root, StringView path) -> typename Interface::StringType;
      95             : 
      96             : template <typename Interface>
      97             : auto merge(SpanView<std::string>) -> typename Interface::StringType;
      98             : 
      99             : template <typename Interface>
     100             : auto merge(SpanView<memory::string>) -> typename Interface::StringType;
     101             : 
     102             : template <typename Interface>
     103             : auto merge(SpanView<StringView>) -> typename Interface::StringType;
     104             : 
     105             : template <typename Interface>
     106             : auto merge(stappler::memory::StandartInterface::StringType &&str) -> typename Interface::StringType;
     107             : 
     108             : template <typename Interface>
     109             : auto merge(stappler::memory::PoolInterface::StringType &&str) -> typename Interface::StringType;
     110             : 
     111             : template <typename Interface, class... Args>
     112       23184 : auto merge(StringView root, StringView path, Args&&... args) -> typename Interface::StringType {
     113       23184 :         return merge<Interface>(_merge<Interface>(root, path), std::forward<Args>(args)...);
     114             : }
     115             : 
     116             : // translate some MIME Content-Type to common extensions
     117             : StringView extensionForContentType(StringView type);
     118             : 
     119             : // replace root path component in filepath
     120             : // replace(/my/dir/first/file, /my/dir/first, /your/dir/second)
     121             : // [/my/dir/first -> /your/dir/second] /file
     122             : // /my/dir/first/file -> /your/dir/second/file
     123             : template <typename Interface>
     124             : auto replace(StringView path, StringView source, StringView dest) -> typename Interface::StringType;
     125             : 
     126             : // Implementation
     127             : 
     128             : template <typename Interface>
     129          25 : auto reconstructPath(StringView path) -> typename Interface::StringType {
     130          25 :         typename Interface::StringType ret; ret.reserve(path.size());
     131          25 :         bool start = (path.front() == '/');
     132          25 :         bool end = (path.back() == '/');
     133             : 
     134          25 :         typename Interface::template VectorType<StringView> retVec;
     135          25 :         StringView r(path);
     136         200 :         while (!r.empty()) {
     137         175 :                 auto str = r.readUntil<StringView::Chars<'/'>>();
     138         175 :                 if (str == ".." && str.size() == 2) {
     139           0 :                         if (!retVec.empty()) {
     140           0 :                                 retVec.pop_back();
     141             :                         }
     142         175 :                 } else if ((str == "." && str.size() == 1) || str.size() == 0) {
     143         150 :                 } else if (!str.empty()) {
     144         150 :                         retVec.emplace_back(str);
     145             :                 }
     146         175 :                 if (r.is('/')) {
     147         150 :                         ++ r;
     148             :                 }
     149             :         }
     150             : 
     151          25 :         if (start) {
     152           0 :                 ret.push_back('/');
     153             :         }
     154             : 
     155          25 :         bool f = false;
     156         175 :         for (auto &it : retVec) {
     157         150 :                 if (f) {
     158         125 :                         ret.push_back('/');
     159             :                 } else {
     160          25 :                         f = true;
     161             :                 }
     162         150 :                 ret.append(it.data(), it.size());
     163             :         }
     164          25 :         if (end) {
     165           0 :                 ret.push_back('/');
     166             :         }
     167          50 :         return ret;
     168          25 : }
     169             : 
     170             : template <typename Interface>
     171          25 : auto split(StringView str) -> typename Interface::template VectorType<StringView> {
     172          25 :         typename Interface::template VectorType<StringView> ret;
     173          25 :         StringView s(str);
     174             :         do {
     175         300 :                 if (s.is('/')) {
     176         300 :                         s ++;
     177             :                 }
     178         300 :                 auto path = s.readUntil<StringView::Chars<'/', '?', ';', '&', '#'>>();
     179         300 :                 ret.push_back(path);
     180         300 :         } while (!s.empty() && s.is('/'));
     181          50 :         return ret;
     182           0 : }
     183             : 
     184             : inline void split(StringView str, const Callback<void(StringView)> &cb) {
     185             :         StringView s(str);
     186             :         do {
     187             :                 if (s.is('/')) {
     188             :                         s ++;
     189             :                 }
     190             :                 auto path = s.readUntil<StringView::Chars<'/', '?', ';', '&', '#'>>();
     191             :                 cb(path);
     192             :         } while (!s.empty() && s.is('/'));
     193             : }
     194             : 
     195             : template <typename Interface>
     196           0 : auto replace(StringView path, StringView source, StringView dest) -> typename Interface::StringType {
     197           0 :         if (path.starts_with(source)) {
     198           0 :                 if (dest.empty()) {
     199           0 :                         return path.sub(source.size()).str<Interface>();
     200             :                 } else {
     201           0 :                         return filepath::merge<Interface>(dest, path.sub(source.size()));
     202             :                 }
     203             :         }
     204           0 :         return path.str<Interface>();
     205             : }
     206             : 
     207             : 
     208             : }
     209             : 
     210             : #endif /* STAPPLER_FILESYSTEM_SPFILEPATH_H_ */

Generated by: LCOV version 1.14