summaryrefslogtreecommitdiffstats
path: root/sal/osl/unx/file_path_helper.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /sal/osl/unx/file_path_helper.cxx
parentInitial commit. (diff)
downloadlibreoffice-upstream.tar.xz
libreoffice-upstream.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sal/osl/unx/file_path_helper.cxx')
-rw-r--r--sal/osl/unx/file_path_helper.cxx262
1 files changed, 262 insertions, 0 deletions
diff --git a/sal/osl/unx/file_path_helper.cxx b/sal/osl/unx/file_path_helper.cxx
new file mode 100644
index 000000000..a8ee5238f
--- /dev/null
+++ b/sal/osl/unx/file_path_helper.cxx
@@ -0,0 +1,262 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <cassert>
+#include <utility>
+
+#include "file_path_helper.hxx"
+#include "uunxapi.hxx"
+
+#include <osl/diagnose.h>
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+
+const sal_Unicode FPH_CHAR_PATH_SEPARATOR = '/';
+const sal_Unicode FPH_CHAR_DOT = '.';
+const sal_Unicode FPH_CHAR_COLON = ':';
+
+void osl_systemPathRemoveSeparator(rtl_String* pstrPath)
+{
+ OSL_PRECOND(nullptr != pstrPath, "osl_systemPathRemoveSeparator: Invalid parameter");
+ if (pstrPath == nullptr)
+ return;
+
+ // maybe there are more than one separator at end
+ // so we run in a loop
+ while ((pstrPath->length > 1) && (pstrPath->buffer[pstrPath->length - 1] == FPH_CHAR_PATH_SEPARATOR))
+ {
+ pstrPath->length--;
+ pstrPath->buffer[pstrPath->length] = '\0';
+ }
+
+ SAL_WARN_IF( !((0 == pstrPath->length) || (1 == pstrPath->length) ||
+ (pstrPath->length > 1 && pstrPath->buffer[pstrPath->length - 1] != FPH_CHAR_PATH_SEPARATOR)),
+ "sal.osl",
+ "osl_systemPathRemoveSeparator: Post condition failed");
+}
+
+namespace {
+
+template<typename T> void systemPathEnsureSeparator(T* ppstrPath)
+{
+ assert(nullptr != ppstrPath);
+ sal_Int32 lp = ppstrPath->getLength();
+ sal_Int32 i = ppstrPath->lastIndexOf(FPH_CHAR_PATH_SEPARATOR);
+
+ if ((lp > 1 && i != (lp - 1)) || ((lp < 2) && i < 0))
+ {
+ *ppstrPath += "/";
+ }
+
+ SAL_WARN_IF( !ppstrPath->endsWith("/"),
+ "sal.osl",
+ "systemPathEnsureSeparator: Post condition failed");
+}
+
+}
+
+bool osl_systemPathIsRelativePath(const rtl_uString* pustrPath)
+{
+ OSL_PRECOND(nullptr != pustrPath, "osl_systemPathIsRelativePath: Invalid parameter");
+ return ((pustrPath == nullptr) || (pustrPath->length == 0) || (pustrPath->buffer[0] != FPH_CHAR_PATH_SEPARATOR));
+}
+
+namespace {
+
+template<typename T> T systemPathMakeAbsolutePath_(
+ const T& BasePath,
+ const T& RelPath)
+{
+ T base(BasePath);
+
+ if (!base.isEmpty())
+ systemPathEnsureSeparator(&base);
+
+ return base + RelPath;
+}
+
+}
+
+OString osl::systemPathMakeAbsolutePath(
+ const OString& BasePath,
+ const OString& RelPath)
+{
+ return systemPathMakeAbsolutePath_(BasePath, RelPath);
+}
+
+OUString osl::systemPathMakeAbsolutePath(
+ const OUString& BasePath,
+ const OUString& RelPath)
+{
+ return systemPathMakeAbsolutePath_(BasePath, RelPath);
+}
+
+void osl_systemPathGetFileNameOrLastDirectoryPart(
+ const rtl_String* pstrPath,
+ rtl_String** ppstrFileNameOrLastDirPart)
+{
+ OSL_PRECOND(pstrPath && ppstrFileNameOrLastDirPart,
+ "osl_systemPathGetFileNameOrLastDirectoryPart: Invalid parameter");
+
+ OString path(const_cast<rtl_String*>(pstrPath));
+
+ osl_systemPathRemoveSeparator(path.pData);
+
+ OString last_part;
+
+ if (path.getLength() > 1 || (path.getLength() == 1 && path[0] != FPH_CHAR_PATH_SEPARATOR))
+ {
+ sal_Int32 idx_ps = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR);
+ idx_ps++; // always right to increment by one even if idx_ps == -1!
+ last_part = path.copy(idx_ps);
+ }
+ rtl_string_assign(ppstrFileNameOrLastDirPart, last_part.pData);
+}
+
+bool osl_systemPathIsHiddenFileOrDirectoryEntry(
+ const rtl_String* pstrPath)
+{
+ OSL_PRECOND(nullptr != pstrPath, "osl_systemPathIsHiddenFileOrDirectoryEntry: Invalid parameter");
+ if ((pstrPath == nullptr) || (pstrPath->length == 0))
+ return false;
+
+ OString fdp;
+ osl_systemPathGetFileNameOrLastDirectoryPart(pstrPath, &fdp.pData);
+
+ return ((fdp.pData->length > 0) &&
+ (fdp.pData->buffer[0] == FPH_CHAR_DOT) &&
+ !osl_systemPathIsLocalOrParentDirectoryEntry(fdp.pData));
+}
+
+bool osl_systemPathIsLocalOrParentDirectoryEntry(
+ const rtl_String* pstrPath)
+{
+ OSL_PRECOND(pstrPath, "osl_systemPathIsLocalOrParentDirectoryEntry: Invalid parameter");
+
+ OString dirent;
+
+ osl_systemPathGetFileNameOrLastDirectoryPart(pstrPath, &dirent.pData);
+
+ return (dirent == "." ||
+ dirent == "..");
+}
+
+namespace {
+
+/** Simple iterator for a path list separated by the specified character
+*/
+class path_list_iterator
+{
+public:
+
+ /* after construction get_current_item
+ returns the first path in list, no need
+ to call reset first
+ */
+ path_list_iterator(OUString path_list, sal_Unicode list_separator = FPH_CHAR_COLON) :
+ m_path_list(std::move(path_list)),
+ m_end(m_path_list.getStr() + m_path_list.getLength() + 1),
+ m_separator(list_separator)
+ {
+ reset();
+ }
+
+ path_list_iterator(const path_list_iterator&) = delete;
+ path_list_iterator& operator=(const path_list_iterator&) = delete;
+
+ void reset()
+ {
+ m_path_segment_begin = m_path_segment_end = m_path_list.getStr();
+ advance();
+ }
+
+ void next()
+ {
+ OSL_PRECOND(!done(), "path_list_iterator: Already done!");
+
+ m_path_segment_begin = ++m_path_segment_end;
+ advance();
+ }
+
+ bool done() const
+ {
+ return (m_path_segment_end >= m_end);
+ }
+
+ OUString get_current_item() const
+ {
+ return OUString(
+ m_path_segment_begin,
+ (m_path_segment_end - m_path_segment_begin));
+ }
+
+private:
+ /* move m_path_end to the next separator or
+ to the end of the string
+ */
+ void advance()
+ {
+ while (!done() && *m_path_segment_end && (*m_path_segment_end != m_separator))
+ ++m_path_segment_end;
+
+ OSL_ASSERT(m_path_segment_end <= m_end);
+ }
+
+private:
+ OUString m_path_list;
+ const sal_Unicode* m_end;
+ const sal_Unicode m_separator;
+ const sal_Unicode* m_path_segment_begin;
+ const sal_Unicode* m_path_segment_end;
+};
+
+}
+
+bool osl_searchPath(
+ const rtl_uString* pustrFilePath,
+ const rtl_uString* pustrSearchPathList,
+ rtl_uString** ppustrPathFound)
+{
+ OSL_PRECOND(pustrFilePath && pustrSearchPathList && ppustrPathFound, "osl_searchPath: Invalid parameter");
+
+ bool bfound = false;
+ OUString fp(const_cast<rtl_uString*>(pustrFilePath));
+ OUString pl(const_cast<rtl_uString*>(pustrSearchPathList));
+ path_list_iterator pli(pl);
+
+ while (!pli.done())
+ {
+ OUString p = pli.get_current_item();
+ systemPathEnsureSeparator(&p);
+ p += fp;
+
+ if (osl::access(osl::OUStringToOString(p), F_OK) > -1)
+ {
+ bfound = true;
+ rtl_uString_assign(ppustrPathFound, p.pData);
+ break;
+ }
+ pli.next();
+ }
+ return bfound;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */